#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <pthread.h>
#include <strings.h>
#include <stdlib.h>
#include <sip.h>
#include "sip_msg.h"
#include "sip_miscdefs.h"
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);
}
static char *
sip_int_to_str(int i)
{
int count;
int t;
int x;
char *str;
if (i < 0)
return (NULL);
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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, 0);
return (ret);
}
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);
}
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);
}
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, 0);
return (ret);
}
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, 0);
return (ret);
}
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, 0);
return (ret);
}
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);
}
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);
}
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, 0);
return (r);
}
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);
}
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);
}
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, 0);
return (ret);
}
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,
0);
}
return (ret);
}
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, 0);
return (ret);
}
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));
}
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, 0);
return (ret);
}
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, 0);
return (ret);
}
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);
}
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, 0);
return (ret);
}
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, 0);
}
return (ret);
}
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,
0);
}
return (ret);
}
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, 0);
} else {
ret = sip_add_2strs_to_msg(sip_msg, SIP_TIMESTAMP, time,
B_FALSE, delay, NULL, ' ');
}
return (ret);
}
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, 0);
return (ret);
}
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, 0);
return (r);
}
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] == '\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);
}
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);
}
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, 0));
}
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));
}
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));
}
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));
}
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, 0));
}
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));
}
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));
}
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, 0));
}
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));
}
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, 0);
if (allocd)
free(callid);
return (ret);
}
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);
}
_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);
}
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);
}
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));
}
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));
}
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);
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}