/*
* 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
* 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 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <pthread.h>
#include <sip.h>
#include "sip_msg.h"
#include "sip_miscdefs.h"
#include "sip_xaction.h"
#include "sip_dialog.h"
#include "sip_parse_generic.h"
const sip_dialog_t) = NULL;
NULL;
/*
* Defaults, overridden by configured values, if any
*/
/*
* list of sent-by values registered by the UA
*/
int sip_sent_by_count = 0;
/*
* Create and send an error response
*/
static void
{
if (sip_msg_resp == NULL) {
/*
* Message was too bad to even create a
* response. Just drop the messge.
*/
return;
}
/*
* We directly send it to the transport here.
*/
if (sip_adjust_msgbuf(sip_msg_resp) != 0) {
return;
}
}
/*
* Validate some of the common headers
*/
{
int err;
goto error;
goto error;
goto error;
goto error;
return (B_FALSE);
return (B_TRUE);
}
/*
* setup pointers to where the headers are.
*/
static int
{
char *msg;
char *end;
/*
* Skip while space.
*/
msg++;
else
return (EINVAL);
}
/*
* We consider Request and Response line as a header
*/
for (;;) {
/*
* Skip CRLF
*/
}
/*
* Start of a header.
* Check for empty line.
*/
/*
* empty line, start of content.
*/
break;
}
/*
* store start of header.
*/
if (sip_msg_header == NULL)
return (EINVAL);
} else {
/*
* Allocate first header structure.
*/
sizeof (_sip_header_t));
if (sip_msg_header == NULL)
return (EINVAL);
}
msg++;
}
/*
* We have reached the end without hitting the empty line.
*/
return (EINVAL);
}
return (EPROTO);
/*
* Move start line to be a separate line.
*/
return (EINVAL);
/*
* Deal with content.
*/
return (0);
}
/*
* The send interface to the sip stack. Used by upper layers.
*/
int
{
int ret = 0;
return (ret);
}
/*
* Send it statefully if:
* if stateful is set in 'flags' AND
* this is not an ACK request, if it is a request (should the upper
* layer set stateful in the latter case?, i.e is the check
* necessary here?)
*/
return (ret);
}
if (ret != 0) {
return (ret);
}
}
/*
* If the appln wants us to create the dialog, create a partial
* dialog at this stage, when we get the response, we will
* complete it.
*/
if (sip_manage_dialog) {
/*
* Dialog is in CONFIRMED state. If logging is enabled
* track the SIP message sent within a dialog.
*/
dialog->sip_dlg_msgcnt++;
sip_req_method == INVITE) {
(void) sip_dialog_add_new_contact(dialog,
_sip_msg);
}
}
}
/*
* if measure sip traffic is enabled, capture the measurements
* Is this the right place to measure or should I put this after
* the call to sip_stack_send()
*/
if (sip_msg_info->is_request) {
} else {
}
_sip_msg->sip_msg_len)) != 0) {
}
return (ret);
}
return (ret);
}
/*
* Given a sent-by value check if it is in the registered list. If no values
* have been registered, the check passes.
*/
static boolean_t
{
int count = 0;
(void) pthread_mutex_lock(&sip_sent_by_lock);
if (sip_sent_by == NULL) {
(void) pthread_mutex_unlock(&sip_sent_by_lock);
return (B_TRUE);
}
sb = sip_sent_by;
sb_val->sip_str_len) == 0) {
(void) pthread_mutex_unlock(&sip_sent_by_lock);
return (B_TRUE);
}
}
(void) pthread_mutex_unlock(&sip_sent_by_lock);
return (B_FALSE);
}
/*
* Given a response, check if the sent-by in the VIA header is valid.
*/
{
int error;
return (B_TRUE);
return (B_TRUE);
return (B_TRUE);
return (B_TRUE);
return (B_FALSE);
}
/*
* The receive interface to the transport layer.
*/
void
{
int transport;
if (transport == IPPROTO_TCP) {
&msglen);
return;
}
} else {
return;
}
}
return;
}
if (sip_setup_header_pointers(sip_msg) != 0) {
return;
}
&sip_msg->sip_msg_req_res)) {
return;
}
return;
}
/*
* Silently discard the response if the top VIA has a sent-by value AND
* the UA has registered sent-by values AND the one in the VIA is
* not part of the registerd sent-by values.
*/
return;
}
return;
}
/*
* msg was retransmission - handled by the transaction
*/
goto check_next;
} else {
/*
* If we are getting an INVITE request, let us send a
* 100 TRYING response here, as in 17.2.1:
* "The server transaction MUST generate a 100 (Trying)
* response unless it knows that the TU will generate a
* provisional or final response within 200 ms".
*/
if (sip_msg_info->is_request &&
}
}
if (sip_manage_dialog) {
if (sip_msg_info->is_request) {
/*
* sip_seed_dialog will check for the
* method in the request
*/
}
} else if (sip_incomplete_dialog(dialog)) {
if (!sip_msg_info->is_request ||
}
/*
* cseq number in error, send a
* SIP_SERVER_INTERNAL_ERROR response.
*/
if (sip_msg_info->is_request) {
}
return;
}
}
if (sip_msg_info->is_request) {
} else {
}
/*
* Check if there are more complete messages in the TCP fragment list
* to be consumed
*/
if (transport == IPPROTO_TCP) {
msglen = 0;
goto next_msg;
}
}
/*
* Initialize the stack. The connection manager functions, upper layer
* receive functions are mandatory.
*/
int
{
#ifdef __linux__
#endif
/*
* If the stack has already been configured, return error
*/
if (sip_stack_send != NULL ||
return (EINVAL);
}
return (EINVAL);
}
sip_conn_transport == NULL) {
sip_ulp_recv = NULL;
return (EINVAL);
}
/*
* Use Appln timeout routines, if provided
*/
goto err_ret;
} else {
goto err_ret;
}
/*
* Manage Dialogs?
*/
if (sip_manage_dialog) {
}
/*
* Initialize SIP traffic counter mutex
*/
/*
* Initialize SIP logfile structures mutex
*/
#ifdef __linux__
goto err_ret;
#else
sip_hash_salt = gethrtime();
#endif
return (0);
}