Przeglądaj źródła

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.

Miklos Tirpak 16 lat temu
rodzic
commit
536065b885
6 zmienionych plików z 129 dodań i 19 usunięć
  1. 115 14
      action.c
  2. 4 0
      cfg.lex
  3. 4 0
      cfg.y
  4. 4 4
      parser/parse_uri.c
  5. 1 0
      parser/parse_uri.h
  6. 1 1
      route_struct.h

+ 115 - 14
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){

+ 4 - 0
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]
 <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; }

+ 4 - 0
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) {

+ 4 - 4
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) {

+ 1 - 0
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:[email protected]:5060;a=b?h=i)
  * len= len of uri

+ 1 - 1
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,