[Serusers] Rewriting URI in the Contact field

Maxim Sobolev sobomax at FreeBSD.org
Mon Jan 20 20:44:31 CET 2003


On Mon, Jan 20, 2003 at 03:22:33PM +0100, Jiri Kuthan wrote:
> At 09:53 PM 1/13/2003, you wrote:
> >Attached please find the patch, which implements t_on_positive()
> >approach. Now my config looks like the following and everything now
> >works as expected:
> 
> thanks for the patch -- I will try to integrate it as I move ahead
> with other changes to TM. Does your nathelper module work now?

Attached please find more fresh patch with several bugs smashed. It
is probably the last one on this topic, because it works reasonably
well and we now have moved to adjusting b2bua for our needs (mostly
radius auth/acc). In addition to nathelper module, this patch
implements rport support as specified in the correstponding IETF
draft.

Thanks!

-Maxim
-------------- next part --------------
--- modules/sl/sl_funcs.c.orig	Mon Oct 21 23:30:15 2002
+++ modules/sl/sl_funcs.c	Mon Jan 20 01:07:48 2003
@@ -121,7 +121,7 @@
 	to.sin_family = AF_INET; */
 
 	if (reply_to_via) {
-		if (update_sock_struct_from_via(  &(to),  msg->via1 )==-1)
+		if (update_sock_struct_from_via(  &(to),  msg->via1, msg)==-1)
 		{
 			LOG(L_ERR, "ERROR: sl_send_reply: "
 				"cannot lookup reply dst: %s\n",
--- modules/tm/h_table.h.orig	Mon Nov 11 23:34:54 2002
+++ modules/tm/h_table.h	Mon Jan 20 01:07:48 2003
@@ -202,6 +202,8 @@
 
 	/* the route to take if no final positive reply arrived */
 	unsigned int on_negative;
+	/* the route to take if final positive reply arrived */
+	unsigned int on_positive;
 	/* set to one if you want to disallow silent transaction
 	   dropping when C timer hits
 	*/
--- modules/tm/t_fwd.c.orig	Mon Oct 21 22:21:50 2002
+++ modules/tm/t_fwd.c	Mon Jan 20 01:07:48 2003
@@ -415,6 +415,8 @@
 
 	/* if someone set on_negative, store in in T-context */
 	t->on_negative=get_on_negative();
+	/* if someone set on_positive, store in in T-context */
+	t->on_positive=get_on_positive();
 
 	/* send them out now */
 	for (i=first_branch; i<t->nr_of_outgoings; i++) {
--- modules/tm/t_lookup.c.orig	Mon Oct 21 22:21:50 2002
+++ modules/tm/t_lookup.c	Mon Jan 20 01:07:48 2003
@@ -717,7 +717,7 @@
 	} else {
 		via=msg->via1;
 		/*init retrans buffer*/
-		if (update_sock_struct_from_via( &(rb->to),via )==-1) {
+		if (update_sock_struct_from_via( &(rb->to),via,msg )==-1) {
 			LOG(L_ERR, "ERROR: init_rb: cannot lookup reply dst: %.*s\n",
 				via->host.len, via->host.s );
 			ser_error=E_BAD_VIA;
--- modules/tm/t_reply.c.orig	Tue Oct 22 00:24:43 2002
+++ modules/tm/t_reply.c	Mon Jan 20 01:07:48 2003
@@ -56,6 +56,8 @@
 
 /* where to go if there is no positive reply */
 static int goto_on_negative=0;
+/* where to go if is a positive reply */
+static int goto_on_positive=0;
 
 /* we store the reply_route # in private memory which is
    then processed during t_relay; we cannot set this value
@@ -73,12 +75,23 @@
 	return 1;
 }
 
+int t_on_positive( unsigned int go_to )
+{
+	goto_on_positive=go_to;
+	return 1;
+}
+
 
 unsigned int get_on_negative()
 {
 	return goto_on_negative;
 }
 
+unsigned int get_on_positive()
+{
+	return goto_on_positive;
+}
+
 void tm_init_tags()
 {
 	init_tags(tm_tags, &tm_tag_suffix, 
@@ -916,4 +929,26 @@
 	if (faked_msg.new_uri.s) pkg_free(faked_msg.new_uri.s);
 }
 
+void on_positive_reply( struct cell* t, struct sip_msg* msg,
+	int code, void *param )
+{
+	int act_ret;
+	struct lump* tmp;
 
+	/* nobody cares about a positive transaction -- ok, return */
+	if (!t->on_positive) {
+		DBG("DBG: on_positive_reply: no on_positive\n");
+		return;
+	}
+
+	tmp = msg->add_rm;
+	msg->add_rm = msg->repl_add_rm;
+	act_ret=run_actions(reply_rlist[t->on_positive], msg);
+	msg->repl_add_rm = msg->add_rm;
+	msg->add_rm = tmp;
+	if (act_ret<0) {
+		LOG(L_ERR, "on_positive_reply: Error in do_action\n");
+	}
+
+	return;
+}
--- modules/tm/t_reply.h.orig	Tue Oct 22 00:24:43 2002
+++ modules/tm/t_reply.h	Mon Jan 20 01:07:48 2003
@@ -101,11 +101,16 @@
 void on_negative_reply( struct cell* t, struct sip_msg* msg,
 	int code, void *param  );
 
+void on_positive_reply( struct cell* t, struct sip_msg* msg,
+	int code, void *param  );
+
 /* set which 'reply' structure to take if only negative
    replies arrive 
 */
 int t_on_negative( unsigned int go_to );
 unsigned int get_on_negative();
+int t_on_positive( unsigned int go_to );
+unsigned int get_on_positive();
 
 int t_retransmit_reply( struct cell *t );
 
--- modules/tm/tm.c.orig	Tue Oct 22 00:24:43 2002
+++ modules/tm/tm.c	Mon Jan 20 01:07:48 2003
@@ -95,6 +95,7 @@
 inline static int w_t_forward_nonack(struct sip_msg* msg, char* str, char* );
 inline static int fixup_hostport2proxy(void** param, int param_no);
 inline static int w_t_on_negative( struct sip_msg* msg, char *go_to, char *foo );
+inline static int w_t_on_positive( struct sip_msg* msg, char *go_to, char *foo );
 
 
 static int mod_init(void);
@@ -121,6 +122,7 @@
 				T_RELAY,
 				T_FORWARD_NONACK,
 				"t_on_negative",
+				"t_on_positive",
 
 				/* not applicable from script ... */
 
@@ -141,6 +143,7 @@
 					w_t_relay,
 					w_t_forward_nonack,
 					w_t_on_negative,
+					w_t_on_positive,
 
 					(cmd_function) register_tmcb,
 					(cmd_function) t_uac,
@@ -159,6 +162,7 @@
 				0, /* t_relay */
 				2, /* t_forward_nonack */
 				1, /* t_on_negative */
+				1, /* t_on_positive */
 				NO_SCRIPT /* register_tmcb */,
 				NO_SCRIPT /* t_uac */,
 				NO_SCRIPT /* load_tm */,
@@ -176,13 +180,14 @@
 				0,						/* t_relay */
 				fixup_hostport2proxy,	/* t_forward_nonack */
 				fixup_str2int,			/* t_on_negative */
+				fixup_str2int,			/* t_on_positive */
 				0,						/* register_tmcb */
 				0,						/* t_uac */
 				0,						/* load_tm */
 				0						/* t_newdlg */
 	
 		},
-	15,
+	16,
 
 	/* ------------ exported variables ---------- */
 	(char *[]) { /* Module parameter names */
@@ -266,6 +271,7 @@
 	   message's t_on_negative value
 	*/
 	t_on_negative( 0 );
+	t_on_positive( 0 );
 
 	return 1;
 }
@@ -332,6 +338,8 @@
 	}
 	register_tmcb( TMCB_ON_NEGATIVE, on_negative_reply, 
 			0 /* empty param */);
+	register_tmcb( TMCB_REPLY_IN, on_positive_reply,
+			0 /* empty param */);
 	/* register post-script clean-up function */
 	register_script_cb( w_t_unref, POST_SCRIPT_CB, 
 			0 /* empty param */ );
@@ -533,6 +541,11 @@
 inline static int w_t_on_negative( struct sip_msg* msg, char *go_to, char *foo )
 {
 	return t_on_negative( (unsigned int ) go_to );
+}
+
+inline static int w_t_on_positive( struct sip_msg* msg, char *go_to, char *foo )
+{
+	return t_on_positive( (unsigned int ) go_to );
 }
 
 inline static int w_t_relay_to( struct sip_msg  *p_msg , 
--- modules/nathelper/Makefile.orig	Mon Jan 20 01:07:47 2003
+++ modules/nathelper/Makefile	Mon Jan 20 01:07:47 2003
@@ -0,0 +1,13 @@
+# $Id: Makefile,v 1.4 2001/12/08 22:06:27 andrei Rel $
+#
+# print example module makefile
+#
+# 
+# WARNING: do not run this directly, it should be run by the master Makefile
+
+auto_gen=
+NAME=nathelper.so
+LIBS=
+
+include ../../Makefile.modules
+
--- modules/nathelper/README.orig	Mon Jan 20 01:07:47 2003
+++ modules/nathelper/README	Mon Jan 20 01:07:47 2003
@@ -0,0 +1,29 @@
+#
+# $Id: README,v 1.1 2002/09/05 10:17:57 andrei Rel $
+#
+
+
+
+This is a module to help with NAT traversal.
+
+
+Exported Functions:
+------------------
+
+
+Name:	add_rport()
+Params:	
+Desc:	Adds blank `rport=' parameter into the first Via field.
+Example:	if (search("User-Agent: Cisco ATA.*") {add_rport();};
+
+
+Name:	fix_nated_contact()
+Params:	
+Desc:	
+Example:	
+
+
+Name:	add_direction_active()
+Params:	
+Desc:	
+Example:	
--- modules/nathelper/nathelper.c.orig	Mon Jan 20 01:07:47 2003
+++ modules/nathelper/nathelper.c	Mon Jan 20 01:07:47 2003
@@ -0,0 +1,392 @@
+/*$Id: nathelper.c,v 1.1 2003/01/10 17:04:41 root Exp root $
+ *
+ * Ser module, it implements the following commands:
+ * add_rport() - insert a rport parameter into the first Via field
+ * fix_nated_contact() - replaces host:port in Contact field with host:port
+ *			 we received this message from
+ * fix_nated_sdp() - replaces IP address in the SDP with IP address
+ *		     and/or adds direction=active option to the SDP
+ *
+ * Beware, those functions will only work correctly if the UA supports
+ * symmetric signalling and media (not all do)!!!
+ * 
+ *
+ * Copyright (C) 2003 Porta Software Ltd
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    info at iptel.org
+ *
+ * ser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "nhelpr_funcs.h"
+#include "../../sr_module.h"
+#include "../../dprint.h"
+#include "../../data_lump.h"
+#include "../../data_lump_rpl.h"
+#include "../../error.h"
+#include "../../mem/mem.h"
+#include "../../parser/parser_f.h"
+#include "../../ut.h"
+#include "../registrar/sip_msg.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int add_rport_f(struct sip_msg*, char*, char*);
+static int fix_nated_contact_f(struct sip_msg*, char*, char*);
+static int fix_nated_sdp_f(struct sip_msg*, char*, char*);
+
+inline static int fixup_str2int(void**, int);
+
+static int mod_init(void);
+
+struct module_exports exports= {
+	"nathelper",
+	(char*[])	{
+			"add_rport",
+			"fix_nated_contact",
+			"fix_nated_sdp",
+	},
+	(cmd_function[]) {
+			add_rport_f,
+			fix_nated_contact_f,
+			fix_nated_sdp_f,
+	},
+	(int[]) {
+			0,
+			0,
+			1,
+	},
+	(fixup_function[]){
+			0,
+			0,
+			fixup_str2int,
+	},
+	3,
+
+	0,      /* Module parameter names */
+	0,      /* Module parameter types */
+	0,      /* Module parameter variable pointers */
+	0,      /* Number of module paramers */
+	mod_init, /* module initialization functon */
+	0, /* response function */
+	0, /* destroy function */
+	0, /* on_cancel function */
+	0, /* per-child init function */
+};
+
+static int
+mod_init(void)
+{
+
+	return 0;
+}
+
+/*
+ * Adds `rport' parameter into the first Via header if it isn't
+ * there. It doesn't modify actual message, just adds a blank
+ * parameter into the msg->via1->rport leaving task of updating
+ * message itself to the core engine.
+ */
+static int
+add_rport_f(struct sip_msg* msg, char* str1, char* str2)
+{
+
+	if (msg->via1 == 0) {
+		if (parse_headers(msg, HDR_VIA1, 0) == -1)
+			LOG(L_ERR, "add_rport(): Error while parsing headers\n");
+		/* Return if no Via field or if it already contains rport */
+		if (msg->via1 == 0 || msg->via1->rport)
+			return -1;
+	}
+	msg->via1->rport = pkg_malloc(sizeof(struct via_param));
+	if (msg->via1->rport == 0) {
+		LOG(L_ERR, "ERROR: add_rport: out of memory\n");
+		return -1;
+	}
+	bzero(msg->via1->rport, (sizeof(struct via_param)));
+	/*add param to the list*/
+	if (msg->via1->last_param)
+		msg->via1->last_param->next = msg->via1->rport;
+	else
+		msg->via1->param_lst = msg->via1->rport;
+	msg->via1->last_param = msg->via1->rport;
+
+	return 1;
+}
+
+/*
+ * 
+ */
+static int
+fix_nated_contact_f(struct sip_msg* msg, char* str1, char* str2)
+{
+	int st, offset, len, len1;
+	str hostname, port;
+	char *cp, *buf, temp[2];
+	contact_t* c;
+	enum {ST1, ST2, ST3, ST4, ST5};
+	struct lump* anchor;
+
+	if ((parse_headers(msg, HDR_CONTACT, 0) == -1) || !msg->contact)
+		return -1;
+	if (!msg->contact->parsed && parse_contact(msg->contact) < 0) {
+		LOG(L_ERR, "fix_nated_contact: Error while parsing Contact body\n");
+		return -1;
+	}
+	c = ((contact_body_t*)msg->contact->parsed)->contacts;
+	if (!c) {
+		LOG(L_ERR, "fix_nated_contact: Error while parsing Contact body\n");
+		return -1;
+	}
+	st = ST1;
+	port.len = 0;
+	for (cp = c->uri.s + 1; cp < c->uri.s + c->uri.len; cp++) {
+		switch (*cp) {
+		case ':':
+			switch (st) {
+			case ST1:
+				st = ST2;
+				break;
+			case ST3:
+				hostname.len = cp - hostname.s + 1;
+				port.s = cp + 1;
+				st = ST4;
+				break;
+			}
+			break;
+
+		case '@':
+			if (st == ST2) {
+				hostname.s = cp + 1;
+				st = ST3;
+			}
+			break;
+
+		case ';':
+		case '>':
+			switch (st) {
+			case ST3:
+				hostname.len = cp - hostname.s;
+				st = ST5;
+				break;
+			case ST4:
+				port.len = cp - port.s;
+				st = ST5;
+				break;
+			}
+			break;
+
+		default:
+			break;
+		}
+	}
+	if (st != ST5 || hostname.len == 0) {
+		LOG(L_ERR, "fix_nated_contact: Error while parsing Contact URI\n");
+		return -1;
+	}
+	if (port.len == 0)
+		port.s = hostname.s + hostname.len;
+
+	offset = c->uri.s - msg->buf;
+	anchor = del_lump(&msg->add_rm, offset, c->uri.len, HDR_CONTACT);
+	if (anchor == 0)
+		return -1;
+
+	cp = ip_addr2a(&msg->src_ip);
+	len = c->uri.len + strlen(cp) + 6 /* :port */ - (hostname.len + port.len) + 1;
+	buf = pkg_malloc(len);
+	if (buf == NULL) {
+		LOG(L_ERR, "ERROR: fix_nated_contact: out of memory\n");
+		return -1;
+	}
+	temp[0] = hostname.s[0];
+	temp[1] = c->uri.s[c->uri.len];
+	c->uri.s[c->uri.len] = hostname.s[0] = '\0';
+	len1 = snprintf(buf, len, "%s%s:%d%s", c->uri.s, cp, msg->src_port_no,
+	    port.s + port.len);
+	if (len1 < len)
+		len = len1;
+	hostname.s[0] = temp[0];
+	c->uri.s[c->uri.len] = temp[1];
+	if (insert_new_lump_after(anchor, buf, len, HDR_CONTACT) == 0) {
+		pkg_free(buf);
+		return -1;
+	}
+	c->uri.s = buf;
+	c->uri.len = len;
+
+	return 1;
+}
+
+inline static int
+fixup_str2int( void** param, int param_no)
+{
+	unsigned int go_to;
+	int err;
+
+	if (param_no == 1) {
+		go_to = str2s(*param, strlen(*param), &err);
+		if (err == 0) {
+			free(*param);
+			*param = (void *)go_to;
+			return 0;
+		} else {
+			LOG(L_ERR, "ERROR: fixup_str2int: bad number <%s>\n",
+				(char *)(*param));
+			return E_CFG;
+		}
+	}
+	return 0;
+}
+
+#define	ADD_ADIRECTION	0x01
+#define	FIX_MEDIAIP	0x02
+
+#define ADIRECTION	"a=direction:active\r\n"
+#define	ADIRECTION_LEN	21
+
+#define CLEN_LEN	10
+
+static int
+fix_nated_sdp_f(struct sip_msg* msg, char* str1, char* str2)
+{
+	str body;
+	int level, added_len, offset, len, nextisip;
+	char *buf, *cp, *cp1;
+	struct lump* anchor;
+	str mediaip;
+
+	level = (int)str1;
+	added_len = 0;
+
+	if (extract_body(msg, &body) == -1 || body.len == 0) {
+		LOG(L_ERR,"ERROR: fix_nated_sdp: cannot extract body from msg!\n");
+		return -1;
+	}
+
+	if (level & ADD_ADIRECTION) {
+		anchor = anchor_lump(&(msg->add_rm),
+		    body.s + body.len - msg->buf, 0, 0);
+		if (anchor == NULL) {
+			LOG(L_ERR, "ERROR: fix_nated_sdp: anchor_lump failed\n");
+			return -1;
+		}
+		buf = pkg_malloc(ADIRECTION_LEN * sizeof(char));
+		if (buf == NULL) {
+			LOG(L_ERR, "ERROR: fix_nated_sdp: out of memory\n");
+			return -1;
+		}
+		memcpy(buf, ADIRECTION, ADIRECTION_LEN);
+		if (insert_new_lump_after(anchor, buf, ADIRECTION_LEN - 1, 0) == NULL) {
+			LOG(L_ERR, "ERROR: fix_nated_sdp: insert_new_lump_after failed\n");
+			pkg_free(buf);
+			return -1;
+		}
+		added_len += ADIRECTION_LEN - 1;
+	}
+
+	if (level & FIX_MEDIAIP) {
+		for (cp = body.s; (len = body.s + body.len - cp) > 0;) {
+			cp1 = strnstr(cp, "c=", len);
+			if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r')
+				break;
+			cp = cp1 + 2;
+		}
+		if (cp1 == NULL) {
+			LOG(L_ERR, "ERROR: fix_nated_sdp: no `c=' in SDP\n");
+			goto finalise;
+		}
+		mediaip.s = cp1 + 2;
+		mediaip.len = eat_line(mediaip.s, body.s + body.len - mediaip.s) - mediaip.s;
+		trim_len(mediaip.len, mediaip.s, mediaip);
+
+		nextisip = 0;
+		for (cp = mediaip.s; cp < mediaip.s + mediaip.len;) {
+			len = eat_token_end(cp, mediaip.s + mediaip.len) - cp;
+			if (nextisip == 1) {
+				mediaip.s = cp;
+				mediaip.len = len;
+				nextisip++;
+				break;
+			}
+			if (len == 3 && memcmp(cp, "IP4", 3) == 0)
+				nextisip = 1;
+			cp = eat_space_end(cp + len, mediaip.s + mediaip.len);
+		}
+		if (nextisip != 2 || mediaip.len == 0) {
+			LOG(L_ERR, "ERROR: fix_nated_sdp: no `IP4' in `c=' field\n");
+			goto finalise;
+		}
+
+		cp = ip_addr2a(&msg->src_ip);
+		len = strlen(cp);
+		/* check that updating mediaip is really necessary */
+		if (len == mediaip.len && memcmp(cp, mediaip.s, len) == 0)
+			goto finalise;
+		buf = pkg_malloc(len);
+		if (buf == NULL) {
+			LOG(L_ERR, "ERROR: fix_nated_sdp: out of memory\n");
+			return -1;
+		}
+		offset = mediaip.s - msg->buf;
+		anchor = del_lump(&msg->add_rm, offset, mediaip.len, 0);
+		if (anchor == NULL) {
+			LOG(L_ERR, "ERROR: fix_nated_sdp: del_lump failed\n");
+			pkg_free(buf);
+			return -1;
+		}
+		memcpy(buf, cp, len);
+		if (insert_new_lump_after(anchor, buf, len, 0) == 0) {
+			LOG(L_ERR, "ERROR: fix_nated_sdp: insert_new_lump_after failed\n");
+			pkg_free(buf);
+			return -1;
+		}
+		added_len += len - mediaip.len;
+	}
+
+finalise:
+	/* Check that Content-Length needs to be updated */
+	if (added_len != 0) {
+		buf = pkg_malloc(CLEN_LEN * sizeof(char));
+		if (buf == NULL) {
+			LOG(L_ERR, "ERROR: fix_nated_sdp: out of memory\n");
+			return -1;
+		}
+		offset = msg->content_length->body.s - msg->buf;
+		len = msg->content_length->body.len;
+		anchor = del_lump(&msg->add_rm, offset, len, HDR_CONTENTLENGTH);
+		if (anchor == NULL) {
+			LOG(L_ERR, "ERROR: fix_nated_sdp: del_lump failed\n");
+			pkg_free(buf);
+			return -1;
+		}
+		len = snprintf(buf, CLEN_LEN, "%d", body.len + added_len);
+		if (len >= CLEN_LEN)
+			len = CLEN_LEN - 1;
+		if (insert_new_lump_after(anchor, buf, len, HDR_CONTENTLENGTH) == NULL) {
+			LOG(L_ERR, "ERROR: fix_nated_sdp: insert_new_lump_after failed\n");
+			pkg_free(buf);
+			return -1;
+		}
+	}
+
+	return 1;
+}
--- modules/nathelper/nhelpr_funcs.c.orig	Mon Jan 20 01:07:47 2003
+++ modules/nathelper/nhelpr_funcs.c	Mon Jan 20 01:07:47 2003
@@ -0,0 +1,225 @@
+/*
+ * $Id: im_funcs.c,v 1.24 2002/09/20 12:04:20 bogdan Rel $
+ *
+ *
+ * Copyright (C) 2001-2003 Fhg Fokus
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    info at iptel.org
+ *
+ * ser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "nhelpr_funcs.h"
+#include "../../dprint.h"
+#include "../../config.h"
+#include "../../ut.h"
+#include "../../forward.h"
+#include "../../resolve.h"
+#include "../../globals.h"
+#include "../../udp_server.h"
+#include "../../pt.h"
+
+
+
+
+#define READ(val) \
+	(*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
+#define advance(_ptr,_n,_str,_error) \
+	do{\
+		if ((_ptr)+(_n)>(_str).s+(_str).len)\
+			goto _error;\
+		(_ptr) = (_ptr) + (_n);\
+	}while(0);
+#define one_of_16( _x , _t ) \
+	(_x==_t[0]||_x==_t[15]||_x==_t[8]||_x==_t[2]||_x==_t[3]||_x==_t[4]\
+	||_x==_t[5]||_x==_t[6]||_x==_t[7]||_x==_t[1]||_x==_t[9]||_x==_t[10]\
+	||_x==_t[11]||_x==_t[12]||_x==_t[13]||_x==_t[14])
+#define one_of_8( _x , _t ) \
+	(_x==_t[0]||_x==_t[7]||_x==_t[1]||_x==_t[2]||_x==_t[3]||_x==_t[4]\
+	||_x==_t[5]||_x==_t[6])
+
+
+
+
+int get_body_len( struct sip_msg* msg)
+{
+	int x,err;
+	str foo;
+
+	if (!msg->content_length)
+	{
+		LOG(L_ERR,"ERROR: get_body_len: Content-Length header absent!\n");
+		goto error;
+	}
+	/* if header is present, trim to get only the string containing numbers */
+	trim_len( foo.len , foo.s , msg->content_length->body );
+	/* convert from string to number */
+	x = str2s( (unsigned char*)foo.s,foo.len,&err);
+	if (err){
+		LOG(L_ERR, "ERROR: get_body_len:"
+			" unable to parse the Content_Length number !\n");
+		goto error;
+	}
+	return x;
+error:
+	return -1;
+}
+
+
+
+
+int check_content_type(struct sip_msg *msg)
+{
+	static unsigned int appl[16] = {
+		0x6c707061/*appl*/,0x6c707041/*Appl*/,0x6c705061/*aPpl*/,
+		0x6c705041/*APpl*/,0x6c507061/*apPl*/,0x6c507041/*ApPl*/,
+		0x6c505061/*aPPl*/,0x6c505041/*APPl*/,0x4c707061/*appL*/,
+		0x4c707041/*AppL*/,0x4c705061/*aPpL*/,0x4c705041/*APpL*/,
+		0x4c507061/*apPL*/,0x4c507041/*ApPL*/,0x4c505061/*aPPL*/,
+		0x4c505041/*APPL*/};
+	static unsigned int icat[16] = {
+		0x74616369/*icat*/,0x74616349/*Icat*/,0x74614369/*iCat*/,
+		0x74614349/*ICat*/,0x74416369/*icAt*/,0x74416349/*IcAt*/,
+		0x74414369/*iCAt*/,0x74414349/*ICAt*/,0x54616369/*icaT*/,
+		0x54616349/*IcaT*/,0x54614369/*iCaT*/,0x54614349/*ICaT*/,
+		0x54416369/*icAT*/,0x54416349/*IcAT*/,0x54414369/*iCAT*/,
+		0x54414349/*ICAT*/};
+	static unsigned int ion_[8] = {
+		0x006e6f69/*ion_*/,0x006e6f49/*Ion_*/,0x006e4f69/*iOn_*/,
+		0x006e4f49/*IOn_*/,0x004e6f69/*ioN_*/,0x004e6f49/*IoN_*/,
+		0x004e4f69/*iON_*/,0x004e4f49/*ION_*/};
+	static unsigned int sdp_[8] = {
+		0x00706473/*sdp_*/,0x00706453/*Sdp_*/,0x00704473/*sDp_*/,
+		0x00704453/*SDp_*/,0x00506473/*sdP_*/,0x00506453/*SdP_*/,
+		0x00504473/*sDP_*/,0x00504453/*SDP_*/};
+	str           str_type;
+	unsigned int  x;
+	char          *p;
+
+	if (!msg->content_type)
+	{
+		LOG(L_WARN,"WARNING: get_body_len: Content-TYPE header absent!"
+			"let's assume the content is text/plain ;-)\n");
+		return 1;
+	}
+
+	trim_len(str_type.len,str_type.s,msg->content_type->body);
+	p = str_type.s;
+	advance(p,4,str_type,error_1);
+	x = READ(p-4);
+	if (!one_of_16(x,appl))
+		goto other;
+	advance(p,4,str_type,error_1);
+	x = READ(p-4);
+	if (!one_of_16(x,icat))
+		goto other;
+	advance(p,3,str_type,error_1);
+	x = READ(p-3) & 0x00ffffff;
+	if (!one_of_8(x,ion_))
+		goto other;
+
+	/* skip spaces and tabs if any */
+	while (*p==' ' || *p=='\t')
+		advance(p,1,str_type,error_1);
+	if (*p!='/')
+	{
+		LOG(L_ERR, "ERROR:check_content_type: parse error:"
+			"no / found after primary type\n");
+		goto error;
+	}
+	advance(p,1,str_type,error_1);
+	while ((*p==' ' || *p=='\t') && p+1<str_type.s+str_type.len)
+		advance(p,1,str_type,error_1);
+
+	advance(p,3,str_type,error_1);
+	x = READ(p-3) & 0x00ffffff;
+	if (!one_of_8(x,sdp_))
+		goto other;
+
+	if (*p==';'||*p==' '||*p=='\t'||*p=='\n'||*p=='\r'||*p==0) {
+		DBG("DEBUG:check_content_type: type <%.*s> found valid\n",
+			p-str_type.s,str_type.s);
+		return 1;
+	} else {
+		LOG(L_ERR,"ERROR:check_content_type: bad end for type!\n");
+		return -1;
+	}
+
+error_1:
+	LOG(L_ERR,"ERROR:check_content_type: parse error: body ended :-(!\n");
+error:
+	return -1;
+other:
+	LOG(L_ERR,"ERROR:check_content_type: invlaid type for a message\n");
+	return -1;
+}
+
+
+
+
+int extract_body(struct sip_msg *msg, str *body )
+{
+	int len;
+	int offset;
+
+	if ( parse_headers(msg,HDR_EOH, 0)==-1 )
+	{
+		LOG(L_ERR,"ERROR: extract_body:unable to parse all headers!\n");
+		goto error;
+	}
+
+	/*is the content type corect?*/
+	if (check_content_type(msg)==-1)
+	{
+		LOG(L_ERR,"ERROR: extract_body: content type mismatching\n");
+		goto error;
+	}
+
+	/* get the lenght from COntent-Lenght header */
+	if ( (len = get_body_len(msg))<0 )
+	{
+		LOG(L_ERR,"ERROR: extract_body: cannot get body length\n");
+		goto error;
+	}
+
+	if ( strncmp(CRLF,msg->unparsed,CRLF_LEN)==0 )
+		offset = CRLF_LEN;
+	else if (*(msg->unparsed)=='\n' || *(msg->unparsed)=='\r' )
+		offset = 1;
+	else{
+		LOG(L_ERR,"ERROR: extract_body:unable to detect the beginning"
+			" of message body!\n ");
+		goto error;
+	}
+
+	body->s = msg->unparsed + offset;
+	body->len = len;
+	DBG("DEBUG:extract_body:=|%.*s|\n",body->len,body->s);
+
+	return 1;
+error:
+	return -1;
+}
+
--- modules/nathelper/nhelpr_funcs.h.orig	Mon Jan 20 01:07:47 2003
+++ modules/nathelper/nhelpr_funcs.h	Mon Jan 20 01:07:47 2003
@@ -0,0 +1,40 @@
+/*
+ * $Id: im_funcs.h,v 1.7 2002/09/20 12:04:20 bogdan Rel $
+ *
+ *
+ * Copyright (C) 2001-2003 Fhg Fokus
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    info at iptel.org
+ *
+ * ser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _NHLPR_FUNCS_H
+#define  _NHLPR_FUNCS_H
+
+#include "../../str.h"
+#include "../../parser/msg_parser.h"
+
+int extract_body(struct sip_msg * , str *);
+int check_content_type(struct sip_msg * );
+int get_body_len( struct sip_msg* );
+
+#endif
--- parser/msg_parser.h.orig	Wed Oct 23 18:12:20 2002
+++ parser/msg_parser.h	Mon Jan 20 01:07:48 2003
@@ -118,6 +118,7 @@
 	char* unparsed;   /* here we stopped parsing*/
 
 	struct ip_addr src_ip;
+	unsigned short src_port_no;
 	struct ip_addr dst_ip;
 	
 	char* orig;       /* original message copy */
--- parser/parse_via.c.orig	Thu Sep 19 15:23:55 2002
+++ parser/parse_via.c	Mon Jan 20 01:07:48 2003
@@ -87,8 +87,10 @@
 	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,
 	     /*GEN_PARAM,
 	       PARAM_ERROR*/ /* declared in msg_parser.h*/
 };
@@ -125,6 +127,7 @@
 					case FIN_TTL:
 					case FIN_MADDR:
 					case FIN_RECEIVED:
+					case FIN_RPORT:
 						*tmp=0;
 						param->type=state;
 						param->name.len=tmp-param->name.s;
@@ -160,6 +163,7 @@
 					case FIN_TTL:
 					case FIN_MADDR:
 					case FIN_RECEIVED:
+					case FIN_RPORT:
 						*tmp=0;
 						param->type=state;
 						param->name.len=tmp-param->name.s;
@@ -200,6 +204,7 @@
 					case FIN_TTL:
 					case FIN_MADDR:
 					case FIN_RECEIVED:
+					case FIN_RPORT:
 						*tmp=0;
 						param->type=state;
 						param->name.len=tmp-param->name.s;
@@ -231,6 +236,7 @@
 					case FIN_TTL:
 					case FIN_MADDR:
 					case FIN_RECEIVED:
+					case FIN_RPORT:
 						*tmp=0;
 						param->type=state;
 						param->name.len=tmp-param->name.s;
@@ -257,6 +263,7 @@
 				break;
 			case ';':
 				switch(state){
+					case FIN_RPORT:
 					case FIN_HIDDEN:
 						*tmp=0;
 						param->type=state;
@@ -296,6 +303,7 @@
 					case FIN_MADDR:
 					case FIN_TTL:
 					case FIN_RECEIVED:
+					case FIN_RPORT:
 						LOG(L_ERR, "ERROR: parse_via_param: new via found" 
 								"(',') when '=' expected (state %d=)\n",
 								state);
@@ -458,6 +466,9 @@
 					case TTL1:
 						state=TTL2;
 						break;
+					case RPORT3:
+						state=FIN_RPORT;
+						break;
 					case GEN_PARAM:
 						break;
 					case F_CR:
@@ -545,6 +556,9 @@
 					case BRANCH1:
 						state=BRANCH2;
 						break;
+					case RPORT2:
+						state=RPORT3;
+						break;
 					case GEN_PARAM:
 						break;
 					case F_CR:
@@ -619,7 +633,36 @@
 						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:
@@ -1681,6 +1724,8 @@
 							vb->branch=param;
 						else if (param->type==PARAM_RECEIVED)
 							vb->received=param;
+						else if (param->type==PARAM_RPORT)
+							vb->rport=param;
 						break;
 					case P_PARAM:
 						break;
--- parser/parse_via.h.orig	Mon Oct 21 18:46:27 2002
+++ parser/parse_via.h	Mon Jan 20 01:07:48 2003
@@ -36,7 +36,7 @@
  */
 enum {
 	PARAM_HIDDEN=230, PARAM_TTL, PARAM_BRANCH, 
-	PARAM_MADDR, PARAM_RECEIVED, GEN_PARAM,
+	PARAM_MADDR, PARAM_RECEIVED, PARAM_RPORT, GEN_PARAM,
 	PARAM_ERROR
 };
 
@@ -70,6 +70,7 @@
 	struct via_param* branch;
 	str tid; /* transaction id, part of branch */
 	struct via_param* received;
+	struct via_param* rport;
 	
 	struct via_body* next; /* pointer to next via body string if
 				  compact via or null */
--- config.h.orig	Mon Oct 21 22:21:50 2002
+++ config.h	Mon Jan 20 01:07:47 2003
@@ -82,6 +82,9 @@
 #define RECEIVED   ";received="
 #define RECEIVED_LEN 10
 
+#define RPORT ";rport="
+#define RPORT_LEN 7
+
 #define SRV_PREFIX "_sip._udp."
 #define SRV_PREFIX_LEN 10
 
@@ -112,6 +115,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
--- forward.c.orig	Thu Oct 24 17:21:08 2002
+++ forward.c	Mon Jan 20 01:07:47 2003
@@ -240,19 +240,27 @@
 int update_sock_struct_from_ip( union sockaddr_union* to,
 	struct sip_msg *msg )
 {
+	unsigned short port_no;
 
-	init_su(to, &msg->src_ip, 
-		(msg->via1->port)?htons(msg->via1->port): htons(SIP_PORT) );
+	if (msg->via1->rport && msg->src_port_no)
+		port_no = msg->src_port_no;
+	else if (msg->via1->port)
+		port_no = msg->via1->port;
+	else
+		port_no = SIP_PORT;
+
+	init_su(to, &msg->src_ip, htons(port_no));
 	return 1;
 }
 
 int update_sock_struct_from_via( union sockaddr_union* to,
-								 struct via_body* via )
+	struct via_body* via, struct sip_msg *msg)
 {
 	struct hostent* he;
 	char *host_copy;
 	str* name;
-	unsigned short port;
+	unsigned short port, rport;
+	int err;
 
 
 	if (via->received){
@@ -266,6 +274,13 @@
 		name=&(via->host);
 		port=via->port;
 	}
+	if (via->rport && via->rport->value.s) {
+		rport=str2s(via->rport->value.s, via->rport->value.len, &err);
+		if (!err)
+			port=rport;
+	} else if (via->rport && !via->rport->value.s) {
+		port = msg->src_port_no;
+	}
 	/* we do now a malloc/memcpy because gethostbyname loves \0-terminated 
 	   strings; -jiri 
 	   but only if host is not null terminated
@@ -353,7 +368,7 @@
 		goto error;
 	}
 
-	if (update_sock_struct_from_via( to, msg->via2 )==-1) goto error;
+	if (update_sock_struct_from_via( to, msg->via2, msg)==-1) goto error;
 	send_sock=get_send_socket(to);
 	if (send_sock==0){
 		LOG(L_ERR, "forward_reply: ERROR: no sending socket found\n");
--- forward.h.orig	Wed Oct 23 18:12:20 2002
+++ forward.h	Mon Jan 20 01:07:47 2003
@@ -40,7 +40,7 @@
 int check_self(str* host, unsigned short port);
 int forward_request( struct sip_msg* msg,  struct proxy_l* p);
 int update_sock_struct_from_via( union sockaddr_union* to,
-								struct via_body* via );
+    struct via_body* via, struct sip_msg *msg );
 int update_sock_struct_from_ip( union sockaddr_union* to,
     struct sip_msg *msg );
 int forward_reply( struct sip_msg* msg);
--- ip_addr.h.orig	Mon Nov  4 19:05:32 2002
+++ ip_addr.h	Mon Jan 20 01:07:47 2003
@@ -201,6 +201,21 @@
 	}
 }
 
+static inline unsigned int su2port_no(union sockaddr_union* su)
+{
+	switch(su->s.sa_family){
+	case AF_INET:
+					return ntohs(su->sin.sin_port);
+#ifdef USE_IPV6
+	case AF_INET6:
+					return ntohs(su->sin6.sin6_port);
+#endif
+	default:
+					LOG(L_CRIT,"su2port_no: BUG: unknown address family %d\n",
+							su->s.sa_family);
+	}
+	return 0;
+}
 
 /* ip_addr2su -> the same as init_su*/
 #define ip_addr2su init_su
--- msg_translator.c.orig	Mon Oct 21 22:21:50 2002
+++ msg_translator.c	Mon Jan 20 01:07:48 2003
@@ -145,9 +145,10 @@
 	else
 		foo=&(msg->first_line.u.request.uri);
 	print_len=snprintf(buf+fix_len, MAX_WARNING_LEN-fix_len,
-		"pid=%d req_src_ip=%s in_uri=%.*s out_uri=%.*s via_cnt%c=%d\"",
+		"pid=%d req_src_ip=%s req_src_port=%d in_uri=%.*s out_uri=%.*s via_cnt%c=%d\"",
 		my_pid(),
 		ip_addr2a(&msg->src_ip),
+		msg->src_port_no,
 		msg->first_line.u.request.uri.len, msg->first_line.u.request.uri.s,
 		foo->len, foo->s, 
 		msg->parsed_flag & HDR_EOH ? '=' : '>', /* should be = */
@@ -208,7 +209,26 @@
 	return buf;
 }
 
+char *rport_builder(struct sip_msg *msg, unsigned int *rport_len)
+{
+	char *buf;
 
+	buf=pkg_malloc(sizeof(char)*MAX_RPORT_SIZE);
+	if (buf==0){
+		ser_error=E_OUT_OF_MEM;
+		LOG(L_ERR, "ERROR: rport_builder: out of memory\n");
+		return 0;
+	}
+	/*
+	 * Don't need any sanity checks here, because
+	 * msg->src_port_no is unsigned int, which means
+	 * that it couldn't be more than 5 chars long in
+	 * string representation.
+	 */
+	*rport_len = snprintf(buf, MAX_RPORT_SIZE, "%s%u", RPORT, msg->src_port_no);
+
+	return buf;
+}
 
 /* computes the "unpacked" len of a lump list,
    code moved from build_req_from_req */
@@ -395,9 +415,10 @@
 								unsigned int *returned_len,
 								struct socket_info* send_sock)
 {
-	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;
@@ -411,8 +432,10 @@
 	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, 
@@ -430,6 +453,11 @@
 		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 also line_buf */
+	}
 
 	/* add via header to the list */
 	/* try to add it before msg. 1st via */
@@ -459,6 +487,32 @@
 		if (insert_new_lump_after(anchor, received_buf, received_len, HDR_VIA)
 				==0 ) goto error02; /* free also line_buf */
 	}
+	/* if rport needs to be updated do it */
+	if (rport_len){
+		if (msg->via1->rport->name.s){
+			/* rport already here - just update it */
+			offset = msg->via1->rport->name.s - buf - 1;
+			anchor=del_lump(&msg->add_rm, offset, msg->via1->rport->size + 1, HDR_VIA);
+		} else {
+			/* no rport in the original message - add it */
+			if (msg->via1->params.s){
+				size= msg->via1->params.s-msg->via1->hdr.s-1;
+			} else {
+				size= msg->via1->host.s-msg->via1->hdr.s+msg->via1->host.len;
+				if (msg->via1->port!=0){
+					size += msg->via1->port_str.len + 1; /* +1 for ':'*/
+				}
+			#ifdef USE_IPV6
+				if(send_sock->address.af==AF_INET6) size+=1; /* +1 for ']'*/
+			#endif
+			}
+			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 (insert_new_lump_after(anchor, rport_buf, rport_len, HDR_VIA)
+				==0 ) goto error02;	/* free also line_buf */
+	}
 
 	/* compute new msg len and fix overlapping zones*/
 	new_len=len+lumps_len(msg->add_rm);
@@ -507,6 +561,7 @@
 	pkg_free(line_buf);
 error02:
 	if (received_buf) pkg_free(received_buf);
+	if (rport_buf) pkg_free(rport_buf);
 error00:
 	*returned_len=0;
 	return 0;
@@ -587,14 +642,18 @@
 	int               i;
 	char              backup;
 	char              *received_buf;
+	char		  *rport_buf;
 	unsigned int               received_len;
+	unsigned int               rport_len;
 	char              *warning;
 	unsigned int      warning_len;
 	int r;
 	str to_tag;
 
 	received_buf=0;
+	rport_buf=0;
 	received_len=0;
+	rport_len=0;
 	buf=0;
 	/* make -Wall happy */
 	warning=0;
@@ -621,6 +680,15 @@
 			goto error00;
 		}
 	}
+        /* 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) {
+			LOG(L_ERR, "ERROR: build_res_buf_from_sip_req: "
+				"alas, rport_builder failed\n");
+                        goto error00;
+		}
+		rport_len -= msg->via1->rport->size;
+        }
 
 	/*computes the lenght of the new response buffer*/
 	len = 0;
@@ -641,7 +709,7 @@
 						len+=new_tag_len+5/*";tag="*/;
 				}
 			case HDR_VIA:
-				if (hdr==msg->h_via1) len += received_len;
+				if (hdr==msg->h_via1) len += received_len + rport_len;
 			case HDR_FROM:
 			case HDR_CALLID:
 			case HDR_CSEQ:
@@ -716,8 +784,22 @@
 					break;
 				}
 			case HDR_VIA:
-				append_str_trans( p, hdr->name.s ,
+				if (hdr==msg->h_via1 && rport_buf && msg->via1->rport->name.s) {
+					append_str_trans( p, hdr->name.s ,
+					    msg->via1->rport->name.s - hdr->name.s - 1, msg);
+					append_str( p, rport_buf,
+					    rport_len + msg->via1->rport->size, msg);
+					append_str_trans( p, msg->via1->rport->name.s +
+					    msg->via1->rport->size,
+					    hdr->body.s + hdr->body.len -
+					    msg->via1->rport->name.s -
+					    msg->via1->rport->size, msg);
+				} else {
+					append_str_trans( p, hdr->name.s ,
 					((hdr->body.s+hdr->body.len )-hdr->name.s ),msg);
+					if (hdr==msg->h_via1 && rport_buf)
+						append_str( p, rport_buf, rport_len, msg);
+				}
 				if (hdr==msg->h_via1 && received_buf)
 					append_str( p, received_buf, received_len, msg);
 				append_str( p, CRLF,CRLF_LEN,msg);
@@ -763,10 +845,12 @@
 	   needs to be deleted here
 	*/
 	if (received_buf) pkg_free(received_buf);
+	if (rport_buf) pkg_free(rport_buf);
 	return buf;
 
 error01:
 	if (received_buf) pkg_free(received_buf);
+	if (rport_buf) pkg_free(rport_buf);
 error00:
 	*returned_len=0;
 	return 0;
--- receive.c.orig	Thu Oct  3 23:06:10 2002
+++ receive.c	Mon Jan 20 01:07:48 2003
@@ -77,6 +77,7 @@
 	   useful as most of the work is done with scrath-pad; -jiri  */
 	buf[len]=0;
 	su2ip_addr(&msg->src_ip, src_su);
+	msg->src_port_no=su2port_no(src_su);
 	msg->dst_ip=bind_address->address; /* won't work if listening on 0.0.0.0 */
 	msg->id=msg_no;
 	/* make a copy of the message */


More information about the sr-users mailing list