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