xref: /onnv-gate/usr/src/lib/libsip/common/sip_reass.c (revision 3439:0302bfe973fe)
12882Svi117747 /*
22882Svi117747  * CDDL HEADER START
32882Svi117747  *
42882Svi117747  * The contents of this file are subject to the terms of the
52882Svi117747  * Common Development and Distribution License (the "License").
62882Svi117747  * You may not use this file except in compliance with the License.
72882Svi117747  *
82882Svi117747  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92882Svi117747  * or http://www.opensolaris.org/os/licensing.
102882Svi117747  * See the License for the specific language governing permissions
112882Svi117747  * and limitations under the License.
122882Svi117747  *
132882Svi117747  * When distributing Covered Code, include this CDDL HEADER in each
142882Svi117747  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152882Svi117747  * If applicable, add the following below this CDDL HEADER, with the
162882Svi117747  * fields enclosed by brackets "[]" replaced with your own identifying
172882Svi117747  * information: Portions Copyright [yyyy] [name of copyright owner]
182882Svi117747  *
192882Svi117747  * CDDL HEADER END
202882Svi117747  */
212882Svi117747 
222882Svi117747 /*
23*3439Svi117747  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
242882Svi117747  * Use is subject to license terms.
252882Svi117747  */
262882Svi117747 
272882Svi117747 #pragma ident	"%Z%%M%	%I%	%E% SMI"
282882Svi117747 
29*3439Svi117747 #include <stdlib.h>
30*3439Svi117747 #include <assert.h>
31*3439Svi117747 #include <ctype.h>
32*3439Svi117747 #include <pthread.h>
33*3439Svi117747 #include <strings.h>
34*3439Svi117747 #include <sip.h>
35*3439Svi117747 
362882Svi117747 #include "sip_miscdefs.h"
372882Svi117747 
382882Svi117747 /*
392882Svi117747  * Local version of case insensitive strstr().
402882Svi117747  */
412882Svi117747 static char *
sip_reass_strstr(const char * as1,const char * as2)422882Svi117747 sip_reass_strstr(const char *as1, const char *as2)
432882Svi117747 {
442882Svi117747 	const char	*s1;
452882Svi117747 	const char	*s2;
462882Svi117747 	const char	*tptr;
472882Svi117747 	char	c;
482882Svi117747 
492882Svi117747 	s1 = as1;
502882Svi117747 	s2 = as2;
512882Svi117747 
522882Svi117747 	if (s2 == NULL || *s2 == '\0')
532882Svi117747 		return ((char *)s1);
542882Svi117747 	c = *s2;
552882Svi117747 
562882Svi117747 	while (*s1)
572882Svi117747 		if (tolower(*s1++) == c) {
582882Svi117747 			tptr = s1;
592882Svi117747 			while ((c = *++s2) == tolower(*s1++) && c)
602882Svi117747 				;
612882Svi117747 			if (c == 0)
622882Svi117747 				return ((char *)tptr - 1);
632882Svi117747 			s1 = tptr;
642882Svi117747 			s2 = as2;
652882Svi117747 			c = *s2;
662882Svi117747 		}
672882Svi117747 
682882Svi117747 	return (NULL);
692882Svi117747 }
702882Svi117747 
712882Svi117747 /*
722882Svi117747  * Get the value in the content-length field and add it to the header length
732882Svi117747  * and return the total length. returns -1 if the length cannot be determined
742882Svi117747  * or if the message does not contain the entire message.
752882Svi117747  */
762882Svi117747 static int
sip_get_msglen(char * p,size_t msglen)772882Svi117747 sip_get_msglen(char *p, size_t msglen)
782882Svi117747 {
792882Svi117747 	int	value = 0;
802882Svi117747 	int 	hlen;
812882Svi117747 	char	*c;
822882Svi117747 	char	*e;
832882Svi117747 	int	base = 10;
842882Svi117747 	char	*edge;
852882Svi117747 	int	digits = 0;
862882Svi117747 
872882Svi117747 	edge = p + msglen;
882882Svi117747 	if ((c = sip_reass_strstr(p, "content-length")) == NULL)
892882Svi117747 		return (-1);
902882Svi117747 	hlen = c - p;
912882Svi117747 	if ((hlen +  strlen("content-length")) >= msglen)
922882Svi117747 		return (-1);
932882Svi117747 	c += strlen("content-length");
942882Svi117747 	e = c + 1;
952882Svi117747 	while (*e == ' ' || *e == ':') {
962882Svi117747 		e++;
972882Svi117747 		if (e == edge)
982882Svi117747 			return (-1);
992882Svi117747 	}
1002882Svi117747 	while (*e  != '\r' && *e != ' ') {
1012882Svi117747 		if (e == edge)
1022882Svi117747 			return (-1);
1032882Svi117747 		if (*e >= '0' && *e <= '9')
1042882Svi117747 			digits = *e - '0';
1052882Svi117747 		else
1062882Svi117747 			return (-1);
1072882Svi117747 		value = (value * base) + digits;
1082882Svi117747 		e++;
1092882Svi117747 	}
1102882Svi117747 	while (*e != '\r') {
1112882Svi117747 		e++;
1122882Svi117747 		if (e == edge)
1132882Svi117747 			return (-1);
1142882Svi117747 	}
1152882Svi117747 	hlen = e - p + 4;	/* 4 for 2 CRLFs ?? */
1162882Svi117747 	value += hlen;
1172882Svi117747 
1182882Svi117747 	return (value);
1192882Svi117747 }
1202882Svi117747 
1212882Svi117747 /*
1222882Svi117747  * We have determined that msg does not contain a *single* complete message.
1232882Svi117747  * Add it to the reassembly list and check if we have a complete message.
1242882Svi117747  * a NULL 'msg' means we are just checking if there are more complete
1252882Svi117747  * messages in the list that can be passed up.
1262882Svi117747  */
1272882Svi117747 char *
sip_get_tcp_msg(sip_conn_object_t obj,char * msg,size_t * msglen)1282882Svi117747 sip_get_tcp_msg(sip_conn_object_t obj, char *msg, size_t *msglen)
1292882Svi117747 {
1302882Svi117747 	int			value;
1312882Svi117747 	sip_conn_obj_pvt_t	*pvt_data;
1322882Svi117747 	sip_reass_entry_t	*reass;
1332882Svi117747 	void			**obj_val;
1342882Svi117747 	char			*msgbuf = NULL;
1352882Svi117747 	int			splitlen;
1362882Svi117747 	char			*splitbuf;
1372882Svi117747 
1382882Svi117747 	if (msg != NULL) {
1392882Svi117747 		assert(*msglen > 0);
1402882Svi117747 		msgbuf = (char *)malloc(*msglen + 1);
1412882Svi117747 		if (msgbuf == NULL)
1422882Svi117747 			return (NULL);
1432882Svi117747 		(void) strncpy(msgbuf, msg, *msglen);
1442882Svi117747 		msgbuf[*msglen] = '\0';
1452882Svi117747 		msg = msgbuf;
1462882Svi117747 	}
1472882Svi117747 	obj_val = (void *)obj;
1482882Svi117747 	pvt_data = (sip_conn_obj_pvt_t *)*obj_val;
1492882Svi117747 	/*
1502882Svi117747 	 * connection object not initialized
1512882Svi117747 	 */
1522882Svi117747 	if (pvt_data == NULL) {
1532882Svi117747 		if (msg == NULL)
1542882Svi117747 			return (NULL);
1552882Svi117747 		value = sip_get_msglen(msg, *msglen);
1562882Svi117747 		if (value == *msglen) {
1572882Svi117747 			return (msg);
1582882Svi117747 		} else {
1592882Svi117747 			if (msgbuf != NULL)
1602882Svi117747 				free(msgbuf);
1612882Svi117747 			return (NULL);
1622882Svi117747 		}
1632882Svi117747 	}
1642882Svi117747 	(void) pthread_mutex_lock(&pvt_data->sip_conn_obj_reass_lock);
1652882Svi117747 	reass = pvt_data->sip_conn_obj_reass;
1662882Svi117747 	assert(reass != NULL);
1672882Svi117747 	if (reass->sip_reass_msg == NULL) {
1682882Svi117747 		assert(reass->sip_reass_msglen == 0);
1692882Svi117747 		if (msg == NULL) {
1702882Svi117747 			(void) pthread_mutex_unlock(
1712882Svi117747 			    &pvt_data->sip_conn_obj_reass_lock);
1722882Svi117747 			return (NULL);
1732882Svi117747 		}
1742882Svi117747 		value = sip_get_msglen(msg, *msglen);
1752882Svi117747 		if (value == *msglen) {
1762882Svi117747 			(void) pthread_mutex_unlock(
1772882Svi117747 			    &pvt_data->sip_conn_obj_reass_lock);
1782882Svi117747 			return (msg);
1792882Svi117747 		}
1802882Svi117747 		reass->sip_reass_msg = msg;
1812882Svi117747 		reass->sip_reass_msglen = *msglen;
1822882Svi117747 		if (value != -1 && value < reass->sip_reass_msglen)
1832882Svi117747 			goto tryone;
1842882Svi117747 		(void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_reass_lock);
1852882Svi117747 		return (NULL);
1862882Svi117747 	} else if (msg != NULL) {
1872882Svi117747 		/*
1882882Svi117747 		 * Resize, not optimal
1892882Svi117747 		 */
1902882Svi117747 		int	newlen = reass->sip_reass_msglen + *msglen;
1912882Svi117747 		char	*newmsg;
1922882Svi117747 
1932882Svi117747 		assert(strlen(reass->sip_reass_msg) == reass->sip_reass_msglen);
1942882Svi117747 		newmsg = malloc(newlen + 1);
1952882Svi117747 		if (newmsg == NULL) {
1962882Svi117747 			(void) pthread_mutex_unlock(
1972882Svi117747 			    &pvt_data->sip_conn_obj_reass_lock);
1982882Svi117747 			if (msgbuf != NULL)
1992882Svi117747 				free(msgbuf);
2002882Svi117747 			return (NULL);
2012882Svi117747 		}
2022882Svi117747 		(void) strncpy(newmsg, reass->sip_reass_msg,
2032882Svi117747 		    reass->sip_reass_msglen);
2042882Svi117747 		newmsg[reass->sip_reass_msglen] = '\0';
2052882Svi117747 		(void) strncat(newmsg, msg, *msglen);
2062882Svi117747 		newmsg[newlen] = '\0';
2072882Svi117747 		assert(strlen(newmsg) == newlen);
2082882Svi117747 		reass->sip_reass_msglen = newlen;
2092882Svi117747 		free(msg);
2102882Svi117747 		free(reass->sip_reass_msg);
2112882Svi117747 		reass->sip_reass_msg = newmsg;
2122882Svi117747 	}
2132882Svi117747 	value = sip_get_msglen(reass->sip_reass_msg, reass->sip_reass_msglen);
2142882Svi117747 	if (value == -1 || value >  reass->sip_reass_msglen) {
2152882Svi117747 		(void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_reass_lock);
2162882Svi117747 		return (NULL);
2172882Svi117747 	}
2182882Svi117747 tryone:
2192882Svi117747 	if (value == reass->sip_reass_msglen) {
2202882Svi117747 		msg = reass->sip_reass_msg;
2212882Svi117747 		*msglen = reass->sip_reass_msglen;
2222882Svi117747 		reass->sip_reass_msg = NULL;
2232882Svi117747 		reass->sip_reass_msglen = 0;
2242882Svi117747 		(void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_reass_lock);
2252882Svi117747 		return (msg);
2262882Svi117747 	}
2272882Svi117747 	splitlen = reass->sip_reass_msglen - value;
2282882Svi117747 	msg = (char *)malloc(value + 1);
2292882Svi117747 	splitbuf = (char *)malloc(splitlen + 1);
2302882Svi117747 	if (msg == NULL || splitbuf == NULL) {
2312882Svi117747 		if (msg != NULL)
2322882Svi117747 			free(msg);
2332882Svi117747 		if (splitbuf != NULL)
2342882Svi117747 			free(splitbuf);
2352882Svi117747 		(void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_reass_lock);
2362882Svi117747 		return (NULL);
2372882Svi117747 	}
2382882Svi117747 	(void) strncpy(msg, reass->sip_reass_msg, value);
2392882Svi117747 	msg[value] = '\0';
2402882Svi117747 	(void) strncpy(splitbuf, reass->sip_reass_msg + value, splitlen);
2412882Svi117747 	splitbuf[splitlen] = '\0';
2422882Svi117747 	free(reass->sip_reass_msg);
2432882Svi117747 	reass->sip_reass_msg = splitbuf;
2442882Svi117747 	reass->sip_reass_msglen = splitlen;
2452882Svi117747 	(void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_reass_lock);
2462882Svi117747 	*msglen = value;
2472882Svi117747 	return (msg);
2482882Svi117747 }
249