1 /**
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 
22 enum {
23 	HDR_HASH_SIZE = 32,
24 	STARTLINE_MAX = 8192,
25 };
26 
27 
hdr_destructor(void * arg)28 static 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 
destructor(void * arg)37 static 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 
hdr_hash(const struct pl * name)49 static 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 
hdr_comma_separated(enum sip_hdrid id)98 static 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 
hdr_add(struct sip_msg * msg,const struct pl * name,enum sip_hdrid id,const char * p,ssize_t l,bool atomic,bool line)152 static 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  */
sip_msg_decode(struct sip_msg ** msgp,struct mbuf * mb)260 int 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  */
sip_msg_hdr(const struct sip_msg * msg,enum sip_hdrid id)448 const 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  */
sip_msg_hdr_apply(const struct sip_msg * msg,bool fwd,enum sip_hdrid id,sip_hdr_h * h,void * arg)465 const 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  */
sip_msg_xhdr(const struct sip_msg * msg,const char * name)503 const 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  */
sip_msg_xhdr_apply(const struct sip_msg * msg,bool fwd,const char * name,sip_hdr_h * h,void * arg)520 const 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 
count_handler(const struct sip_hdr * hdr,const struct sip_msg * msg,void * arg)553 static 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  */
sip_msg_hdr_count(const struct sip_msg * msg,enum sip_hdrid id)574 uint32_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  */
sip_msg_xhdr_count(const struct sip_msg * msg,const char * name)592 uint32_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 
value_handler(const struct sip_hdr * hdr,const struct sip_msg * msg,void * arg)602 static 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  */
sip_msg_hdr_has_value(const struct sip_msg * msg,enum sip_hdrid id,const char * value)620 bool 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  */
sip_msg_xhdr_has_value(const struct sip_msg * msg,const char * name,const char * value)637 bool 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  */
sip_msg_dump(const struct sip_msg * msg)650 void 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 }
683