Hello,
I will review the patch and let you know.
Thanks! In the meantime, I've located and fixed several bugs in it,
so that please don't hurry up applying it to the repository yet.
-Maxim
regards, Jan.
On 11-01 06:50, Maxim Sobolev wrote:
Thank you for the explanation! Attached please
find first version
of `rport' support for SER (we need it in the core engine), the
module will follow probably tomorrow. Please note that the code
is quite raw (6:20 am here ;) and I did not perform any seriuos
tests yet.
The code does the following:
1. Adds support for `rport' Via field parameter into the message
parser;
2. Extends parser to allow valueless parameters as requred by
the draft RFC. This will probably requre additional code
review, as there may be places in the code where it is
assumed that parameter value could not be a NULL pointer;
3. Fills in blank rport parameter if present before forwarding
a request or replying to it;
4. Changes the code, so that if `rport' is present, then this
port is used for connecting to that UA.
Any comments, corrections or suggestions are highly appreciated!
-Maxim
On Sat, Jan 11, 2003 at 12:04:34AM +0100, Jiri Kuthan wrote:
> that's correct.
>
> >1. Check that _m->somefield is NULL and call parse_headers() with the
> >appropriate HDR_FOO flag.
>
> yes. you can skip the first check, parse_headers will do it;
> don't forget to handle errors if parse_headers returns -1
> (most likely mem alloc failure)
>
> >2. Check that _m->somefield is non-NULL and return if false.
>
> yes, that means, that the header field is not in message.
>
> note too that some header fields may occur multiple times; in which case
> msg->hdr_foo points to the first occurence; if you wish to
> process all of them, you need to traverse the list
> msg->headers
>
> example from record-routing (XXX are my extra comments):
>
> int find_first_route(struct sip_msg* _m)
> {
> /* XXX don't look at _m->route ... parse_headers will do it for you */
> if (parse_headers(_m, HDR_ROUTE, 0) == -1) {
> /* XXX -1 is some bad error, most likely lack of memory -- leave! */
> LOG(L_ERR, "find_first_route(): Error while parsing headers\n");
> return -1;
> } else {
>
> if (_m->route) {
> return 0;
> } else { /* XXX not found .... the header field is not there */
> DBG("find_first_route(): No Route headers found\n");
> return 1;
> }
> }
> }
>
>
>
> >3. Modify _m->somefield according to the type of that field.
> >4. Using del_lump() mark original version of the header for deletion and
> >using insert_new_lump() indicate where modified version should be placed
> >before sending a message out.
>
> 3 is the same as 4, isn't it. you modify a header field by creating
> a delete lump refering the old value and an insert lump with the new
> value. the new value must be created using pkg_malloc. the replace
> action in textops module is a good example. (The lump lists, sort
> of "diffs", is processed when later on the message is printed and
forwarded.)
>
> -Jiri
--- modules/sl/sl_funcs.c.orig Mon Oct 21
23:30:15 2002
+++ modules/sl/sl_funcs.c Sat Jan 11 06:09:54 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/t_lookup.c.orig Mon Oct 21 22:21:50 2002
+++ modules/tm/t_lookup.c Sat Jan 11 06:09:54 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;
--- parser/msg_parser.h.orig Wed Oct 23 18:12:20 2002
+++ parser/msg_parser.h Sat Jan 11 06:15:11 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 Sat Jan 11 06:09:54 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;
@@ -267,6 +273,7 @@
case FIN_MADDR:
case FIN_TTL:
case FIN_RECEIVED:
+ case FIN_RPORT:
LOG(L_ERR, "ERROR: parse_via: invalid char <%c> in"
" state %d\n", *tmp, state);
goto error;
@@ -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:
@@ -750,6 +793,11 @@
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:
@@ -1681,6 +1729,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 Sat Jan 11 06:09:54 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 Sat Jan 11 06:09:54 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.h.orig Wed Oct 23 18:12:20 2002
+++ forward.h Sat Jan 11 06:09:54 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 Sat Jan 11 06:09:54 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 Sat Jan 11 06:09:54 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,14 @@
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){
+ offset = msg->via1->rport->value.s - buf - 1;
+ anchor=del_lump(&msg->add_rm, offset, msg->via1->rport->size + 1,
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 +543,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 +624,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 +662,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 +691,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,10 +766,23 @@
break;
}
case HDR_VIA:
- append_str_trans( p, hdr->name.s ,
+ if (hdr==msg->h_via1 && rport_buf) {
+ 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 && received_buf)
append_str( p, received_buf, received_len, msg);
+
append_str( p, CRLF,CRLF_LEN,msg);
break;
case HDR_FROM:
@@ -763,10 +826,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 Sat Jan 11 06:09:54 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 */
--- forward.c.orig Thu Oct 24 17:21:08 2002
+++ forward.c Sat Jan 11 06:21:11 2003
@@ -240,14 +240,21 @@
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->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;
@@ -266,6 +273,11 @@
name=&(via->host);
port=via->port;
}
+ if (via->rport && via->rport->value.s) {
+ port=atoi(via->rport->value.s);
+ } else if (via->rport && via->rport->value.s==0 &&
!via->received) {
+ return update_sock_struct_from_ip( to, msg);
+ }
/* we do now a malloc/memcpy because gethostbyname loves \0-terminated
strings; -jiri
but only if host is not null terminated
@@ -353,7 +365,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");