From e4614cf487c86ab85ced9a187109be6be32128fb Mon Sep 17 00:00:00 2001 From: Mark Spencer Date: Tue, 12 Aug 2003 16:48:16 +0000 Subject: Add optional pedantic SIP checking git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@1298 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_sip.c | 63 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 14 deletions(-) (limited to 'channels') diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 86455c321..b847ef925 100755 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -83,6 +83,8 @@ static char *config = "sip.conf"; #define DEFAULT_SIP_PORT 5060 /* From RFC 2543 */ #define SIP_MAX_PACKET 1500 /* Also from RFC 2543, should sub headers tho */ +#define ALLOWED_METHODS "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER" + static char context[AST_MAX_EXTENSION] = "default"; static char language[MAX_LANGUAGE] = ""; @@ -95,6 +97,8 @@ static char notifymime[AST_MAX_EXTENSION] = "application/simple-message-summary" static int srvlookup = 0; +static int pedanticsipchecking = 0; + static int usecnt =0; static pthread_mutex_t usecnt_lock = AST_MUTEX_INITIALIZER; @@ -1459,7 +1463,45 @@ static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *si { struct sip_pvt *p; char *callid; + char tmp[256] = ""; + char *cmd; + char *tag = "", *c; + int themisfrom; callid = get_header(req, "Call-ID"); + + if (pedanticsipchecking) { + /* In principle Call-ID's uniquely identify a call, however some vendors + (i.e. Pingtel) send multiple calls with the same Call-ID and different + tags in order to simplify billing. The RFC does state that we have to + compare tags in addition to the call-id, but this generate substantially + more overhead which is totally unnecessary for the vast majority of sane + SIP implementations, and thus Asterisk does not enable this behavior + by default. Short version: You'll need this option to support conferencing + on the pingtel */ + strncpy(tmp, req->header[0], sizeof(tmp) - 1); + cmd = tmp; + c = strchr(tmp, ' '); + if (c) + *c = '\0'; + if (!strcasecmp(cmd, "SIP/2.0")) { + themisfrom = 0; + } else { + themisfrom = 1; + } + if (themisfrom) + strncpy(tmp, get_header(req, "From"), sizeof(tmp) - 1); + else + strncpy(tmp, get_header(req, "To"), sizeof(tmp) - 1); + tag = strstr(tmp, "tag="); + if (tag) { + tag += 4; + c = strchr(tag, ';'); + if (c) + *c = '\0'; + } + + } + if (!strlen(callid)) { ast_log(LOG_WARNING, "Call missing call ID from '%s'\n", inet_ntoa(sin->sin_addr)); return NULL; @@ -1467,20 +1509,9 @@ static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *si ast_pthread_mutex_lock(&iflock); p = iflist; while(p) { - if (!strcmp(p->callid, callid)) { + if (!strcmp(p->callid, callid) && + (!pedanticsipchecking || !strlen(p->theirtag) || !strcmp(p->theirtag, tag))) { /* Found the call */ -#if 0 - if (!p->insecure && ((p->sa.sin_addr.s_addr != sin->sin_addr.s_addr) || - (p->sa.sin_port != sin->sin_port))) { - char orig[80]; - char new[80]; - snprintf(orig, sizeof(orig), "%s:%d", inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port)); - snprintf(new, sizeof(new), "%s:%d", inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); - ast_log(LOG_WARNING, "Looks like %s is trying to steal call '%s' from %s?\n", new, p->callid, orig); - ast_pthread_mutex_unlock(&iflock); - return NULL; - } -#endif ast_pthread_mutex_lock(&p->lock); ast_pthread_mutex_unlock(&iflock); return p; @@ -2194,7 +2225,7 @@ static int transmit_response_with_allow(struct sip_pvt *p, char *msg, struct sip { struct sip_request resp; respprep(&resp, p, msg, req); - add_header(&resp, "Allow", "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER"); + add_header(&resp, "Allow", ALLOWED_METHODS); add_header(&resp, "Accept", "application/sdp"); add_header(&resp, "Content-Length", "0"); add_blank_header(&resp); @@ -2581,6 +2612,7 @@ static int transmit_invite(struct sip_pvt *p, char *cmd, int sdp, char *auth, ch { add_header(&req, "Alert-info",distinctive_ring); } + add_header(&req, "Allow", ALLOWED_METHODS); if (sdp) { add_sdp(&req, p, NULL, NULL); } else { @@ -5500,6 +5532,7 @@ static int reload_config(void) strcpy(fromdomain, ""); globalcanreinvite = REINVITE_INVITE; videosupport = 0; + pedanticsipchecking=0; v = ast_variable_browse(cfg, "general"); while(v) { /* Create the interface list */ @@ -5530,6 +5563,8 @@ static int reload_config(void) globalnat = ast_true(v->value); } else if (!strcasecmp(v->name, "srvlookup")) { srvlookup = ast_true(v->value); + } else if (!strcasecmp(v->name, "pedantic")) { + pedanticsipchecking = ast_true(v->value); } else if (!strcasecmp(v->name, "canreinvite")) { if (!strcasecmp(v->value, "update")) globalcanreinvite = REINVITE_UPDATE; -- cgit v1.2.3