--- asterisk/channels/chan_sip.c.orig Thu Apr 22 02:20:33 2004 +++ asterisk/channels/chan_sip.c Thu Apr 22 18:33:37 2004 @@ -96,6 +96,10 @@ static char mydbname[80]; #endif + /* SIP Debug */ +#define DEBUG_READ 0 /* Recieved data */ +#define DEBUG_SEND 1 /* Transmit data */ + static char *desc = "Session Initiation Protocol (SIP)"; static char *type = "SIP"; static char *tdesc = "Session Initiation Protocol (SIP)"; @@ -149,6 +153,7 @@ static int ourport; static int sipdebug = 0; +static struct sockaddr_in debugaddr; static int tos = 0; @@ -451,6 +456,8 @@ static int find_user(struct sip_pvt *fup, int event); static void prune_peers(void); static int sip_do_reload(void); +static int sip_debug_test_addr(struct sockaddr_in *addr); +static int sip_debug_test_pvt(struct sip_pvt *p); static int __sip_xmit(struct sip_pvt *p, char *data, int len) { @@ -491,7 +498,7 @@ ast_mutex_lock(&pkt->owner->lock); if (pkt->retrans < MAX_RETRANS) { pkt->retrans++; - if (sipdebug) { + if (sip_debug_test_pvt(pkt->owner)) { if (pkt->owner->nat) ast_verbose("Retransmitting #%d (NAT):\n%s\n to %s:%d\n", pkt->retrans, pkt->data, inet_ntoa(pkt->owner->recv.sin_addr), ntohs(pkt->owner->recv.sin_port)); else @@ -569,7 +576,7 @@ static int sip_scheddestroy(struct sip_pvt *p, int ms) { - if (sipdebug) + if (sip_debug_test_pvt(p)) ast_verbose("Scheduling destruction of call '%s' in %d ms\n", p->callid, ms); if (p->autokillid > -1) ast_sched_del(sched, p->autokillid); @@ -639,7 +646,7 @@ static int send_response(struct sip_pvt *p, struct sip_request *req, int reliable, int seqno) { int res; - if (sipdebug) { + if (sip_debug_test_pvt(p)) { if (p->nat) ast_verbose("%sTransmitting (NAT):\n%s\n to %s:%d\n", reliable ? "Reliably " : "", req->data, inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port)); else @@ -657,7 +664,7 @@ static int send_request(struct sip_pvt *p, struct sip_request *req, int reliable, int seqno) { int res; - if (sipdebug) { + if (sip_debug_test_pvt(p)) { if (p->nat) ast_verbose("%sTransmitting:\n%s (NAT) to %s:%d\n", reliable ? "Reliably " : "", req->data, inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port)); else @@ -690,13 +697,13 @@ static int sip_sendtext(struct ast_channel *ast, char *text) { struct sip_pvt *p = ast->pvt->pvt; - if (sipdebug) + if (sip_debug_test_pvt(p)) ast_verbose("Sending text %s on %s\n", text, ast->name); if (!p) return -1; if (!text || !strlen(text)) return 0; - if (sipdebug) + if (sip_debug_test_pvt(p)) ast_verbose("Really sending text %s on %s\n", text, ast->name); transmit_message_with_text(p, text); return 0; @@ -805,6 +812,22 @@ } #endif /* MYSQL_FRIENDS */ +static int sip_debug_test_addr(struct sockaddr_in *addr) { + /* See if we pass debug IP filter */ + if (sipdebug == 0) return 0; + if (debugaddr.sin_addr.s_addr) { + if (((ntohs(debugaddr.sin_port) != 0) && + (debugaddr.sin_port != addr->sin_port)) || + (debugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) + return 0; + } + return 1; +} + +static int sip_debug_test_pvt(struct sip_pvt *p) { + return (sipdebug && sip_debug_test_addr((p->nat ? &p->recv : &p->sa))); +} + static int create_addr(struct sip_pvt *r, char *peer) { struct hostent *hp; @@ -1056,7 +1079,7 @@ { struct sip_pvt *cur, *prev = NULL; struct sip_pkt *cp; - if (sipdebug) + if (sip_debug_test_pvt(p)) ast_verbose("Destroying call '%s'\n", p->callid); if (p->stateid > -1) ast_extension_state_del(p->stateid, NULL); @@ -1993,8 +2016,6 @@ if (strlen(req->line[f])) f++; req->lines = f; - if (sipdebug) - ast_verbose("%d headers, %d lines\n", req->headers, req->lines); if (*c) ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c); } @@ -2052,7 +2073,7 @@ ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs); return -1; } - if (sipdebug) + if (sip_debug_test_pvt(p)) ast_verbose("Found audio format %s\n", ast_getformatname(codec)); ast_rtp_set_m_type(p->rtp, codec); codecs += len; @@ -2072,7 +2093,7 @@ ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs); return -1; } - if (sipdebug) + if (sip_debug_test_pvt(p)) ast_verbose("Found video format %s\n", ast_getformatname(codec)); ast_rtp_set_m_type(p->vrtp, codec); codecs += len; @@ -2107,7 +2128,7 @@ sendonly=0; } if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2) continue; - if (sipdebug) + if (sip_debug_test_pvt(p)) ast_verbose("Found description format %s\n", mimeSubtype); // Note: should really look at the 'freq' and '#chans' params too ast_rtp_set_rtpmap_type(p->rtp, codec, "audio", mimeSubtype); @@ -2124,7 +2145,7 @@ p->jointcapability = p->capability & (peercapability | vpeercapability); p->noncodeccapability = noncodeccapability & (peernoncodeccapability | vpeernoncodeccapability); - if (sipdebug) { + if (sip_debug_test_pvt(p)) { ast_verbose("Capabilities: us - %d, them - %d/%d, combined - %d\n", p->capability, peercapability, vpeercapability, p->jointcapability); ast_verbose("Non-codec capabilities: us - %d, them - %d, combined - %d\n", @@ -2323,7 +2344,7 @@ /* Parse uri to h (host) and port - uri is already just the part inside the <> */ /* general form we are expecting is sip[s]:username[:password]@host[:port][;...] */ - if (sipdebug) + if (sip_debug_test_pvt(p)) ast_verbose("set_destination: Parsing <%s> for address/port to send to\n", uri); /* Find and parse hostname */ @@ -2368,7 +2389,7 @@ p->sa.sin_family = AF_INET; memcpy(&p->sa.sin_addr, hp->h_addr, sizeof(p->sa.sin_addr)); p->sa.sin_port = htons(port); - if (sipdebug) + if (sip_debug_test_pvt(p)) ast_verbose("set_destination: set destination to %s, port %d\n", inet_ntoa(p->sa.sin_addr), port); } @@ -2687,9 +2708,9 @@ vdest.sin_port = vsin.sin_port; } } - if (sipdebug) + if (sip_debug_test_pvt(p)) ast_verbose("We're at %s port %d\n", inet_ntoa(p->ourip), ntohs(sin.sin_port)); - if (sipdebug && p->vrtp) + if (sip_debug_test_pvt(p) && p->vrtp) ast_verbose("Video is at %s port %d\n", inet_ntoa(p->ourip), ntohs(vsin.sin_port)); snprintf(v, sizeof(v), "v=0\r\n"); snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", p->sessionid, p->sessionversion, inet_ntoa(dest.sin_addr)); @@ -2699,7 +2720,7 @@ snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port)); snprintf(m2, sizeof(m2), "m=video %d RTP/AVP", ntohs(vdest.sin_port)); if (p->jointcapability & p->prefcodec) { - if (sipdebug) + if (sip_debug_test_pvt(p)) ast_verbose("Answering/Requesting with root capability %d\n", p->prefcodec); codec = ast_rtp_lookup_code(p->rtp, 1, p->prefcodec); if (codec > -1) { @@ -2720,7 +2741,7 @@ cur = prefs; while(cur) { if (p->jointcapability & cur->codec) { - if (sipdebug) + if (sip_debug_test_pvt(p)) ast_verbose("Answering/Requesting with preferred capability %d\n", cur->codec); codec = ast_rtp_lookup_code(p->rtp, 1, cur->codec); if (codec > -1) { @@ -2742,7 +2763,7 @@ /* Now send any other common codecs, and non-codec formats: */ for (x = 1; x <= (videosupport ? AST_FORMAT_MAX_VIDEO : AST_FORMAT_MAX_AUDIO); x <<= 1) { if ((p->jointcapability & x) && !(alreadysent & x)) { - if (sipdebug) + if (sip_debug_test_pvt(p)) ast_verbose("Answering with capability %d\n", x); codec = ast_rtp_lookup_code(p->rtp, 1, x); if (codec > -1) { @@ -2761,7 +2782,7 @@ } for (x = 1; x <= AST_RTP_MAX; x <<= 1) { if (p->noncodeccapability & x) { - if (sipdebug) + if (sip_debug_test_pvt(p)) ast_verbose("Answering with non-codec capability %d\n", x); codec = ast_rtp_lookup_code(p->rtp, 0, x); if (codec > -1) { @@ -2904,6 +2925,8 @@ /* Use this as the basis */ copy_request(&p->initreq, &req); parse(&p->initreq); + if (sip_debug_test_pvt(p)) + ast_verbose("%d headers, %d lines\n", p->initreq.headers, p->initreq.lines); determine_firstline_parts(&p->initreq); p->lastinvite = p->ocseq; p->outgoing = 1; @@ -3050,6 +3073,8 @@ /* Use this as the basis */ copy_request(&p->initreq, &req); parse(&p->initreq); + if (sip_debug_test_pvt(p)) + ast_verbose("%d headers, %d lines\n", p->initreq.headers, p->initreq.lines); determine_firstline_parts(&p->initreq); } p->lastinvite = p->ocseq; @@ -3165,6 +3190,8 @@ /* Use this as the basis */ copy_request(&p->initreq, &req); parse(&p->initreq); + if (sip_debug_test_pvt(p)) + ast_verbose("%d headers, %d lines\n", p->initreq.headers, p->initreq.lines); determine_firstline_parts(&p->initreq); } @@ -3321,6 +3348,8 @@ add_blank_header(&req); copy_request(&p->initreq, &req); parse(&p->initreq); + if (sip_debug_test_pvt(p)) + ast_verbose("%d headers, %d lines\n", p->initreq.headers, p->initreq.lines); determine_firstline_parts(&p->initreq); r->regstate=auth?REG_STATE_AUTHSENT:REG_STATE_REGSENT; return send_request(p, &req, 2, p->ocseq); @@ -3673,7 +3702,7 @@ p->route = head; /* For debugging dump what we ended up with */ - if (sipdebug) + if (sip_debug_test_pvt(p)) list_route(p->route); } @@ -3923,7 +3952,7 @@ if ((a = strchr(c, '@')) || (a = strchr(c, ';'))) { *a = '\0'; } - if (sipdebug) + if (sip_debug_test_pvt(p)) ast_verbose("RDNIS is %s\n", c); strncpy(p->rdnis, c, sizeof(p->rdnis) - 1); @@ -3974,7 +4003,7 @@ strncpy(p->fromdomain, a + 1, sizeof(p->fromdomain) - 1); } } - if (sipdebug) + if (sip_debug_test_pvt(p)) ast_verbose("Looking for %s in %s\n", c, p->context); if (ast_exists_extension(NULL, p->context, c, 1, fr) || !strcmp(c, ast_pickup_ext())) { @@ -4072,7 +4101,7 @@ *a2 = '\0'; - if (sipdebug) { + if (sip_debug_test_pvt(p)) { ast_verbose("Looking for %s in %s\n", c, p->context); ast_verbose("Looking for %s in %s\n", c2, p->context); } @@ -4144,7 +4173,7 @@ if ((a = strchr(c, ';'))) *a = '\0'; - if (sipdebug) { + if (sip_debug_test_pvt(p)) { ast_verbose("Looking for %s in %s\n", c, p->context); } if (ast_exists_extension(NULL, p->context, c, 1, NULL)) { @@ -4199,7 +4228,7 @@ p->sa.sin_family = AF_INET; memcpy(&p->sa.sin_addr, hp->h_addr, sizeof(p->sa.sin_addr)); p->sa.sin_port = htons(pt ? atoi(pt) : DEFAULT_SIP_PORT); - if (sipdebug) { + if (sip_debug_test_pvt(p)) { if (p->nat) ast_verbose("Sending to %s : %d (NAT)\n", inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port)); else @@ -4404,7 +4433,7 @@ return; } if (p->owner) { - if (sipdebug) + if (sip_debug_test_pvt(p)) ast_verbose("Message received: '%s'\n", buf); memset(&f, 0, sizeof(f)); f.frametype = AST_FRAME_TEXT; @@ -4659,7 +4688,7 @@ if (p->owner) { if (strlen(buf)) { - if (sipdebug) + if (sip_debug_test_pvt(p)) ast_verbose("DTMF received: '%c'\n", buf[0]); if (buf[0] == '*') event = 10; @@ -4687,11 +4716,80 @@ } } -static int sip_do_debug(int fd, int argc, char *argv[]) +static int sip_do_debug_ip(int fd, int argc, char *argv[]) { - if (argc != 2) + struct hostent *hp; + struct ast_hostent ahp; + int port = 0; + char *p, *arg; + if (argc != 4) + return RESULT_SHOWUSAGE; + arg = argv[3]; + p = strstr(arg, ":"); + if (p) { + *p = '\0'; + p++; + port = atoi(p); + } + hp = ast_gethostbyname(arg, &ahp); + if (hp == NULL) { return RESULT_SHOWUSAGE; + } + debugaddr.sin_family = AF_INET; + memcpy(&debugaddr.sin_addr, hp->h_addr, sizeof(debugaddr.sin_addr)); + debugaddr.sin_port = htons(port); + if (port == 0) + ast_cli(fd, "SIP Debugging Enabled for IP: %s\n", inet_ntoa(debugaddr.sin_addr)); + else + ast_cli(fd, "SIP Debugging Enabled for IP: %s:%d\n", inet_ntoa(debugaddr.sin_addr), port); + sipdebug = 1; + return RESULT_SUCCESS; +} + +static int sip_do_debug_peer(int fd, int argc, char *argv[]) +{ + struct sip_peer *peer; + if (argc != 4) + return RESULT_SHOWUSAGE; + ast_mutex_lock(&peerl.lock); + for (peer = peerl.peers;peer;peer = peer->next) + if (!strcmp(peer->name, argv[3])) + break; + ast_mutex_unlock(&peerl.lock); +#ifdef MYSQL_FRIENDS + if (!peer) + peer = mysql_peer(argv[3], NULL); +#endif + if (peer) { + if (peer->addr.sin_addr.s_addr) { + debugaddr.sin_family = AF_INET; + memcpy(&debugaddr.sin_addr, &peer->addr.sin_addr, sizeof(debugaddr.sin_addr)); + debugaddr.sin_port = peer->addr.sin_port; + ast_cli(fd, "SIP Debugging Enabled for IP: %s:%d\n", inet_ntoa(debugaddr.sin_addr), ntohs(debugaddr.sin_port)); + sipdebug = 1; + } else + ast_cli(fd, "Unable to get IP address of peer '%s'\n", argv[3]); + if (peer->temponly) + free(peer); + peer = NULL; + } else + ast_cli(fd, "No such peer '%s'\n", argv[3]); + return RESULT_SUCCESS; +} + +static int sip_do_debug(int fd, int argc, char *argv[]) +{ + if (argc != 2) { + if (argc != 4) + return RESULT_SHOWUSAGE; + else if (strncmp(argv[2], "ip\0", 3) == 0) + return sip_do_debug_ip(fd, argc, argv); + else if (strncmp(argv[2], "peer\0", 5) == 0) + return sip_do_debug_peer(fd, argc, argv); + else return RESULT_SHOWUSAGE; + } sipdebug = 1; + memset(&debugaddr, 0, sizeof(debugaddr)); ast_cli(fd, "SIP Debugging Enabled\n"); return RESULT_SUCCESS; } @@ -4894,7 +4992,12 @@ static char debug_usage[] = "Usage: sip debug\n" -" Enables dumping of SIP packets for debugging purposes\n"; +" Enables dumping of SIP packets for debugging purposes\n\n" +" sip debug ip \n" +" Enables dumping of SIP packets to and from host.\n\n" +" sip debug peer \n" +" Enables dumping of SIP packets to and from host.\n" +" Require peer to be registered.\n"; static char no_debug_usage[] = "Usage: sip no debug\n" @@ -4910,6 +5013,10 @@ { { "sip", "show", "channels", NULL }, sip_show_channels, "Show active SIP channels", show_channels_usage}; static struct ast_cli_entry cli_show_channel = { { "sip", "show", "channel", NULL }, sip_show_channel, "Show detailed SIP channel info", show_channel_usage, complete_sipch }; +static struct ast_cli_entry cli_debug_ip = + { { "sip", "debug", "ip", NULL }, sip_do_debug, "Enable SIP debugging on IP", debug_usage }; +static struct ast_cli_entry cli_debug_peer = + { { "sip", "debug", "peer", NULL }, sip_do_debug, "Enable SIP debugging on Peername", debug_usage }; static struct ast_cli_entry cli_show_peers = { { "sip", "show", "peers", NULL }, sip_show_peers, "Show defined SIP peers", show_peers_usage }; static struct ast_cli_entry cli_inuse_show = @@ -5222,7 +5329,7 @@ ast_log(LOG_NOTICE, "Dunno anything about a %d %s response from %s\n", resp, rest, p->owner ? p->owner->name : inet_ntoa(p->sa.sin_addr)); } } else { - if (sipdebug) + if (sip_debug_test_pvt(p)) ast_verbose("Message is %s\n", msg); switch(resp) { case 200: @@ -5391,7 +5498,7 @@ /* Process the SDP portion */ if (!ignore) { /* Use this as the basis */ - if (sipdebug) + if (sip_debug_test_pvt(p)) ast_verbose("Using latest request as basis request\n"); /* This call is no longer outgoing if it ever was */ p->outgoing = 0; @@ -5407,7 +5514,7 @@ /* Queue NULL frame to prod ast_rtp_bridge if appropriate */ if (p->owner) ast_queue_frame(p->owner, &af); - } else if (sipdebug) + } else if (sip_debug_test_pvt(p)) ast_verbose("Ignoring this request\n"); if (!p->lastinvite) { /* Handle authentication if this is our first invite */ @@ -5621,20 +5728,20 @@ p->needdestroy = 1; transmit_response(p, "200 OK", req); } else if (!strcasecmp(cmd, "MESSAGE")) { - if (sipdebug) + if (sip_debug_test_pvt(p)) ast_verbose("Receiving message!\n"); receive_message(p, req); transmit_response(p, "200 OK", req); } else if (!strcasecmp(cmd, "SUBSCRIBE")) { if (!ignore) { /* Use this as the basis */ - if (sipdebug) + if (sip_debug_test_pvt(p)) ast_verbose("Using latest SUBSCRIBE request as basis request\n"); /* This call is no longer outgoing if it ever was */ p->outgoing = 0; copy_request(&p->initreq, req); check_via(p, req); - } else if (sipdebug) + } else if (sip_debug_test_pvt(p)) ast_verbose("Ignoring this request\n"); if (!p->lastinvite) { @@ -5691,13 +5798,13 @@ transmit_state_notify(p, ast_extension_state(NULL, p->context, p->exten),1); } } else if (!strcasecmp(cmd, "INFO")) { - if (sipdebug) + if (sip_debug_test_pvt(p)) ast_verbose("Receiving DTMF!\n"); receive_info(p, req); transmit_response(p, "200 OK", req); } else if (!strcasecmp(cmd, "REGISTER")) { /* Use this as the basis */ - if (sipdebug) + if (sip_debug_test_pvt(p)) ast_verbose("Using latest request as basis request\n"); copy_request(&p->initreq, req); check_via(p, req); @@ -5756,9 +5863,11 @@ } req.data[res] = '\0'; req.len = res; - if (sipdebug) + if (sip_debug_test_addr(&sin)) ast_verbose("\n\nSip read: \n%s\n", req.data); parse(&req); + if (sip_debug_test_addr(&sin)) + ast_verbose("%d headers, %d lines\n", req.headers, req.lines); if (req.headers < 2) { /* Must have at least two headers */ return 1; @@ -6947,6 +7056,8 @@ ast_cli_register(&cli_show_peers); ast_cli_register(&cli_show_registry); ast_cli_register(&cli_debug); + ast_cli_register(&cli_debug_ip); + ast_cli_register(&cli_debug_peer); ast_cli_register(&cli_no_debug); ast_cli_register(&cli_sip_reload); ast_cli_register(&cli_inuse_show); @@ -6981,6 +7092,8 @@ ast_cli_unregister(&cli_show_peers); ast_cli_unregister(&cli_show_registry); ast_cli_unregister(&cli_debug); + ast_cli_unregister(&cli_debug_ip); + ast_cli_unregister(&cli_debug_peer); ast_cli_unregister(&cli_no_debug); ast_cli_unregister(&cli_sip_reload); ast_cli_unregister(&cli_inuse_show);