diff options
Diffstat (limited to 'usr/src/lib/libsip/common/sip_add_hdrs.c')
-rw-r--r-- | usr/src/lib/libsip/common/sip_add_hdrs.c | 1594 |
1 files changed, 1594 insertions, 0 deletions
diff --git a/usr/src/lib/libsip/common/sip_add_hdrs.c b/usr/src/lib/libsip/common/sip_add_hdrs.c new file mode 100644 index 0000000000..3b696fd60a --- /dev/null +++ b/usr/src/lib/libsip/common/sip_add_hdrs.c @@ -0,0 +1,1594 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "sip_parse_uri.h" +#include "sip_msg.h" +#include "sip_miscdefs.h" +#include "sip_parse_generic.h" + +/* + * Returns number of digits in the given int + */ +static int +sip_num_of_digits(int num) +{ + int num_of_bytes = 0; + + do { + num_of_bytes += 1; + num = num / 10; + } while (num > 0); + return (num_of_bytes); +} + +/* + * Return the int as a string + */ +static char * +sip_int_to_str(int i) +{ + int count; + int t; + int x; + char *str; + + if (i < 0) + return (NULL); + /* + * the following two loops convert int i to str + */ + count = 1; + t = i; + while ((t = t / 10) != 0) { + count++; + } + + str = calloc(1, sizeof (char) * count + 1); + if (str == NULL) + return (NULL); + t = i; + for (x = 0; x < count; x++) { + int a; + a = t % 10; + str[count - 1 - x] = a + '0'; + t = t / 10; + } + str[count] = '\0'; + return (str); +} + +/* + * Add quotes to the give str and return the quoted string + */ +static char * +sip_add_aquot_to_str(char *str, boolean_t *alloc) +{ + char *new_str; + char *tmp = str; + int size; + + while (isspace(*tmp)) + tmp++; + + *alloc = B_FALSE; + if (*tmp != SIP_LAQUOT) { + size = strlen(str) + 2 * sizeof (char); + new_str = calloc(1, size + 1); + if (new_str == NULL) + return (NULL); + new_str[0] = SIP_LAQUOT; + new_str[1] = '\0'; + (void) strncat(new_str, str, strlen(str)); + (void) strncat(new_str, ">", 1); + new_str[size] = '\0'; + *alloc = B_TRUE; + return (new_str); + } + + return (str); +} + +/* + * Add an empty header + */ +static int +sip_add_empty_hdr(sip_msg_t sip_msg, char *hdr_name) +{ + _sip_header_t *new_header; + int header_size; + _sip_msg_t *_sip_msg; + int csize = sizeof (char); + + if (sip_msg == NULL || hdr_name == NULL) + return (EINVAL); + _sip_msg = (_sip_msg_t *)sip_msg; + (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); + if (_sip_msg->sip_msg_cannot_be_modified) { + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + return (ENOTSUP); + } + + header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize; + + new_header = sip_new_header(header_size); + if (new_header == NULL) { + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + return (ENOMEM); + } + + (void) snprintf(new_header->sip_hdr_start, header_size + 1, + "%s %c", hdr_name, SIP_HCOLON); + + _sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, hdr_name); + if (_sip_msg->sip_msg_buf != NULL) + _sip_msg->sip_msg_modified = B_TRUE; + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + + return (0); +} + +/* + * Generic function to add a header with two strings to message + */ +static int +sip_add_2strs_to_msg(sip_msg_t sip_msg, char *hdr_name, char *str1, + boolean_t qstr1, char *str2, char *plist, char sep) +{ + _sip_header_t *new_header; + int header_size; + _sip_msg_t *_sip_msg; + int csize = sizeof (char); + + if (sip_msg == NULL || str1 == NULL || str2 == NULL || + (str1 != NULL && str1[0] == '\0') || + (str2 != NULL && str2[0] == '\0')) { + return (EINVAL); + } + _sip_msg = (_sip_msg_t *)sip_msg; + (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); + if (_sip_msg->sip_msg_cannot_be_modified) { + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + return (ENOTSUP); + } + + if (plist == NULL) { + header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize + + SIP_SPACE_LEN + strlen(str1) + csize + strlen(str2) + + strlen(SIP_CRLF); + } else { + header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize + + SIP_SPACE_LEN + strlen(str1) + csize + strlen(str2) + + csize + strlen(plist) + strlen(SIP_CRLF); + } + if (qstr1) + header_size += 2 * sizeof (char); + + new_header = sip_new_header(header_size); + if (new_header == NULL) { + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + return (ENOMEM); + } + + if (plist == NULL) { + if (qstr1) { + (void) snprintf(new_header->sip_hdr_start, + header_size + 1, "%s %c \"%s\"%c%s%s", + hdr_name, SIP_HCOLON, str1, sep, str2, SIP_CRLF); + } else { + (void) snprintf(new_header->sip_hdr_start, + header_size + 1, "%s %c %s%c%s%s", + hdr_name, SIP_HCOLON, str1, sep, str2, SIP_CRLF); + } + } else { + if (qstr1) { + (void) snprintf(new_header->sip_hdr_start, + header_size + 1, + "%s %c \"%s\"%c%s%c%s%s", hdr_name, SIP_HCOLON, + str1, sep, str2, SIP_SEMI, plist, SIP_CRLF); + } else { + (void) snprintf(new_header->sip_hdr_start, + header_size + 1, "%s %c %s%c%s%c%s%s", + hdr_name, SIP_HCOLON, str1, sep, str2, SIP_SEMI, + plist, SIP_CRLF); + } + } + _sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL); + if (_sip_msg->sip_msg_buf != NULL) + _sip_msg->sip_msg_modified = B_TRUE; + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + + return (0); +} + +/* + * Generic function to add a header with a string to message + */ +static int +sip_add_str_to_msg(sip_msg_t sip_msg, char *hdr_name, char *str, char *plist, + char param_sep) +{ + _sip_header_t *new_header; + int header_size; + _sip_msg_t *_sip_msg; + int csize = sizeof (char); + + if (sip_msg == NULL || str == NULL || (str != NULL && str[0] == '\0')) + return (EINVAL); + _sip_msg = (_sip_msg_t *)sip_msg; + (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); + if (_sip_msg->sip_msg_cannot_be_modified) { + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + return (ENOTSUP); + } + + if (plist == NULL) { + header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize + + SIP_SPACE_LEN + + strlen(str) + strlen(SIP_CRLF); + } else { + header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize + + SIP_SPACE_LEN + + strlen(str) + csize + strlen(plist) + + strlen(SIP_CRLF); + } + + new_header = sip_new_header(header_size); + if (new_header == NULL) { + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + return (ENOMEM); + } + if (plist == NULL) { + (void) snprintf(new_header->sip_hdr_start, header_size + 1, + "%s %c %s%s", hdr_name, SIP_HCOLON, str, SIP_CRLF); + } else { + (void) snprintf(new_header->sip_hdr_start, header_size + 1, + "%s %c %s%c%s%s", hdr_name, SIP_HCOLON, str, param_sep, + plist, SIP_CRLF); + } + _sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL); + if (_sip_msg->sip_msg_buf != NULL) + _sip_msg->sip_msg_modified = B_TRUE; + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + + return (0); +} + +/* + * Add an header with an int to sip_msg + */ +static int +sip_add_int_to_msg(sip_msg_t sip_msg, char *hdr_name, int i, char *plist) +{ + _sip_header_t *new_header; + int header_size; + _sip_msg_t *_sip_msg; + char *digit_str; + int csize = sizeof (char); + + if (sip_msg == NULL || (hdr_name == NULL)) + return (EINVAL); + _sip_msg = (_sip_msg_t *)sip_msg; + (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); + if (_sip_msg->sip_msg_cannot_be_modified) { + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + return (ENOTSUP); + } + + /* + * the following two loops convert int i to str + */ + digit_str = sip_int_to_str(i); + if (digit_str == NULL) + return (EINVAL); + + if (plist == NULL) { + header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize + + SIP_SPACE_LEN + strlen(digit_str) + strlen(SIP_CRLF); + } else { + header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize + + SIP_SPACE_LEN + strlen(digit_str) + csize + + strlen(plist) + strlen(SIP_CRLF); + } + + new_header = sip_new_header(header_size); + if (new_header == NULL) { + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + free(digit_str); + return (ENOMEM); + } + + if (plist == NULL) { + (void) snprintf(new_header->sip_hdr_start, header_size + 1, + "%s %c %s%s", hdr_name, SIP_HCOLON, digit_str, SIP_CRLF); + } else { + (void) snprintf(new_header->sip_hdr_start, header_size + 1, + "%s %c %s%c%s%s", hdr_name, SIP_HCOLON, digit_str, + SIP_SEMI, plist, SIP_CRLF); + } + free(digit_str); + _sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL); + if (_sip_msg->sip_msg_buf != NULL) + _sip_msg->sip_msg_modified = B_TRUE; + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + + return (0); +} + +/* + * Add a header with an int and string to sip_msg + */ +static int +sip_add_intstr_to_msg(sip_msg_t sip_msg, char *hdr_name, int i, char *s, + char *plist) +{ + _sip_header_t *new_header; + int header_size; + _sip_msg_t *_sip_msg; + char *digit_str; + int csize = sizeof (char); + + if (sip_msg == NULL || (hdr_name == NULL)) + return (EINVAL); + _sip_msg = (_sip_msg_t *)sip_msg; + (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); + if (_sip_msg->sip_msg_cannot_be_modified) { + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + return (ENOTSUP); + } + + /* + * the following two loops convert int i to str + */ + digit_str = sip_int_to_str(i); + if (digit_str == NULL) { + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + return (EINVAL); + } + if (plist == NULL) { + header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize + + SIP_SPACE_LEN + strlen(digit_str) + csize + strlen(s) + + strlen(SIP_CRLF); + } else { + header_size = strlen(hdr_name) + SIP_SPACE_LEN + csize + + SIP_SPACE_LEN + strlen(digit_str) + csize + strlen(s) + + csize + strlen(plist) + strlen(SIP_CRLF); + } + + new_header = sip_new_header(header_size); + if (new_header == NULL) { + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + free(digit_str); + return (ENOMEM); + } + + if (plist == NULL) { + (void) snprintf(new_header->sip_hdr_start, header_size + 1, + "%s %c %s %s%s", hdr_name, SIP_HCOLON, digit_str, s, + SIP_CRLF); + } else { + (void) snprintf(new_header->sip_hdr_start, header_size + 1, + "%s %c %s %s%c%s%s", hdr_name, SIP_HCOLON, digit_str, + s, SIP_SEMI, plist, SIP_CRLF); + } + free(digit_str); + _sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL); + if (_sip_msg->sip_msg_buf != NULL) + _sip_msg->sip_msg_modified = B_TRUE; + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + + return (0); +} + +/* + * Generic function to add Contact, From, To, Route or Record-Route header + */ +static int +sip_add_name_aspec(sip_msg_t sip_msg, char *display_name, char *uri, + char *tags, boolean_t add_aquot, char *header_name, char *params) +{ + char *t = uri; + boolean_t qalloc = B_FALSE; + boolean_t palloc = B_FALSE; + int r; + + if (sip_msg == NULL || uri == NULL || header_name == NULL) + return (EINVAL); + if (display_name != NULL && !add_aquot) + return (EINVAL); + if (add_aquot) { + t = sip_add_aquot_to_str(uri, &qalloc); + if (t == NULL) + return (ENOMEM); + } + if (tags != NULL) { + int plen; + + if (params != NULL) + return (EINVAL); + + plen = strlen(SIP_TAG) + strlen(tags) + 1; + params = malloc(plen); + if (params == NULL) + return (ENOMEM); + (void) snprintf(params, plen, "%s%s", SIP_TAG, tags); + params[plen - 1] = '\0'; + palloc = B_TRUE; + } + if (display_name == NULL) { + r = sip_add_2strs_to_msg(sip_msg, header_name, " ", B_FALSE, + t, params, SIP_SP); + } else { + r = sip_add_2strs_to_msg(sip_msg, header_name, display_name, + B_TRUE, t, params, SIP_SP); + } + if (qalloc) + free(t); + if (palloc) + free(params); + return (r); +} + +/* + * Accept = "Accept" ":" (media-range [ accept-params ]) + * media-range = ( "X/X" | (type "/" "*") | (type "/" subtype))*(";" parameter) + * accept-params = ";" "q" "=" qvalue *(accept-extension) + * accept-extension = ";" token [ "=" (token | quoted-str) + * + * function take two char ptrs - type and subtype - if any of them is NULL + * the corresponding value will be set to "*" in header + */ +int +sip_add_accept(sip_msg_t sip_msg, char *type, char *subtype, char *m_par, + char *a_par) +{ + int ret; + char *plist; + int size; + boolean_t alloc = B_FALSE; + + if (type == NULL && subtype == NULL) { + ret = sip_add_empty_hdr(sip_msg, SIP_ACCEPT); + return (ret); + } + + if ((m_par != NULL) && (a_par != NULL)) { + size = strlen(m_par) + strlen(a_par) + 2 * sizeof (char); + plist = calloc(1, size * sizeof (char)); + (void) strncpy(plist, m_par, strlen(m_par)); + (void) strncat(plist, ";", 1); + (void) strncat(plist, a_par, strlen(a_par)); + alloc = B_TRUE; + } else if (m_par != NULL) { + plist = m_par; + } else + plist = a_par; + + if ((type != NULL) && (subtype != NULL)) { + ret = sip_add_2strs_to_msg(sip_msg, SIP_ACCEPT, type, B_FALSE, + subtype, plist, SIP_SLASH); + } else if (type != NULL) { + ret = sip_add_2strs_to_msg(sip_msg, SIP_ACCEPT, type, B_FALSE, + "*", plist, SIP_SLASH); + } else { + ret = EINVAL; + } + + if (alloc == B_TRUE) + free(plist); + + return (ret); +} + + +/* + * Accept-Encoding = "Accept-Encoding" ":" 1#(codings [ ";" "q" "=" qval]) + * codings = ( content-coding | "*" ) + * content-coding = token + * + * function take one char ptr, if NULL value will be set to "*" + */ +int +sip_add_accept_enc(sip_msg_t sip_msg, char *code, char *plist) +{ + int ret; + + if (code == NULL) { + ret = sip_add_str_to_msg(sip_msg, SIP_ACCEPT_ENCODE, "*", plist, + SIP_SEMI); + } else { + ret = sip_add_str_to_msg(sip_msg, SIP_ACCEPT_ENCODE, code, + plist, SIP_SEMI); + } + return (ret); +} + +/* + * Accept-Language = "Accept-Language" ":" 1#( language-range [ ";" "q""=" val]) + * language-range = ( ( 1*8ALPHA *("-" 1*8ALPHA))|"*") + */ +int +sip_add_accept_lang(sip_msg_t sip_msg, char *lang, char *plist) +{ + int ret; + + if (lang == NULL) { + ret = sip_add_empty_hdr(sip_msg, SIP_ACCEPT_LANG); + return (ret); + } + ret = sip_add_str_to_msg(sip_msg, SIP_ACCEPT_LANG, lang, plist, + SIP_SEMI); + return (ret); +} + +/* + * Alert-Info = "Alert-Info" ":" "<" URI ">" + */ +int +sip_add_alert_info(sip_msg_t sip_msg, char *alert, char *plist) +{ + int ret; + char *tmp; + boolean_t alloc; + + if (alert == NULL) + return (EINVAL); + tmp = sip_add_aquot_to_str(alert, &alloc); + if (tmp == NULL) + return (ENOMEM); + ret = sip_add_str_to_msg(sip_msg, SIP_ALERT_INFO, tmp, plist, SIP_SEMI); + if (alloc) + free(tmp); + return (ret); +} + +/* + * Allow = "Allow" ":" method-name1[, method-name2..] + * method-name = "INVITE" | "ACK" | "OPTIONS" | "CANCEL" | "BYE" + */ +int +sip_add_allow(sip_msg_t sip_msg, sip_method_t method) +{ + int ret; + + if (method == 0 || method >= MAX_SIP_METHODS) + return (EINVAL); + ret = sip_add_str_to_msg(sip_msg, SIP_ALLOW, sip_methods[method].name, + NULL, (char)NULL); + return (ret); +} + +/* + * Call-Info = "Call-Info" HCOLON info *(COMMA info) + * info = LAQUOT absoluteURI RAQUOT *( SEMI info-param) + * info-param = ( "purpose" EQUAL ( "icon" / "info" + * / "card" / token ) ) / generic-param + */ +int +sip_add_call_info(sip_msg_t sip_msg, char *uri, char *plist) +{ + char *tmp; + boolean_t alloc; + int r; + + if (uri == NULL) + return (EINVAL); + tmp = sip_add_aquot_to_str(uri, &alloc); + if (tmp == NULL) + return (ENOMEM); + r = sip_add_str_to_msg(sip_msg, SIP_CALL_INFO, tmp, plist, SIP_SEMI); + if (alloc) + free(tmp); + return (r); +} + +/* + * Content-Disposition = "Content-Disposition" HCOLON + * disp-type *( SEMI disp-param ) + * disp-type = "render" / "session" / "icon" / "alert" + * / disp-extension-token + * disp-param = handling-param / generic-param + * handling-param = "handling" EQUAL + * ( "optional" / "required" + * / other-handling ) + * other-handling = token + * disp-extension-token = token + */ +int +sip_add_content_disp(sip_msg_t sip_msg, char *dis_type, char *plist) +{ + int ret; + + if (dis_type == NULL) + return (EINVAL); + + ret = sip_add_str_to_msg(sip_msg, SIP_CONTENT_DIS, dis_type, plist, + SIP_SEMI); + return (ret); +} + +/* + * Content-Encoding = ( "Content-Encoding" / "e" ) HCOLON + * content-coding *(COMMA content-coding) + * content-coding = token + */ +int +sip_add_content_enc(sip_msg_t sip_msg, char *code) +{ + int ret; + + if (code == NULL) + return (EINVAL); + + ret = sip_add_str_to_msg(sip_msg, SIP_CONTENT_ENCODE, code, NULL, + (char)NULL); + return (ret); +} + +/* + * Content-Language = "Content-Language" HCOLON + * language-tag *(COMMA language-tag) + * language-tag = primary-tag *( "-" subtag ) + * primary-tag = 1*8ALPHA + * subtag = 1*8ALPHA + */ +int +sip_add_content_lang(sip_msg_t sip_msg, char *lang) +{ + int ret; + + if (lang == NULL) + return (EINVAL); + ret = sip_add_str_to_msg(sip_msg, SIP_CONTENT_LANG, lang, NULL, + (char)NULL); + return (ret); +} + +/* + * Date = "Date" HCOLON SIP-date + * SIP-date = rfc1123-date + * rfc1123-date = wkday "," SP date1 SP time SP "GMT" + * date1 = 2DIGIT SP month SP 4DIGIT + * ; day month year (e.g., 02 Jun 1982) + * time = 2DIGIT ":" 2DIGIT ":" 2DIGIT + * ; 00:00:00 - 23:59:59 + * wkday = "Mon" / "Tue" / "Wed" + * / "Thu" / "Fri" / "Sat" / "Sun" + * month = "Jan" / "Feb" / "Mar" / "Apr" + * / "May" / "Jun" / "Jul" / "Aug" + * / "Sep" / "Oct" / "Nov" / "Dec" + */ +int +sip_add_date(sip_msg_t sip_msg, char *date) +{ + int ret; + + if (date == NULL) + return (EINVAL); + ret = sip_add_str_to_msg(sip_msg, SIP_DATE, date, NULL, (char)NULL); + return (ret); +} + +/* + * Error-Info = "Error-Info" HCOLON error-uri *(COMMA error-uri) + * error-uri = LAQUOT absoluteURI RAQUOT *( SEMI generic-param ) + */ +int +sip_add_error_info(sip_msg_t sip_msg, char *uri, char *plist) +{ + char *tmp; + boolean_t alloc; + int r; + + if (uri == NULL) + return (EINVAL); + tmp = sip_add_aquot_to_str(uri, &alloc); + if (tmp == NULL) + return (EINVAL); + + r = sip_add_str_to_msg(sip_msg, SIP_ERROR_INFO, tmp, plist, SIP_SEMI); + if (alloc) + free(tmp); + return (r); +} + +/* + * Expires = "Expires" HCOLON delta-seconds + * delta-seconds = 1*DIGIT + */ +int +sip_add_expires(sip_msg_t sip_msg, int secs) +{ + int ret; + + if (sip_msg == NULL || (int)secs < 0) + return (EINVAL); + + ret = sip_add_int_to_msg(sip_msg, SIP_EXPIRE, secs, NULL); + return (ret); +} + +/* + * In-Reply-To = "In-Reply-To" HCOLON callid *(COMMA callid) + * callid = word [ "@" word ] + */ +int +sip_add_in_reply_to(sip_msg_t sip_msg, char *reply_id) +{ + int r; + + if (reply_id == NULL) + return (EINVAL); + r = sip_add_str_to_msg(sip_msg, SIP_IN_REPLY_TO, reply_id, NULL, + (char)NULL); + return (r); +} + +/* + * RSeq = "RSeq" HCOLON response-num + */ +int +sip_add_rseq(sip_msg_t sip_msg, int resp_num) +{ + int ret; + + if (sip_msg == NULL || resp_num <= 0) + return (EINVAL); + ret = sip_add_int_to_msg(sip_msg, SIP_RSEQ, resp_num, NULL); + return (ret); +} + +/* + * Min-Expires = "Min-Expires" HCOLON delta-seconds + */ +int +sip_add_min_expires(sip_msg_t sip_msg, int secs) +{ + int ret; + + if (sip_msg == NULL || (int)secs < 0) + return (EINVAL); + ret = sip_add_int_to_msg(sip_msg, SIP_MIN_EXPIRE, secs, NULL); + return (ret); +} + +/* + * MIME-Version = "MIME-Version" HCOLON 1*DIGIT "." 1*DIGIT + */ +int +sip_add_mime_version(sip_msg_t sip_msg, char *version) +{ + int ret; + + if (version == NULL) + return (EINVAL); + ret = sip_add_str_to_msg(sip_msg, SIP_MIME_VERSION, version, NULL, + (char)NULL); + return (ret); +} + +/* + * Organization = "Organization" HCOLON [TEXT-UTF8-TRIM] + */ +int +sip_add_org(sip_msg_t sip_msg, char *org) +{ + int ret; + + if (org == NULL) { + ret = sip_add_empty_hdr(sip_msg, SIP_ORGANIZATION); + } else { + ret = sip_add_str_to_msg(sip_msg, SIP_ORGANIZATION, org, NULL, + (char)NULL); + } + return (ret); +} + +/* + * Priority = "Priority" HCOLON priority-value + * priority-value = "emergency" / "urgent" / "normal" + * / "non-urgent" / other-priority + * other-priority = token + */ +int +sip_add_priority(sip_msg_t sip_msg, char *prio) +{ + int ret; + + if (prio == NULL) + return (EINVAL); + ret = sip_add_str_to_msg(sip_msg, SIP_PRIORITY, prio, NULL, (char)NULL); + + return (ret); +} + +/* + * Reply-To = "Reply-To" HCOLON rplyto-spec + * rplyto-spec = ( name-addr / addr-spec ) + * *( SEMI rplyto-param ) + * rplyto-param = generic-param + */ +int +sip_add_reply_to(sip_msg_t sip_msg, char *uname, char *addr, char *plist, + boolean_t add_aquot) +{ + return (sip_add_name_aspec(sip_msg, uname, addr, NULL, add_aquot, + SIP_REPLYTO, plist)); +} + + +/* + * Privacy-hdr = "Privacy" HCOLON priv-value *(";" priv-value) + * priv-value = "header" / "session" / "user" / "none" / "critical" + * / token + */ +int +sip_add_privacy(sip_msg_t sip_msg, char *priv_val) +{ + int ret; + + if (priv_val == NULL) + return (EINVAL); + ret = sip_add_str_to_msg(sip_msg, SIP_PRIVACY, priv_val, NULL, + (char)NULL); + return (ret); +} + +/* + * Require = "Require" HCOLON option-tag *(COMMA option-tag) + * option-tag = token + */ +int +sip_add_require(sip_msg_t sip_msg, char *req) +{ + int ret; + + if (req == NULL) + return (EINVAL); + ret = sip_add_str_to_msg(sip_msg, SIP_REQUIRE, req, NULL, (char)NULL); + return (ret); +} + +/* + * Retry-After = "Retry-After" HCOLON delta-seconds + * [ comment ] *( SEMI retry-param ) + * retry-param = ("duration" EQUAL delta-seconds) + * / generic-param + */ +int +sip_add_retry_after(sip_msg_t sip_msg, int secs, char *cmt, char *plist) +{ + int r; + + if (secs <= 0) + return (EINVAL); + + if (cmt == NULL) { + r = sip_add_int_to_msg(sip_msg, SIP_RETRY_AFTER, secs, plist); + return (r); + } + + r = sip_add_intstr_to_msg(sip_msg, SIP_RETRY_AFTER, secs, cmt, plist); + return (r); +} + +/* + * Server = "Server" HCOLON server-val *(LWS server-val) + * server-val = product / comment + * product = token [SLASH product-version] + * product-version = token + */ +int +sip_add_server(sip_msg_t sip_msg, char *svr) +{ + int ret; + + if (svr == NULL) + return (EINVAL); + ret = sip_add_str_to_msg(sip_msg, SIP_SERVER, svr, NULL, (char)NULL); + return (ret); +} + +/* + * Subject = ( "Subject" / "s" ) HCOLON [TEXT-UTF8-TRIM] + */ +int +sip_add_subject(sip_msg_t sip_msg, char *subject) +{ + int ret; + + if (subject == NULL) { + ret = sip_add_empty_hdr(sip_msg, SIP_SUBJECT); + } else { + ret = sip_add_str_to_msg(sip_msg, SIP_SUBJECT, subject, NULL, + (char)NULL); + } + return (ret); +} + +/* + * Supported = ( "Supported" / "k" ) HCOLON + * [option-tag *(COMMA option-tag)] + */ +int +sip_add_supported(sip_msg_t sip_msg, char *support) +{ + int ret; + + if (support == NULL) { + ret = sip_add_empty_hdr(sip_msg, SIP_SUPPORT); + } else { + ret = sip_add_str_to_msg(sip_msg, SIP_SUPPORT, support, NULL, + (char)NULL); + } + return (ret); +} + +/* + * Timestamp = "Timestamp" HCOLON 1*(DIGIT) + * [ "." *(DIGIT) ] [ LWS delay ] + * delay = *(DIGIT) [ "." *(DIGIT) ] + */ +int +sip_add_tstamp(sip_msg_t sip_msg, char *time, char *delay) +{ + int ret; + + if (delay == NULL) { + ret = sip_add_str_to_msg(sip_msg, SIP_TIMESTAMP, time, NULL, + (char)NULL); + } else { + ret = sip_add_2strs_to_msg(sip_msg, SIP_TIMESTAMP, time, + B_FALSE, delay, NULL, ' '); + } + return (ret); +} + +/* + * Unsupported = "Unsupported" HCOLON option-tag *(COMMA option-tag) + */ +int +sip_add_unsupported(sip_msg_t sip_msg, char *unsupport) +{ + int ret; + + if (unsupport == NULL) + return (EINVAL); + ret = sip_add_str_to_msg(sip_msg, SIP_UNSUPPORT, unsupport, NULL, + (char)NULL); + return (ret); +} + +/* + * User-Agent = "User-Agent" HCOLON server-val *(LWS server-val) + */ +int +sip_add_user_agent(sip_msg_t sip_msg, char *usr) +{ + int r; + + if (usr == NULL) + return (EINVAL); + r = sip_add_str_to_msg(sip_msg, SIP_USER_AGENT, usr, NULL, (char)NULL); + return (r); +} + +/* + * Warning = "Warning" HCOLON warning-value *(COMMA warning-value) + * warning-value = warn-code SP warn-agent SP warn-text + * warn-code = 3DIGIT + * warn-agent = hostport / pseudonym + * ; the name or pseudonym of the server adding + * ; the Warning header, for use in debugging + * warn-text = quoted-string + * pseudonym = token + */ +int +sip_add_warning(sip_msg_t sip_msg, int code, char *addr, char *msg) +{ + _sip_header_t *new_header; + int header_size; + _sip_msg_t *_sip_msg; + char *hdr_name = SIP_WARNING; + + if (sip_msg == NULL || addr == NULL || msg == NULL || + addr[0] == '\0' || msg == '\0' || code < 100 || code > 999) { + return (EINVAL); + } + + _sip_msg = (_sip_msg_t *)sip_msg; + (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); + if (_sip_msg->sip_msg_cannot_be_modified) { + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + return (ENOTSUP); + } + + header_size = strlen(hdr_name) + SIP_SPACE_LEN + sizeof (char) + + SIP_SPACE_LEN + sip_num_of_digits(code) + SIP_SPACE_LEN + + strlen(addr) + SIP_SPACE_LEN + sizeof (char) + strlen(msg) + + sizeof (char) + strlen(SIP_CRLF); + + new_header = sip_new_header(header_size); + if (new_header == NULL) { + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + return (ENOMEM); + } + + (void) snprintf(new_header->sip_hdr_start, header_size + 1, + "%s %c %d %s \"%s\"%s", hdr_name, SIP_HCOLON, code, addr, + msg, SIP_CRLF); + _sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL); + if (_sip_msg->sip_msg_buf != NULL) + _sip_msg->sip_msg_modified = B_TRUE; + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + + return (0); +} + +/* + * RAck = "RAck" HCOLON response-num LWS CSeq-num LWS Method + * response-num = 1*DIGIT + * CSeq-num = 1*DIGIT + */ +int +sip_add_rack(sip_msg_t sip_msg, int resp_num, int cseq, sip_method_t method) +{ + _sip_header_t *new_header; + int header_size; + _sip_msg_t *_sip_msg; + char *hdr_name = SIP_RACK; + + if (sip_msg == NULL || resp_num <= 0 || cseq < 0 || method <= 0 || + method >= MAX_SIP_METHODS) { + return (EINVAL); + } + + _sip_msg = (_sip_msg_t *)sip_msg; + (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); + if (_sip_msg->sip_msg_cannot_be_modified) { + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + return (ENOTSUP); + } + + header_size = strlen(hdr_name) + SIP_SPACE_LEN + sizeof (char) + + SIP_SPACE_LEN + sip_num_of_digits(resp_num) + SIP_SPACE_LEN + + sip_num_of_digits(cseq) + SIP_SPACE_LEN + + strlen(sip_methods[method].name) + strlen(SIP_CRLF); + + new_header = sip_new_header(header_size); + if (new_header == NULL) { + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + return (ENOMEM); + } + + (void) snprintf(new_header->sip_hdr_start, header_size + 1, + "%s %c %d %d %s%s", hdr_name, SIP_HCOLON, resp_num, cseq, + sip_methods[method].name, SIP_CRLF); + + _sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL); + if (_sip_msg->sip_msg_buf != NULL) + _sip_msg->sip_msg_modified = B_TRUE; + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + + return (0); + +} + +/* + * Allow-Events = ( "Allow-Events" / "u" ) HCOLON event-type + * *(COMMA event-type) + */ +int +sip_add_allow_events(sip_msg_t sip_msg, char *t_event) +{ + return (sip_add_str_to_msg(sip_msg, SIP_ALLOW_EVENTS, t_event, NULL, + (char)NULL)); +} + +/* + * Event = ( "Event" / "o" ) HCOLON event-type + * *( SEMI event-param ) + * event-type = event-package *( "." event-template ) + * event-package = token-nodot + * event-template = token-nodot + * token-nodot = 1*( alphanum / "-" / "!" / "%" / "*" + * / "_" / "+" / "`" / "'" / "~" ) + * event-param = generic-param / ( "id" EQUAL token ) + */ +int +sip_add_event(sip_msg_t sip_msg, char *t_event, char *plist) +{ + return (sip_add_str_to_msg(sip_msg, SIP_EVENT, t_event, plist, + SIP_SEMI)); +} + +/* + * Subscription-State = "Subscription-State" HCOLON substate-value + * *( SEMI subexp-params ) + * substate-value = "active" / "pending" / "terminated" + * / extension-substate + * extension-substate = token + * subexp-params = ("reason" EQUAL event-reason-value) + * / ("expires" EQUAL delta-seconds)* + * / ("retry-after" EQUAL delta-seconds) + * / generic-param + * event-reason-value = "deactivated" + * / "probation" + * / "rejected" + * / "timeout" + * / "giveup" + * / "noresource" + * / event-reason-extension + * event-reason-extension = token + */ +int +sip_add_substate(sip_msg_t sip_msg, char *sub, char *plist) +{ + return (sip_add_str_to_msg(sip_msg, SIP_SUBSCRIPTION_STATE, sub, plist, + SIP_SEMI)); +} + +/* + * Authorization = "Authorization" HCOLON credentials + * credentials = ("Digest" LWS digest-response) + * / other-response + * digest-response = dig-resp *(COMMA dig-resp) + * dig-resp = username / realm / nonce / digest-uri + * / dresponse / algorithm / cnonce + * / opaque / message-qop + * / nonce-count / auth-param + * username = "username" EQUAL username-value + * username-value = quoted-string + * digest-uri = "uri" EQUAL LDQUOT digest-uri-value RDQUOT + * digest-uri-value = rquest-uri ; Equal to request-uri as specified + * by HTTP/1.1 + * message-qop = "qop" EQUAL qop-value + * cnonce = "cnonce" EQUAL cnonce-value + * cnonce-value = nonce-value + * nonce-count = "nc" EQUAL nc-value + * nc-value = 8LHEX + * dresponse = "response" EQUAL request-digest + * request-digest = LDQUOT 32LHEX RDQUOT + * auth-param = auth-param-name EQUAL + * ( token / quoted-string ) + * auth-param-name = token + * other-response = auth-scheme LWS auth-param + * *(COMMA auth-param) + * auth-scheme = token + */ +int +sip_add_author(sip_msg_t sip_msg, char *scheme, char *param) +{ + return (sip_add_str_to_msg(sip_msg, SIP_AUTHOR, scheme, param, SIP_SP)); +} + +/* + * Authentication-Info = "Authentication-Info" HCOLON ainfo + * *(COMMA ainfo) + * ainfo = nextnonce / message-qop + * / response-auth / cnonce + * / nonce-count + * nextnonce = "nextnonce" EQUAL nonce-value + * response-auth = "rspauth" EQUAL response-digest + * response-digest = LDQUOT *LHEX RDQUOT + */ +int +sip_add_authen_info(sip_msg_t sip_msg, char *ainfo) +{ + return (sip_add_str_to_msg(sip_msg, SIP_AUTHEN_INFO, ainfo, NULL, + (char)NULL)); +} + +/* + * Proxy-Authenticate = "Proxy-Authenticate" HCOLON challenge + * challenge = ("Digest" LWS digest-cln *(COMMA digest-cln)) + * / other-challenge + * other-challenge = auth-scheme LWS auth-param + * *(COMMA auth-param) + * digest-cln = realm / domain / nonce + * / opaque / stale / algorithm + * / qop-options / auth-param + * realm = "realm" EQUAL realm-value + * realm-value = quoted-string + * domain = "domain" EQUAL LDQUOT URI + * *( 1*SP URI ) RDQUOT + * URI = absoluteURI / abs-path + * nonce = "nonce" EQUAL nonce-value + * nonce-value = quoted-string + * opaque = "opaque" EQUAL quoted-string + * stale = "stale" EQUAL ( "true" / "false" ) + * algorithm = "algorithm" EQUAL ( "MD5" / "MD5-sess" + * / token ) + * qop-options = "qop" EQUAL LDQUOT qop-value + * *("," qop-value) RDQUOT + * qop-value = "auth" / "auth-int" / token + */ +int +sip_add_proxy_authen(sip_msg_t sip_msg, char *pascheme, char *paparam) +{ + return (sip_add_str_to_msg(sip_msg, SIP_PROXY_AUTHEN, pascheme, paparam, + SIP_SP)); +} + +/* + * Proxy-Authorization = "Proxy-Authorization" HCOLON credentials + */ +int +sip_add_proxy_author(sip_msg_t sip_msg, char *paschem, char *paparam) +{ + return (sip_add_str_to_msg(sip_msg, SIP_PROXY_AUTHOR, paschem, paparam, + SIP_SP)); +} + +/* + * Proxy-Require = "Proxy-Require" HCOLON option-tag + * *(COMMA option-tag) + * option-tag = token + */ +int +sip_add_proxy_require(sip_msg_t sip_msg, char *opt) +{ + return (sip_add_str_to_msg(sip_msg, SIP_PROXY_REQ, opt, NULL, + (char)NULL)); +} + +/* + * WWW-Authenticate = "WWW-Authenticate" HCOLON challenge + * extension-header = header-name HCOLON header-value + * header-name = token + * header-value = *(TEXT-UTF8char / UTF8-CONT / LWS) + * message-body = *OCTET + */ +int +sip_add_www_authen(sip_msg_t sip_msg, char *wascheme, char *waparam) +{ + return (sip_add_str_to_msg(sip_msg, SIP_WWW_AUTHEN, wascheme, waparam, + SIP_SP)); +} + +/* + * Call-ID = ( "Call-ID" / "i" ) HCOLON callid + */ +int +sip_add_callid(sip_msg_t sip_msg, char *callid) +{ + int ret; + boolean_t allocd = B_FALSE; + + if (sip_msg == NULL || (callid != NULL && callid[0] == '\0')) + return (EINVAL); + if (callid == NULL) { + callid = (char *)sip_guid(); + if (callid == NULL) + return (ENOMEM); + allocd = B_TRUE; + } + ret = sip_add_str_to_msg(sip_msg, SIP_CALL_ID, callid, NULL, + (char)NULL); + if (allocd) + free(callid); + return (ret); +} + +/* + * CSeq = "CSeq" HCOLON 1*DIGIT LWS Method + */ +int +sip_add_cseq(sip_msg_t sip_msg, sip_method_t method, uint32_t cseq) +{ + int r; + + if (sip_msg == NULL || (int)cseq < 0 || method == 0 || + method >= MAX_SIP_METHODS) { + return (EINVAL); + } + r = sip_add_intstr_to_msg(sip_msg, SIP_CSEQ, cseq, + sip_methods[method].name, NULL); + return (r); +} + +/* + * Via = ( "Via" / "v" ) HCOLON via-parm *(COMMA via-parm) + * via-parm = sent-protocol LWS sent-by *( SEMI via-params ) + * via-params = via-ttl / via-maddr + * / via-received / via-branch + * / via-extension + * via-ttl = "ttl" EQUAL ttl + * via-maddr = "maddr" EQUAL host + * via-received = "received" EQUAL (IPv4address / IPv6address) + * via-branch = "branch" EQUAL token + * via-extension = generic-param + * sent-protocol = protocol-name SLASH protocol-version + * SLASH transport + * protocol-name = "SIP" / token + * protocol-version = token + * transport = "UDP" / "TCP" / "TLS" / "SCTP" + * / other-transport + * sent-by = host [ COLON port ] + * ttl = 1*3DIGIT ; 0 to 255 + */ +_sip_header_t * +sip_create_via_hdr(char *sent_protocol_transport, char *sent_by_host, + int sent_by_port, char *via_params) +{ + _sip_header_t *new_header; + int header_size; + int count; + + header_size = strlen(SIP_VIA) + SIP_SPACE_LEN + sizeof (char) + + SIP_SPACE_LEN + strlen(SIP_VERSION) + sizeof (char) + + strlen(sent_protocol_transport) + SIP_SPACE_LEN + + strlen(sent_by_host) + strlen(SIP_CRLF); + + if (sent_by_port > 0) { + header_size += SIP_SPACE_LEN + sizeof (char) + SIP_SPACE_LEN + + sip_num_of_digits(sent_by_port); + } + + if (via_params != NULL) { + header_size += SIP_SPACE_LEN + sizeof (char) + + strlen(via_params); + } + new_header = sip_new_header(header_size); + if (new_header->sip_hdr_start == NULL) + return (NULL); + count = snprintf(new_header->sip_hdr_current, header_size + 1, + "%s %c %s/%s %s", + SIP_VIA, SIP_HCOLON, SIP_VERSION, sent_protocol_transport, + sent_by_host); + new_header->sip_hdr_current += count; + header_size -= count; + + if (sent_by_port > 0) { + count = snprintf(new_header->sip_hdr_current, header_size + 1, + " %c %d", SIP_HCOLON, sent_by_port); + new_header->sip_hdr_current += count; + header_size -= count; + } + + if (via_params != NULL) { + count = snprintf(new_header->sip_hdr_current, header_size + 1, + " %c%s", SIP_SEMI, via_params); + new_header->sip_hdr_current += count; + header_size -= count; + } + + (void) snprintf(new_header->sip_hdr_current, header_size + 1, + "%s", SIP_CRLF); + return (new_header); +} + +/* + * There can be multiple via headers we always append the header. + * We expect the via params to be a semi-colon separated list of parameters. + * We will add a semi-clone, before adding the list to the header. + */ +int +sip_add_via(sip_msg_t sip_msg, char *sent_protocol_transport, + char *sent_by_host, int sent_by_port, char *via_params) +{ + _sip_header_t *new_header; + _sip_msg_t *_sip_msg; + + if (sip_msg == NULL || sent_protocol_transport == NULL || + sent_by_host == NULL || sent_by_port < 0) { + return (EINVAL); + } + + _sip_msg = (_sip_msg_t *)sip_msg; + (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); + if (_sip_msg->sip_msg_cannot_be_modified) { + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + return (ENOTSUP); + } + + new_header = sip_create_via_hdr(sent_protocol_transport, sent_by_host, + sent_by_port, via_params); + if (new_header == NULL) { + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + return (ENOMEM); + } + _sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL); + if (_sip_msg->sip_msg_buf != NULL) + _sip_msg->sip_msg_modified = B_TRUE; + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + return (0); +} + +/* + * Max-Forwards = "Max-Forwards" HCOLON 1*DIGIT + */ +int +sip_add_maxforward(sip_msg_t sip_msg, uint_t maxforward) +{ + if (sip_msg == NULL || (int)maxforward < 0) + return (EINVAL); + return (sip_add_int_to_msg(sip_msg, SIP_MAX_FORWARDS, maxforward, + NULL)); +} + +/* + * Content-Type = ( "Content-Type" / "c" ) HCOLON media-type + * media-type = m-type SLASH m-subtype *(SEMI m-parameter) + * m-type = discrete-type / composite-type + * discrete-type = "text" / "image" / "audio" / "video" + * / "application" / extension-token + * composite-type = "message" / "multipart" / extension-token + * extension-token = ietf-token / x-token + * ietf-token = token + * x-token = "x-" token + * m-subtype = extension-token / iana-token + * iana-token = token + * m-parameter = m-attribute EQUAL m-value + * m-attribute = token + * m-value = token / quoted-string + */ +int +sip_add_content_type(sip_msg_t sip_msg, char *type, char *subtype) +{ + if (sip_msg == NULL || type == NULL || subtype == NULL) + return (EINVAL); + return (sip_add_2strs_to_msg(sip_msg, SIP_CONTENT_TYPE, type, B_FALSE, + subtype, NULL, SIP_SLASH)); +} + +/* + * Content-Length = ( "Content-Length" / "l" ) HCOLON 1*DIGIT + */ +int +sip_add_content_length(_sip_msg_t *_sip_msg, int length) +{ + _sip_header_t *new_header; + int header_size; + + if (_sip_msg == NULL || length < 0) + return (EINVAL); + (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex); + if (_sip_msg->sip_msg_cannot_be_modified) { + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + return (ENOTSUP); + } + + header_size = strlen(SIP_CONTENT_LENGTH) + SIP_SPACE_LEN + + sizeof (char) + SIP_SPACE_LEN + sip_num_of_digits(length) + + strlen(SIP_CRLF) + strlen(SIP_CRLF); + + new_header = sip_new_header(header_size); + if (new_header == NULL) { + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + return (ENOMEM); + } + (void) snprintf(new_header->sip_hdr_start, header_size + 1, + "%s %c %u%s%s", SIP_CONTENT_LENGTH, SIP_HCOLON, length, + SIP_CRLF, SIP_CRLF); + + _sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, NULL); + if (_sip_msg->sip_msg_buf != NULL) + _sip_msg->sip_msg_modified = B_TRUE; + (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex); + return (0); +} + + +/* + * Contact = ("Contact" / "m" ) HCOLON + * ( STAR / (contact-param *(COMMA contact-param))) + * contact-param = (name-addr / addr-spec) *(SEMI contact-params) + * name-addr = [ display-name ] LAQUOT addr-spec RAQUOT + * addr-spec = SIP-URI / SIPS-URI / absoluteURI + * display-name = *(token LWS)/ quoted-string + * contact-params = c-p-q / c-p-expires + * / contact-extension + */ +int +sip_add_contact(sip_msg_t sip_msg, char *display_name, char *contact_uri, + boolean_t add_aquot, char *contact_params) +{ + return (sip_add_name_aspec(sip_msg, display_name, contact_uri, NULL, + add_aquot, SIP_CONTACT, contact_params)); +} + +/* + * From = ( "From" / "f" ) HCOLON from-spec + * from-spec = ( name-addr / addr-spec ) + * *( SEMI from-param ) + * from-param = tag-param / generic-param + * tag-param = "tag" EQUAL token + * + * Since there can be more than one tags, fromtags is a semi colon separated + * list of tags. + */ +int +sip_add_from(sip_msg_t sip_msg, char *display_name, char *from_uri, + char *fromtags, boolean_t add_aquot, char *from_params) +{ + return (sip_add_name_aspec(sip_msg, display_name, from_uri, fromtags, + add_aquot, SIP_FROM, from_params)); +} + +/* + * To = ( "To" / "t" ) HCOLON ( name-addr + * / addr-spec ) *( SEMI to-param ) + * to-param = tag-param / generic-param + */ +int +sip_add_to(sip_msg_t sip_msg, char *display_name, char *to_uri, + char *totags, boolean_t add_aquot, char *to_params) +{ + return (sip_add_name_aspec(sip_msg, display_name, to_uri, totags, + add_aquot, SIP_TO, to_params)); +} + +/* + * Route = "Route" HCOLON route-param *(COMMA route-param) + * route-param = name-addr *( SEMI rr-param ) + */ +int +sip_add_route(sip_msg_t sip_msg, char *display_name, char *uri, + char *route_params) +{ + return (sip_add_name_aspec(sip_msg, display_name, uri, NULL, B_TRUE, + SIP_ROUTE, route_params)); +} + +/* + * Record-Route = "Record-Route" HCOLON rec-route *(COMMA rec-route) + * rec-route = name-addr *( SEMI rr-param ) + * rr-param = generic-param + */ +int +sip_add_record_route(sip_msg_t sip_msg, char *display_name, char *uri, + char *route_params) +{ + return (sip_add_name_aspec(sip_msg, display_name, uri, NULL, B_TRUE, + SIP_RECORD_ROUTE, route_params)); +} + + +/* + * PAssertedID = "P-Asserted-Identity" HCOLON PAssertedID-value + * *(COMMA PAssertedID-value) + * PAssertedID-value = name-addr / addr-spec + */ +int +sip_add_passertedid(sip_msg_t sip_msg, char *display_name, char *addr, + boolean_t add_aquot) +{ + return (sip_add_name_aspec(sip_msg, display_name, addr, NULL, add_aquot, + SIP_PASSERTEDID, NULL)); +} + +/* + * PPreferredID = "P-Preferred-Identity" HCOLON PPreferredID-value + * *(COMMA PPreferredID-value) + * PPreferredID-value = name-addr / addr-spec + */ +int +sip_add_ppreferredid(sip_msg_t sip_msg, char *display_name, char *addr, + boolean_t add_aquot) +{ + return (sip_add_name_aspec(sip_msg, display_name, addr, NULL, add_aquot, + SIP_PPREFERREDID, NULL)); +} |