1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <stdio.h>
30 #include <assert.h>
31 #include <errno.h>
32 #include <pthread.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <sip.h>
36
37 #include "sip_msg.h"
38 #include "sip_miscdefs.h"
39 #include "sip_parse_generic.h"
40
41 sip_methods_t sip_methods[MAX_SIP_METHODS] = {
42 {"UNKNOWN", 7},
43 {"INVITE", 6},
44 {"ACK", 3},
45 {"OPTIONS", 7},
46 {"BYE", 3},
47 {"CANCEL", 6},
48 {"REGISTER", 8},
49 {"REFER", 5},
50 {"INFO", 4},
51 {"SUBSCRIBE", 9},
52 {"NOTIFY", 6},
53 {"PRACK", 5}
54 };
55
56 /*
57 * Built-In Header function table
58 */
59 sip_header_function_t sip_header_function_table[] = {
60 {"Unknown", NULL, sip_parse_unknown_header, NULL, NULL, NULL},
61 {"CONTACT", "m", sip_parse_cftr_header, NULL, NULL,
62 sip_free_cftr_header},
63 {"FROM", "F", sip_parse_cftr_header, NULL, NULL, sip_free_cftr_header},
64 {"TO", "T", sip_parse_cftr_header, NULL, NULL, sip_free_cftr_header},
65 {"CONTENT-LENGTH", "l", sip_parse_clen_header, NULL, NULL,
66 sip_free_phdr},
67 {"CONTENT-TYPE", "c", sip_parse_ctype_header, NULL, NULL,
68 sip_free_phdr},
69 {"CALL-ID", "i", sip_parse_cid_header, NULL, NULL, sip_free_phdr},
70 {"CSEQ", NULL, sip_parse_cseq_header, NULL, NULL, sip_free_phdr},
71 {"VIA", "v", sip_parse_via_header, NULL, NULL, sip_free_phdr},
72 {"Max-Forwards", NULL, sip_parse_maxf_header, NULL, NULL,
73 sip_free_phdr},
74 {"RECORD-ROUTE", NULL, sip_parse_cftr_header, NULL, NULL,
75 sip_free_cftr_header},
76 {"ROUTE", NULL, sip_parse_cftr_header, NULL, NULL,
77 sip_free_cftr_header},
78 {"ACCEPT", NULL, sip_parse_acpt_header, NULL, NULL, sip_free_phdr},
79 {"ACCEPT-ENCODING", NULL, sip_parse_acpt_encode_header, NULL, NULL,
80 sip_free_phdr},
81 {"ACCEPT-LANGUAGE", NULL, sip_parse_acpt_lang_header, NULL, NULL,
82 sip_free_phdr},
83 {"ALERT-INFO", NULL, sip_parse_alert_header, NULL, NULL, sip_free_phdr},
84 {"ALLOW", NULL, sip_parse_allow_header, NULL, NULL, sip_free_phdr},
85 {"CALL-INFO", NULL, sip_parse_callinfo_header, NULL, NULL,
86 sip_free_phdr},
87 {"CONTENT-DISPOSITION", NULL, sip_parse_contentdis_header, NULL, NULL,
88 sip_free_phdr},
89 {"CONTENT-ENCODING", "e", sip_parse_contentencode_header, NULL, NULL,
90 sip_free_phdr},
91 {"CONTENT-LANGUAGE", NULL, sip_parse_contentlang_header, NULL, NULL,
92 sip_free_phdr},
93 {"DATE", NULL, sip_parse_date_header, NULL, NULL, sip_free_phdr},
94 {"ERROR-INFO", NULL, sip_parse_errorinfo_header, NULL, NULL,
95 sip_free_phdr},
96 {"EXPIRES", NULL, sip_parse_expire_header, NULL, NULL, sip_free_phdr},
97 {"IN-REPLY-TO", NULL, sip_parse_inreplyto_header, NULL, NULL,
98 sip_free_phdr},
99 {"MIN-EXPIRES", NULL, sip_parse_minexpire_header, NULL, NULL,
100 sip_free_phdr},
101 {"MIME-VERSION", NULL, sip_parse_mimeversion_header, NULL, NULL,
102 sip_free_phdr},
103 {"ORGANIZATION", NULL, sip_parse_org_header, NULL, NULL, sip_free_phdr},
104 {"PRIORITY", NULL, sip_parse_priority_header, NULL, NULL,
105 sip_free_phdr},
106 {"REQUIRE", NULL, sip_parse_require_header, NULL, NULL, sip_free_phdr},
107 {"REPLY-TO", NULL, sip_parse_replyto_header, NULL, NULL, sip_free_phdr},
108 {"RETRY-AFTER", NULL, sip_parse_retryaft_header, NULL, NULL,
109 sip_free_phdr},
110 {"SERVER", NULL, sip_parse_server_header, NULL, NULL, sip_free_phdr},
111 {"SUBJECT", "s", sip_parse_subject_header, NULL, NULL, sip_free_phdr},
112 {"TIMESTAMP", NULL, sip_parse_timestamp_header, NULL, NULL,
113 sip_free_phdr},
114 {"UNSUPPORTED", NULL, sip_parse_usupport_header, NULL, NULL,
115 sip_free_phdr},
116 {"SUPPORTED", "k", sip_parse_support_header, NULL, NULL, sip_free_phdr},
117 {"USER-AGENT", NULL, sip_parse_useragt_header, NULL, NULL,
118 sip_free_phdr},
119 {"WARNING", NULL, sip_parse_warn_header, NULL, NULL, sip_free_phdr},
120 {"ALLOW-EVENTS", "u", sip_parse_allow_events_header, NULL, NULL,
121 sip_free_phdr},
122 {"EVENT", "o", sip_parse_event_header, NULL, NULL, sip_free_phdr},
123 {"SUBSCRIPTION-STATE", NULL, sip_parse_substate_header, NULL, NULL,
124 sip_free_phdr},
125 {"AUTHORIZATION", NULL, sip_parse_author_header, NULL, NULL,
126 sip_free_phdr},
127 {"AUTHENTICATION-INFO", NULL, sip_parse_ainfo_header, NULL, NULL,
128 sip_free_phdr},
129 {"PROXY-AUTHORIZATION", NULL, sip_parse_pauthor_header, NULL, NULL,
130 sip_free_phdr},
131 {"PROXY-AUTHENTICATE", NULL, sip_parse_pauthen_header, NULL, NULL,
132 sip_free_phdr},
133 {"PROXY-REQUIRE", NULL, sip_parse_preq_header, NULL, NULL,
134 sip_free_phdr},
135 {"WWW-AUTHENTICATE", NULL, sip_parse_wauthen_header, NULL, NULL,
136 sip_free_phdr},
137 {"RSEQ", NULL, sip_parse_rseq, NULL, NULL, sip_free_phdr},
138 {"RACK", NULL, sip_parse_rack, NULL, NULL, sip_free_phdr},
139 {"P-ASSERTED-IDENTITY", NULL, sip_parse_passertedid, NULL, NULL,
140 sip_free_phdr},
141 {"P-PREFERRED-IDENTITY", NULL, sip_parse_ppreferredid, NULL, NULL,
142 sip_free_phdr},
143 {"PRIVACY", NULL, sip_parse_privacy_header, NULL, NULL, sip_free_phdr},
144 {NULL, NULL, NULL, NULL, NULL, NULL},
145 };
146
147 #define MAX_SIP_HEADERS \
148 sizeof (sip_header_function_table) / sizeof (sip_header_function_t)
149
150 /*
151 * External/application provided function table
152 */
153 sip_header_function_t *sip_header_function_table_external = NULL;
154
155 /*
156 * Free parameter list
157 */
158 static void
sip_free_params(sip_param_t * param_list)159 sip_free_params(sip_param_t *param_list)
160 {
161 sip_param_t *param, *next_param;
162
163 param = param_list;
164
165 while (param != NULL) {
166 next_param = param->param_next;
167 free(param);
168 param = next_param;
169 }
170 }
171
172 /*
173 * Common header free routine
174 */
175 void
sip_free_phdr(sip_parsed_header_t * header)176 sip_free_phdr(sip_parsed_header_t *header)
177 {
178 sip_hdr_value_t *value;
179 sip_hdr_value_t *next_value;
180
181 if (header == NULL)
182 return;
183 value = (sip_hdr_value_t *)header->value;
184 while (value != NULL) {
185 sip_free_params(value->sip_param_list);
186 next_value = value->sip_next_value;
187 free(value);
188 value = next_value;
189 }
190 free(header);
191 }
192
193 /*
194 * Free Contact/From/To header
195 */
196 void
sip_free_cftr_header(sip_parsed_header_t * header)197 sip_free_cftr_header(sip_parsed_header_t *header)
198 {
199 sip_hdr_value_t *value;
200 sip_hdr_value_t *next_value;
201
202 if (header == NULL)
203 return;
204 value = (sip_hdr_value_t *)header->value;
205 while (value != NULL) {
206 next_value = value->sip_next_value;
207 sip_free_params(value->sip_param_list);
208 if (value->cftr_name != NULL)
209 free(value->cftr_name);
210 if (value->sip_value_parsed_uri != NULL) {
211 sip_free_parsed_uri(value->sip_value_parsed_uri);
212 value->sip_value_parsed_uri = NULL;
213 }
214 free(value);
215 value = next_value;
216 }
217 free(header);
218 }
219
220 /*
221 * Return new header
222 */
223 _sip_header_t *
sip_new_header(int header_size)224 sip_new_header(int header_size)
225 {
226 _sip_header_t *new_header;
227
228 new_header = calloc(1, sizeof (_sip_header_t));
229 if (new_header == NULL)
230 return (NULL);
231
232 /*
233 * We are using snprintf which adds a null character
234 * so allocate an extra byte which is not part of
235 * the message header
236 */
237 new_header->sip_hdr_start = calloc(1, header_size + 1);
238 if (new_header->sip_hdr_start == NULL) {
239 free(new_header);
240 return (NULL);
241 }
242 new_header->sip_hdr_end = new_header->sip_hdr_start + header_size;
243 new_header->sip_hdr_current = new_header->sip_hdr_start;
244 new_header->sip_hdr_allocated = B_TRUE;
245 return (new_header);
246 }
247
248 /*
249 * Free the given header
250 */
251 void
sip_free_header(_sip_header_t * sip_header)252 sip_free_header(_sip_header_t *sip_header)
253 {
254 if (sip_header->sip_hdr_allocated) {
255 assert(sip_header->sip_hdr_start != NULL);
256 free(sip_header->sip_hdr_start);
257 }
258 if (sip_header->sip_hdr_parsed != NULL) {
259 assert(sip_header->sip_header_functions != NULL);
260 if (sip_header->sip_header_functions->header_free != NULL) {
261 sip_header->sip_header_functions->header_free(
262 sip_header->sip_hdr_parsed);
263 }
264 }
265 free(sip_header);
266 }
267
268 /*
269 * Return a copy of the header passed in.
270 */
271 _sip_header_t *
sip_dup_header(_sip_header_t * from)272 sip_dup_header(_sip_header_t *from)
273 {
274 size_t hdr_size;
275 _sip_header_t *to;
276
277 hdr_size = from->sip_hdr_end - from->sip_hdr_start;
278 to = sip_new_header(hdr_size);
279 if (to == NULL)
280 return (NULL);
281 if (from->sip_header_state == SIP_HEADER_DELETED_VAL) {
282 to->sip_hdr_end = to->sip_hdr_start +
283 sip_copy_values(to->sip_hdr_start, from);
284 } else {
285 (void) memcpy(to->sip_hdr_start, from->sip_hdr_start, hdr_size);
286 to->sip_hdr_end = to->sip_hdr_start + hdr_size;
287 }
288 to->sip_header_functions = from->sip_header_functions;
289 return (to);
290 }
291
292 /*
293 * Copy header with extra_param, if any, to sip_msg
294 */
295 int
_sip_copy_header(_sip_msg_t * sip_msg,_sip_header_t * header,char * extra_param,boolean_t skip_crlf)296 _sip_copy_header(_sip_msg_t *sip_msg, _sip_header_t *header, char *extra_param,
297 boolean_t skip_crlf)
298 {
299 _sip_header_t *new_header;
300 int hdrlen;
301 int extra_len = 0;
302 int ncrlf = 0;
303 char *p;
304
305 #ifdef __solaris__
306 assert(mutex_held(&sip_msg->sip_msg_mutex));
307 #endif
308 if (extra_param != NULL) {
309 extra_len = SIP_SPACE_LEN + sizeof (char) + SIP_SPACE_LEN +
310 strlen(extra_param);
311 }
312 /*
313 * Just take one if there are more, i.e. if this is the last header
314 * before the content.
315 */
316 if (skip_crlf) {
317 if (header->sip_hdr_end - strlen(SIP_CRLF) <=
318 header->sip_hdr_start) {
319 goto proceed;
320 }
321 p = header->sip_hdr_end - strlen(SIP_CRLF);
322 while (strncmp(SIP_CRLF, p, strlen(SIP_CRLF)) == 0) {
323 ncrlf++;
324 if (p - strlen(SIP_CRLF) < header->sip_hdr_start)
325 break;
326 p -= strlen(SIP_CRLF);
327 }
328 /*
329 * Take one CRLF.
330 */
331 ncrlf = (ncrlf - 1) * strlen(SIP_CRLF);
332 }
333 proceed:
334 hdrlen = header->sip_hdr_end - header->sip_hdr_start - ncrlf;
335 new_header = sip_new_header(hdrlen + extra_len);
336 if (new_header == NULL)
337 return (ENOMEM);
338 if (header->sip_header_state == SIP_HEADER_DELETED_VAL) {
339 int len;
340
341 len = sip_copy_values(new_header->sip_hdr_start, header);
342 new_header->sip_hdr_end = new_header->sip_hdr_start + len;
343 hdrlen = hdrlen - len + extra_len;
344 } else {
345 (void) memcpy(new_header->sip_hdr_start, header->sip_hdr_start,
346 hdrlen);
347 new_header->sip_hdr_end = new_header->sip_hdr_start + hdrlen;
348 hdrlen = extra_len;
349 }
350 if (extra_param != NULL) {
351 /*
352 * Find CR
353 */
354 if (sip_find_cr(new_header) != 0) {
355 sip_free_header(new_header);
356 return (EINVAL);
357 }
358 hdrlen += new_header->sip_hdr_end - new_header->sip_hdr_current;
359 (void) snprintf(new_header->sip_hdr_current, hdrlen + 1,
360 " %c %s%s", SIP_SEMI, extra_param, SIP_CRLF);
361 }
362
363 new_header->sip_hdr_end += extra_len;
364 new_header->sip_header_functions = header->sip_header_functions;
365 _sip_add_header(sip_msg, new_header, B_TRUE, B_FALSE, NULL);
366 return (0);
367 }
368
369 /*
370 * Copy all "header_name" headers from _old_msg to _new_msg
371 */
372 int
_sip_find_and_copy_all_header(_sip_msg_t * _old_msg,_sip_msg_t * _new_msg,char * header_name)373 _sip_find_and_copy_all_header(_sip_msg_t *_old_msg, _sip_msg_t *_new_msg,
374 char *header_name)
375 {
376 _sip_header_t *header;
377 int ret = 0;
378
379 if (_old_msg == NULL || _new_msg == NULL)
380 return (EINVAL);
381 #ifdef __solaris__
382 assert(mutex_held(&_old_msg->sip_msg_mutex));
383 #endif
384 if (_old_msg != _new_msg)
385 (void) pthread_mutex_lock(&_new_msg->sip_msg_mutex);
386 header = sip_search_for_header(_old_msg, header_name, NULL);
387 while (header != NULL) {
388 ret = _sip_copy_header(_new_msg, header, NULL, B_TRUE);
389 if (ret != 0)
390 break;
391 header = sip_search_for_header(_old_msg, header_name, header);
392 }
393 if (_old_msg != _new_msg)
394 (void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
395 return (ret);
396 }
397
398 /*
399 * Copy header_name from _old_msg to _new_msg with extra_parm.
400 */
401 int
_sip_find_and_copy_header(sip_msg_t _old_msg,sip_msg_t _new_msg,char * header_name,char * extra_param,boolean_t lock_newmsg)402 _sip_find_and_copy_header(sip_msg_t _old_msg, sip_msg_t _new_msg,
403 char *header_name, char *extra_param, boolean_t lock_newmsg)
404 {
405 _sip_header_t *header;
406 int ret;
407
408 if (_old_msg == NULL || _new_msg == NULL)
409 return (EINVAL);
410 #ifdef __solaris__
411 assert(mutex_held(&_old_msg->sip_msg_mutex));
412 #endif
413 header = sip_search_for_header(_old_msg, header_name, NULL);
414 if (header == NULL)
415 return (EINVAL);
416 if (lock_newmsg)
417 (void) pthread_mutex_lock(&_new_msg->sip_msg_mutex);
418 ret = _sip_copy_header(_new_msg, header, extra_param, B_TRUE);
419 if (lock_newmsg)
420 (void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
421 return (ret);
422 }
423
424 /*
425 * Copy all headers from old_msg to new_msg
426 */
427 int
sip_copy_all_headers(sip_msg_t old_msg,sip_msg_t new_msg)428 sip_copy_all_headers(sip_msg_t old_msg, sip_msg_t new_msg)
429 {
430 _sip_header_t *header;
431 _sip_msg_t *_old_msg;
432 _sip_msg_t *_new_msg;
433 int ret = 0;
434
435 if (old_msg == NULL || new_msg == NULL)
436 return (EINVAL);
437 _old_msg = (_sip_msg_t *)old_msg;
438 _new_msg = (_sip_msg_t *)new_msg;
439
440 (void) pthread_mutex_lock(&_old_msg->sip_msg_mutex);
441 (void) pthread_mutex_lock(&_new_msg->sip_msg_mutex);
442 header = sip_search_for_header(_old_msg, NULL, NULL);
443 while (header != NULL) {
444 ret = _sip_copy_header(_new_msg, header, NULL, B_FALSE);
445 if (ret != 0)
446 goto done;
447 header = sip_search_for_header(_old_msg, NULL, header);
448 }
449 done:
450 (void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
451 (void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
452 return (ret);
453 }
454
455 /*
456 * Copy start line from msg to sip_msg
457 */
458 int
sip_copy_start_line(sip_msg_t msg,sip_msg_t sip_msg)459 sip_copy_start_line(sip_msg_t msg, sip_msg_t sip_msg)
460 {
461 int len;
462 _sip_header_t *new_header;
463 _sip_msg_t *_old_msg;
464 _sip_msg_t *_sip_msg;
465
466 if (msg == NULL || sip_msg == NULL)
467 return (EINVAL);
468 _old_msg = (_sip_msg_t *)msg;
469 _sip_msg = (_sip_msg_t *)sip_msg;
470
471 (void) pthread_mutex_lock(&_old_msg->sip_msg_mutex);
472 if (_old_msg->sip_msg_start_line == NULL) {
473 (void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
474 return (EINVAL);
475 }
476 len = _old_msg->sip_msg_start_line->sip_hdr_end -
477 _old_msg->sip_msg_start_line->sip_hdr_start;
478 new_header = sip_new_header(len);
479 if (new_header == NULL) {
480 (void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
481 return (ENOMEM);
482 }
483 new_header->sip_hdr_sipmsg = _sip_msg;
484 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
485 _sip_msg->sip_msg_start_line = new_header;
486 _sip_msg->sip_msg_len = len;
487 (void) strncpy(_sip_msg->sip_msg_start_line->sip_hdr_start,
488 _old_msg->sip_msg_start_line->sip_hdr_start, len);
489 (void) sip_parse_first_line(_sip_msg->sip_msg_start_line,
490 &_sip_msg->sip_msg_req_res);
491 (void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
492 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
493 return (0);
494 }
495
496 /*
497 * Delete start line from sip_msg
498 */
499 int
sip_delete_start_line_locked(_sip_msg_t * _sip_msg)500 sip_delete_start_line_locked(_sip_msg_t *_sip_msg)
501 {
502 _sip_header_t *header;
503 _sip_header_t *next_header;
504
505 if (_sip_msg->sip_msg_start_line == NULL)
506 return (EINVAL);
507
508 header = _sip_msg->sip_msg_start_line;
509 while (header != NULL) {
510 next_header = header->sip_hdr_next;
511 _sip_msg->sip_msg_len -= (header->sip_hdr_end -
512 header->sip_hdr_start);
513 sip_free_header(header);
514 header = next_header;
515 }
516 _sip_msg->sip_msg_start_line = NULL;
517
518 /*
519 * Also delete the sip_msg_req_res info since we don't have a start
520 * line.
521 */
522 while (_sip_msg->sip_msg_req_res != NULL) {
523 sip_message_type_t *sip_msg_type_ptr;
524
525 sip_msg_type_ptr = _sip_msg->sip_msg_req_res->sip_next;
526 if (_sip_msg->sip_msg_req_res->is_request) {
527 sip_request_t *reqline;
528
529 reqline = &_sip_msg->sip_msg_req_res->U.sip_request;
530 if (reqline->sip_parse_uri != NULL) {
531 sip_free_parsed_uri(reqline->sip_parse_uri);
532 reqline->sip_parse_uri = NULL;
533 }
534 }
535 free(_sip_msg->sip_msg_req_res);
536 _sip_msg->sip_msg_req_res = sip_msg_type_ptr;
537 }
538 return (0);
539 }
540
541
542 /*
543 * Delete start line from sip_msg
544 */
545 int
sip_delete_start_line(sip_msg_t sip_msg)546 sip_delete_start_line(sip_msg_t sip_msg)
547 {
548 _sip_msg_t *_sip_msg;
549 int ret;
550
551 if (sip_msg == NULL)
552 return (EINVAL);
553
554 _sip_msg = (_sip_msg_t *)sip_msg;
555 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
556 ret = sip_delete_start_line_locked(_sip_msg);
557 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
558
559 return (ret);
560 }
561
562 /*
563 * Delete all headers from _sip_msg
564 */
565 void
sip_delete_all_headers(_sip_msg_t * _sip_msg)566 sip_delete_all_headers(_sip_msg_t *_sip_msg)
567 {
568 _sip_header_t *header;
569
570 #ifdef __solaris__
571 assert(mutex_held(&_sip_msg->sip_msg_mutex));
572 #endif
573
574 header = _sip_msg->sip_msg_headers_start;
575 while (header != NULL) {
576 _sip_header_t *next_header;
577 next_header = header->sip_hdr_next;
578 sip_free_header(header);
579 header = next_header;
580 }
581 _sip_msg->sip_msg_headers_start = NULL;
582 _sip_msg->sip_msg_headers_end = NULL;
583 }
584
585 /*
586 * Delete and free the named header. If header_name is null
587 * free all headers.
588 */
589 void
sip_delete_headers(sip_msg_t sip_msg,char * header_name)590 sip_delete_headers(sip_msg_t sip_msg, char *header_name)
591 {
592 _sip_header_t *header;
593 _sip_msg_t *_sip_msg;
594
595 _sip_msg = (_sip_msg_t *)sip_msg;
596 #ifdef __solaris__
597 assert(mutex_held(&_sip_msg->sip_msg_mutex));
598 #endif
599 header = sip_search_for_header(_sip_msg, header_name, NULL);
600 if (header == NULL)
601 return;
602 while (header != NULL) {
603 if (_sip_msg->sip_msg_headers_start == header) {
604 _sip_msg->sip_msg_headers_start = header->sip_hdr_next;
605 } else {
606 header->sip_hdr_prev->sip_hdr_next =
607 header->sip_hdr_next;
608 }
609 if (_sip_msg->sip_msg_headers_end == header) {
610 _sip_msg->sip_msg_headers_end = header->sip_hdr_prev;
611 } else {
612 header->sip_hdr_next->sip_hdr_prev =
613 header->sip_hdr_prev;
614 }
615 sip_free_header(header);
616 if (header_name != NULL)
617 return;
618 else
619 header = sip_search_for_header(_sip_msg, NULL, NULL);
620 }
621 }
622
623 /*
624 * Add a header to sip_msg. If header_name is provided then the new header
625 * is added before that header, if first is set, or after. If append is
626 * set, then the header is added to the end of the header list.
627 */
628 void
_sip_add_header(_sip_msg_t * sip_msg,_sip_header_t * new_header,boolean_t append,boolean_t first,char * header_name)629 _sip_add_header(_sip_msg_t *sip_msg, _sip_header_t *new_header,
630 boolean_t append, boolean_t first, char *header_name)
631 {
632 _sip_header_t *header = NULL;
633
634 if (sip_msg == NULL || new_header == NULL)
635 return;
636 #ifdef __solaris__
637 assert(mutex_held(&sip_msg->sip_msg_mutex));
638 #endif
639 new_header->sip_hdr_sipmsg = sip_msg;
640 if (header_name != NULL) {
641 _sip_header_t *header_tmp;
642
643 header = sip_search_for_header(sip_msg, header_name, NULL);
644 header_tmp = header;
645 if (!first) {
646 while (header != NULL) {
647 header_tmp = header;
648 header = sip_search_for_header(sip_msg,
649 header_name, header);
650 }
651 }
652 header = header_tmp;
653 if (header == NULL)
654 append = B_TRUE;
655 }
656
657 if (header != NULL) {
658 if (append) {
659 new_header->sip_hdr_prev = header;
660 if (sip_msg->sip_msg_headers_end == header) {
661 sip_msg->sip_msg_headers_end = new_header;
662 new_header->sip_hdr_next = NULL;
663 } else {
664 header->sip_hdr_next->sip_hdr_prev = new_header;
665 new_header->sip_hdr_next = header->sip_hdr_next;
666 }
667 header->sip_hdr_next = new_header;
668 } else {
669 new_header->sip_hdr_next = header;
670 if (sip_msg->sip_msg_headers_start == header) {
671 sip_msg->sip_msg_headers_start = new_header;
672 new_header->sip_hdr_prev = NULL;
673 } else {
674 header->sip_hdr_prev->sip_hdr_next = new_header;
675 new_header->sip_hdr_prev = header->sip_hdr_prev;
676 }
677 header->sip_hdr_prev = new_header;
678 }
679 } else {
680 if (append) {
681 if (sip_msg->sip_msg_headers_end != NULL) {
682 sip_msg->sip_msg_headers_end->sip_hdr_next =
683 new_header;
684 } else {
685 sip_msg->sip_msg_headers_start = new_header;
686 }
687 new_header->sip_hdr_prev =
688 sip_msg->sip_msg_headers_end;
689 new_header->sip_hdr_next = NULL;
690 sip_msg->sip_msg_headers_end = new_header;
691 } else {
692 if (sip_msg->sip_msg_headers_start != NULL) {
693 sip_msg->sip_msg_headers_start->sip_hdr_prev =
694 new_header;
695 } else {
696 sip_msg->sip_msg_headers_end = new_header;
697 }
698 new_header->sip_hdr_next =
699 sip_msg->sip_msg_headers_start;
700 new_header->sip_hdr_prev = NULL;
701 sip_msg->sip_msg_headers_start = new_header;
702 }
703 }
704 sip_msg->sip_msg_len += new_header->sip_hdr_end -
705 new_header->sip_hdr_start;
706 }
707
708 /*
709 * Scan through the function table and return the entry for the given header
710 * type.
711 */
712 sip_header_function_t *
_sip_get_header_functions(sip_header_function_t * sip_header_function_table,_sip_header_t * sip_header,char * header_name)713 _sip_get_header_functions(sip_header_function_t *sip_header_function_table,
714 _sip_header_t *sip_header, char *header_name)
715 {
716 int len;
717 int i = 0;
718
719 if (sip_header == NULL && header_name == NULL)
720 return (NULL);
721
722 /*
723 * If header_name is NULL we first have to locate the name
724 */
725 if (header_name == NULL) {
726 if (sip_skip_white_space(sip_header) != 0) {
727 return (NULL);
728 }
729 header_name = sip_header->sip_hdr_current;
730 if (sip_find_separator(sip_header, SIP_HCOLON, (char)NULL,
731 (char)NULL, B_FALSE) != 0) {
732 return (NULL);
733 }
734 len = sip_header->sip_hdr_current - header_name;
735 } else {
736 len = strlen(header_name);
737 }
738
739 if (len > 0) {
740 while (sip_header_function_table[i].header_name != NULL ||
741 sip_header_function_table[i].header_short_name != NULL) {
742 if (sip_header_function_table[i].header_name != NULL &&
743 len ==
744 strlen(sip_header_function_table[i].header_name)) {
745 if (strncasecmp(header_name,
746 sip_header_function_table[i].
747 header_name, len) == 0) {
748 break;
749 }
750 } else if (sip_header_function_table[i].
751 header_short_name != NULL && len ==
752 strlen(sip_header_function_table[i].
753 header_short_name)) {
754 if (strncasecmp(header_name,
755 sip_header_function_table[i].
756 header_short_name, len) == 0) {
757 break;
758 }
759 }
760 i++;
761 }
762 }
763
764 if (sip_header != NULL)
765 sip_header->sip_hdr_current = sip_header->sip_hdr_start;
766 if (sip_header_function_table[i].header_name == NULL)
767 return (NULL);
768 return (&sip_header_function_table[i]);
769 }
770
771 /*
772 * Return the entry from the function table for the given header
773 */
774 sip_header_function_t *
sip_get_header_functions(_sip_header_t * sip_header,char * header_name)775 sip_get_header_functions(_sip_header_t *sip_header, char *header_name)
776 {
777 sip_header_function_t *func;
778 sip_header_function_t *header_f_table = NULL;
779
780 if (sip_header_function_table_external != NULL) {
781 header_f_table = _sip_get_header_functions(
782 sip_header_function_table_external,
783 sip_header, header_name);
784 if (header_f_table != NULL)
785 return (header_f_table);
786 }
787 func = _sip_get_header_functions(sip_header_function_table, sip_header,
788 header_name);
789 return (func);
790 }
791
792 /*
793 * Search for the header name passed in.
794 */
795 _sip_header_t *
sip_search_for_header(_sip_msg_t * sip_msg,char * header_name,_sip_header_t * old_header)796 sip_search_for_header(_sip_msg_t *sip_msg, char *header_name,
797 _sip_header_t *old_header)
798 {
799 int len = 0;
800 int full_len = 0;
801 int compact_len = 0;
802 _sip_header_t *header = NULL;
803 char *compact_name = NULL;
804 char *full_name = NULL;
805 sip_header_function_t *header_f_table = NULL;
806
807 if (sip_msg == NULL)
808 return (NULL);
809 #ifdef __solaris__
810 assert(mutex_held(&sip_msg->sip_msg_mutex));
811 #endif
812
813 if (header_name != NULL) {
814 header_f_table = sip_get_header_functions(NULL, header_name);
815 if (header_f_table != NULL) {
816 full_name = header_f_table->header_name;
817 compact_name = header_f_table->header_short_name;
818 if (full_name != NULL)
819 full_len = strlen(full_name);
820 if (compact_name != NULL)
821 compact_len = strlen(compact_name);
822 } else {
823 header_f_table = &sip_header_function_table[0];
824 full_name = header_name;
825 full_len = strlen(full_name);
826 }
827 }
828
829 if (old_header != NULL)
830 header = old_header->sip_hdr_next;
831 else
832 header = sip_msg->sip_msg_headers_start;
833
834 while (header != NULL) {
835
836 if (header->sip_header_state == SIP_HEADER_DELETED) {
837 header = header->sip_hdr_next;
838 continue;
839 }
840
841 if (compact_len == 0 && full_len == 0)
842 break;
843
844 header->sip_hdr_current = header->sip_hdr_start;
845
846 if (sip_skip_white_space(header)) {
847 header = header->sip_hdr_next;
848 continue;
849 }
850
851 len = header->sip_hdr_end - header->sip_hdr_current;
852
853 if (full_name != NULL && (full_len <= len) &&
854 strncasecmp(header->sip_hdr_current, full_name,
855 full_len) == 0) {
856 header->sip_hdr_current += full_len;
857 if (sip_skip_white_space(header)) {
858 header = header->sip_hdr_next;
859 continue;
860 }
861
862 if (*header->sip_hdr_current == SIP_HCOLON) {
863 header_name = full_name;
864 break;
865 }
866 }
867
868 if (compact_name != NULL && (compact_len <= len) &&
869 strncasecmp(header->sip_hdr_current, compact_name,
870 compact_len) == 0) {
871 header->sip_hdr_current += compact_len;
872 if (sip_skip_white_space(header)) {
873 header = header->sip_hdr_next;
874 continue;
875 }
876 if (*header->sip_hdr_current == SIP_HCOLON) {
877 header_name = compact_name;
878 break;
879 }
880 }
881 header = header->sip_hdr_next;
882 }
883
884 if (header != NULL) {
885 header->sip_hdr_current = header->sip_hdr_start;
886 if (header_f_table == NULL) {
887 header_f_table =
888 sip_get_header_functions(header, header_name);
889 if (header_f_table == NULL)
890 header_f_table = &sip_header_function_table[0];
891 }
892
893 header->sip_header_functions = header_f_table;
894 }
895 return (header);
896 }
897
898 /*
899 * Return the start line as a string. Caller frees string
900 */
901 char *
_sip_startline_to_str(_sip_msg_t * sip_msg,int * error)902 _sip_startline_to_str(_sip_msg_t *sip_msg, int *error)
903 {
904 char *slstr;
905 int len;
906
907 if (error != NULL)
908 *error = 0;
909
910 if (sip_msg == NULL || sip_msg->sip_msg_start_line == NULL) {
911 if (error != NULL)
912 *error = EINVAL;
913 return (NULL);
914 }
915 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
916 len = sip_msg->sip_msg_start_line->sip_hdr_end -
917 sip_msg->sip_msg_start_line->sip_hdr_start - 2;
918 if ((slstr = malloc(len + 1)) == NULL) {
919 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
920 if (error != NULL)
921 *error = ENOMEM;
922 return (NULL);
923 }
924 (void) strncpy(slstr, sip_msg->sip_msg_start_line->sip_hdr_start, len);
925 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
926 slstr[len] = '\0';
927 return (slstr);
928 }
929
930 /*
931 * Return the given header as a string. Caller frees string
932 */
933 char *
sip_hdr_to_str(sip_header_t sip_header,int * error)934 sip_hdr_to_str(sip_header_t sip_header, int *error)
935 {
936 char *hdrstr;
937 char *tmpptr;
938 _sip_header_t *_sip_header;
939 int len;
940
941 if (error != NULL)
942 *error = 0;
943
944 if (sip_header == NULL) {
945 if (error != NULL)
946 *error = EINVAL;
947 return (NULL);
948 }
949 _sip_header = (_sip_header_t *)sip_header;
950 if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
951 if (_sip_header->sip_hdr_sipmsg != NULL) {
952 (void) pthread_mutex_unlock(
953 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
954 }
955 if (error != NULL)
956 *error = EINVAL;
957 return (NULL);
958 }
959 if (_sip_header->sip_hdr_sipmsg != NULL) {
960 (void) pthread_mutex_lock(
961 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
962 }
963 len = _sip_header->sip_hdr_end - _sip_header->sip_hdr_start;
964 hdrstr = malloc(len);
965 if (hdrstr == NULL) {
966 if (_sip_header->sip_hdr_sipmsg != NULL) {
967 (void) pthread_mutex_unlock(
968 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
969 }
970 if (error != NULL)
971 *error = ENOMEM;
972 return (NULL);
973 }
974 if (_sip_header->sip_header_state == SIP_HEADER_DELETED_VAL) {
975 len = sip_copy_values(hdrstr, _sip_header);
976 } else {
977 (void) strncpy(hdrstr, _sip_header->sip_hdr_start, len);
978 }
979 if (_sip_header->sip_hdr_sipmsg != NULL) {
980 (void) pthread_mutex_unlock(
981 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
982 }
983 tmpptr = hdrstr + len;
984 while (*tmpptr-- != '\n') {
985 if (tmpptr == _sip_header->sip_hdr_start) {
986 free(hdrstr);
987 if (error != NULL)
988 *error = EINVAL;
989 return (NULL);
990 }
991 }
992 *tmpptr = '\0';
993 return (hdrstr);
994 }
995
996 /*
997 * Given a param list find the named parameter.
998 * Returns a pointer to the value or NULL.
999 */
1000 sip_param_t *
sip_get_param_from_list(sip_param_t * param_list,char * param_name)1001 sip_get_param_from_list(sip_param_t *param_list, char *param_name)
1002 {
1003 while (param_list != NULL) {
1004 if (param_list->param_name.sip_str_len == strlen(param_name) &&
1005 strncasecmp(param_list->param_name.sip_str_ptr, param_name,
1006 strlen(param_name)) == 0) {
1007 return (param_list);
1008 }
1009 param_list = param_list->param_next;
1010 }
1011 return (NULL);
1012 }
1013