--- 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; inr_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@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 +#include +#include + +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@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 +#include +#include +#include +#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 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@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 */