140cb5e5dSvi117747 /* 240cb5e5dSvi117747 * CDDL HEADER START 340cb5e5dSvi117747 * 440cb5e5dSvi117747 * The contents of this file are subject to the terms of the 540cb5e5dSvi117747 * Common Development and Distribution License (the "License"). 640cb5e5dSvi117747 * You may not use this file except in compliance with the License. 740cb5e5dSvi117747 * 840cb5e5dSvi117747 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 940cb5e5dSvi117747 * or http://www.opensolaris.org/os/licensing. 1040cb5e5dSvi117747 * See the License for the specific language governing permissions 1140cb5e5dSvi117747 * and limitations under the License. 1240cb5e5dSvi117747 * 1340cb5e5dSvi117747 * When distributing Covered Code, include this CDDL HEADER in each 1440cb5e5dSvi117747 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1540cb5e5dSvi117747 * If applicable, add the following below this CDDL HEADER, with the 1640cb5e5dSvi117747 * fields enclosed by brackets "[]" replaced with your own identifying 1740cb5e5dSvi117747 * information: Portions Copyright [yyyy] [name of copyright owner] 1840cb5e5dSvi117747 * 1940cb5e5dSvi117747 * CDDL HEADER END 2040cb5e5dSvi117747 */ 2140cb5e5dSvi117747 2240cb5e5dSvi117747 /* 23*2c2c4183Svi117747 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 2440cb5e5dSvi117747 * Use is subject to license terms. 2540cb5e5dSvi117747 */ 2640cb5e5dSvi117747 2740cb5e5dSvi117747 #pragma ident "%Z%%M% %I% %E% SMI" 2840cb5e5dSvi117747 29*2c2c4183Svi117747 #include <stdlib.h> 30*2c2c4183Svi117747 #include <assert.h> 31*2c2c4183Svi117747 #include <ctype.h> 32*2c2c4183Svi117747 #include <pthread.h> 33*2c2c4183Svi117747 #include <strings.h> 34*2c2c4183Svi117747 #include <sip.h> 35*2c2c4183Svi117747 3640cb5e5dSvi117747 #include "sip_miscdefs.h" 3740cb5e5dSvi117747 3840cb5e5dSvi117747 /* 3940cb5e5dSvi117747 * Local version of case insensitive strstr(). 4040cb5e5dSvi117747 */ 4140cb5e5dSvi117747 static char * 4240cb5e5dSvi117747 sip_reass_strstr(const char *as1, const char *as2) 4340cb5e5dSvi117747 { 4440cb5e5dSvi117747 const char *s1; 4540cb5e5dSvi117747 const char *s2; 4640cb5e5dSvi117747 const char *tptr; 4740cb5e5dSvi117747 char c; 4840cb5e5dSvi117747 4940cb5e5dSvi117747 s1 = as1; 5040cb5e5dSvi117747 s2 = as2; 5140cb5e5dSvi117747 5240cb5e5dSvi117747 if (s2 == NULL || *s2 == '\0') 5340cb5e5dSvi117747 return ((char *)s1); 5440cb5e5dSvi117747 c = *s2; 5540cb5e5dSvi117747 5640cb5e5dSvi117747 while (*s1) 5740cb5e5dSvi117747 if (tolower(*s1++) == c) { 5840cb5e5dSvi117747 tptr = s1; 5940cb5e5dSvi117747 while ((c = *++s2) == tolower(*s1++) && c) 6040cb5e5dSvi117747 ; 6140cb5e5dSvi117747 if (c == 0) 6240cb5e5dSvi117747 return ((char *)tptr - 1); 6340cb5e5dSvi117747 s1 = tptr; 6440cb5e5dSvi117747 s2 = as2; 6540cb5e5dSvi117747 c = *s2; 6640cb5e5dSvi117747 } 6740cb5e5dSvi117747 6840cb5e5dSvi117747 return (NULL); 6940cb5e5dSvi117747 } 7040cb5e5dSvi117747 7140cb5e5dSvi117747 /* 7240cb5e5dSvi117747 * Get the value in the content-length field and add it to the header length 7340cb5e5dSvi117747 * and return the total length. returns -1 if the length cannot be determined 7440cb5e5dSvi117747 * or if the message does not contain the entire message. 7540cb5e5dSvi117747 */ 7640cb5e5dSvi117747 static int 7740cb5e5dSvi117747 sip_get_msglen(char *p, size_t msglen) 7840cb5e5dSvi117747 { 7940cb5e5dSvi117747 int value = 0; 8040cb5e5dSvi117747 int hlen; 8140cb5e5dSvi117747 char *c; 8240cb5e5dSvi117747 char *e; 8340cb5e5dSvi117747 int base = 10; 8440cb5e5dSvi117747 char *edge; 8540cb5e5dSvi117747 int digits = 0; 8640cb5e5dSvi117747 8740cb5e5dSvi117747 edge = p + msglen; 8840cb5e5dSvi117747 if ((c = sip_reass_strstr(p, "content-length")) == NULL) 8940cb5e5dSvi117747 return (-1); 9040cb5e5dSvi117747 hlen = c - p; 9140cb5e5dSvi117747 if ((hlen + strlen("content-length")) >= msglen) 9240cb5e5dSvi117747 return (-1); 9340cb5e5dSvi117747 c += strlen("content-length"); 9440cb5e5dSvi117747 e = c + 1; 9540cb5e5dSvi117747 while (*e == ' ' || *e == ':') { 9640cb5e5dSvi117747 e++; 9740cb5e5dSvi117747 if (e == edge) 9840cb5e5dSvi117747 return (-1); 9940cb5e5dSvi117747 } 10040cb5e5dSvi117747 while (*e != '\r' && *e != ' ') { 10140cb5e5dSvi117747 if (e == edge) 10240cb5e5dSvi117747 return (-1); 10340cb5e5dSvi117747 if (*e >= '0' && *e <= '9') 10440cb5e5dSvi117747 digits = *e - '0'; 10540cb5e5dSvi117747 else 10640cb5e5dSvi117747 return (-1); 10740cb5e5dSvi117747 value = (value * base) + digits; 10840cb5e5dSvi117747 e++; 10940cb5e5dSvi117747 } 11040cb5e5dSvi117747 while (*e != '\r') { 11140cb5e5dSvi117747 e++; 11240cb5e5dSvi117747 if (e == edge) 11340cb5e5dSvi117747 return (-1); 11440cb5e5dSvi117747 } 11540cb5e5dSvi117747 hlen = e - p + 4; /* 4 for 2 CRLFs ?? */ 11640cb5e5dSvi117747 value += hlen; 11740cb5e5dSvi117747 11840cb5e5dSvi117747 return (value); 11940cb5e5dSvi117747 } 12040cb5e5dSvi117747 12140cb5e5dSvi117747 /* 12240cb5e5dSvi117747 * We have determined that msg does not contain a *single* complete message. 12340cb5e5dSvi117747 * Add it to the reassembly list and check if we have a complete message. 12440cb5e5dSvi117747 * a NULL 'msg' means we are just checking if there are more complete 12540cb5e5dSvi117747 * messages in the list that can be passed up. 12640cb5e5dSvi117747 */ 12740cb5e5dSvi117747 char * 12840cb5e5dSvi117747 sip_get_tcp_msg(sip_conn_object_t obj, char *msg, size_t *msglen) 12940cb5e5dSvi117747 { 13040cb5e5dSvi117747 int value; 13140cb5e5dSvi117747 sip_conn_obj_pvt_t *pvt_data; 13240cb5e5dSvi117747 sip_reass_entry_t *reass; 13340cb5e5dSvi117747 void **obj_val; 13440cb5e5dSvi117747 char *msgbuf = NULL; 13540cb5e5dSvi117747 int splitlen; 13640cb5e5dSvi117747 char *splitbuf; 13740cb5e5dSvi117747 13840cb5e5dSvi117747 if (msg != NULL) { 13940cb5e5dSvi117747 assert(*msglen > 0); 14040cb5e5dSvi117747 msgbuf = (char *)malloc(*msglen + 1); 14140cb5e5dSvi117747 if (msgbuf == NULL) 14240cb5e5dSvi117747 return (NULL); 14340cb5e5dSvi117747 (void) strncpy(msgbuf, msg, *msglen); 14440cb5e5dSvi117747 msgbuf[*msglen] = '\0'; 14540cb5e5dSvi117747 msg = msgbuf; 14640cb5e5dSvi117747 } 14740cb5e5dSvi117747 obj_val = (void *)obj; 14840cb5e5dSvi117747 pvt_data = (sip_conn_obj_pvt_t *)*obj_val; 14940cb5e5dSvi117747 /* 15040cb5e5dSvi117747 * connection object not initialized 15140cb5e5dSvi117747 */ 15240cb5e5dSvi117747 if (pvt_data == NULL) { 15340cb5e5dSvi117747 if (msg == NULL) 15440cb5e5dSvi117747 return (NULL); 15540cb5e5dSvi117747 value = sip_get_msglen(msg, *msglen); 15640cb5e5dSvi117747 if (value == *msglen) { 15740cb5e5dSvi117747 return (msg); 15840cb5e5dSvi117747 } else { 15940cb5e5dSvi117747 if (msgbuf != NULL) 16040cb5e5dSvi117747 free(msgbuf); 16140cb5e5dSvi117747 return (NULL); 16240cb5e5dSvi117747 } 16340cb5e5dSvi117747 } 16440cb5e5dSvi117747 (void) pthread_mutex_lock(&pvt_data->sip_conn_obj_reass_lock); 16540cb5e5dSvi117747 reass = pvt_data->sip_conn_obj_reass; 16640cb5e5dSvi117747 assert(reass != NULL); 16740cb5e5dSvi117747 if (reass->sip_reass_msg == NULL) { 16840cb5e5dSvi117747 assert(reass->sip_reass_msglen == 0); 16940cb5e5dSvi117747 if (msg == NULL) { 17040cb5e5dSvi117747 (void) pthread_mutex_unlock( 17140cb5e5dSvi117747 &pvt_data->sip_conn_obj_reass_lock); 17240cb5e5dSvi117747 return (NULL); 17340cb5e5dSvi117747 } 17440cb5e5dSvi117747 value = sip_get_msglen(msg, *msglen); 17540cb5e5dSvi117747 if (value == *msglen) { 17640cb5e5dSvi117747 (void) pthread_mutex_unlock( 17740cb5e5dSvi117747 &pvt_data->sip_conn_obj_reass_lock); 17840cb5e5dSvi117747 return (msg); 17940cb5e5dSvi117747 } 18040cb5e5dSvi117747 reass->sip_reass_msg = msg; 18140cb5e5dSvi117747 reass->sip_reass_msglen = *msglen; 18240cb5e5dSvi117747 if (value != -1 && value < reass->sip_reass_msglen) 18340cb5e5dSvi117747 goto tryone; 18440cb5e5dSvi117747 (void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_reass_lock); 18540cb5e5dSvi117747 return (NULL); 18640cb5e5dSvi117747 } else if (msg != NULL) { 18740cb5e5dSvi117747 /* 18840cb5e5dSvi117747 * Resize, not optimal 18940cb5e5dSvi117747 */ 19040cb5e5dSvi117747 int newlen = reass->sip_reass_msglen + *msglen; 19140cb5e5dSvi117747 char *newmsg; 19240cb5e5dSvi117747 19340cb5e5dSvi117747 assert(strlen(reass->sip_reass_msg) == reass->sip_reass_msglen); 19440cb5e5dSvi117747 newmsg = malloc(newlen + 1); 19540cb5e5dSvi117747 if (newmsg == NULL) { 19640cb5e5dSvi117747 (void) pthread_mutex_unlock( 19740cb5e5dSvi117747 &pvt_data->sip_conn_obj_reass_lock); 19840cb5e5dSvi117747 if (msgbuf != NULL) 19940cb5e5dSvi117747 free(msgbuf); 20040cb5e5dSvi117747 return (NULL); 20140cb5e5dSvi117747 } 20240cb5e5dSvi117747 (void) strncpy(newmsg, reass->sip_reass_msg, 20340cb5e5dSvi117747 reass->sip_reass_msglen); 20440cb5e5dSvi117747 newmsg[reass->sip_reass_msglen] = '\0'; 20540cb5e5dSvi117747 (void) strncat(newmsg, msg, *msglen); 20640cb5e5dSvi117747 newmsg[newlen] = '\0'; 20740cb5e5dSvi117747 assert(strlen(newmsg) == newlen); 20840cb5e5dSvi117747 reass->sip_reass_msglen = newlen; 20940cb5e5dSvi117747 free(msg); 21040cb5e5dSvi117747 free(reass->sip_reass_msg); 21140cb5e5dSvi117747 reass->sip_reass_msg = newmsg; 21240cb5e5dSvi117747 } 21340cb5e5dSvi117747 value = sip_get_msglen(reass->sip_reass_msg, reass->sip_reass_msglen); 21440cb5e5dSvi117747 if (value == -1 || value > reass->sip_reass_msglen) { 21540cb5e5dSvi117747 (void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_reass_lock); 21640cb5e5dSvi117747 return (NULL); 21740cb5e5dSvi117747 } 21840cb5e5dSvi117747 tryone: 21940cb5e5dSvi117747 if (value == reass->sip_reass_msglen) { 22040cb5e5dSvi117747 msg = reass->sip_reass_msg; 22140cb5e5dSvi117747 *msglen = reass->sip_reass_msglen; 22240cb5e5dSvi117747 reass->sip_reass_msg = NULL; 22340cb5e5dSvi117747 reass->sip_reass_msglen = 0; 22440cb5e5dSvi117747 (void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_reass_lock); 22540cb5e5dSvi117747 return (msg); 22640cb5e5dSvi117747 } 22740cb5e5dSvi117747 splitlen = reass->sip_reass_msglen - value; 22840cb5e5dSvi117747 msg = (char *)malloc(value + 1); 22940cb5e5dSvi117747 splitbuf = (char *)malloc(splitlen + 1); 23040cb5e5dSvi117747 if (msg == NULL || splitbuf == NULL) { 23140cb5e5dSvi117747 if (msg != NULL) 23240cb5e5dSvi117747 free(msg); 23340cb5e5dSvi117747 if (splitbuf != NULL) 23440cb5e5dSvi117747 free(splitbuf); 23540cb5e5dSvi117747 (void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_reass_lock); 23640cb5e5dSvi117747 return (NULL); 23740cb5e5dSvi117747 } 23840cb5e5dSvi117747 (void) strncpy(msg, reass->sip_reass_msg, value); 23940cb5e5dSvi117747 msg[value] = '\0'; 24040cb5e5dSvi117747 (void) strncpy(splitbuf, reass->sip_reass_msg + value, splitlen); 24140cb5e5dSvi117747 splitbuf[splitlen] = '\0'; 24240cb5e5dSvi117747 free(reass->sip_reass_msg); 24340cb5e5dSvi117747 reass->sip_reass_msg = splitbuf; 24440cb5e5dSvi117747 reass->sip_reass_msglen = splitlen; 24540cb5e5dSvi117747 (void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_reass_lock); 24640cb5e5dSvi117747 *msglen = value; 24740cb5e5dSvi117747 return (msg); 24840cb5e5dSvi117747 } 249