Strip, prefix, rewriteuser, ... all the SET_* actions preserve the
authorMiklos Tirpak <miklos@iptel.org>
Tue, 10 Mar 2009 16:26:35 +0000 (16:26 +0000)
committerMiklos Tirpak <miklos@iptel.org>
Tue, 10 Mar 2009 16:26:35 +0000 (16:26 +0000)
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
cfg.lex
cfg.y
parser/parse_uri.c
parser/parse_uri.h
route_struct.h

index f825626..b35a543 100644 (file)
--- 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;
        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
 
        /* 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 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);
                                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;
                                        }
                                                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);
                                                        a->val[0].type);
-                                       ret=E_BUG;
-                                       break;
+                                               ret=E_BUG;
+                                               break;
+                                       }
                                }
                                if (a->type==SET_URI_T){
                                        if (msg->new_uri.s) {
                                }
                                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;
                                }
                                        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;
                                        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;
                                        }
                                                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){
                                        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;
                                        }
                                                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;
                                }
 
                                } 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 "
                                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 */
                                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 */
 
 
                                /* 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 */
                                        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)
                                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;
                                        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;
                                        tmp=uri.host.s;
-                                       len = uri.host.len;
+                                       len=uri.host.len;
+                               } else {
+                                       tmp=0;
                                }
                                if (tmp){
                                }
                                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;
                                }
                                        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;
                                        }
                                }
                                                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){
                                /* headers */
                                tmp=uri.headers.s;
                                if (tmp){
diff --git a/cfg.lex b/cfg.lex
index 175ac68..73c23ef 100644 (file)
--- 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)
  *  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"
 PREFIX                 "prefix"
 STRIP                  "strip"
 STRIP_TAIL             "strip_tail"
+SET_USERPHONE          "userphone"
 APPEND_BRANCH  "append_branch"
 IF                             "if"
 ELSE                   "else"
 APPEND_BRANCH  "append_branch"
 IF                             "if"
 ELSE                   "else"
@@ -465,6 +467,8 @@ EAT_ABLE    [\ \t\b\r]
 <INITIAL>{STRIP_TAIL}  { count(); yylval.strval=yytext; return STRIP_TAIL; }
 <INITIAL>{APPEND_BRANCH}       { count(); yylval.strval=yytext;
                                                                return APPEND_BRANCH; }
 <INITIAL>{STRIP_TAIL}  { count(); yylval.strval=yytext; return STRIP_TAIL; }
 <INITIAL>{APPEND_BRANCH}       { count(); yylval.strval=yytext;
                                                                return APPEND_BRANCH; }
+<INITIAL>{SET_USERPHONE}       { count(); yylval.strval=yytext;
+                                                               return SET_USERPHONE; }
 <INITIAL>{FORCE_RPORT} { count(); yylval.strval=yytext; return FORCE_RPORT; }
 <INITIAL>{FORCE_TCP_ALIAS}     { count(); yylval.strval=yytext;
                                                                return FORCE_TCP_ALIAS; }
 <INITIAL>{FORCE_RPORT} { count(); yylval.strval=yytext; return FORCE_RPORT; }
 <INITIAL>{FORCE_TCP_ALIAS}     { count(); yylval.strval=yytext;
                                                                return FORCE_TCP_ALIAS; }
diff --git a/cfg.y b/cfg.y
index 862ff74..91d4d48 100644 (file)
--- 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)
  * 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 PREFIX
 %token STRIP
 %token STRIP_TAIL
+%token SET_USERPHONE
 %token APPEND_BRANCH
 %token SET_USER
 %token SET_USERPASS
 %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"); }
        | 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) {
        | APPEND_BRANCH LPAREN STRING COMMA STRING RPAREN {
                qvalue_t q;
                if (str2q(&q, $5, strlen($5)) < 0) {
index a0638bd..85328f8 100644 (file)
@@ -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) {
 static str     s_null = STR_STATIC_INIT("");
 
 inline void uri_type_to_str(uri_type type, str *s) {
index 6dc96a1..874a468 100644 (file)
@@ -38,6 +38,7 @@
 #include "../parser/msg_parser.h"
 
 
 #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
 
 /* buf= pointer to begining of uri (sip:x@foo.bar:5060;a=b?h=i)
  * len= len of uri
index 2539c36..701326a 100644 (file)
@@ -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,
 
 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,
                IF_T, MODULE_T,
                SETFLAG_T, RESETFLAG_T, ISFLAGSET_T ,
                AVPFLAG_OPER_T,