blob: 2647e0b2be2ae3537e0ee5eef98aaae517137f09 [file] [log] [blame]
James Kuszmaul82f6c042021-01-17 11:30:16 -08001/**
2 * @file sip/msg.c SIP Message decode
3 *
4 * Copyright (C) 2010 Creytiv.com
5 */
6#include <ctype.h>
7#include <re_types.h>
8#include <re_mem.h>
9#include <re_sys.h>
10#include <re_mbuf.h>
11#include <re_sa.h>
12#include <re_list.h>
13#include <re_hash.h>
14#include <re_fmt.h>
15#include <re_uri.h>
16#include <re_udp.h>
17#include <re_msg.h>
18#include <re_sip.h>
19#include "sip.h"
20
21
22enum {
23 HDR_HASH_SIZE = 32,
24 STARTLINE_MAX = 8192,
25};
26
27
28static void hdr_destructor(void *arg)
29{
30 struct sip_hdr *hdr = arg;
31
32 list_unlink(&hdr->le);
33 hash_unlink(&hdr->he);
34}
35
36
37static void destructor(void *arg)
38{
39 struct sip_msg *msg = arg;
40
41 list_flush(&msg->hdrl);
42 hash_flush(msg->hdrht);
43 mem_deref(msg->hdrht);
44 mem_deref(msg->sock);
45 mem_deref(msg->mb);
46}
47
48
49static enum sip_hdrid hdr_hash(const struct pl *name)
50{
51 if (!name->l)
52 return SIP_HDR_NONE;
53
54 if (name->l > 1) {
55 switch (name->p[0]) {
56
57 case 'x':
58 case 'X':
59 if (name->p[1] == '-')
60 return SIP_HDR_NONE;
61
62 /*@fallthrough@*/
63
64 default:
65 return (enum sip_hdrid)
66 (hash_joaat_ci(name->p, name->l) & 0xfff);
67 }
68 }
69
70 /* compact headers */
71 switch (tolower(name->p[0])) {
72
73 case 'a': return SIP_HDR_ACCEPT_CONTACT;
74 case 'b': return SIP_HDR_REFERRED_BY;
75 case 'c': return SIP_HDR_CONTENT_TYPE;
76 case 'd': return SIP_HDR_REQUEST_DISPOSITION;
77 case 'e': return SIP_HDR_CONTENT_ENCODING;
78 case 'f': return SIP_HDR_FROM;
79 case 'i': return SIP_HDR_CALL_ID;
80 case 'j': return SIP_HDR_REJECT_CONTACT;
81 case 'k': return SIP_HDR_SUPPORTED;
82 case 'l': return SIP_HDR_CONTENT_LENGTH;
83 case 'm': return SIP_HDR_CONTACT;
84 case 'n': return SIP_HDR_IDENTITY_INFO;
85 case 'o': return SIP_HDR_EVENT;
86 case 'r': return SIP_HDR_REFER_TO;
87 case 's': return SIP_HDR_SUBJECT;
88 case 't': return SIP_HDR_TO;
89 case 'u': return SIP_HDR_ALLOW_EVENTS;
90 case 'v': return SIP_HDR_VIA;
91 case 'x': return SIP_HDR_SESSION_EXPIRES;
92 case 'y': return SIP_HDR_IDENTITY;
93 default: return SIP_HDR_NONE;
94 }
95}
96
97
98static inline bool hdr_comma_separated(enum sip_hdrid id)
99{
100 switch (id) {
101
102 case SIP_HDR_ACCEPT:
103 case SIP_HDR_ACCEPT_CONTACT:
104 case SIP_HDR_ACCEPT_ENCODING:
105 case SIP_HDR_ACCEPT_LANGUAGE:
106 case SIP_HDR_ACCEPT_RESOURCE_PRIORITY:
107 case SIP_HDR_ALERT_INFO:
108 case SIP_HDR_ALLOW:
109 case SIP_HDR_ALLOW_EVENTS:
110 case SIP_HDR_AUTHENTICATION_INFO:
111 case SIP_HDR_CALL_INFO:
112 case SIP_HDR_CONTACT:
113 case SIP_HDR_CONTENT_ENCODING:
114 case SIP_HDR_CONTENT_LANGUAGE:
115 case SIP_HDR_ERROR_INFO:
116 case SIP_HDR_HISTORY_INFO:
117 case SIP_HDR_IN_REPLY_TO:
118 case SIP_HDR_P_ASSERTED_IDENTITY:
119 case SIP_HDR_P_ASSOCIATED_URI:
120 case SIP_HDR_P_EARLY_MEDIA:
121 case SIP_HDR_P_MEDIA_AUTHORIZATION:
122 case SIP_HDR_P_PREFERRED_IDENTITY:
123 case SIP_HDR_P_REFUSED_URI_LIST:
124 case SIP_HDR_P_VISITED_NETWORK_ID:
125 case SIP_HDR_PATH:
126 case SIP_HDR_PERMISSION_MISSING:
127 case SIP_HDR_PROXY_REQUIRE:
128 case SIP_HDR_REASON:
129 case SIP_HDR_RECORD_ROUTE:
130 case SIP_HDR_REJECT_CONTACT:
131 case SIP_HDR_REQUEST_DISPOSITION:
132 case SIP_HDR_REQUIRE:
133 case SIP_HDR_RESOURCE_PRIORITY:
134 case SIP_HDR_ROUTE:
135 case SIP_HDR_SECURITY_CLIENT:
136 case SIP_HDR_SECURITY_SERVER:
137 case SIP_HDR_SECURITY_VERIFY:
138 case SIP_HDR_SERVICE_ROUTE:
139 case SIP_HDR_SUPPORTED:
140 case SIP_HDR_TRIGGER_CONSENT:
141 case SIP_HDR_UNSUPPORTED:
142 case SIP_HDR_VIA:
143 case SIP_HDR_WARNING:
144 return true;
145
146 default:
147 return false;
148 }
149}
150
151
152static inline int hdr_add(struct sip_msg *msg, const struct pl *name,
153 enum sip_hdrid id, const char *p, ssize_t l,
154 bool atomic, bool line)
155{
156 struct sip_hdr *hdr;
157 int err = 0;
158
159 hdr = mem_zalloc(sizeof(*hdr), hdr_destructor);
160 if (!hdr)
161 return ENOMEM;
162
163 hdr->name = *name;
164 hdr->val.p = p;
165 hdr->val.l = MAX(l, 0);
166 hdr->id = id;
167
168 switch (id) {
169
170 case SIP_HDR_VIA:
171 case SIP_HDR_ROUTE:
172 if (!atomic)
173 break;
174
175 hash_append(msg->hdrht, id, &hdr->he, mem_ref(hdr));
176 list_append(&msg->hdrl, &hdr->le, mem_ref(hdr));
177 break;
178
179 default:
180 if (atomic)
181 hash_append(msg->hdrht, id, &hdr->he, mem_ref(hdr));
182 if (line)
183 list_append(&msg->hdrl, &hdr->le, mem_ref(hdr));
184 break;
185 }
186
187 /* parse common headers */
188 switch (id) {
189
190 case SIP_HDR_VIA:
191 if (!atomic || pl_isset(&msg->via.sentby))
192 break;
193
194 err = sip_via_decode(&msg->via, &hdr->val);
195 break;
196
197 case SIP_HDR_TO:
198 err = sip_addr_decode((struct sip_addr *)&msg->to, &hdr->val);
199 if (err)
200 break;
201
202 (void)msg_param_decode(&msg->to.params, "tag", &msg->to.tag);
203 msg->to.val = hdr->val;
204 break;
205
206 case SIP_HDR_FROM:
207 err = sip_addr_decode((struct sip_addr *)&msg->from,
208 &hdr->val);
209 if (err)
210 break;
211
212 (void)msg_param_decode(&msg->from.params, "tag",
213 &msg->from.tag);
214 msg->from.val = hdr->val;
215 break;
216
217 case SIP_HDR_CALL_ID:
218 msg->callid = hdr->val;
219 break;
220
221 case SIP_HDR_CSEQ:
222 err = sip_cseq_decode(&msg->cseq, &hdr->val);
223 break;
224
225 case SIP_HDR_MAX_FORWARDS:
226 msg->maxfwd = hdr->val;
227 break;
228
229 case SIP_HDR_CONTENT_TYPE:
230 err = msg_ctype_decode(&msg->ctyp, &hdr->val);
231 break;
232
233 case SIP_HDR_CONTENT_LENGTH:
234 msg->clen = hdr->val;
235 break;
236
237 case SIP_HDR_EXPIRES:
238 msg->expires = hdr->val;
239 break;
240
241 default:
242 /* re_printf("%r = %u\n", &hdr->name, id); */
243 break;
244 }
245
246 mem_deref(hdr);
247
248 return err;
249}
250
251
252/**
253 * Decode a SIP message
254 *
255 * @param msgp Pointer to allocated SIP Message
256 * @param mb Buffer containing SIP Message
257 *
258 * @return 0 if success, otherwise errorcode
259 */
260int sip_msg_decode(struct sip_msg **msgp, struct mbuf *mb)
261{
262 struct pl x, y, z, e, name;
263 const char *p, *v, *cv;
264 struct sip_msg *msg;
265 bool comsep, quote;
266 enum sip_hdrid id = SIP_HDR_NONE;
267 uint32_t ws, lf;
268 size_t l;
269 int err;
270
271 if (!msgp || !mb)
272 return EINVAL;
273
274 p = (const char *)mbuf_buf(mb);
275 l = mbuf_get_left(mb);
276
277 if (re_regex(p, l, "[^ \t\r\n]+ [^ \t\r\n]+ [^\r\n]*[\r]*[\n]1",
278 &x, &y, &z, NULL, &e) || x.p != (char *)mbuf_buf(mb))
279 return (l > STARTLINE_MAX) ? EBADMSG : ENODATA;
280
281 msg = mem_zalloc(sizeof(*msg), destructor);
282 if (!msg)
283 return ENOMEM;
284
285 err = hash_alloc(&msg->hdrht, HDR_HASH_SIZE);
286 if (err)
287 goto out;
288
289 msg->tag = rand_u64();
290 msg->mb = mem_ref(mb);
291 msg->req = (0 == pl_strcmp(&z, "SIP/2.0"));
292
293 if (msg->req) {
294
295 msg->met = x;
296 msg->ruri = y;
297 msg->ver = z;
298
299 if (uri_decode(&msg->uri, &y)) {
300 err = EBADMSG;
301 goto out;
302 }
303 }
304 else {
305 msg->ver = x;
306 msg->scode = pl_u32(&y);
307 msg->reason = z;
308
309 if (!msg->scode) {
310 err = EBADMSG;
311 goto out;
312 }
313 }
314
315 l -= e.p + e.l - p;
316 p = e.p + e.l;
317
318 name.p = v = cv = NULL;
319 name.l = ws = lf = 0;
320 comsep = false;
321 quote = false;
322
323 for (; l > 0; p++, l--) {
324
325 switch (*p) {
326
327 case ' ':
328 case '\t':
329 lf = 0; /* folding */
330 ++ws;
331 break;
332
333 case '\r':
334 ++ws;
335 break;
336
337 case '\n':
338 ++ws;
339
340 if (!lf++)
341 break;
342
343 ++p; --l; /* eoh */
344
345 /*@fallthrough@*/
346
347 default:
348 if (lf || (*p == ',' && comsep && !quote)) {
349
350 if (!name.l) {
351 err = EBADMSG;
352 goto out;
353 }
354
355 err = hdr_add(msg, &name, id, cv ? cv : p,
356 cv ? p - cv - ws : 0,
357 true, cv == v && lf);
358 if (err)
359 goto out;
360
361 if (!lf) { /* comma separated */
362 cv = NULL;
363 break;
364 }
365
366 if (cv != v) {
367 err = hdr_add(msg, &name, id,
368 v ? v : p,
369 v ? p - v - ws : 0,
370 false, true);
371 if (err)
372 goto out;
373 }
374
375 if (lf > 1) { /* eoh */
376 err = 0;
377 goto out;
378 }
379
380 comsep = false;
381 name.p = NULL;
382 cv = v = NULL;
383 lf = 0;
384 }
385
386 if (!name.p) {
387 name.p = p;
388 name.l = 0;
389 ws = 0;
390 }
391
392 if (!name.l) {
393 if (*p != ':') {
394 ws = 0;
395 break;
396 }
397
398 name.l = MAX((int)(p - name.p - ws), 0);
399 if (!name.l) {
400 err = EBADMSG;
401 goto out;
402 }
403
404 id = hdr_hash(&name);
405 comsep = hdr_comma_separated(id);
406 break;
407 }
408
409 if (!cv) {
410 quote = false;
411 cv = p;
412 }
413
414 if (!v) {
415 v = p;
416 }
417
418 if (*p == '"')
419 quote = !quote;
420
421 ws = 0;
422 break;
423 }
424 }
425
426 err = ENODATA;
427
428 out:
429 if (err)
430 mem_deref(msg);
431 else {
432 *msgp = msg;
433 mb->pos = mb->end - l;
434 }
435
436 return err;
437}
438
439
440/**
441 * Get a SIP Header from a SIP Message
442 *
443 * @param msg SIP Message
444 * @param id SIP Header ID
445 *
446 * @return SIP Header if found, NULL if not found
447 */
448const struct sip_hdr *sip_msg_hdr(const struct sip_msg *msg, enum sip_hdrid id)
449{
450 return sip_msg_hdr_apply(msg, true, id, NULL, NULL);
451}
452
453
454/**
455 * Apply a function handler to certain SIP Headers
456 *
457 * @param msg SIP Message
458 * @param fwd True to traverse forwards, false to traverse backwards
459 * @param id SIP Header ID
460 * @param h Function handler
461 * @param arg Handler argument
462 *
463 * @return SIP Header if handler returns true, otherwise NULL
464 */
465const struct sip_hdr *sip_msg_hdr_apply(const struct sip_msg *msg,
466 bool fwd, enum sip_hdrid id,
467 sip_hdr_h *h, void *arg)
468{
469 struct list *lst;
470 struct le *le;
471
472 if (!msg)
473 return NULL;
474
475 lst = hash_list(msg->hdrht, id);
476
477 le = fwd ? list_head(lst) : list_tail(lst);
478
479 while (le) {
480 const struct sip_hdr *hdr = le->data;
481
482 le = fwd ? le->next : le->prev;
483
484 if (hdr->id != id)
485 continue;
486
487 if (!h || h(hdr, msg, arg))
488 return hdr;
489 }
490
491 return NULL;
492}
493
494
495/**
496 * Get an unknown SIP Header from a SIP Message
497 *
498 * @param msg SIP Message
499 * @param name Header name
500 *
501 * @return SIP Header if found, NULL if not found
502 */
503const struct sip_hdr *sip_msg_xhdr(const struct sip_msg *msg, const char *name)
504{
505 return sip_msg_xhdr_apply(msg, true, name, NULL, NULL);
506}
507
508
509/**
510 * Apply a function handler to certain unknown SIP Headers
511 *
512 * @param msg SIP Message
513 * @param fwd True to traverse forwards, false to traverse backwards
514 * @param name SIP Header name
515 * @param h Function handler
516 * @param arg Handler argument
517 *
518 * @return SIP Header if handler returns true, otherwise NULL
519 */
520const struct sip_hdr *sip_msg_xhdr_apply(const struct sip_msg *msg,
521 bool fwd, const char *name,
522 sip_hdr_h *h, void *arg)
523{
524 struct list *lst;
525 struct le *le;
526 struct pl pl;
527
528 if (!msg || !name)
529 return NULL;
530
531 pl_set_str(&pl, name);
532
533 lst = hash_list(msg->hdrht, hdr_hash(&pl));
534
535 le = fwd ? list_head(lst) : list_tail(lst);
536
537 while (le) {
538 const struct sip_hdr *hdr = le->data;
539
540 le = fwd ? le->next : le->prev;
541
542 if (pl_casecmp(&hdr->name, &pl))
543 continue;
544
545 if (!h || h(hdr, msg, arg))
546 return hdr;
547 }
548
549 return NULL;
550}
551
552
553static bool count_handler(const struct sip_hdr *hdr, const struct sip_msg *msg,
554 void *arg)
555{
556 uint32_t *n = arg;
557 (void)hdr;
558 (void)msg;
559
560 ++(*n);
561
562 return false;
563}
564
565
566/**
567 * Count the number of SIP Headers
568 *
569 * @param msg SIP Message
570 * @param id SIP Header ID
571 *
572 * @return Number of SIP Headers
573 */
574uint32_t sip_msg_hdr_count(const struct sip_msg *msg, enum sip_hdrid id)
575{
576 uint32_t n = 0;
577
578 sip_msg_hdr_apply(msg, true, id, count_handler, &n);
579
580 return n;
581}
582
583
584/**
585 * Count the number of unknown SIP Headers
586 *
587 * @param msg SIP Message
588 * @param name SIP Header name
589 *
590 * @return Number of SIP Headers
591 */
592uint32_t sip_msg_xhdr_count(const struct sip_msg *msg, const char *name)
593{
594 uint32_t n = 0;
595
596 sip_msg_xhdr_apply(msg, true, name, count_handler, &n);
597
598 return n;
599}
600
601
602static bool value_handler(const struct sip_hdr *hdr, const struct sip_msg *msg,
603 void *arg)
604{
605 (void)msg;
606
607 return 0 == pl_strcasecmp(&hdr->val, (const char *)arg);
608}
609
610
611/**
612 * Check if a SIP Header matches a certain value
613 *
614 * @param msg SIP Message
615 * @param id SIP Header ID
616 * @param value Header value to check
617 *
618 * @return True if value matches, false if not
619 */
620bool sip_msg_hdr_has_value(const struct sip_msg *msg, enum sip_hdrid id,
621 const char *value)
622{
623 return NULL != sip_msg_hdr_apply(msg, true, id, value_handler,
624 (void *)value);
625}
626
627
628/**
629 * Check if an unknown SIP Header matches a certain value
630 *
631 * @param msg SIP Message
632 * @param name SIP Header name
633 * @param value Header value to check
634 *
635 * @return True if value matches, false if not
636 */
637bool sip_msg_xhdr_has_value(const struct sip_msg *msg, const char *name,
638 const char *value)
639{
640 return NULL != sip_msg_xhdr_apply(msg, true, name, value_handler,
641 (void *)value);
642}
643
644
645/**
646 * Print a SIP Message to stdout
647 *
648 * @param msg SIP Message
649 */
650void sip_msg_dump(const struct sip_msg *msg)
651{
652 struct le *le;
653 uint32_t i;
654
655 if (!msg)
656 return;
657
658 for (i=0; i<HDR_HASH_SIZE; i++) {
659
660 le = list_head(hash_list(msg->hdrht, i));
661
662 while (le) {
663 const struct sip_hdr *hdr = le->data;
664
665 le = le->next;
666
667 (void)re_printf("%02u '%r'='%r'\n", i, &hdr->name,
668 &hdr->val);
669 }
670 }
671
672 le = list_head(&msg->hdrl);
673
674 while (le) {
675 const struct sip_hdr *hdr = le->data;
676
677 le = le->next;
678
679 (void)re_printf("%02u '%r'='%r'\n", hdr->id, &hdr->name,
680 &hdr->val);
681 }
682}