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