libc: make stdio_impl.h an internal libc header
[unleashed/tickless.git] / usr / src / lib / libsip / common / sip_headers.c
blob2ef1a4a9dda656e9ccc6f51c75d07632a9786f10
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
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>
35 #include "sip_msg.h"
36 #include "sip_miscdefs.h"
37 #include "sip_parse_generic.h"
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}
55 * Built-In Header function table
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},
145 #define MAX_SIP_HEADERS \
146 sizeof (sip_header_function_table) / sizeof (sip_header_function_t)
149 * External/application provided function table
151 sip_header_function_t *sip_header_function_table_external = NULL;
154 * Free parameter list
156 static void
157 sip_free_params(sip_param_t *param_list)
159 sip_param_t *param, *next_param;
161 param = param_list;
163 while (param != NULL) {
164 next_param = param->param_next;
165 free(param);
166 param = next_param;
171 * Common header free routine
173 void
174 sip_free_phdr(sip_parsed_header_t *header)
176 sip_hdr_value_t *value;
177 sip_hdr_value_t *next_value;
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;
188 free(header);
192 * Free Contact/From/To header
194 void
195 sip_free_cftr_header(sip_parsed_header_t *header)
197 sip_hdr_value_t *value;
198 sip_hdr_value_t *next_value;
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 free(value->cftr_name);
207 if (value->sip_value_parsed_uri != NULL) {
208 sip_free_parsed_uri(value->sip_value_parsed_uri);
209 value->sip_value_parsed_uri = NULL;
211 free(value);
212 value = next_value;
214 free(header);
218 * Return new header
220 _sip_header_t *
221 sip_new_header(int header_size)
223 _sip_header_t *new_header;
225 new_header = calloc(1, sizeof (_sip_header_t));
226 if (new_header == NULL)
227 return (NULL);
230 * We are using snprintf which adds a null character
231 * so allocate an extra byte which is not part of
232 * the message header
234 new_header->sip_hdr_start = calloc(1, header_size + 1);
235 if (new_header->sip_hdr_start == NULL) {
236 free(new_header);
237 return (NULL);
239 new_header->sip_hdr_end = new_header->sip_hdr_start + header_size;
240 new_header->sip_hdr_current = new_header->sip_hdr_start;
241 new_header->sip_hdr_allocated = B_TRUE;
242 return (new_header);
246 * Free the given header
248 void
249 sip_free_header(_sip_header_t *sip_header)
251 if (sip_header->sip_hdr_allocated) {
252 assert(sip_header->sip_hdr_start != NULL);
253 free(sip_header->sip_hdr_start);
255 if (sip_header->sip_hdr_parsed != NULL) {
256 assert(sip_header->sip_header_functions != NULL);
257 if (sip_header->sip_header_functions->header_free != NULL) {
258 sip_header->sip_header_functions->header_free(
259 sip_header->sip_hdr_parsed);
262 free(sip_header);
266 * Return a copy of the header passed in.
268 _sip_header_t *
269 sip_dup_header(_sip_header_t *from)
271 size_t hdr_size;
272 _sip_header_t *to;
274 hdr_size = from->sip_hdr_end - from->sip_hdr_start;
275 to = sip_new_header(hdr_size);
276 if (to == NULL)
277 return (NULL);
278 if (from->sip_header_state == SIP_HEADER_DELETED_VAL) {
279 to->sip_hdr_end = to->sip_hdr_start +
280 sip_copy_values(to->sip_hdr_start, from);
281 } else {
282 (void) memcpy(to->sip_hdr_start, from->sip_hdr_start, hdr_size);
283 to->sip_hdr_end = to->sip_hdr_start + hdr_size;
285 to->sip_header_functions = from->sip_header_functions;
286 return (to);
290 * Copy header with extra_param, if any, to sip_msg
293 _sip_copy_header(_sip_msg_t *sip_msg, _sip_header_t *header, char *extra_param,
294 boolean_t skip_crlf)
296 _sip_header_t *new_header;
297 int hdrlen;
298 int extra_len = 0;
299 int ncrlf = 0;
300 char *p;
302 #ifdef __solaris__
303 assert(mutex_held(&sip_msg->sip_msg_mutex));
304 #endif
305 if (extra_param != NULL) {
306 extra_len = SIP_SPACE_LEN + sizeof (char) + SIP_SPACE_LEN +
307 strlen(extra_param);
310 * Just take one if there are more, i.e. if this is the last header
311 * before the content.
313 if (skip_crlf) {
314 if (header->sip_hdr_end - strlen(SIP_CRLF) <=
315 header->sip_hdr_start) {
316 goto proceed;
318 p = header->sip_hdr_end - strlen(SIP_CRLF);
319 while (strncmp(SIP_CRLF, p, strlen(SIP_CRLF)) == 0) {
320 ncrlf++;
321 if (p - strlen(SIP_CRLF) < header->sip_hdr_start)
322 break;
323 p -= strlen(SIP_CRLF);
326 * Take one CRLF.
328 ncrlf = (ncrlf - 1) * strlen(SIP_CRLF);
330 proceed:
331 hdrlen = header->sip_hdr_end - header->sip_hdr_start - ncrlf;
332 new_header = sip_new_header(hdrlen + extra_len);
333 if (new_header == NULL)
334 return (ENOMEM);
335 if (header->sip_header_state == SIP_HEADER_DELETED_VAL) {
336 int len;
338 len = sip_copy_values(new_header->sip_hdr_start, header);
339 new_header->sip_hdr_end = new_header->sip_hdr_start + len;
340 hdrlen = hdrlen - len + extra_len;
341 } else {
342 (void) memcpy(new_header->sip_hdr_start, header->sip_hdr_start,
343 hdrlen);
344 new_header->sip_hdr_end = new_header->sip_hdr_start + hdrlen;
345 hdrlen = extra_len;
347 if (extra_param != NULL) {
349 * Find CR
351 if (sip_find_cr(new_header) != 0) {
352 sip_free_header(new_header);
353 return (EINVAL);
355 hdrlen += new_header->sip_hdr_end - new_header->sip_hdr_current;
356 (void) snprintf(new_header->sip_hdr_current, hdrlen + 1,
357 " %c %s%s", SIP_SEMI, extra_param, SIP_CRLF);
360 new_header->sip_hdr_end += extra_len;
361 new_header->sip_header_functions = header->sip_header_functions;
362 _sip_add_header(sip_msg, new_header, B_TRUE, B_FALSE, NULL);
363 return (0);
367 * Copy all "header_name" headers from _old_msg to _new_msg
370 _sip_find_and_copy_all_header(_sip_msg_t *_old_msg, _sip_msg_t *_new_msg,
371 char *header_name)
373 _sip_header_t *header;
374 int ret = 0;
376 if (_old_msg == NULL || _new_msg == NULL)
377 return (EINVAL);
378 #ifdef __solaris__
379 assert(mutex_held(&_old_msg->sip_msg_mutex));
380 #endif
381 if (_old_msg != _new_msg)
382 (void) pthread_mutex_lock(&_new_msg->sip_msg_mutex);
383 header = sip_search_for_header(_old_msg, header_name, NULL);
384 while (header != NULL) {
385 ret = _sip_copy_header(_new_msg, header, NULL, B_TRUE);
386 if (ret != 0)
387 break;
388 header = sip_search_for_header(_old_msg, header_name, header);
390 if (_old_msg != _new_msg)
391 (void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
392 return (ret);
396 * Copy header_name from _old_msg to _new_msg with extra_parm.
399 _sip_find_and_copy_header(sip_msg_t _old_msg, sip_msg_t _new_msg,
400 char *header_name, char *extra_param, boolean_t lock_newmsg)
402 _sip_header_t *header;
403 int ret;
405 if (_old_msg == NULL || _new_msg == NULL)
406 return (EINVAL);
407 #ifdef __solaris__
408 assert(mutex_held(&_old_msg->sip_msg_mutex));
409 #endif
410 header = sip_search_for_header(_old_msg, header_name, NULL);
411 if (header == NULL)
412 return (EINVAL);
413 if (lock_newmsg)
414 (void) pthread_mutex_lock(&_new_msg->sip_msg_mutex);
415 ret = _sip_copy_header(_new_msg, header, extra_param, B_TRUE);
416 if (lock_newmsg)
417 (void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
418 return (ret);
422 * Copy all headers from old_msg to new_msg
425 sip_copy_all_headers(sip_msg_t old_msg, sip_msg_t new_msg)
427 _sip_header_t *header;
428 _sip_msg_t *_old_msg;
429 _sip_msg_t *_new_msg;
430 int ret = 0;
432 if (old_msg == NULL || new_msg == NULL)
433 return (EINVAL);
434 _old_msg = (_sip_msg_t *)old_msg;
435 _new_msg = (_sip_msg_t *)new_msg;
437 (void) pthread_mutex_lock(&_old_msg->sip_msg_mutex);
438 (void) pthread_mutex_lock(&_new_msg->sip_msg_mutex);
439 header = sip_search_for_header(_old_msg, NULL, NULL);
440 while (header != NULL) {
441 ret = _sip_copy_header(_new_msg, header, NULL, B_FALSE);
442 if (ret != 0)
443 goto done;
444 header = sip_search_for_header(_old_msg, NULL, header);
446 done:
447 (void) pthread_mutex_unlock(&_new_msg->sip_msg_mutex);
448 (void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
449 return (ret);
453 * Copy start line from msg to sip_msg
456 sip_copy_start_line(sip_msg_t msg, sip_msg_t sip_msg)
458 int len;
459 _sip_header_t *new_header;
460 _sip_msg_t *_old_msg;
461 _sip_msg_t *_sip_msg;
463 if (msg == NULL || sip_msg == NULL)
464 return (EINVAL);
465 _old_msg = (_sip_msg_t *)msg;
466 _sip_msg = (_sip_msg_t *)sip_msg;
468 (void) pthread_mutex_lock(&_old_msg->sip_msg_mutex);
469 if (_old_msg->sip_msg_start_line == NULL) {
470 (void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
471 return (EINVAL);
473 len = _old_msg->sip_msg_start_line->sip_hdr_end -
474 _old_msg->sip_msg_start_line->sip_hdr_start;
475 new_header = sip_new_header(len);
476 if (new_header == NULL) {
477 (void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
478 return (ENOMEM);
480 new_header->sip_hdr_sipmsg = _sip_msg;
481 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
482 _sip_msg->sip_msg_start_line = new_header;
483 _sip_msg->sip_msg_len = len;
484 (void) strncpy(_sip_msg->sip_msg_start_line->sip_hdr_start,
485 _old_msg->sip_msg_start_line->sip_hdr_start, len);
486 (void) sip_parse_first_line(_sip_msg->sip_msg_start_line,
487 &_sip_msg->sip_msg_req_res);
488 (void) pthread_mutex_unlock(&_old_msg->sip_msg_mutex);
489 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
490 return (0);
494 * Delete start line from sip_msg
497 sip_delete_start_line_locked(_sip_msg_t *_sip_msg)
499 _sip_header_t *header;
500 _sip_header_t *next_header;
502 if (_sip_msg->sip_msg_start_line == NULL)
503 return (EINVAL);
505 header = _sip_msg->sip_msg_start_line;
506 while (header != NULL) {
507 next_header = header->sip_hdr_next;
508 _sip_msg->sip_msg_len -= (header->sip_hdr_end -
509 header->sip_hdr_start);
510 sip_free_header(header);
511 header = next_header;
513 _sip_msg->sip_msg_start_line = NULL;
516 * Also delete the sip_msg_req_res info since we don't have a start
517 * line.
519 while (_sip_msg->sip_msg_req_res != NULL) {
520 sip_message_type_t *sip_msg_type_ptr;
522 sip_msg_type_ptr = _sip_msg->sip_msg_req_res->sip_next;
523 if (_sip_msg->sip_msg_req_res->is_request) {
524 sip_request_t *reqline;
526 reqline = &_sip_msg->sip_msg_req_res->U.sip_request;
527 if (reqline->sip_parse_uri != NULL) {
528 sip_free_parsed_uri(reqline->sip_parse_uri);
529 reqline->sip_parse_uri = NULL;
532 free(_sip_msg->sip_msg_req_res);
533 _sip_msg->sip_msg_req_res = sip_msg_type_ptr;
535 return (0);
540 * Delete start line from sip_msg
543 sip_delete_start_line(sip_msg_t sip_msg)
545 _sip_msg_t *_sip_msg;
546 int ret;
548 if (sip_msg == NULL)
549 return (EINVAL);
551 _sip_msg = (_sip_msg_t *)sip_msg;
552 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
553 ret = sip_delete_start_line_locked(_sip_msg);
554 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
556 return (ret);
560 * Delete all headers from _sip_msg
562 void
563 sip_delete_all_headers(_sip_msg_t *_sip_msg)
565 _sip_header_t *header;
567 #ifdef __solaris__
568 assert(mutex_held(&_sip_msg->sip_msg_mutex));
569 #endif
571 header = _sip_msg->sip_msg_headers_start;
572 while (header != NULL) {
573 _sip_header_t *next_header;
574 next_header = header->sip_hdr_next;
575 sip_free_header(header);
576 header = next_header;
578 _sip_msg->sip_msg_headers_start = NULL;
579 _sip_msg->sip_msg_headers_end = NULL;
583 * Delete and free the named header. If header_name is null
584 * free all headers.
586 void
587 sip_delete_headers(sip_msg_t sip_msg, char *header_name)
589 _sip_header_t *header;
590 _sip_msg_t *_sip_msg;
592 _sip_msg = (_sip_msg_t *)sip_msg;
593 #ifdef __solaris__
594 assert(mutex_held(&_sip_msg->sip_msg_mutex));
595 #endif
596 header = sip_search_for_header(_sip_msg, header_name, NULL);
597 if (header == NULL)
598 return;
599 while (header != NULL) {
600 if (_sip_msg->sip_msg_headers_start == header) {
601 _sip_msg->sip_msg_headers_start = header->sip_hdr_next;
602 } else {
603 header->sip_hdr_prev->sip_hdr_next =
604 header->sip_hdr_next;
606 if (_sip_msg->sip_msg_headers_end == header) {
607 _sip_msg->sip_msg_headers_end = header->sip_hdr_prev;
608 } else {
609 header->sip_hdr_next->sip_hdr_prev =
610 header->sip_hdr_prev;
612 sip_free_header(header);
613 if (header_name != NULL)
614 return;
615 else
616 header = sip_search_for_header(_sip_msg, NULL, NULL);
621 * Add a header to sip_msg. If header_name is provided then the new header
622 * is added before that header, if first is set, or after. If append is
623 * set, then the header is added to the end of the header list.
625 void
626 _sip_add_header(_sip_msg_t *sip_msg, _sip_header_t *new_header,
627 boolean_t append, boolean_t first, char *header_name)
629 _sip_header_t *header = NULL;
631 if (sip_msg == NULL || new_header == NULL)
632 return;
633 #ifdef __solaris__
634 assert(mutex_held(&sip_msg->sip_msg_mutex));
635 #endif
636 new_header->sip_hdr_sipmsg = sip_msg;
637 if (header_name != NULL) {
638 _sip_header_t *header_tmp;
640 header = sip_search_for_header(sip_msg, header_name, NULL);
641 header_tmp = header;
642 if (!first) {
643 while (header != NULL) {
644 header_tmp = header;
645 header = sip_search_for_header(sip_msg,
646 header_name, header);
649 header = header_tmp;
650 if (header == NULL)
651 append = B_TRUE;
654 if (header != NULL) {
655 if (append) {
656 new_header->sip_hdr_prev = header;
657 if (sip_msg->sip_msg_headers_end == header) {
658 sip_msg->sip_msg_headers_end = new_header;
659 new_header->sip_hdr_next = NULL;
660 } else {
661 header->sip_hdr_next->sip_hdr_prev = new_header;
662 new_header->sip_hdr_next = header->sip_hdr_next;
664 header->sip_hdr_next = new_header;
665 } else {
666 new_header->sip_hdr_next = header;
667 if (sip_msg->sip_msg_headers_start == header) {
668 sip_msg->sip_msg_headers_start = new_header;
669 new_header->sip_hdr_prev = NULL;
670 } else {
671 header->sip_hdr_prev->sip_hdr_next = new_header;
672 new_header->sip_hdr_prev = header->sip_hdr_prev;
674 header->sip_hdr_prev = new_header;
676 } else {
677 if (append) {
678 if (sip_msg->sip_msg_headers_end != NULL) {
679 sip_msg->sip_msg_headers_end->sip_hdr_next =
680 new_header;
681 } else {
682 sip_msg->sip_msg_headers_start = new_header;
684 new_header->sip_hdr_prev =
685 sip_msg->sip_msg_headers_end;
686 new_header->sip_hdr_next = NULL;
687 sip_msg->sip_msg_headers_end = new_header;
688 } else {
689 if (sip_msg->sip_msg_headers_start != NULL) {
690 sip_msg->sip_msg_headers_start->sip_hdr_prev =
691 new_header;
692 } else {
693 sip_msg->sip_msg_headers_end = new_header;
695 new_header->sip_hdr_next =
696 sip_msg->sip_msg_headers_start;
697 new_header->sip_hdr_prev = NULL;
698 sip_msg->sip_msg_headers_start = new_header;
701 sip_msg->sip_msg_len += new_header->sip_hdr_end -
702 new_header->sip_hdr_start;
706 * Scan through the function table and return the entry for the given header
707 * type.
709 sip_header_function_t *
710 _sip_get_header_functions(sip_header_function_t *sip_header_function_table,
711 _sip_header_t *sip_header, char *header_name)
713 int len;
714 int i = 0;
716 if (sip_header == NULL && header_name == NULL)
717 return (NULL);
720 * If header_name is NULL we first have to locate the name
722 if (header_name == NULL) {
723 if (sip_skip_white_space(sip_header) != 0) {
724 return (NULL);
726 header_name = sip_header->sip_hdr_current;
727 if (sip_find_separator(sip_header, SIP_HCOLON, SIP_NUL,
728 SIP_NUL, B_FALSE) != 0) {
729 return (NULL);
731 len = sip_header->sip_hdr_current - header_name;
732 } else {
733 len = strlen(header_name);
736 if (len > 0) {
737 while (sip_header_function_table[i].header_name != NULL ||
738 sip_header_function_table[i].header_short_name != NULL) {
739 if (sip_header_function_table[i].header_name != NULL &&
740 len ==
741 strlen(sip_header_function_table[i].header_name)) {
742 if (strncasecmp(header_name,
743 sip_header_function_table[i].
744 header_name, len) == 0) {
745 break;
747 } else if (sip_header_function_table[i].
748 header_short_name != NULL && len ==
749 strlen(sip_header_function_table[i].
750 header_short_name)) {
751 if (strncasecmp(header_name,
752 sip_header_function_table[i].
753 header_short_name, len) == 0) {
754 break;
757 i++;
761 if (sip_header != NULL)
762 sip_header->sip_hdr_current = sip_header->sip_hdr_start;
763 if (sip_header_function_table[i].header_name == NULL)
764 return (NULL);
765 return (&sip_header_function_table[i]);
769 * Return the entry from the function table for the given header
771 sip_header_function_t *
772 sip_get_header_functions(_sip_header_t *sip_header, char *header_name)
774 sip_header_function_t *func;
775 sip_header_function_t *header_f_table = NULL;
777 if (sip_header_function_table_external != NULL) {
778 header_f_table = _sip_get_header_functions(
779 sip_header_function_table_external,
780 sip_header, header_name);
781 if (header_f_table != NULL)
782 return (header_f_table);
784 func = _sip_get_header_functions(sip_header_function_table, sip_header,
785 header_name);
786 return (func);
790 * Search for the header name passed in.
792 _sip_header_t *
793 sip_search_for_header(_sip_msg_t *sip_msg, char *header_name,
794 _sip_header_t *old_header)
796 int len = 0;
797 int full_len = 0;
798 int compact_len = 0;
799 _sip_header_t *header = NULL;
800 char *compact_name = NULL;
801 char *full_name = NULL;
802 sip_header_function_t *header_f_table = NULL;
804 if (sip_msg == NULL)
805 return (NULL);
806 #ifdef __solaris__
807 assert(mutex_held(&sip_msg->sip_msg_mutex));
808 #endif
810 if (header_name != NULL) {
811 header_f_table = sip_get_header_functions(NULL, header_name);
812 if (header_f_table != NULL) {
813 full_name = header_f_table->header_name;
814 compact_name = header_f_table->header_short_name;
815 if (full_name != NULL)
816 full_len = strlen(full_name);
817 if (compact_name != NULL)
818 compact_len = strlen(compact_name);
819 } else {
820 header_f_table = &sip_header_function_table[0];
821 full_name = header_name;
822 full_len = strlen(full_name);
826 if (old_header != NULL)
827 header = old_header->sip_hdr_next;
828 else
829 header = sip_msg->sip_msg_headers_start;
831 while (header != NULL) {
833 if (header->sip_header_state == SIP_HEADER_DELETED) {
834 header = header->sip_hdr_next;
835 continue;
838 if (compact_len == 0 && full_len == 0)
839 break;
841 header->sip_hdr_current = header->sip_hdr_start;
843 if (sip_skip_white_space(header)) {
844 header = header->sip_hdr_next;
845 continue;
848 len = header->sip_hdr_end - header->sip_hdr_current;
850 if (full_name != NULL && (full_len <= len) &&
851 strncasecmp(header->sip_hdr_current, full_name,
852 full_len) == 0) {
853 header->sip_hdr_current += full_len;
854 if (sip_skip_white_space(header)) {
855 header = header->sip_hdr_next;
856 continue;
859 if (*header->sip_hdr_current == SIP_HCOLON) {
860 header_name = full_name;
861 break;
865 if (compact_name != NULL && (compact_len <= len) &&
866 strncasecmp(header->sip_hdr_current, compact_name,
867 compact_len) == 0) {
868 header->sip_hdr_current += compact_len;
869 if (sip_skip_white_space(header)) {
870 header = header->sip_hdr_next;
871 continue;
873 if (*header->sip_hdr_current == SIP_HCOLON) {
874 header_name = compact_name;
875 break;
878 header = header->sip_hdr_next;
881 if (header != NULL) {
882 header->sip_hdr_current = header->sip_hdr_start;
883 if (header_f_table == NULL) {
884 header_f_table =
885 sip_get_header_functions(header, header_name);
886 if (header_f_table == NULL)
887 header_f_table = &sip_header_function_table[0];
890 header->sip_header_functions = header_f_table;
892 return (header);
896 * Return the start line as a string. Caller frees string
898 char *
899 _sip_startline_to_str(_sip_msg_t *sip_msg, int *error)
901 char *slstr;
902 int len;
904 if (error != NULL)
905 *error = 0;
907 if (sip_msg == NULL || sip_msg->sip_msg_start_line == NULL) {
908 if (error != NULL)
909 *error = EINVAL;
910 return (NULL);
912 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
913 len = sip_msg->sip_msg_start_line->sip_hdr_end -
914 sip_msg->sip_msg_start_line->sip_hdr_start - 2;
915 if ((slstr = malloc(len + 1)) == NULL) {
916 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
917 if (error != NULL)
918 *error = ENOMEM;
919 return (NULL);
921 (void) strncpy(slstr, sip_msg->sip_msg_start_line->sip_hdr_start, len);
922 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
923 slstr[len] = SIP_NUL;
924 return (slstr);
928 * Return the given header as a string. Caller frees string
930 char *
931 sip_hdr_to_str(sip_header_t sip_header, int *error)
933 char *hdrstr;
934 char *tmpptr;
935 _sip_header_t *_sip_header;
936 int len;
938 if (error != NULL)
939 *error = 0;
941 if (sip_header == NULL) {
942 if (error != NULL)
943 *error = EINVAL;
944 return (NULL);
946 _sip_header = (_sip_header_t *)sip_header;
947 if (_sip_header->sip_header_state == SIP_HEADER_DELETED) {
948 if (_sip_header->sip_hdr_sipmsg != NULL) {
949 (void) pthread_mutex_unlock(
950 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
952 if (error != NULL)
953 *error = EINVAL;
954 return (NULL);
956 if (_sip_header->sip_hdr_sipmsg != NULL) {
957 (void) pthread_mutex_lock(
958 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
960 len = _sip_header->sip_hdr_end - _sip_header->sip_hdr_start;
961 hdrstr = malloc(len);
962 if (hdrstr == NULL) {
963 if (_sip_header->sip_hdr_sipmsg != NULL) {
964 (void) pthread_mutex_unlock(
965 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
967 if (error != NULL)
968 *error = ENOMEM;
969 return (NULL);
971 if (_sip_header->sip_header_state == SIP_HEADER_DELETED_VAL) {
972 len = sip_copy_values(hdrstr, _sip_header);
973 } else {
974 (void) strncpy(hdrstr, _sip_header->sip_hdr_start, len);
976 if (_sip_header->sip_hdr_sipmsg != NULL) {
977 (void) pthread_mutex_unlock(
978 &_sip_header->sip_hdr_sipmsg->sip_msg_mutex);
980 tmpptr = hdrstr + len;
981 while (*tmpptr-- != '\n') {
982 if (tmpptr == _sip_header->sip_hdr_start) {
983 free(hdrstr);
984 if (error != NULL)
985 *error = EINVAL;
986 return (NULL);
989 *tmpptr = SIP_NUL;
990 return (hdrstr);
994 * Given a param list find the named parameter.
995 * Returns a pointer to the value or NULL.
997 sip_param_t *
998 sip_get_param_from_list(sip_param_t *param_list, char *param_name)
1000 while (param_list != NULL) {
1001 if (param_list->param_name.sip_str_len == strlen(param_name) &&
1002 strncasecmp(param_list->param_name.sip_str_ptr, param_name,
1003 strlen(param_name)) == 0) {
1004 return (param_list);
1006 param_list = param_list->param_next;
1008 return (NULL);