Browse Source

- applied parts of Maxim Sobolev patches (rport parsing)
- fixed them so they should work
- added a new via param (i=) for tcp use
- fixed a bug in the via parser (transport.s not initialized), the bug was found by bogdan & daniel.
- added an int2str function in ut.h (faster than snprintf %d).

Andrei Pelinescu-Onciul 22 years ago
parent
commit
09f7cd2c4e
5 changed files with 179 additions and 26 deletions
  1. 4 0
      config.h
  2. 49 10
      msg_translator.c
  3. 92 14
      parser/parse_via.c
  4. 12 2
      parser/parse_via.h
  5. 22 0
      ut.h

+ 4 - 0
config.h

@@ -85,6 +85,9 @@
 #define TOTAG_TOKEN ";tag="
 #define TOTAG_TOKEN_LEN (sizeof(TOTAG_TOKEN)-1)
 
+#define RPORT ";rport="
+#define RPORT_LEN 7
+
 #define SRV_PREFIX "_sip._udp."
 #define SRV_PREFIX_LEN 10
 
@@ -115,6 +118,7 @@
 /* forwarding  -- Via buffer dimensioning */
 #define MAX_VIA_LINE_SIZE	240
 #define MAX_RECEIVED_SIZE	57
+#define MAX_RPORT_SIZE		13
 
 /* maximum number of branches per transaction */
 #define MAX_BRANCHES    4

+ 49 - 10
msg_translator.c

@@ -183,7 +183,6 @@ char* received_builder(struct sip_msg *msg, unsigned int *received_len)
 
 	extra_len = 0;
 	source_ip=&msg->rcv.src_ip;
-	buf = 0;
 
 	buf=pkg_malloc(sizeof(char)*MAX_RECEIVED_SIZE);
 	if (buf==0){
@@ -191,16 +190,11 @@ char* received_builder(struct sip_msg *msg, unsigned int *received_len)
 		LOG(L_ERR, "ERROR: received_builder: out of memory\n");
 		return 0;
 	}
-	/*
-	received_len=snprintf(buf, MAX_RECEIVED_SIZE,
-							";received=%s",
-							inet_ntoa(*(struct in_addr *)&source_ip));
-	*/
 	memcpy(buf, RECEIVED, RECEIVED_LEN);
 	if ( (tmp=ip_addr2a(source_ip))==0)
 		return 0; /* error*/
 	tmp_len=strlen(tmp);
-	len=RECEIVED_LEN+tmp_len;
+	len=RECEIVED_LEN+tmp_len+1; /* space for  null termination */
 	if(source_ip->af==AF_INET6){
 		len+=2;
 		buf[RECEIVED_LEN]='[';
@@ -217,6 +211,32 @@ char* received_builder(struct sip_msg *msg, unsigned int *received_len)
 
 
 
+char* rport_builder(struct sip_msg *msg, unsigned int *rport_len)
+{
+	char* buf;
+	char* tmp;
+	int tmp_len;
+	int len;
+	
+	tmp_len=0;
+	tmp=int2str(ntohs(msg->rcv.src_port), &tmp_len);
+	len=RPORT_LEN+tmp_len+1; /* space for null term */
+	buf=pkg_malloc(sizeof(char)*len);
+	if (buf==0){
+		ser_error=E_OUT_OF_MEM;
+		LOG(L_ERR, "ERROR: rport_builder: out of memory\n");
+		return 0;
+	}
+	memcpy(buf, RPORT, RPORT_LEN);
+	memcpy(buf+RPORT_LEN, tmp, tmp_len);
+	buf[len]=0; /*null terminate it*/
+	
+	*rport_len=len;
+	return buf;
+}
+
+
+
 /* computes the "unpacked" len of a lump list,
    code moved from build_req_from_req */
 static inline int lumps_len(struct lump* l)
@@ -402,9 +422,10 @@ char * build_req_buf_from_sip_req( struct sip_msg* msg,
 								unsigned int *returned_len,
 								struct socket_info* send_sock, int proto)
 {
-	unsigned int len, new_len, received_len, uri_len, via_len;
+	unsigned int len, new_len, received_len, rport_len, uri_len, via_len;
 	char* line_buf;
 	char* received_buf;
+	char* rport_buf;
 	char* new_buf;
 	char* orig;
 	char* buf;
@@ -418,8 +439,10 @@ char * build_req_buf_from_sip_req( struct sip_msg* msg,
 	buf=msg->buf;
 	len=msg->len;
 	received_len=0;
+	rport_len=0;
 	new_buf=0;
 	received_buf=0;
+	rport_buf=0;
 
 
 	line_buf = via_builder( &via_len, send_sock, 
@@ -437,6 +460,12 @@ char * build_req_buf_from_sip_req( struct sip_msg* msg,
 		if ((received_buf=received_builder(msg,&received_len))==0)
 			goto error01;  /* free also line_buf */
 	}
+	
+	/* check if rport needs to be updated */
+	if (msg->via1->rport && msg->via1->rport->value.s==0){
+		if ((rport_buf=rport_builder(msg, &rport_len))==0)
+			goto error01; /* free everything */
+	}
 
 	/* add via header to the list */
 	/* try to add it before msg. 1st via */
@@ -462,9 +491,17 @@ char * build_req_buf_from_sip_req( struct sip_msg* msg,
 		}
 		anchor=anchor_lump(&(msg->add_rm),msg->via1->hdr.s-buf+size,0,
 				HDR_VIA);
-		if (anchor==0) goto error02; /* free also line_buf */
+		if (anchor==0) goto error02; /* free received_buf */
 		if (insert_new_lump_after(anchor, received_buf, received_len, HDR_VIA)
-				==0 ) goto error02; /* free also line_buf */
+				==0 ) goto error02; /* free received_buf */
+	}
+	/* if rport needs to be updated, delete it and add it's value */
+	if (rport_len){
+		anchor=del_lump(&(msg->add_rm), msg->via1->rport->name.s-buf,
+							msg->via1->rport->name.len, HDR_VIA);
+		if (anchor==0) goto error03; /* free rport_buf*/
+		if (insert_new_lump_after(anchor, rport_buf, rport_len, HDR_VIA)==0)
+			goto error03; /* free rport_buf*/
 	}
 
 	/* compute new msg len and fix overlapping zones*/
@@ -514,6 +551,8 @@ error01:
 	pkg_free(line_buf);
 error02:
 	if (received_buf) pkg_free(received_buf);
+error03:
+	if (rport_buf) pkg_free(rport_buf);
 error00:
 	*returned_len=0;
 	return 0;

+ 92 - 14
parser/parse_via.c

@@ -29,14 +29,14 @@
  */
 
 
-/* parsing:           compact form:
- */
 
 /* 
- * still TODO/test:
- *  x parse next via
- *  - return a list of header structs
- *  - return list of params
+ *  2003-01-21  added rport parsing code, contributed by
+ *               Maxim Sobolev  <[email protected]>
+ *  2003-01-23  added extra via param parsing code (i=...), used
+ *               by tcp to identify the sending socket, by andrei
+ *  2003-01-23  fixed rport parsing code to accept rport w/o any value,
+ *               by andrei
  */
 
 
@@ -80,8 +80,8 @@ enum {
 
 
 /* param related states
- * WARNING: keep the FIN*, GEN_PARAM & PARAM_ERROR in sync w/ PARAM_* from
- * msg_parser.h !*/
+ * WARNING: keep in sync with parse_via.h, PARAM_HIDDEN, ...
+ */
 enum {	
 	L_VALUE = 200, F_VALUE, P_VALUE, P_STRING,
 	HIDDEN1, HIDDEN2, HIDDEN3, HIDDEN4, HIDDEN5,
@@ -90,8 +90,10 @@ enum {
 	MADDR1, MADDR2, MADDR3, MADDR4,
 	RECEIVED1, RECEIVED2, RECEIVED3, RECEIVED4, RECEIVED5, RECEIVED6,
 	RECEIVED7,
+	RPORT1, RPORT2, RPORT3,
 	     /* fin states (227-...)*/
 	FIN_HIDDEN = 230, FIN_TTL, FIN_BRANCH, FIN_MADDR, FIN_RECEIVED,
+	FIN_RPORT, FIN_I
 	     /*GEN_PARAM,
 	       PARAM_ERROR*/ /* declared in msg_parser.h*/
 };
@@ -130,6 +132,8 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 					case FIN_TTL:
 					case FIN_MADDR:
 					case FIN_RECEIVED:
+					case FIN_RPORT:
+					case FIN_I:
 						*tmp=0;
 						param->type=state;
 						param->name.len=tmp-param->name.s;
@@ -165,6 +169,8 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 					case FIN_TTL:
 					case FIN_MADDR:
 					case FIN_RECEIVED:
+					case FIN_RPORT:
+					case FIN_I:
 						*tmp=0;
 						param->type=state;
 						param->name.len=tmp-param->name.s;
@@ -205,6 +211,8 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 					case FIN_TTL:
 					case FIN_MADDR:
 					case FIN_RECEIVED:
+					case FIN_RPORT:
+					case FIN_I:
 						*tmp=0;
 						param->type=state;
 						param->name.len=tmp-param->name.s;
@@ -236,6 +244,8 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 					case FIN_TTL:
 					case FIN_MADDR:
 					case FIN_RECEIVED:
+					case FIN_RPORT:
+					case FIN_I:
 						*tmp=0;
 						param->type=state;
 						param->name.len=tmp-param->name.s;
@@ -263,6 +273,7 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 			case ';':
 				switch(state){
 					case FIN_HIDDEN:
+					case FIN_RPORT: /* rport can appear w/o a value */
 						*tmp=0;
 						param->type=state;
 						param->name.len=tmp-param->name.s;
@@ -272,6 +283,7 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 					case FIN_MADDR:
 					case FIN_TTL:
 					case FIN_RECEIVED:
+					case FIN_I:
 						LOG(L_ERR, "ERROR: parse_via: invalid char <%c> in"
 								" state %d\n", *tmp, state);
 						goto error;
@@ -292,6 +304,7 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 			case ',':
 				switch(state){
 					case FIN_HIDDEN:
+					case FIN_RPORT:
 						*tmp=0;
 						param->type=state;
 						param->name.len=tmp-param->name.s;
@@ -301,6 +314,7 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 					case FIN_MADDR:
 					case FIN_TTL:
 					case FIN_RECEIVED:
+					case FIN_I:
 						LOG(L_ERR, "ERROR: parse_via_param: new via found" 
 								"(',') when '=' expected (state %d=)\n",
 								state);
@@ -346,7 +360,7 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 			case 'I':
 				switch(state){
 					case F_PARAM:
-						state=GEN_PARAM;
+						state=FIN_I;
 						param->name.s=tmp;
 						break;
 					case HIDDEN1:
@@ -463,6 +477,9 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 					case TTL1:
 						state=TTL2;
 						break;
+					case RPORT3:
+						state=FIN_RPORT;
+						break;
 					case GEN_PARAM:
 						break;
 					case F_CR:
@@ -550,6 +567,9 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 					case BRANCH1:
 						state=BRANCH2;
 						break;
+					case RPORT2:
+						state=RPORT3;
+						break;
 					case GEN_PARAM:
 						break;
 					case F_CR:
@@ -624,14 +644,43 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 						state=GEN_PARAM;
 				}
 				break;
-
+			case 'p':
+			case 'P':
+				switch(state){
+					case RECEIVED1:
+						state=RPORT1;
+						break;
+					case F_CR:
+					case F_LF:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end_via;
+					default:
+						state=GEN_PARAM;
+				}
+				break;
+			case 'o':
+			case 'O':
+				switch(state){
+					case RPORT1:
+						state=RPORT2;
+						break;
+					case F_CR:
+					case F_LF:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end_via;
+					default:
+						state=GEN_PARAM;
+				}
+				break;
 			default:
 				switch(state){
 					case F_PARAM:
 						state=GEN_PARAM;
 						param->name.s=tmp;
 						break;
-					case  GEN_PARAM:
+					case GEN_PARAM:
 						break;
 					case F_CR:
 					case F_LF:
@@ -755,6 +804,11 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 						param->value.len=tmp-param->value.s;
 						state=F_PARAM;
 						goto endofvalue;
+					case F_VALUE:
+						*tmp=0;
+						param->value.len=0;
+						state=F_PARAM;
+						goto endofvalue;
 					case P_STRING:
 						break; /* what to do? */
 					case F_LF:
@@ -762,6 +816,14 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 					case F_CRLF:
 						state=END_OF_HEADER;
 						goto end_via;
+					case L_VALUE:
+						if (param->type==FIN_RPORT){
+							param->value.len=0;
+							param->value.s=0; /* null value */
+							state=F_PARAM;
+							goto endofvalue;
+						};
+						/* no break */
 					default:
 						LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
 								" in state %d\n", *tmp, state);
@@ -776,11 +838,19 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 						state=F_VIA;
 						goto endofvalue;
 					case P_STRING:
-						case F_LF:
+					case F_LF:
 					case F_CR:
 					case F_CRLF:
 						state=END_OF_HEADER;
 						goto end_via;
+					case L_VALUE:
+						if (param->type==FIN_RPORT){
+							param->value.len=0;
+							param->value.s=0; /* null value */
+							state=F_VIA;
+							goto endofvalue;
+						};
+						/* no break */
 					default:
 						LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
 								" in state %d\n", *tmp, state);
@@ -847,8 +917,10 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 	
  end_via:
 	     /* if we are here we found an "unexpected" end of via
-	      *  (cr/lf). This is valid only if the param type is GEN_PARAM*/
-	if (param->type==GEN_PARAM){
+	      *  (cr/lf). This is valid only if the param type is GEN_PARAM or
+		  *  RPORT (the only ones which can miss the value; HIDDEN is a 
+		  *  special case )*/
+	if ((param->type==GEN_PARAM)||(param->type==PARAM_RPORT)){
 		saved_state=L_PARAM; /* change the saved_state, we have an unknown
 		                        param. w/o a value */
 		goto endofparam;
@@ -1097,6 +1169,7 @@ parse_again:
 				switch(state){
 					case F_PROTO:
 						state=UDP1;
+						vb->transport.s=tmp;
 						break;
 					default:
 						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
@@ -1121,6 +1194,7 @@ parse_again:
 				switch(state){
 					case F_PROTO:
 						state=TCP1;
+						vb->transport.s=tmp;
 						break;
 					default:
 						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
@@ -1713,6 +1787,10 @@ parse_again:
 							vb->branch=param;
 						else if (param->type==PARAM_RECEIVED)
 							vb->received=param;
+						else if (param->type==PARAM_RPORT)
+							vb->rport=param;
+						else if (param->type==PARAM_I)
+							vb->i=param;
 						break;
 					case P_PARAM:
 						break;

+ 12 - 2
parser/parse_via.h

@@ -25,6 +25,14 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+/* 
+ *  2003-01-21  added rport parsing code, contributed by
+ *               Maxim Sobolev  <[email protected]>
+ *  2003-01-21  added extra via param parsing code (i=...), used
+ *               by tcp to identify the sending socket, by andrei
+ */
+
+
 
 #ifndef PARSE_VIA_H
 #define PARSE_VIA_H
@@ -32,11 +40,11 @@
 #include "../str.h"
 
 /* via param types
- * WARNING: keep in sync w/ FIN_*, GEN_PARAM and PARAM_ERROR from via_parse.c
+ * WARNING: keep in sync with parse_via.c FIN_HIDDEN... 
  */
 enum {
 	PARAM_HIDDEN=230, PARAM_TTL, PARAM_BRANCH, 
-	PARAM_MADDR, PARAM_RECEIVED, GEN_PARAM,
+	PARAM_MADDR, PARAM_RECEIVED, PARAM_RPORT, PARAM_I, GEN_PARAM,
 	PARAM_ERROR
 };
 
@@ -72,6 +80,8 @@ struct via_body {
 	struct via_param* branch;
 	str tid; /* transaction id, part of branch */
 	struct via_param* received;
+	struct via_param* rport;
+	struct via_param* i;
 	
 	struct via_body* next; /* pointer to next via body string if
 				  compact via or null */

+ 22 - 0
ut.h

@@ -143,6 +143,28 @@ static inline int btostr( char *p,  unsigned char val)
 
 
 
+/* returns a pointer to a static buffer containint l in asciiz & sets len */
+static inline char* int2str(unsigned int l, int* len)
+{
+	static char r[11]; /* 10 digits + 0 */
+	int i;
+	
+	i=9;
+	r[10]=0; /* null terminate */
+	do{
+		r[i]=l%10+'0';
+		i--;
+		l/=10;
+	}while(l && (i>=0));
+	if (l && (i<0)){
+		LOG(L_CRIT, "BUG: int2str: overflow\n");
+	}
+	if (len) *len=9-i;
+	return &r[i+1];
+}
+
+
+
 /* faster memchr version */
 static inline char* q_memchr(char* p, int c, unsigned int size)
 {