1 /**************************************************************************
2  **
3  ** sngrep - SIP Messages flow viewer
4  **
5  ** Copyright (C) 2013-2018 Ivan Alonso (Kaian)
6  ** Copyright (C) 2013-2018 Irontec SL. All rights reserved.
7  **
8  ** This program is free software: you can redistribute it and/or modify
9  ** it under the terms of the GNU General Public License as published by
10  ** the Free Software Foundation, either version 3 of the License, or
11  ** (at your option) any later version.
12  **
13  ** This program is distributed in the hope that it will be useful,
14  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  ** GNU General Public License for more details.
17  **
18  ** You should have received a copy of the GNU General Public License
19  ** along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  **
21  ****************************************************************************/
22 /**
23  * @file sip.c
24  * @author Ivan Alonso [aka Kaian] <kaian@irontec.com>
25  *
26  * @brief Source of functions defined in sip.h
27  */
28 #include "config.h"
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdio.h>
32 #include <time.h>
33 #include <pthread.h>
34 #include <stdarg.h>
35 #include "sip.h"
36 #include "option.h"
37 #include "setting.h"
38 #include "filter.h"
39 
40 /**
41  * @brief Linked list of parsed calls
42  *
43  * All parsed calls will be added to this list, only accesible from
44  * this awesome structure, so, keep it thread-safe.
45  */
46 sip_call_list_t calls =
47 { 0 };
48 
49 /* @brief list of methods and responses */
50 sip_code_t sip_codes[] = {
51     { SIP_METHOD_REGISTER,  "REGISTER" },
52     { SIP_METHOD_INVITE,    "INVITE" },
53     { SIP_METHOD_SUBSCRIBE, "SUBSCRIBE" },
54     { SIP_METHOD_NOTIFY,    "NOTIFY" },
55     { SIP_METHOD_OPTIONS,   "OPTIONS" },
56     { SIP_METHOD_PUBLISH,   "PUBLISH" },
57     { SIP_METHOD_KDMQ,      "KDMQ" },
58     { SIP_METHOD_MESSAGE,   "MESSAGE" },
59     { SIP_METHOD_CANCEL,    "CANCEL" },
60     { SIP_METHOD_BYE,       "BYE" },
61     { SIP_METHOD_ACK,       "ACK" },
62     { SIP_METHOD_PRACK,     "PRACK" },
63     { SIP_METHOD_INFO,      "INFO" },
64     { SIP_METHOD_REFER,     "REFER" },
65     { SIP_METHOD_UPDATE,    "UPDATE" },
66     { 100, "100 Trying" },
67     { 180, "180 Ringing" },
68     { 181, "181 Call is Being Forwarded" },
69     { 182, "182 Queued" },
70     { 183, "183 Session Progress" },
71     { 199, "199 Early Dialog Terminated" },
72     { 200, "200 OK" },
73     { 202, "202 Accepted" },
74     { 204, "204 No Notification" },
75     { 300, "300 Multiple Choices" },
76     { 301, "301 Moved Permanently" },
77     { 302, "302 Moved Temporarily" },
78     { 305, "305 Use Proxy" },
79     { 380, "380 Alternative Service" },
80     { 400, "400 Bad Request" },
81     { 401, "401 Unauthorized" },
82     { 402, "402 Payment Required" },
83     { 403, "403 Forbidden" },
84     { 404, "404 Not Found" },
85     { 405, "405 Method Not Allowed" },
86     { 406, "406 Not Acceptable" },
87     { 407, "407 Proxy Authentication Required" },
88     { 408, "408 Request Timeout" },
89     { 409, "409 Conflict" },
90     { 410, "410 Gone" },
91     { 411, "411 Length Required" },
92     { 412, "412 Conditional Request Failed" },
93     { 413, "413 Request Entity Too Large" },
94     { 414, "414 Request-URI Too Long" },
95     { 415, "415 Unsupported Media Type" },
96     { 416, "416 Unsupported URI Scheme" },
97     { 417, "417 Unknown Resource-Priority" },
98     { 420, "420 Bad Extension" },
99     { 421, "421 Extension Required" },
100     { 422, "422 Session Interval Too Small" },
101     { 423, "423 Interval Too Brief" },
102     { 424, "424 Bad Location Information" },
103     { 428, "428 Use Identity Header" },
104     { 429, "429 Provide Referrer Identity" },
105     { 430, "430 Flow Failed" },
106     { 433, "433 Anonymity Disallowed" },
107     { 436, "436 Bad Identity-Info" },
108     { 437, "437 Unsupported Certificate" },
109     { 438, "438 Invalid Identity Header" },
110     { 439, "439 First Hop Lacks Outbound Support" },
111     { 470, "470 Consent Needed" },
112     { 480, "480 Temporarily Unavailable" },
113     { 481, "481 Call/Transaction Does Not Exist" },
114     { 482, "482 Loop Detected." },
115     { 483, "483 Too Many Hops" },
116     { 484, "484 Address Incomplete" },
117     { 485, "485 Ambiguous" },
118     { 486, "486 Busy Here" },
119     { 487, "487 Request Terminated" },
120     { 488, "488 Not Acceptable Here" },
121     { 489, "489 Bad Event" },
122     { 491, "491 Request Pending" },
123     { 493, "493 Undecipherable" },
124     { 494, "494 Security Agreement Required" },
125     { 500, "500 Server Internal Error" },
126     { 501, "501 Not Implemented" },
127     { 502, "502 Bad Gateway" },
128     { 503, "503 Service Unavailable" },
129     { 504, "504 Server Time-out" },
130     { 505, "505 Version Not Supported" },
131     { 513, "513 Message Too Large" },
132     { 580, "580 Precondition Failure" },
133     { 600, "600 Busy Everywhere" },
134     { 603, "603 Decline" },
135     { 604, "604 Does Not Exist Anywhere" },
136     { 606, "606 Not Acceptable" },
137     { -1 , NULL },
138 };
139 
140 void
sip_init(int limit,int only_calls,int no_incomplete)141 sip_init(int limit, int only_calls, int no_incomplete)
142 {
143     int match_flags, reg_rule_len, reg_rule_err;
144     char reg_rule[SIP_ATTR_MAXLEN];
145     const char *setting = NULL;
146 
147     // Store capture limit
148     calls.limit = limit;
149     calls.only_calls = only_calls;
150     calls.ignore_incomplete = no_incomplete;
151     calls.last_index = 0;
152 
153     // Create a vector to store calls
154     calls.list = vector_create(200, 50);
155     vector_set_destroyer(calls.list, call_destroyer);
156     vector_set_sorter(calls.list, sip_list_sorter);
157     calls.active = vector_create(10, 10);
158 
159     // Create hash table for callid search
160     calls.callids = htable_create(calls.limit);
161 
162     // Set default sorting field
163     if (sip_attr_from_name(setting_get_value(SETTING_CL_SORTFIELD)) >= 0) {
164         calls.sort.by = sip_attr_from_name(setting_get_value(SETTING_CL_SORTFIELD));
165         calls.sort.asc = (!strcmp(setting_get_value(SETTING_CL_SORTORDER), "asc"));
166     } else {
167         // Fallback to default sorting field
168         calls.sort.by = SIP_ATTR_CALLINDEX;
169         calls.sort.asc = true;
170     }
171 
172     // Initialize payload parsing regexp
173     match_flags = REG_EXTENDED | REG_ICASE | REG_NEWLINE;
174     regcomp(&calls.reg_method, "^([a-zA-Z]+) [a-zA-Z]+:.* SIP/2.0[ ]*\r", match_flags & ~REG_NEWLINE);
175     regcomp(&calls.reg_callid, "^(Call-ID|i):[ ]*([^ ]+)[ ]*\r$", match_flags);
176     setting = setting_get_value(SETTING_SIP_HEADER_X_CID);
177     reg_rule_len = strlen(setting) + 22;
178     if (reg_rule_len >= SIP_ATTR_MAXLEN) {
179         setting = "X-Call-ID|X-CID";
180         reg_rule_len = strlen(setting) + 22;
181         fprintf(stderr, "%s setting too long, using default.\n",
182             setting_name(SETTING_SIP_HEADER_X_CID));
183     }
184     snprintf(reg_rule, reg_rule_len, "^(%s):[ ]*([^ ]+)[ ]*\r$", setting);
185     reg_rule_err = regcomp(&calls.reg_xcallid, reg_rule, match_flags);
186     if(reg_rule_err != 0) {
187         regerror(reg_rule_err, &calls.reg_xcallid, reg_rule, SIP_ATTR_MAXLEN);
188         regfree(&calls.reg_xcallid);
189         fprintf(stderr, "%s setting produces regex compilation error: %s"
190             "using default value instead\n",
191             setting_name(SETTING_SIP_HEADER_X_CID), reg_rule);
192         regcomp(&calls.reg_xcallid,
193             "^(X-Call-ID|X-CID):[ ]*([^ ]+)[ ]*\r$", match_flags);
194     }
195     regcomp(&calls.reg_response, "^SIP/2.0[ ]*(([0-9]{3}) [^\r]*)[ ]*\r", match_flags & ~REG_NEWLINE);
196     regcomp(&calls.reg_cseq, "^CSeq:[ ]*([0-9]{1,10}) .+\r$", match_flags);
197     regcomp(&calls.reg_from, "^(From|f):[ ]*[^:]*:(([^@>]+)@?[^\r>;]+)", match_flags);
198     regcomp(&calls.reg_to, "^(To|t):[ ]*[^:]*:(([^@>]+)@?[^\r>;]+)", match_flags);
199     regcomp(&calls.reg_valid, "^([A-Z]+ [a-zA-Z]+:|SIP/2.0 [0-9]{3})", match_flags & ~REG_NEWLINE);
200     regcomp(&calls.reg_cl, "^(Content-Length|l):[ ]*([0-9]+)[ ]*\r$", match_flags);
201     regcomp(&calls.reg_body, "\r\n\r\n(.*)", match_flags & ~REG_NEWLINE);
202     regcomp(&calls.reg_reason, "Reason:[ ]*[^\r]*;text=\"([^\r]+)\"", match_flags);
203     regcomp(&calls.reg_warning, "Warning:[ ]*([0-9]*)", match_flags);
204 
205 }
206 
207 void
sip_deinit()208 sip_deinit()
209 {
210     // Remove all calls
211     sip_calls_clear();
212     // Remove Call-id hash table
213     htable_destroy(calls.callids);
214     // Remove calls vector
215     vector_destroy(calls.list);
216     vector_destroy(calls.active);
217     // Deallocate regular expressions
218     regfree(&calls.reg_method);
219     regfree(&calls.reg_callid);
220     regfree(&calls.reg_xcallid);
221     regfree(&calls.reg_response);
222     regfree(&calls.reg_cseq);
223     regfree(&calls.reg_from);
224     regfree(&calls.reg_to);
225     regfree(&calls.reg_valid);
226     regfree(&calls.reg_cl);
227     regfree(&calls.reg_body);
228     regfree(&calls.reg_reason);
229     regfree(&calls.reg_warning);
230 }
231 
232 
233 char *
sip_get_callid(const char * payload,char * callid)234 sip_get_callid(const char* payload, char *callid)
235 {
236     regmatch_t pmatch[3];
237 
238     // Try to get Call-ID from payload
239     if (regexec(&calls.reg_callid, payload, 3, pmatch, 0) == 0) {
240         // Copy the matching part of payload
241         strncpy(callid, payload + pmatch[2].rm_so, (int) pmatch[2].rm_eo - pmatch[2].rm_so);
242     }
243 
244     return callid;
245 }
246 
247 char *
sip_get_xcallid(const char * payload,char * xcallid)248 sip_get_xcallid(const char *payload, char *xcallid)
249 {
250     regmatch_t pmatch[3];
251 
252     // Try to get X-Call-ID from payload
253     if (regexec(&calls.reg_xcallid, (const char *)payload, 3, pmatch, 0) == 0) {
254         strncpy(xcallid, (const char *)payload +  pmatch[2].rm_so, (int)pmatch[2].rm_eo - pmatch[2].rm_so);
255     }
256 
257     return xcallid;
258 }
259 
260 int
sip_validate_packet(packet_t * packet)261 sip_validate_packet(packet_t *packet)
262 {
263     uint32_t plen = packet_payloadlen(packet);
264     u_char payload[MAX_SIP_PAYLOAD];
265     regmatch_t pmatch[4];
266     char cl_header[10];
267     int content_len;
268     int bodylen;
269 
270     // Max SIP payload allowed
271     if (plen == 0 || plen > MAX_SIP_PAYLOAD)
272         return VALIDATE_NOT_SIP;
273 
274     // Get payload from packet(s)
275     memset(payload, 0, MAX_SIP_PAYLOAD);
276     memcpy(payload, packet_payload(packet), plen);
277 
278     // Initialize variables
279     memset(cl_header, 0, sizeof(cl_header));
280 
281     // Check if the first line follows SIP request or response format
282     if (regexec(&calls.reg_valid, (const char *) payload, 2, pmatch, 0) != 0) {
283         // Not a SIP message AT ALL
284         return VALIDATE_NOT_SIP;
285     }
286 
287     // Check if we have Content Length header
288     if (regexec(&calls.reg_cl, (const char *) payload, 4, pmatch, 0) != 0) {
289         // Not a SIP message or not complete
290         return VALIDATE_PARTIAL_SIP;
291     }
292 
293     strncpy(cl_header, (const char *)payload +  pmatch[2].rm_so, (int)pmatch[2].rm_eo - pmatch[2].rm_so);
294     content_len = atoi(cl_header);
295 
296     // Check if we have Body separator field
297     if (regexec(&calls.reg_body, (const char *) payload, 2, pmatch, 0) != 0) {
298         // Not a SIP message or not complete
299         return VALIDATE_PARTIAL_SIP;
300     }
301 
302     // Get the SIP message body length
303     bodylen = (int) pmatch[1].rm_eo - pmatch[1].rm_so;
304 
305     // The SDP body of the SIP message ends in another packet
306     if (content_len > bodylen) {
307         return VALIDATE_PARTIAL_SIP;
308     }
309 
310     if (content_len < bodylen) {
311         // Check body ends with '\r\n'
312         if (payload[pmatch[1].rm_so + content_len - 1] != '\n')
313             return VALIDATE_NOT_SIP;
314         if (payload[pmatch[1].rm_so + content_len - 2] != '\r')
315             return VALIDATE_NOT_SIP;
316         // We got more than one SIP message in the same packet
317         packet_set_payload(packet, payload, pmatch[1].rm_so + content_len);
318         return VALIDATE_MULTIPLE_SIP;
319     }
320 
321     // We got all the SDP body of the SIP message
322     return VALIDATE_COMPLETE_SIP;
323 }
324 
325 sip_msg_t *
sip_check_packet(packet_t * packet)326 sip_check_packet(packet_t *packet)
327 {
328     sip_msg_t *msg;
329     sip_call_t *call;
330     char callid[1024], xcallid[1024];
331     u_char payload[MAX_SIP_PAYLOAD];
332     bool newcall = false;
333 
334     // Max SIP payload allowed
335     if (packet->payload_len > MAX_SIP_PAYLOAD)
336         return NULL;
337 
338     // Initialize local variables
339     memset(callid, 0, sizeof(callid));
340     memset(xcallid, 0, sizeof(xcallid));
341 
342     // Get payload from packet(s)
343     memset(payload, 0, MAX_SIP_PAYLOAD);
344     memcpy(payload, packet_payload(packet), packet_payloadlen(packet));
345 
346     // Get the Call-ID of this message
347     if (!sip_get_callid((const char*) payload, callid))
348         return NULL;
349 
350     // Create a new message from this data
351     if (!(msg = msg_create((const char*) payload)))
352         return NULL;
353 
354     // Get Method and request for the following checks
355     // There is no need to parse all payload at this point
356     // If no response or request code is found, this is not a SIP message
357     if (!sip_get_msg_reqresp(msg, payload)) {
358         // Deallocate message memory
359         msg_destroy(msg);
360         return NULL;
361     }
362 
363     // Find the call for this msg
364     if (!(call = sip_find_by_callid(callid))) {
365 
366         // Check if payload matches expression
367         if (!sip_check_match_expression((const char*) payload))
368             goto skip_message;
369 
370         // User requested only INVITE starting dialogs
371         if (calls.only_calls && msg->reqresp != SIP_METHOD_INVITE)
372             goto skip_message;
373 
374         // Only create a new call if the first msg
375         // is a request message in the following gorup
376         if (calls.ignore_incomplete && msg->reqresp > SIP_METHOD_MESSAGE)
377             goto skip_message;
378 
379         // Get the Call-ID of this message
380         sip_get_xcallid((const char*) payload, xcallid);
381 
382         // Rotate call list if limit has been reached
383         if (calls.limit == sip_calls_count())
384             sip_calls_rotate();
385 
386         // Create the call if not found
387         if (!(call = call_create(callid, xcallid)))
388             goto skip_message;
389 
390         // Add this Call-Id to hash table
391         htable_insert(calls.callids, call->callid, call);
392 
393         // Set call index
394         call->index = ++calls.last_index;
395 
396         // Mark this as a new call
397         newcall = true;
398     }
399 
400     // At this point we know we're handling an interesting SIP Packet
401     msg->packet = packet;
402 
403     // Always parse first call message
404     if (call_msg_count(call) == 0) {
405         // Parse SIP payload
406         sip_parse_msg_payload(msg, payload);
407         // If this call has X-Call-Id, append it to the parent call
408         if (strlen(call->xcallid)) {
409             call_add_xcall(sip_find_by_callid(call->xcallid), call);
410         }
411     }
412 
413     // Add the message to the call
414     call_add_message(call, msg);
415 
416     // check if message is a retransmission
417     call_msg_retrans_check(msg);
418 
419     if (call_is_invite(call)) {
420         // Parse media data
421         sip_parse_msg_media(msg, payload);
422         // Update Call State
423         call_update_state(call, msg);
424         // Parse extra fields
425         sip_parse_extra_headers(msg, payload);
426         // Check if this call should be in active call list
427         if (call_is_active(call)) {
428             if (sip_call_is_active(call)) {
429                 vector_append(calls.active, call);
430             }
431         } else {
432             if (sip_call_is_active(call)) {
433                 vector_remove(calls.active, call);
434             }
435         }
436     }
437 
438     if (newcall) {
439         // Append this call to the call list
440         vector_append(calls.list, call);
441     }
442 
443     // Mark the list as changed
444     calls.changed = true;
445 
446     // Return the loaded message
447     return msg;
448 
449 skip_message:
450     // Deallocate message memory
451     msg_destroy(msg);
452     return NULL;
453 
454 }
455 
456 bool
sip_calls_has_changed()457 sip_calls_has_changed()
458 {
459     bool changed = calls.changed;
460     calls.changed = false;
461     return changed;
462 }
463 
464 int
sip_calls_count()465 sip_calls_count()
466 {
467     return vector_count(calls.list);
468 }
469 
470 vector_iter_t
sip_calls_iterator()471 sip_calls_iterator()
472 {
473     return vector_iterator(calls.list);
474 }
475 
476 vector_iter_t
sip_active_calls_iterator()477 sip_active_calls_iterator()
478 {
479     return vector_iterator(calls.active);
480 }
481 
482 bool
sip_call_is_active(sip_call_t * call)483 sip_call_is_active(sip_call_t *call)
484 {
485     return vector_index(calls.active, call) != -1;
486 }
487 
488 vector_t *
sip_calls_vector()489 sip_calls_vector()
490 {
491     return calls.list;
492 }
493 
494 vector_t *
sip_active_calls_vector()495 sip_active_calls_vector()
496 {
497     return calls.active;
498 }
499 
500 sip_stats_t
sip_calls_stats()501 sip_calls_stats()
502 {
503     sip_stats_t stats;
504     vector_iter_t it = vector_iterator(calls.list);
505 
506     // Total number of calls without filtering
507     stats.total = vector_iterator_count(&it);
508     // Total number of calls after filtering
509     vector_iterator_set_filter(&it, filter_check_call);
510     stats.displayed = vector_iterator_count(&it);
511     return stats;
512 }
513 
514 sip_call_t *
sip_find_by_index(int index)515 sip_find_by_index(int index)
516 {
517     return vector_item(calls.list, index);
518 }
519 
520 sip_call_t *
sip_find_by_callid(const char * callid)521 sip_find_by_callid(const char *callid)
522 {
523     return htable_find(calls.callids, callid);
524 }
525 
526 int
sip_get_msg_reqresp(sip_msg_t * msg,const u_char * payload)527 sip_get_msg_reqresp(sip_msg_t *msg, const u_char *payload)
528 {
529     regmatch_t pmatch[3];
530     char resp_str[SIP_ATTR_MAXLEN];
531     char reqresp[SIP_ATTR_MAXLEN];
532     char cseq[11];
533     const char *resp_def;
534 
535     // Initialize variables
536     memset(pmatch, 0, sizeof(pmatch));
537     memset(resp_str, 0, sizeof(resp_str));
538     memset(reqresp, 0, sizeof(reqresp));
539 
540     // If not already parsed
541     if (!msg->reqresp) {
542 
543         // Method & CSeq
544         if (regexec(&calls.reg_method, (const char *)payload, 2, pmatch, 0) == 0) {
545             if ((int)(pmatch[1].rm_eo - pmatch[1].rm_so) >= SIP_ATTR_MAXLEN) {
546                 strncpy(reqresp, "<malformed>", 11);
547             } else {
548                 sprintf(reqresp, "%.*s", (int) (pmatch[1].rm_eo - pmatch[1].rm_so), payload + pmatch[1].rm_so);
549             }
550         }
551 
552         // CSeq
553         if (regexec(&calls.reg_cseq, (char*)payload, 2, pmatch, 0) == 0) {
554             sprintf(cseq, "%.*s", (int)(pmatch[1].rm_eo - pmatch[1].rm_so), payload + pmatch[1].rm_so);
555             msg->cseq = atoi(cseq);
556         }
557 
558 
559         // Response code
560         if (regexec(&calls.reg_response, (const char *)payload, 3, pmatch, 0) == 0) {
561             if ((int)(pmatch[1].rm_eo - pmatch[1].rm_so) >= SIP_ATTR_MAXLEN) {
562                 strncpy(resp_str, "<malformed>", 11);
563             } else {
564                 sprintf(resp_str, "%.*s", (int) (pmatch[1].rm_eo - pmatch[1].rm_so), payload + pmatch[1].rm_so);
565             }
566             if ((int)(pmatch[2].rm_eo - pmatch[2].rm_so) >= SIP_ATTR_MAXLEN) {
567                 strncpy(resp_str, "<malformed>", 11);
568             } else {
569                 sprintf(reqresp, "%.*s", (int) (pmatch[2].rm_eo - pmatch[2].rm_so), payload + pmatch[2].rm_so);
570             }
571         }
572 
573         // Get Request/Response Code
574         msg->reqresp = sip_method_from_str(reqresp);
575 
576         // For response codes, check if the text matches the default
577         if (!msg_is_request(msg)) {
578             resp_def = sip_method_str(msg->reqresp);
579             if (!resp_def || strcmp(resp_def, resp_str)) {
580                 msg->resp_str = strdup(resp_str);
581             }
582         }
583     }
584 
585     return msg->reqresp;
586 }
587 
588 const char *
sip_get_msg_reqresp_str(sip_msg_t * msg)589 sip_get_msg_reqresp_str(sip_msg_t *msg)
590 {
591     // Check if code has non-standard text
592     if (msg->resp_str) {
593         return msg->resp_str;
594     } else {
595         return sip_method_str(msg->reqresp);
596     }
597 }
598 
599 sip_msg_t *
sip_parse_msg(sip_msg_t * msg)600 sip_parse_msg(sip_msg_t *msg)
601 {
602     if (msg && !msg->cseq) {
603         sip_parse_msg_payload(msg, (u_char*) msg_get_payload(msg));
604     }
605     return msg;
606 }
607 
608 int
sip_parse_msg_payload(sip_msg_t * msg,const u_char * payload)609 sip_parse_msg_payload(sip_msg_t *msg, const u_char *payload)
610 {
611     regmatch_t pmatch[4];
612 
613     // From
614     if (regexec(&calls.reg_from, (const char *)payload, 4, pmatch, 0) == 0) {
615         msg->sip_from = sng_malloc((int)pmatch[2].rm_eo - pmatch[2].rm_so + 1);
616         strncpy(msg->sip_from, (const char *)payload +  pmatch[2].rm_so, (int)pmatch[2].rm_eo - pmatch[2].rm_so);
617     } else {
618         // Malformed From Header
619         msg->sip_from = sng_malloc(12);
620         strncpy(msg->sip_from, "<malformed>", 11);
621     }
622 
623     // To
624     if (regexec(&calls.reg_to, (const char *)payload, 4, pmatch, 0) == 0) {
625         msg->sip_to = sng_malloc((int)pmatch[2].rm_eo - pmatch[2].rm_so + 1);
626         strncpy(msg->sip_to, (const char *)payload +  pmatch[2].rm_so, (int)pmatch[2].rm_eo - pmatch[2].rm_so);
627     } else {
628         // Malformed To Header
629         msg->sip_to = sng_malloc(12);
630         strncpy(msg->sip_to, "<malformed>", 11);
631     }
632 
633     return 0;
634 }
635 
636 void
sip_parse_msg_media(sip_msg_t * msg,const u_char * payload)637 sip_parse_msg_media(sip_msg_t *msg, const u_char *payload)
638 {
639 
640 #define ADD_STREAM(stream) \
641     if (stream) { \
642         if (!rtp_find_call_stream(call, src, stream->dst)) { \
643           call_add_stream(call, stream); \
644       } else { \
645           sng_free(stream); \
646           stream = NULL; \
647       } \
648     }
649 
650     address_t dst, src = { };
651     rtp_stream_t *rtp_stream = NULL, *rtcp_stream = NULL, *msg_rtp_stream = NULL;
652     char media_type[MEDIATYPELEN + 1] = { };
653     char media_format[30] = { };
654     char address[ADDRESSLEN + 1] = { };
655     uint32_t media_fmt_pref;
656     uint32_t media_fmt_code;
657     sdp_media_t *media = NULL;
658     char *payload2, *tofree, *line;
659     sip_call_t *call = msg_get_call(msg);
660 
661     // If message is retrans, there's no need to parse the payload again
662     if (msg->retrans) {
663         // Use the media vector from the original message
664         msg->medias = msg->retrans->medias;
665         return;
666     }
667 
668     // Parse each line of payload looking for sdp information
669     tofree = payload2 = strdup((char*)payload);
670     while ((line = strsep(&payload2, "\r\n")) != NULL) {
671         // Check if we have a media string
672         if (!strncmp(line, "m=", 2)) {
673             if (sscanf(line, "m=%" STRINGIFY(MEDIATYPELEN) "s %hu RTP/%*s %u", media_type, &dst.port, &media_fmt_pref) == 3
674             ||  sscanf(line, "m=%" STRINGIFY(MEDIATYPELEN) "s %hu UDP/%*s %u", media_type, &dst.port, &media_fmt_pref) == 3) {
675 
676                 // Add streams from previous 'm=' line to the call
677                 ADD_STREAM(msg_rtp_stream);
678                 ADD_STREAM(rtp_stream);
679                 ADD_STREAM(rtcp_stream);
680 
681                 // Create a new media structure for this message
682                 if ((media = media_create(msg))) {
683                     media_set_type(media, media_type);
684                     media_set_address(media, dst);
685                     media_set_prefered_format(media, media_fmt_pref);
686                     msg_add_media(msg, media);
687 
688                     /**
689                      * From SDP we can only guess destination address port. RTP Capture proccess
690                      * will determine when the stream has been completed, getting source address
691                      * and port of the stream.
692                      */
693                     // Create a new stream with this destination address:port
694 
695                     // Create RTP stream with source of message as destination address
696                     msg_rtp_stream = stream_create(media, dst, PACKET_RTP);
697                     msg_rtp_stream->dst = msg->packet->src;
698                     msg_rtp_stream->dst.port = dst.port;
699 
700                     // Create RTP stream
701                     rtp_stream = stream_create(media, dst, PACKET_RTP);
702 
703                     // Create RTCP stream
704                     rtcp_stream = stream_create(media, dst, PACKET_RTCP);
705                     rtcp_stream->dst.port++;
706                 }
707             }
708         }
709 
710         // Check if we have a connection string
711         if (!strncmp(line, "c=", 2)) {
712             if (sscanf(line, "c=IN IP%*c %" STRINGIFY(ADDRESSLEN) "s", address)) {
713                 strncpy(dst.ip, address, ADDRESSLEN - 1);
714                 if (media) {
715                     media_set_address(media, dst);
716                     strcpy(rtp_stream->dst.ip, dst.ip);
717                     strcpy(rtcp_stream->dst.ip, dst.ip);
718                 }
719             }
720         }
721 
722         // Check if we have attribute format string
723         if (!strncmp(line, "a=rtpmap:", 9)) {
724             if (media && sscanf(line, "a=rtpmap:%u %29[^ ]", &media_fmt_code, media_format)) {
725                 media_add_format(media, media_fmt_code, media_format);
726             }
727         }
728 
729         // Check if we have attribute format RTCP port
730         if (!strncmp(line, "a=rtcp:", 7) && rtcp_stream) {
731             sscanf(line, "a=rtcp:%hu", &rtcp_stream->dst.port);
732         }
733 
734 
735     }
736 
737     // Add streams from last 'm=' line to the call
738     ADD_STREAM(msg_rtp_stream);
739     ADD_STREAM(rtp_stream);
740     ADD_STREAM(rtcp_stream);
741 
742     sng_free(tofree);
743 
744 #undef ADD_STREAM
745 }
746 
747 void
sip_parse_extra_headers(sip_msg_t * msg,const u_char * payload)748 sip_parse_extra_headers(sip_msg_t *msg, const u_char *payload)
749 {
750     regmatch_t pmatch[4];
751     char warning[10];
752 
753      // Reason text
754      if (regexec(&calls.reg_reason, (const char *)payload, 2, pmatch, 0) == 0) {
755          msg->call->reasontxt = sng_malloc((int)pmatch[1].rm_eo - pmatch[1].rm_so + 1);
756          strncpy(msg->call->reasontxt, (const char *)payload +  pmatch[1].rm_so, (int)pmatch[1].rm_eo - pmatch[1].rm_so);
757      }
758 
759      // Warning code
760      if (regexec(&calls.reg_warning, (const char *)payload, 2, pmatch, 0) == 0) {
761          strncpy(warning, (const char *)payload +  pmatch[1].rm_so, (int)pmatch[1].rm_eo - pmatch[1].rm_so);
762          msg->call->warning = atoi(warning);
763      }
764 }
765 
766 void
sip_calls_clear()767 sip_calls_clear()
768 {
769     // Create again the callid hash table
770     htable_destroy(calls.callids);
771     calls.callids = htable_create(calls.limit);
772 
773     // Remove all items from vector
774     vector_clear(calls.list);
775     vector_clear(calls.active);
776 }
777 
778 void
sip_calls_clear_soft()779 sip_calls_clear_soft()
780 {
781         // Create again the callid hash table
782         htable_destroy(calls.callids);
783         calls.callids = htable_create(calls.limit);
784 
785         // Repopulate list applying current filter
786         calls.list = vector_copy_if(sip_calls_vector(), filter_check_call);
787         calls.active = vector_copy_if(sip_active_calls_vector(), filter_check_call);
788 
789         // Repopulate callids based on filtered list
790         sip_call_t *call;
791         vector_iter_t it = vector_iterator(calls.list);
792 
793         while ((call = vector_iterator_next(&it)))
794         {
795                 htable_insert(calls.callids, call->callid, call);
796         }
797 }
798 
799 void
sip_calls_rotate()800 sip_calls_rotate()
801 {
802     sip_call_t *call;
803     vector_iter_t it = vector_iterator(calls.list);
804     while ((call = vector_iterator_next(&it))) {
805         if (!call->locked) {
806             // Remove from callids hash
807             htable_remove(calls.callids, call->callid);
808             // Remove first call from active and call lists
809             vector_remove(calls.active, call);
810             vector_remove(calls.list, call);
811             return;
812         }
813     }
814 }
815 
816 int
sip_set_match_expression(const char * expr,int insensitive,int invert)817 sip_set_match_expression(const char *expr, int insensitive, int invert)
818 {
819     // Store expression text
820     calls.match_expr = expr;
821     // Set invert flag
822     calls.match_invert = invert;
823 
824 #ifdef WITH_PCRE
825     const char *re_err = NULL;
826     int32_t err_offset;
827     int32_t pflags = PCRE_UNGREEDY | PCRE_DOTALL;
828 
829     if (insensitive)
830         pflags |= PCRE_CASELESS;
831 
832     // Check if we have a valid expression
833     calls.match_regex = pcre_compile(expr, pflags, &re_err, &err_offset, 0);
834     return calls.match_regex == NULL;
835 #else
836     int cflags = REG_EXTENDED;
837 
838     // Case insensitive requested
839     if (insensitive)
840         cflags |= REG_ICASE;
841 
842     // Check the expresion is a compilable regexp
843     return regcomp(&calls.match_regex, expr, cflags) != 0;
844 #endif
845 }
846 
847 const char *
sip_get_match_expression()848 sip_get_match_expression()
849 {
850     return calls.match_expr;
851 }
852 
853 int
sip_check_match_expression(const char * payload)854 sip_check_match_expression(const char *payload)
855 {
856     // Everything matches when there is no match
857     if (!calls.match_expr)
858         return 1;
859 
860 #ifdef WITH_PCRE
861     switch (pcre_exec(calls.match_regex, 0, payload, strlen(payload), 0, 0, 0, 0)) {
862         case PCRE_ERROR_NOMATCH:
863             return 1 == calls.match_invert;
864     }
865 
866     return 0 == calls.match_invert;
867 #else
868     // Check if payload matches the given expresion
869     return (regexec(&calls.match_regex, payload, 0, NULL, 0) == calls.match_invert);
870 #endif
871 }
872 
873 const char *
sip_method_str(int method)874 sip_method_str(int method)
875 {
876     int i;
877 
878     // Standard method
879     for (i = 0; sip_codes[i].id > 0; i++) {
880         if (method == sip_codes[i].id)
881             return sip_codes[i].text;
882     }
883     return NULL;
884 }
885 
886 int
sip_method_from_str(const char * method)887 sip_method_from_str(const char *method)
888 {
889     int i;
890 
891     // Standard method
892     for (i = 0; sip_codes[i].id > 0; i++) {
893         if (!strcmp(method, sip_codes[i].text))
894             return sip_codes[i].id;
895     }
896     return atoi(method);
897 }
898 
899 const char *
sip_transport_str(int transport)900 sip_transport_str(int transport)
901 {
902     switch(transport)
903     {
904         case PACKET_SIP_UDP:
905             return "UDP";
906         case PACKET_SIP_TCP:
907             return "TCP";
908         case PACKET_SIP_TLS:
909             return "TLS";
910         case PACKET_SIP_WS:
911             return "WS";
912         case PACKET_SIP_WSS:
913             return "WSS";
914     }
915     return "";
916 }
917 
918 char *
sip_get_msg_header(sip_msg_t * msg,char * out)919 sip_get_msg_header(sip_msg_t *msg, char *out)
920 {
921     char from_addr[80], to_addr[80], time[80], date[80];
922 
923     // Source and Destination address
924     msg_get_attribute(msg, SIP_ATTR_DATE, date);
925     msg_get_attribute(msg, SIP_ATTR_TIME, time);
926     msg_get_attribute(msg, SIP_ATTR_SRC, from_addr);
927     msg_get_attribute(msg, SIP_ATTR_DST, to_addr);
928 
929     // Get msg header
930     if (setting_enabled(SETTING_DISPLAY_ALIAS)) {
931         sprintf(out, "%s %s %s -> %s", date, time, get_alias_value(from_addr), get_alias_value(to_addr));
932     } else {
933         sprintf(out, "%s %s %s -> %s", date, time, from_addr, to_addr);
934     }
935     return out;
936 }
937 
938 void
sip_set_sort_options(sip_sort_t sort)939 sip_set_sort_options(sip_sort_t sort)
940 {
941     calls.sort = sort;
942     sip_sort_list();
943 }
944 
945 sip_sort_t
sip_sort_options()946 sip_sort_options()
947 {
948     return calls.sort;
949 }
950 
951 void
sip_sort_list()952 sip_sort_list()
953 {
954     // Cloning the vector automatically sorts it
955     vector_t *clone = vector_clone(calls.list);
956 
957     // FIXME FIXME FIXME
958     // There should be a way to destroy the vector without calling the
959     // vector destroyer for each item...
960     vector_set_destroyer(calls.list, NULL);
961     vector_destroy(calls.list);
962 
963     // The new sorted list
964     calls.list = clone;
965 }
966 
967 void
sip_list_sorter(vector_t * vector,void * item)968 sip_list_sorter(vector_t *vector, void *item)
969 {
970     sip_call_t *prev, *cur = (sip_call_t *)item;
971     int count = vector_count(vector);
972     int i;
973 
974     // First item is alway sorted
975     if (vector_count(vector) == 1)
976         return;
977 
978     for (i = count - 2 ; i >= 0; i--) {
979         // Get previous item
980         prev = vector_item(vector, i);
981         // Check if the item is already in a sorted position
982         int cmp = call_attr_compare(cur, prev, calls.sort.by);
983         if ((calls.sort.asc && cmp > 0) || (!calls.sort.asc && cmp < 0)) {
984             vector_insert(vector, item, i + 1);
985             return;
986         }
987     }
988 
989     // Put this item at the begining of the vector
990     vector_insert(vector, item, 0);
991 }
992