handle improperly formatted initial requests properly (issue #5483)
[asterisk/asterisk.git] / channels / chan_sip.c
index 8b538b5..fa0431a 100755 (executable)
@@ -2217,10 +2217,6 @@ static int update_call_counter(struct sip_pvt *fup, int event)
                        if (*call_limit > 0 ) {
                                if (*inuse >= *call_limit) {
                                        ast_log(LOG_ERROR, "Call %s %s '%s' rejected due to usage limit of %d\n", outgoing ? "to" : "from", u ? "user":"peer", name, *call_limit);
-                                       /* inc inUse as well */
-                                       if ( event == INC_CALL_LIMIT ) {
-                                               (*inuse)++;
-                                       }
                                        if (u)
                                                ASTOBJ_UNREF(u,sip_destroy_user);
                                        else
@@ -3299,7 +3295,7 @@ static void parse_request(struct sip_request *req)
                        *c = 0;
 
                        if (sipdebug && option_debug > 3)
-                               ast_log(LOG_DEBUG, "Header: %s (%d)\n", req->header[f], (int) strlen(req->header[f]));
+                               ast_log(LOG_DEBUG, "Header %d: %s (%d)\n", f, req->header[f], (int) strlen(req->header[f]));
                        if (ast_strlen_zero(req->header[f])) {
                                /* Line by itself means we're now in content */
                                c++;
@@ -3317,8 +3313,11 @@ static void parse_request(struct sip_request *req)
                c++;
        }
        /* Check for last header */
-       if (!ast_strlen_zero(req->header[f])) 
+       if (!ast_strlen_zero(req->header[f])) {
+               if (sipdebug && option_debug > 3)
+                       ast_log(LOG_DEBUG, "Header %d: %s (%d)\n", f, req->header[f], (int) strlen(req->header[f]));
                f++;
+       }
        req->headers = f;
        /* Now we process any mime content */
        f = 0;
@@ -10813,6 +10812,7 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
        char iabuf[INET_ADDRSTRLEN];
        int debug = sip_debug_test_pvt(p);
        char *e;
+       int error = 0;
 
        /* Clear out potential response */
        memset(&resp, 0, sizeof(resp));
@@ -10822,10 +10822,17 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
        cmd = req->header[0];
 
        /* Must have Cseq */
-       if (ast_strlen_zero(cmd) || ast_strlen_zero(cseq))
-               return -1;
-       if (sscanf(cseq, "%d%n", &seqno, &len) != 1) {
-               ast_log(LOG_DEBUG, "No seqno in '%s'\n", cmd);
+       if (ast_strlen_zero(cmd) || ast_strlen_zero(cseq)) {
+               ast_log(LOG_ERROR, "Missing Cseq. Dropping this SIP message, it's incomplete.\n");
+               error = 1;
+       }
+       if (!error && sscanf(cseq, "%d%n", &seqno, &len) != 1) {
+               ast_log(LOG_ERROR, "No seqno in '%s'. Dropping incomplete message.\n", cmd);
+               error = 1;
+       }
+       if (error) {
+               if (!p->initreq.header) /* New call */
+                       ast_set_flag(p, SIP_NEEDDESTROY);       /* Make sure we destroy this dialog */
                return -1;
        }
        /* Get the command XXX */
@@ -11011,6 +11018,9 @@ static int sipsock_read(int *id, int fd, short events, void *ignore)
                        ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno));
                return 1;
        }
+       if (res == sizeof(req.data)) {
+               ast_log(LOG_DEBUG, "Received packet exceeds buffer. Data is possibly lost\n");
+       }
        req.data[res] = '\0';
        req.len = res;
        if(sip_debug_test_addr(&sin))
@@ -11057,7 +11067,11 @@ retrylock:
                        append_history(p, "Rx", tmp);
                }
                nounlock = 0;
-               handle_request(p, &req, &sin, &recount, &nounlock);
+               if (handle_request(p, &req, &sin, &recount, &nounlock) == -1) {
+                       /* Request failed */
+                       ast_log(LOG_DEBUG, "SIP message could not be handled, bad request: %-70.70s\n", p->callid[0] ? p->callid : "<no callid>");
+               }
+               
                if (p->owner && !nounlock)
                        ast_mutex_unlock(&p->owner->lock);
                ast_mutex_unlock(&p->lock);
@@ -11203,9 +11217,14 @@ restartsearch:
                if (fastrestart)
                        res = 1;
                res = ast_io_wait(io, res);
+               if (res > 20)
+                       ast_log(LOG_WARNING, "chan_sip: ast_io_wait ran %d all at once\n", res);
                ast_mutex_lock(&monlock);
-               if (res >= 0) 
-                       ast_sched_runq(sched);
+               if (res >= 0)  {
+                       res = ast_sched_runq(sched);
+                       if (res >= 20)
+                               ast_log(LOG_WARNING, "chan_sip: ast_sched_runq ran %d all at once\n", res);
+               }
 
                /* needs work to send mwi to realtime peers */
                time(&t);
@@ -11835,7 +11854,7 @@ static struct sip_user *build_user(const char *name, struct ast_variable *v, int
                        user->pickupgroup = ast_get_group(v->value);
                } else if (!strcasecmp(v->name, "language")) {
                        ast_copy_string(user->language, v->value, sizeof(user->language));
-               } else if (!strcasecmp(v->name, "musiconhold")) {
+               } else if (!strcasecmp(v->name, "musicclass") || !strcasecmp(v->name, "musiconhold")) {
                        ast_copy_string(user->musicclass, v->value, sizeof(user->musicclass));
                } else if (!strcasecmp(v->name, "accountcode")) {
                        ast_copy_string(user->accountcode, v->value, sizeof(user->accountcode));
@@ -12891,12 +12910,18 @@ static void sip_poke_all_peers(void)
 static void sip_send_all_registers(void)
 {
        int ms;
-
+       int regspacing;
+       if (!regobjs)
+               return;
+       regspacing = default_expiry * 1000/regobjs;
+       if (regspacing > 100)
+               regspacing = 100;
+       ms = regspacing;
        ASTOBJ_CONTAINER_TRAVERSE(&regl, 1, do {
                ASTOBJ_WRLOCK(iterator);
                if (iterator->expire > -1)
                        ast_sched_del(sched, iterator->expire);
-               ms = (rand() >> 12) & 0x1fff;
+               ms += regspacing;
                iterator->expire = ast_sched_add(sched, ms, sip_reregister, iterator);
                ASTOBJ_UNLOCK(iterator);
        } while (0)