From 536065b88589f9f8fa82b1942fee143cfd75fbdd Mon Sep 17 00:00:00 2001 From: Miklos Tirpak Date: Tue, 10 Mar 2009 16:26:35 +0000 Subject: [PATCH 1/1] Strip, prefix, rewriteuser, ... all the SET_* actions preserve the original URI scheme unless the host name is rewritten. If the host name is set, then tel: and tels: URIs are converted to sip: or sips:, and the user=phone parameter is added. A script function, userphone(), is introduced: It adds the "user=phone" parameter to a sip: or sips: RURI if the param is not yet present. (Does not change tel: and tels: URIs). (Patch has been created with cooperation with Michal Matyska.) Fixes SER-435. --- action.c | 129 ++++++++++++++++++++++++++++++++++++++++----- cfg.lex | 4 ++ cfg.y | 4 ++ parser/parse_uri.c | 8 +-- parser/parse_uri.h | 1 + route_struct.h | 2 +- 6 files changed, 129 insertions(+), 19 deletions(-) diff --git a/action.c b/action.c index f825626df6..b35a543da6 100644 --- a/action.c +++ b/action.c @@ -110,6 +110,7 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg) unsigned short flags; int_str name, value; str* dst_host; + int orig_p2t; /* reset the value of error to E_UNSPEC so avoid unknowledgable functions to return with error (status<0) and not setting it @@ -483,18 +484,22 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg) case PREFIX_T: case STRIP_T: case STRIP_TAIL_T: + case SET_USERPHONE_T: user=0; if (a->type==STRIP_T || a->type==STRIP_TAIL_T) { if (a->val[0].type!=NUMBER_ST) { LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n", a->val[0].type); + ret=E_BUG; break; } - } else if (a->val[0].type!=STRING_ST){ - LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n", + } else if (a->type!=SET_USERPHONE_T) { + if (a->val[0].type!=STRING_ST) { + LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n", a->val[0].type); - ret=E_BUG; - break; + ret=E_BUG; + break; + } } if (a->type==SET_URI_T){ if (msg->new_uri.s) { @@ -517,7 +522,7 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg) ret=1; break; } - if (msg->parsed_uri_ok==0) { + if ((msg->parsed_uri_ok==0) || ((uri.flags & URI_SIP_USER_PHONE)!=0)) { if (msg->new_uri.s) { tmp=msg->new_uri.s; len=msg->new_uri.len; @@ -525,16 +530,41 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg) tmp=msg->first_line.u.request.uri.s; len=msg->first_line.u.request.uri.len; } + /* don't convert sip:user=phone to tel, otherwise we loose parameters */ + orig_p2t=phone2tel; + phone2tel=0; + msg->parsed_uri_ok=0; if (parse_uri(tmp, len, &uri)<0){ + phone2tel=orig_p2t; LOG(L_ERR, "ERROR: do_action: bad uri <%s>, dropping" " packet\n", tmp); ret=E_UNSPEC; break; } + phone2tel=orig_p2t; } else { uri=msg->parsed_uri; } + /* skip SET_USERPHONE_T action if the URI is already + * a tel: or tels: URI, or contains the user=phone param */ + if ((a->type==SET_USERPHONE_T) + && ((uri.type==TEL_URI_T) || (uri.type==TELS_URI_T) + || ((uri.user_param_val.len==5) && (memcmp(uri.user_param_val.s, "phone", 5)==0))) + ) { + ret=1; + break; + } + /* SET_PORT_T does not work with tel: URIs */ + if ((a->type==SET_PORT_T) + && ((uri.type==TEL_URI_T) || (uri.type==TELS_URI_T)) + && ((uri.flags & URI_SIP_USER_PHONE)==0) + ) { + LOG(L_ERR, "ERROR: do_action: port number of a tel: URI cannot be set\n"); + ret=E_UNSPEC; + break; + } + new_uri=pkg_malloc(MAX_URI_SIZE); if (new_uri==0){ LOG(L_ERR, "ERROR: do_action: memory allocation " @@ -545,8 +575,57 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg) end=new_uri+MAX_URI_SIZE; crt=new_uri; /* begin copying */ - len=strlen("sip:"); if(crt+len>end) goto error_uri; - memcpy(crt,"sip:",len);crt+=len; + /* Preserve the URI scheme unless the host part needs + * to be rewritten, and the shceme is tel: or tels: */ + switch (uri.type) { + case SIP_URI_T: + len=s_sip.len; + tmp=s_sip.s; + break; + + case SIPS_URI_T: + len=s_sips.len; + tmp=s_sips.s; + break; + + case TEL_URI_T: + if ((uri.flags & URI_SIP_USER_PHONE) + || (a->type==SET_HOST_T) + || (a->type==SET_HOSTPORT_T) + || (a->type==SET_HOSTPORTTRANS_T) + ) { + len=s_sip.len; + tmp=s_sip.s; + break; + } + len=s_tel.len; + tmp=s_tel.s; + break; + + case TELS_URI_T: + if ((uri.flags & URI_SIP_USER_PHONE) + || (a->type==SET_HOST_T) + || (a->type==SET_HOSTPORT_T) + || (a->type==SET_HOSTPORTTRANS_T) + ) { + len=s_sips.len; + tmp=s_sips.s; + break; + } + len=s_tels.len; + tmp=s_tels.s; + break; + + default: + LOG(L_ERR, "ERROR: Unsupported URI scheme (%d), " + "reverted to sip:\n", + uri.type); + len=s_sip.len; + tmp=s_sip.s; + } + if(crt+len+1 /* colon */ >end) goto error_uri; + memcpy(crt,tmp,len);crt+=len; + *crt=':'; crt++; /* user */ @@ -607,21 +686,27 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg) memcpy(crt,tmp,len);crt+=len; } /* host */ - if (user || tmp){ /* add @ */ - if(crt+1>end) goto error_uri; - *crt='@'; crt++; - } if ((a->type==SET_HOST_T) || (a->type==SET_HOSTPORT_T) - || (a->type==SET_HOSTPORTTRANS_T)) { + || (a->type==SET_HOSTPORTTRANS_T) + ) { tmp=a->val[0].u.string; if (tmp) len = strlen(tmp); else len=0; - } else { + } else if ((uri.type==SIP_URI_T) + || (uri.type==SIPS_URI_T) + || (uri.flags & URI_SIP_USER_PHONE) + ) { tmp=uri.host.s; - len = uri.host.len; + len=uri.host.len; + } else { + tmp=0; } if (tmp){ + if (user) { /* add @ */ + if(crt+1>end) goto error_uri; + *crt='@'; crt++; + } if(crt+len>end) goto error_uri; memcpy(crt,tmp,len);crt+=len; } @@ -669,6 +754,22 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg) memcpy(crt,tmp,len);crt+=len; } } + /* Add the user=phone param if a tel: or tels: + * URI was converted to sip: or sips:. + * (host part of a tel/tels URI was set.) + * Or in case of sip: URI and SET_USERPHONE_T action */ + if (((((uri.type==TEL_URI_T) || (uri.type==TELS_URI_T)) + && ((uri.flags & URI_SIP_USER_PHONE)==0)) + && ((a->type==SET_HOST_T) + || (a->type==SET_HOSTPORT_T) + || (a->type==SET_HOSTPORTTRANS_T))) + || (a->type==SET_USERPHONE_T) + ) { + tmp=";user=phone"; + len=strlen(tmp); + if(crt+len>end) goto error_uri; + memcpy(crt,tmp,len);crt+=len; + } /* headers */ tmp=uri.headers.s; if (tmp){ diff --git a/cfg.lex b/cfg.lex index 175ac686f4..73c23ef612 100644 --- a/cfg.lex +++ b/cfg.lex @@ -75,6 +75,7 @@ * 2007-11-28 added TCP_OPT_{FD_CACHE, DEFER_ACCEPT, DELAYED_ACK, SYNCNT, * LINGER2, KEEPALIVE, KEEPIDLE, KEEPINTVL, KEEPCNT} (andrei) * 2008-01-24 added CFG_DESCRIPTION used by cfg_var (Miklos) + * 2009-03-10 added SET_USERPHONE action (Miklos) */ @@ -164,6 +165,7 @@ REVERT_URI "revert_uri" PREFIX "prefix" STRIP "strip" STRIP_TAIL "strip_tail" +SET_USERPHONE "userphone" APPEND_BRANCH "append_branch" IF "if" ELSE "else" @@ -465,6 +467,8 @@ EAT_ABLE [\ \t\b\r] {STRIP_TAIL} { count(); yylval.strval=yytext; return STRIP_TAIL; } {APPEND_BRANCH} { count(); yylval.strval=yytext; return APPEND_BRANCH; } +{SET_USERPHONE} { count(); yylval.strval=yytext; + return SET_USERPHONE; } {FORCE_RPORT} { count(); yylval.strval=yytext; return FORCE_RPORT; } {FORCE_TCP_ALIAS} { count(); yylval.strval=yytext; return FORCE_TCP_ALIAS; } diff --git a/cfg.y b/cfg.y index 862ff742af..91d4d48110 100644 --- a/cfg.y +++ b/cfg.y @@ -88,6 +88,7 @@ * 2007-11-28 added TCP_OPT_{FD_CACHE, DEFER_ACCEPT, DELAYED_ACK, SYNCNT, * LINGER2, KEEPALIVE, KEEPIDLE, KEEPINTVL, KEEPCNT} (andrei) * 2008-01-24 added cfg_var definition (Miklos) + * 2009-03-10 added SET_USERPHONE action (Miklos) */ %{ @@ -238,6 +239,7 @@ static void free_socket_id_lst(struct socket_id* i); %token PREFIX %token STRIP %token STRIP_TAIL +%token SET_USERPHONE %token APPEND_BRANCH %token SET_USER %token SET_USERPASS @@ -2312,6 +2314,8 @@ cmd: | STRIP LPAREN NUMBER RPAREN { $$=mk_action(STRIP_T, 1, NUMBER_ST, (void*) $3); } | STRIP error { $$=0; yyerror("missing '(' or ')' ?"); } | STRIP LPAREN error RPAREN { $$=0; yyerror("bad argument, number expected"); } + | SET_USERPHONE LPAREN RPAREN { $$=mk_action(SET_USERPHONE_T, 0); } + | SET_USERPHONE error { $$=0; yyerror("missing '(' or ')' ?"); } | APPEND_BRANCH LPAREN STRING COMMA STRING RPAREN { qvalue_t q; if (str2q(&q, $5, strlen($5)) < 0) { diff --git a/parser/parse_uri.c b/parser/parse_uri.c index a0638bd394..85328f84d9 100644 --- a/parser/parse_uri.c +++ b/parser/parse_uri.c @@ -1431,10 +1431,10 @@ inline int normalize_tel_user(char* res, str* src) { } -static str s_sip = STR_STATIC_INIT("sip"); -static str s_sips = STR_STATIC_INIT("sips"); -static str s_tel = STR_STATIC_INIT("tel"); -static str s_tels = STR_STATIC_INIT("tels"); +str s_sip = STR_STATIC_INIT("sip"); +str s_sips = STR_STATIC_INIT("sips"); +str s_tel = STR_STATIC_INIT("tel"); +str s_tels = STR_STATIC_INIT("tels"); static str s_null = STR_STATIC_INIT(""); inline void uri_type_to_str(uri_type type, str *s) { diff --git a/parser/parse_uri.h b/parser/parse_uri.h index 6dc96a10a8..874a4687f0 100644 --- a/parser/parse_uri.h +++ b/parser/parse_uri.h @@ -38,6 +38,7 @@ #include "../parser/msg_parser.h" +extern str s_sip, s_sips, s_tel, s_tels; /* buf= pointer to begining of uri (sip:x@foo.bar:5060;a=b?h=i) * len= len of uri diff --git a/route_struct.h b/route_struct.h index 2539c36170..701326abc6 100644 --- a/route_struct.h +++ b/route_struct.h @@ -70,7 +70,7 @@ enum { METHOD_O=1, URI_O, FROM_URI_O, TO_URI_O, SRCIP_O, SRCPORT_O, enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T, SET_HOST_T, SET_HOSTPORT_T, SET_USER_T, SET_USERPASS_T, - SET_PORT_T, SET_URI_T, SET_HOSTPORTTRANS_T, + SET_PORT_T, SET_URI_T, SET_HOSTPORTTRANS_T, SET_USERPHONE_T, IF_T, MODULE_T, SETFLAG_T, RESETFLAG_T, ISFLAGSET_T , AVPFLAG_OPER_T, -- 2.20.1