aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2003-08-12 16:48:16 +0000
committermarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2003-08-12 16:48:16 +0000
commit5cda84a62ef175bdd3fcdee97b2dfef3752818db (patch)
tree0634cc184a01218e86bc49e2593af0cbb94d1266
parenta16e82db70e03b1f5344840d7b9df3387798d17a (diff)
Add optional pedantic SIP checking
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@1298 f38db490-d61c-443f-a65b-d21fe96a405b
-rwxr-xr-xCHANGES1
-rwxr-xr-xchannels/chan_sip.c63
-rwxr-xr-xconfigs/sip.conf.sample1
3 files changed, 51 insertions, 14 deletions
diff --git a/CHANGES b/CHANGES
index 85d89df30..16c88e52f 100755
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,4 @@
+ -- Add optional pedantic SIP checking for Pingtel
-- Allow extension names, include context, switch to use global vars.
-- Allow variables in extensions.conf to reference previously defined ones
-- Merge voicemail enhancements (app_voicemail2)
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;
diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample
index aa54ea02c..2c8a5e4d3 100755
--- a/configs/sip.conf.sample
+++ b/configs/sip.conf.sample
@@ -6,6 +6,7 @@ port = 5060 ; Port to bind to
bindaddr = 0.0.0.0 ; Address to bind to
context = default ; Default for incoming calls
;srvlookup = yes ; Enable SRV lookups on outbound calls
+;pedantic = yes ; Enable slow, pedantic checking for Pingtel
;tos=lowdelay
;tos=184
;maxexpirey=3600 ; Max length of incoming registration we allow