--- asterisk/channels/chan_sip.c.20040420 Tue Apr 20 00:55:35 2004 +++ asterisk/channels/chan_sip.c Wed Apr 21 02:27:49 2004 @@ -96,6 +96,21 @@ static char mydbname[80]; #endif + + /* SIP Debug */ +#define DEBUG_READ 0 /* Recieved data */ +#define DEBUG_SEND 1 /* Transmit data */ + + /* Levels: */ +#define DEBUG_OFF 0 /* No debug */ +#define DEBUG_HEADERS 1 /* Show headers only */ +#define DEBUG_PACKETS 2 /* Show Full packets */ +#define DEBUG_VERBOSE_RTP 4 /* Verbose comments RTPstream */ +#define DEBUG_VERBOSE_AUTH 8 /* Verbose comments authentication*/ +#define DEBUG_VERBOSE_OTHER 128 /* Verbose comments */ + + + static char *desc = "Session Initiation Protocol (SIP)"; static char *type = "SIP"; static char *tdesc = "Session Initiation Protocol (SIP)"; @@ -148,7 +163,7 @@ static struct in_addr __ourip; static int ourport; -static int sipdebug = 0; +static int sipdebug = DEBUG_OFF; static int tos = 0; @@ -400,6 +415,11 @@ struct sip_registry *next; }; +struct sip_debug_filter { + struct sockaddr_in addr; + struct sip_debug_filter *next; +}; + static struct ast_user_list { struct sip_user *users; ast_mutex_t lock; @@ -426,6 +446,9 @@ static int globalnat = 0; static int globalcanreinvite = REINVITE_INVITE; +static struct ast_debug_filter { + struct sip_debug_filter *filters; +} debfilterl = { NULL }; static struct sockaddr_in bindaddr; static struct sockaddr_in localnet; @@ -451,14 +474,18 @@ static int find_user(struct sip_pvt *fup, int event); static void prune_peers(void); static int sip_do_reload(void); +static void filter_sip_debug(int direction, char *data, int len, struct sockaddr_in *addr); static int __sip_xmit(struct sip_pvt *p, char *data, int len) { int res; - if (p->nat) - res=sendto(sipsock, data, len, 0, (struct sockaddr *)&p->recv, sizeof(struct sockaddr_in)); - else - res=sendto(sipsock, data, len, 0, (struct sockaddr *)&p->sa, sizeof(struct sockaddr_in)); + if (p->nat) { + filter_sip_debug(DEBUG_SEND, data, len, &p->recv); + res=sendto(sipsock, data, len, 0, (struct sockaddr *)&p->recv, sizeof(struct sockaddr_in)); + } else { + filter_sip_debug(DEBUG_SEND, data, len, &p->sa); + res=sendto(sipsock, data, len, 0, (struct sockaddr *)&p->sa, sizeof(struct sockaddr_in)); + } if (res != len) { ast_log(LOG_WARNING, "sip_xmit of %p (len %d) to %s returned %d: %s\n", data, len, inet_ntoa(p->sa.sin_addr), res, strerror(errno)); } @@ -491,11 +518,11 @@ ast_mutex_lock(&pkt->owner->lock); if (pkt->retrans < MAX_RETRANS) { pkt->retrans++; - if (sipdebug) { + if (sipdebug & DEBUG_VERBOSE_OTHER) { 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)); + ast_verbose("Retransmitting (NAT):\n"); else - ast_verbose("Retransmitting #%d (no NAT):\n%s\n to %s:%d\n", pkt->retrans, pkt->data, inet_ntoa(pkt->owner->sa.sin_addr), ntohs(pkt->owner->sa.sin_port)); + ast_verbose("Retransmitting (no NAT):\n"); } __sip_xmit(pkt->owner, pkt->data, pkt->packetlen); res = 1; @@ -569,7 +596,7 @@ static int sip_scheddestroy(struct sip_pvt *p, int ms) { - if (sipdebug) + if (sipdebug & DEBUG_VERBOSE_OTHER) 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,11 +666,11 @@ static int send_response(struct sip_pvt *p, struct sip_request *req, int reliable, int seqno) { int res; - if (sipdebug) { + if (sipdebug & DEBUG_VERBOSE_OTHER) { 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)); + ast_verbose("%sTransmitting (NAT) to %s:%d\n", reliable ? "Reliably " : "", inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port)); else - ast_verbose("%sTransmitting (no NAT):\n%s\n to %s:%d\n", reliable ? "Reliably " : "", req->data, inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port)); + ast_verbose("%sTransmitting (no NAT) to %s:%d\n", reliable ? "Reliably " : "", inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port)); } if (reliable) res = __sip_reliable_xmit(p, seqno, 1, req->data, req->len, (reliable > 1)); @@ -657,11 +684,11 @@ static int send_request(struct sip_pvt *p, struct sip_request *req, int reliable, int seqno) { int res; - if (sipdebug) { + if (sipdebug & DEBUG_VERBOSE_OTHER) { 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)); + ast_verbose("%sTransmitting (NAT):\n", reliable ? "Reliably " : ""); else - ast_verbose("%sTransmitting:\n%s (no NAT) to %s:%d\n", reliable ? "Reliably " : "", req->data, inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port)); + ast_verbose("%sTransmitting (no NAT):\n", reliable ? "Reliably " : ""); } if (reliable) res = __sip_reliable_xmit(p, seqno, 0, req->data, req->len, (reliable > 1)); @@ -690,13 +717,13 @@ static int sip_sendtext(struct ast_channel *ast, char *text) { struct sip_pvt *p = ast->pvt->pvt; - if (sipdebug) + if (sipdebug & DEBUG_VERBOSE_OTHER) ast_verbose("Sending text %s on %s\n", text, ast->name); if (!p) return -1; if (!text || !strlen(text)) return 0; - if (sipdebug) + if (sipdebug & DEBUG_VERBOSE_OTHER) ast_verbose("Really sending text %s on %s\n", text, ast->name); transmit_message_with_text(p, text); return 0; @@ -805,6 +832,101 @@ } #endif /* MYSQL_FRIENDS */ +static void filter_sip_debug(int direction, char *data, int len, struct sockaddr_in *addr) +{ +#define FORMAT "\r%s %-75s %-15s %-5d %-21s\n" +#define FORMAT2 "\r%s %-75s %-15s %-5d %s:%d\n" +#define FORMAT3 " %s\n" + static struct sip_debug_filter *filter; + static struct sip_peer *peer; + static char row[SIP_MAX_PACKET]; + static int i, j, rowno, pass, seqno; + static char *cp; + if ((sipdebug & (DEBUG_HEADERS | DEBUG_PACKETS)) == 0) return; + seqno = 0; + pass = 0; + /* See if we pass debug IP filter */ + if (debfilterl.filters) { + for (filter = debfilterl.filters; filter; filter = filter->next) + if (((ntohs(filter->addr.sin_port) == 0) && + (filter->addr.sin_addr.s_addr == addr->sin_addr.s_addr)) || + ((filter->addr.sin_port == addr->sin_port) && + (filter->addr.sin_addr.s_addr == addr->sin_addr.s_addr))) { + pass = 1; + break; + } + if (!pass) return; + } + /* Find peer */ + if (sipdebug & DEBUG_HEADERS) { + peer = NULL; + if (!ast_mutex_trylock(&peerl.lock)) { + for (peer = peerl.peers;peer;peer = peer->next) + if ((peer->addr.sin_addr.s_addr == addr->sin_addr.s_addr) && + (peer->addr.sin_port == addr->sin_port)) + break; + ast_mutex_unlock(&peerl.lock); + } +#ifdef MYSQL_FRIENDS + if (!peer) + peer = mysql_peer(NULL, addr); +#endif + + /* Scan data for CSeq */ + j = 0; + for (i = 0; isin_port) == 5060) + ast_verbose(FORMAT, + (direction==DEBUG_READ ? "<--" : "-->"), + row, + (peer?peer->name:"?"), + seqno, + inet_ntoa(addr->sin_addr)); + else + ast_verbose(FORMAT2, + (direction==DEBUG_READ ? "<--" : "-->"), + row, + (peer?peer->name:"?"), + seqno, + inet_ntoa(addr->sin_addr), + ntohs(addr->sin_port)); + if ((sipdebug & DEBUG_PACKETS) == 0) { + if (peer && peer->temponly) { + free(peer); + peer = NULL; + } + return; + } + } else + ast_verbose(FORMAT3, row); + rowno++; + j = 0; + } else if (data[i] != '\r' ) + row[j++] = data[i]; + } + if (peer && peer->temponly) { + free(peer); + peer = NULL; + } +#undef FORMAT +#undef FORMAT2 +#undef FORMAT3 +} + static int create_addr(struct sip_pvt *r, char *peer) { struct hostent *hp; @@ -1055,7 +1177,7 @@ { struct sip_pvt *cur, *prev = NULL; struct sip_pkt *cp; - if (sipdebug) + if (sipdebug & DEBUG_VERBOSE_OTHER) ast_verbose("Destroying call '%s'\n", p->callid); if (p->stateid > -1) ast_extension_state_del(p->stateid, NULL); @@ -1991,7 +2113,7 @@ if (strlen(req->line[f])) f++; req->lines = f; - if (sipdebug) + if (sipdebug & DEBUG_VERBOSE_OTHER) 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); @@ -2049,7 +2171,7 @@ ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs); return -1; } - if (sipdebug) + if (sipdebug & DEBUG_VERBOSE_RTP) ast_verbose("Found audio format %s\n", ast_getformatname(codec)); ast_rtp_set_m_type(p->rtp, codec); codecs += len; @@ -2069,7 +2191,7 @@ ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs); return -1; } - if (sipdebug) + if (sipdebug & DEBUG_VERBOSE_RTP) ast_verbose("Found video format %s\n", ast_getformatname(codec)); ast_rtp_set_m_type(p->vrtp, codec); codecs += len; @@ -2088,9 +2210,8 @@ sin.sin_port = htons(vportno); if (p->vrtp && sin.sin_port) ast_rtp_set_peer(p->vrtp, &sin); -#if 0 - printf("Peer RTP is at port %s:%d\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); -#endif + if (sipdebug & DEBUG_VERBOSE_RTP) + ast_verbose("Peer RTP is at port %s:%d\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); // Next, scan through each "a=rtpmap:" line, noting each // specified RTP payload type (with corresponding MIME subtype): sdpLineNum_iterator_init(&iterator); @@ -2104,7 +2225,7 @@ sendonly=0; } if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2) continue; - if (sipdebug) + if (sipdebug & DEBUG_VERBOSE_RTP) 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); @@ -2121,7 +2242,7 @@ p->jointcapability = p->capability & (peercapability | vpeercapability); p->noncodeccapability = noncodeccapability & (peernoncodeccapability | vpeernoncodeccapability); - if (sipdebug) { + if (sipdebug & DEBUG_VERBOSE_RTP) { 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", @@ -2319,7 +2440,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 (sipdebug & DEBUG_VERBOSE_OTHER) ast_verbose("set_destination: Parsing <%s> for address/port to send to\n", uri); /* Find and parse hostname */ @@ -2364,7 +2485,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 (sipdebug & DEBUG_VERBOSE_OTHER) ast_verbose("set_destination: set destination to %s, port %d\n", inet_ntoa(p->sa.sin_addr), port); } @@ -2683,9 +2804,9 @@ vdest.sin_port = vsin.sin_port; } } - if (sipdebug) + if (sipdebug & DEBUG_VERBOSE_RTP) ast_verbose("We're at %s port %d\n", inet_ntoa(p->ourip), ntohs(sin.sin_port)); - if (sipdebug && p->vrtp) + if ((sipdebug & DEBUG_VERBOSE_RTP) && 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)); @@ -2695,7 +2816,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 (sipdebug & DEBUG_VERBOSE_RTP) ast_verbose("Answering/Requesting with root capability %d\n", p->prefcodec); codec = ast_rtp_lookup_code(p->rtp, 1, p->prefcodec); if (codec > -1) { @@ -2716,7 +2837,7 @@ cur = prefs; while(cur) { if (p->jointcapability & cur->codec) { - if (sipdebug) + if (sipdebug & DEBUG_VERBOSE_RTP) ast_verbose("Answering/Requesting with preferred capability %d\n", cur->codec); codec = ast_rtp_lookup_code(p->rtp, 1, cur->codec); if (codec > -1) { @@ -2738,7 +2859,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 (sipdebug & DEBUG_VERBOSE_RTP) ast_verbose("Answering with capability %d\n", x); codec = ast_rtp_lookup_code(p->rtp, 1, x); if (codec > -1) { @@ -2757,7 +2878,7 @@ } for (x = 1; x <= AST_RTP_MAX; x <<= 1) { if (p->noncodeccapability & x) { - if (sipdebug) + if (sipdebug & DEBUG_VERBOSE_RTP) ast_verbose("Answering with non-codec capability %d\n", x); codec = ast_rtp_lookup_code(p->rtp, 0, x); if (codec > -1) { @@ -3667,7 +3788,7 @@ p->route = head; /* For debugging dump what we ended up with */ - if (sipdebug) + if (sipdebug & DEBUG_VERBOSE_OTHER) list_route(p->route); } @@ -3689,8 +3810,11 @@ { int res = -1; /* Always OK if no secret */ - if (!strlen(secret) && !strlen(md5secret)) + if (!strlen(secret) && !strlen(md5secret)) { + if (sipdebug & DEBUG_VERBOSE_AUTH) + ast_verbose("Authentication for '%s': PASS (no password)\n", username); return 0; + } if (ignore && strlen(randdata) && !strlen(get_header(req, "Proxy-Authorization"))) { /* This is a retransmitted invite/register/etc, don't reconstruct authentication information */ @@ -3784,6 +3908,8 @@ } /* Assume success ;-) */ } + if (sipdebug & DEBUG_VERBOSE_AUTH) + ast_verbose("Authentication for '%s': %s\n", username, ( res == -1 ? "FAIL" : "PASS")); return res; } @@ -3917,7 +4043,7 @@ if ((a = strchr(c, '@')) || (a = strchr(c, ';'))) { *a = '\0'; } - if (sipdebug) + if (sipdebug & DEBUG_VERBOSE_OTHER) ast_verbose("RDNIS is %s\n", c); strncpy(p->rdnis, c, sizeof(p->rdnis) - 1); @@ -3968,7 +4094,7 @@ strncpy(p->fromdomain, a + 1, sizeof(p->fromdomain) - 1); } } - if (sipdebug) + if (sipdebug & DEBUG_VERBOSE_OTHER) 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())) { @@ -4066,7 +4192,7 @@ *a2 = '\0'; - if (sipdebug) { + if (sipdebug & DEBUG_VERBOSE_OTHER) { ast_verbose("Looking for %s in %s\n", c, p->context); ast_verbose("Looking for %s in %s\n", c2, p->context); } @@ -4138,7 +4264,7 @@ if ((a = strchr(c, ';'))) *a = '\0'; - if (sipdebug) { + if (sipdebug & DEBUG_VERBOSE_OTHER) { ast_verbose("Looking for %s in %s\n", c, p->context); } if (ast_exists_extension(NULL, p->context, c, 1, NULL)) { @@ -4192,7 +4318,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 (sipdebug & DEBUG_VERBOSE_OTHER) { if (p->nat) ast_verbose("Sending to %s : %d (NAT)\n", inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port)); else @@ -4397,7 +4523,7 @@ return; } if (p->owner) { - if (sipdebug) + if (sipdebug & DEBUG_VERBOSE_OTHER) ast_verbose("Message received: '%s'\n", buf); memset(&f, 0, sizeof(f)); f.frametype = AST_FRAME_TEXT; @@ -4500,6 +4626,111 @@ #undef FORMAT2 } +static int sip_show_dfilter(int fd, int argc, char *argv[]) +{ +#define FORMAT2 "%-15.15s %-8s\n" +#define FORMAT "%-15.15s %-8d\n" + struct sip_debug_filter *filter; + if (argc != 3) + return RESULT_SHOWUSAGE; + ast_cli(fd, FORMAT2, "IP", "Port"); + for (filter = debfilterl.filters;filter;filter = filter->next) { + if (ntohs(filter->addr.sin_port) == 0) + ast_cli(fd, FORMAT2, + inet_ntoa(filter->addr.sin_addr) , + ""); + else + ast_cli(fd, FORMAT, + inet_ntoa(filter->addr.sin_addr) , + ntohs(filter->addr.sin_port)); + } + return RESULT_SUCCESS; +#undef FORMAT +#undef FORMAT2 +} + +static int sip_dfilter_clear(int fd, int argc, char *argv[]) +{ + struct sip_debug_filter *filter; + struct sip_debug_filter *filter2; + if (argc != 3) + return RESULT_SHOWUSAGE; + for (filter = debfilterl.filters;filter;) { + filter2 = filter->next; + free(filter); + filter = filter2; + } + debfilterl.filters = NULL; + return RESULT_SUCCESS; +} + +static int sip_dfilter_add_ip(int fd, int argc, char *argv[]) +{ + struct sip_debug_filter *filter; + struct hostent *hp; + int port = 0; + char *p, *arg; + if (argc != 5) + return RESULT_SHOWUSAGE; + arg = argv[4]; + p = strstr(arg, ":"); + if (p) { + *p = '\0'; + p++; + port = atoi(p); + } + hp = gethostbyname(arg); + if (hp == NULL) { + return RESULT_SHOWUSAGE; + } + filter = (struct sip_debug_filter *)malloc(sizeof(struct sip_debug_filter)); + if (filter) { + filter->next = debfilterl.filters; + filter->addr.sin_family = AF_INET; + memcpy(&filter->addr.sin_addr, hp->h_addr, sizeof(filter->addr.sin_addr)); + filter->addr.sin_port = htons(port); + debfilterl.filters = filter; + } + return RESULT_SUCCESS; +} + +static int sip_dfilter_add_peer(int fd, int argc, char *argv[]) +{ + struct sip_debug_filter *filter; + struct sip_peer *peer; + if (argc != 5) + return RESULT_SHOWUSAGE; + ast_mutex_lock(&peerl.lock); + for (peer = peerl.peers;peer;peer = peer->next) + if (!strcmp(peer->name, argv[4])) + break; + ast_mutex_unlock(&peerl.lock); +#ifdef MYSQL_FRIENDS + if (!peer) + peer = mysql_peer(argv[4], NULL); +#endif + if (peer) { + if (peer->addr.sin_addr.s_addr) { + filter = (struct sip_debug_filter *)malloc(sizeof(struct sip_debug_filter)); + if (filter) { + filter->next = debfilterl.filters; + filter->addr.sin_family = AF_INET; + memcpy(&filter->addr.sin_addr, &peer->addr.sin_addr, sizeof(filter->addr.sin_addr)); + filter->addr.sin_port = peer->addr.sin_port; + debfilterl.filters = filter; + } + } else + ast_cli(fd, "Unable to get IP address of peer '%s'\n", argv[4]); + if (peer->temponly) + free(peer); + peer = NULL; + } else + ast_cli(fd, "No such peer '%s'\n", argv[4]); + return RESULT_SUCCESS; +} + + + static char *regstate2str(int regstate) { switch(regstate) { @@ -4652,7 +4883,7 @@ if (p->owner) { if (strlen(buf)) { - if (sipdebug) + if (sipdebug & DEBUG_VERBOSE_OTHER) ast_verbose("DTMF received: '%c'\n", buf[0]); if (buf[0] == '*') event = 10; @@ -4682,10 +4913,21 @@ static int sip_do_debug(int fd, int argc, char *argv[]) { - if (argc != 2) + int tmp; + if (argc != 3) return RESULT_SHOWUSAGE; - sipdebug = 1; - ast_cli(fd, "SIP Debugging Enabled\n"); + tmp = atoi(argv[2]); + if (tmp < 1 || tmp > 255) + return RESULT_SHOWUSAGE; + sipdebug = tmp; + ast_cli(fd, "SIP Debug status:\n"); + ast_cli(fd, "Show packet headers :%s\n", (sipdebug & DEBUG_HEADERS ? "On" : "Off")); + ast_cli(fd, "Show packet content :%s\n", (sipdebug & DEBUG_PACKETS ? "On" : "Off")); + ast_cli(fd, "Verbose RTP :%s\n", (sipdebug & DEBUG_VERBOSE_RTP ? "On" : "Off")); + ast_cli(fd, "Verbose autentication :%s\n", (sipdebug & DEBUG_VERBOSE_AUTH ? "On" : "Off")); + ast_cli(fd, "Other :%s\n", (sipdebug & DEBUG_VERBOSE_OTHER ? "On" : "Off")); + if (sipdebug & DEBUG_HEADERS) + ast_cli(fd, "\r%s %-75s %-15s %-5s %s\n", "DIR", "Sip data", "Peer", "CSeq", "IP"); return RESULT_SUCCESS; } @@ -4693,7 +4935,7 @@ { if (argc != 3) return RESULT_SHOWUSAGE; - sipdebug = 0; + sipdebug = DEBUG_OFF; ast_cli(fd, "SIP Debugging Disabled\n"); return RESULT_SUCCESS; } @@ -4881,13 +5123,35 @@ "Usage: sip show peers\n" " Lists all known SIP peers.\n"; +static char show_dfilter_usage[] = +"Usage: sip show dfilter\n" +" Lists IP-adresses and ports used for SIP debug output filtering.\n"; + +static char show_dfilter_add_ip_usage[] = +"Usage: sip dfilter add ip \n" +" Adds an IP for filtered SIP debug output.\n"; + +static char show_dfilter_clear[] = +"Usage: sip dfilter clear\n" +" Clears filtering list for SIP debug output.\n"; + +static char show_dfilter_add_peer_usage[] = +"Usage: sip dfilter add peer \n" +" Adds an IP to filter for filtering SIP debug output.\n"; + static char show_reg_usage[] = "Usage: sip show registry\n" " Lists all registration requests and status.\n"; static char debug_usage[] = -"Usage: sip debug\n" -" Enables dumping of SIP packets for debugging purposes\n"; +"Usage: sip debug \n" +" Enables dumping of SIP packets\n" +" Bit 0 ( 1): Dumping IP, Port and SIP-headers\n" +" Bit 1 ( 2): Full SIP-packets\n" +" Bit 2 ( 4): Verbose RTPstream & codecs\n" +" Bit 3 ( 8): Verbose authentication\n" +" Bit 7 (128): Other\n" +" Example: sip debug 255 will enable every level.\n"; static char no_debug_usage[] = "Usage: sip no debug\n" @@ -4903,6 +5167,14 @@ { { "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_show_dfilter = + { { "sip", "show", "dfilter", NULL }, sip_show_dfilter, "Show SIP debug filter", show_dfilter_usage }; +static struct ast_cli_entry cli_dfilter_add_ip = + { { "sip", "dfilter", "add", "ip", NULL }, sip_dfilter_add_ip, "Add IP to SIP debug filter", show_dfilter_add_ip_usage }; +static struct ast_cli_entry cli_clear_dfilter = + { { "sip", "dfilter", "clear", NULL }, sip_dfilter_clear, "Clear SIP debug filter", show_dfilter_clear }; +static struct ast_cli_entry cli_dfilter_add_peer = + { { "sip", "dfilter", "add", "peer", NULL }, sip_dfilter_add_peer, "Add IP by peer to SIP debug filter", show_dfilter_add_peer_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 = @@ -5215,7 +5487,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 (sipdebug & DEBUG_VERBOSE_OTHER) ast_verbose("Message is %s\n", msg); switch(resp) { case 200: @@ -5384,7 +5656,7 @@ /* Process the SDP portion */ if (!ignore) { /* Use this as the basis */ - if (sipdebug) + if (sipdebug & DEBUG_VERBOSE_OTHER) ast_verbose("Using latest request as basis request\n"); /* This call is no longer outgoing if it ever was */ p->outgoing = 0; @@ -5400,7 +5672,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 (sipdebug & DEBUG_VERBOSE_OTHER) ast_verbose("Ignoring this request\n"); if (!p->lastinvite) { /* Handle authentication if this is our first invite */ @@ -5614,20 +5886,20 @@ p->needdestroy = 1; transmit_response(p, "200 OK", req); } else if (!strcasecmp(cmd, "MESSAGE")) { - if (sipdebug) + if (sipdebug & DEBUG_VERBOSE_OTHER) 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 (sipdebug & DEBUG_VERBOSE_OTHER) 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 (sipdebug & DEBUG_VERBOSE_OTHER) ast_verbose("Ignoring this request\n"); if (!p->lastinvite) { @@ -5684,13 +5956,13 @@ transmit_state_notify(p, ast_extension_state(NULL, p->context, p->exten),1); } } else if (!strcasecmp(cmd, "INFO")) { - if (sipdebug) + if (sipdebug & DEBUG_VERBOSE_OTHER) 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 (sipdebug & DEBUG_VERBOSE_OTHER) ast_verbose("Using latest request as basis request\n"); copy_request(&p->initreq, req); check_via(p, req); @@ -5749,8 +6021,7 @@ } req.data[res] = '\0'; req.len = res; - if (sipdebug) - ast_verbose("\n\nSip read: \n%s\n", req.data); + filter_sip_debug(DEBUG_READ, req.data, res, &sin); parse(&req); if (req.headers < 2) { /* Must have at least two headers */ @@ -6935,6 +7206,10 @@ ast_cli_register(&cli_show_users); ast_cli_register(&cli_show_channels); ast_cli_register(&cli_show_channel); + ast_cli_register(&cli_show_dfilter); + ast_cli_register(&cli_dfilter_add_ip); + ast_cli_register(&cli_clear_dfilter); + ast_cli_register(&cli_dfilter_add_peer); ast_cli_register(&cli_show_peers); ast_cli_register(&cli_show_registry); ast_cli_register(&cli_debug); @@ -6969,6 +7244,10 @@ ast_cli_unregister(&cli_show_users); ast_cli_unregister(&cli_show_channels); ast_cli_unregister(&cli_show_channel); + ast_cli_unregister(&cli_show_dfilter); + ast_cli_unregister(&cli_dfilter_add_ip); + ast_cli_unregister(&cli_clear_dfilter); + ast_cli_unregister(&cli_dfilter_add_peer); ast_cli_unregister(&cli_show_peers); ast_cli_unregister(&cli_show_registry); ast_cli_unregister(&cli_debug);