Browse code

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 authored on 10/03/2009 16:26:35
Showing 6 changed files
... ...
@@ -110,6 +110,7 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
110 110
 	unsigned short flags;
111 111
 	int_str name, value;
112 112
 	str* dst_host;
113
+	int orig_p2t;
113 114
 
114 115
 	/* reset the value of error to E_UNSPEC so avoid unknowledgable
115 116
 	   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)
483 483
 		case PREFIX_T:
484 484
 		case STRIP_T:
485 485
 		case STRIP_TAIL_T:
486
+		case SET_USERPHONE_T:
486 487
 				user=0;
487 488
 				if (a->type==STRIP_T || a->type==STRIP_TAIL_T) {
488 489
 					if (a->val[0].type!=NUMBER_ST) {
489 490
 						LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
490 491
 							a->val[0].type);
492
+						ret=E_BUG;
491 493
 						break;
492 494
 					}
493
-				} else if (a->val[0].type!=STRING_ST){
494
-					LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
495
+				} else if (a->type!=SET_USERPHONE_T) {
496
+					if (a->val[0].type!=STRING_ST) {
497
+						LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
495 498
 							a->val[0].type);
496
-					ret=E_BUG;
497
-					break;
499
+						ret=E_BUG;
500
+						break;
501
+					}
498 502
 				}
499 503
 				if (a->type==SET_URI_T){
500 504
 					if (msg->new_uri.s) {
... ...
@@ -517,7 +522,7 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
517 517
 					ret=1;
518 518
 					break;
519 519
 				}
520
-				if (msg->parsed_uri_ok==0) {
520
+				if ((msg->parsed_uri_ok==0) || ((uri.flags & URI_SIP_USER_PHONE)!=0)) {
521 521
 					if (msg->new_uri.s) {
522 522
 						tmp=msg->new_uri.s;
523 523
 						len=msg->new_uri.len;
... ...
@@ -525,16 +530,41 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
525 525
 						tmp=msg->first_line.u.request.uri.s;
526 526
 						len=msg->first_line.u.request.uri.len;
527 527
 					}
528
+					/* don't convert sip:user=phone to tel, otherwise we loose parameters */
529
+					orig_p2t=phone2tel;
530
+					phone2tel=0;
531
+					msg->parsed_uri_ok=0;
528 532
 					if (parse_uri(tmp, len, &uri)<0){
533
+						phone2tel=orig_p2t;
529 534
 						LOG(L_ERR, "ERROR: do_action: bad uri <%s>, dropping"
530 535
 									" packet\n", tmp);
531 536
 						ret=E_UNSPEC;
532 537
 						break;
533 538
 					}
539
+					phone2tel=orig_p2t;
534 540
 				} else {
535 541
 					uri=msg->parsed_uri;
536 542
 				}
537 543
 
544
+				/* skip SET_USERPHONE_T action if the URI is already
545
+				 * a tel: or tels: URI, or contains the user=phone param */
546
+				if ((a->type==SET_USERPHONE_T) 
547
+					&& ((uri.type==TEL_URI_T) || (uri.type==TELS_URI_T)
548
+						|| ((uri.user_param_val.len==5) && (memcmp(uri.user_param_val.s, "phone", 5)==0)))
549
+				) {
550
+					ret=1;
551
+					break;
552
+				}
553
+				/* SET_PORT_T does not work with tel: URIs */
554
+				if ((a->type==SET_PORT_T)
555
+					&& ((uri.type==TEL_URI_T) || (uri.type==TELS_URI_T))
556
+					&& ((uri.flags & URI_SIP_USER_PHONE)==0)
557
+				) {
558
+					LOG(L_ERR, "ERROR: do_action: port number of a tel: URI cannot be set\n");
559
+					ret=E_UNSPEC;
560
+					break;
561
+				}
562
+
538 563
 				new_uri=pkg_malloc(MAX_URI_SIZE);
539 564
 				if (new_uri==0){
540 565
 					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)
545 545
 				end=new_uri+MAX_URI_SIZE;
546 546
 				crt=new_uri;
547 547
 				/* begin copying */
548
-				len=strlen("sip:"); if(crt+len>end) goto error_uri;
549
-				memcpy(crt,"sip:",len);crt+=len;
548
+				/* Preserve the URI scheme unless the host part needs
549
+				 * to be rewritten, and the shceme is tel: or tels: */
550
+				switch (uri.type) {
551
+				case SIP_URI_T:
552
+					len=s_sip.len;
553
+					tmp=s_sip.s;
554
+					break;
555
+
556
+				case SIPS_URI_T:
557
+					len=s_sips.len;
558
+					tmp=s_sips.s;
559
+					break;
560
+
561
+				case TEL_URI_T:
562
+					if ((uri.flags & URI_SIP_USER_PHONE)
563
+						|| (a->type==SET_HOST_T)
564
+						|| (a->type==SET_HOSTPORT_T)
565
+						|| (a->type==SET_HOSTPORTTRANS_T)
566
+					) {
567
+						len=s_sip.len;
568
+						tmp=s_sip.s;
569
+						break;
570
+					}
571
+					len=s_tel.len;
572
+					tmp=s_tel.s;
573
+					break;
574
+
575
+				case TELS_URI_T:
576
+					if ((uri.flags & URI_SIP_USER_PHONE)
577
+						|| (a->type==SET_HOST_T)
578
+						|| (a->type==SET_HOSTPORT_T)
579
+						|| (a->type==SET_HOSTPORTTRANS_T)
580
+					) {
581
+						len=s_sips.len;
582
+						tmp=s_sips.s;
583
+						break;
584
+					}
585
+					len=s_tels.len;
586
+					tmp=s_tels.s;
587
+					break;
588
+
589
+				default:
590
+					LOG(L_ERR, "ERROR: Unsupported URI scheme (%d), "
591
+						"reverted to sip:\n",
592
+						uri.type);
593
+					len=s_sip.len;
594
+					tmp=s_sip.s;
595
+				}
596
+				if(crt+len+1 /* colon */ >end) goto error_uri;
597
+				memcpy(crt,tmp,len);crt+=len;
598
+				*crt=':'; crt++;
550 599
 
551 600
 				/* user */
552 601
 
... ...
@@ -607,21 +686,27 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
607 607
 					memcpy(crt,tmp,len);crt+=len;
608 608
 				}
609 609
 				/* host */
610
-				if (user || tmp){ /* add @ */
611
-					if(crt+1>end) goto error_uri;
612
-					*crt='@'; crt++;
613
-				}
614 610
 				if ((a->type==SET_HOST_T)
615 611
 						|| (a->type==SET_HOSTPORT_T)
616
-						|| (a->type==SET_HOSTPORTTRANS_T)) {
612
+						|| (a->type==SET_HOSTPORTTRANS_T)
613
+				) {
617 614
 					tmp=a->val[0].u.string;
618 615
 					if (tmp) len = strlen(tmp);
619 616
 					else len=0;
620
-				} else {
617
+				} else if ((uri.type==SIP_URI_T)
618
+					|| (uri.type==SIPS_URI_T)
619
+					|| (uri.flags & URI_SIP_USER_PHONE)
620
+				) {
621 621
 					tmp=uri.host.s;
622
-					len = uri.host.len;
622
+					len=uri.host.len;
623
+				} else {
624
+					tmp=0;
623 625
 				}
624 626
 				if (tmp){
627
+					if (user) { /* add @ */
628
+						if(crt+1>end) goto error_uri;
629
+						*crt='@'; crt++;
630
+					}
625 631
 					if(crt+len>end) goto error_uri;
626 632
 					memcpy(crt,tmp,len);crt+=len;
627 633
 				}
... ...
@@ -669,6 +754,22 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
669 669
 						memcpy(crt,tmp,len);crt+=len;
670 670
 					}
671 671
 				}
672
+				/* Add the user=phone param if a tel: or tels:
673
+				 * URI was converted to sip: or sips:.
674
+				 * (host part of a tel/tels URI was set.)
675
+				 * Or in case of sip: URI and SET_USERPHONE_T action */
676
+				if (((((uri.type==TEL_URI_T) || (uri.type==TELS_URI_T))
677
+					&& ((uri.flags & URI_SIP_USER_PHONE)==0))
678
+					&& ((a->type==SET_HOST_T)
679
+						|| (a->type==SET_HOSTPORT_T)
680
+						|| (a->type==SET_HOSTPORTTRANS_T)))
681
+					|| (a->type==SET_USERPHONE_T)
682
+				) {
683
+					tmp=";user=phone";
684
+					len=strlen(tmp);
685
+					if(crt+len>end) goto error_uri;
686
+					memcpy(crt,tmp,len);crt+=len;
687
+				}
672 688
 				/* headers */
673 689
 				tmp=uri.headers.s;
674 690
 				if (tmp){
... ...
@@ -75,6 +75,7 @@
75 75
  *  2007-11-28  added TCP_OPT_{FD_CACHE, DEFER_ACCEPT, DELAYED_ACK, SYNCNT,
76 76
  *              LINGER2, KEEPALIVE, KEEPIDLE, KEEPINTVL, KEEPCNT} (andrei)
77 77
  *  2008-01-24  added CFG_DESCRIPTION used by cfg_var (Miklos)
78
+ *  2009-03-10  added SET_USERPHONE action (Miklos)
78 79
 */
79 80
 
80 81
 
... ...
@@ -164,6 +165,7 @@ REVERT_URI		"revert_uri"
164 164
 PREFIX			"prefix"
165 165
 STRIP			"strip"
166 166
 STRIP_TAIL		"strip_tail"
167
+SET_USERPHONE		"userphone"
167 168
 APPEND_BRANCH	"append_branch"
168 169
 IF				"if"
169 170
 ELSE			"else"
... ...
@@ -465,6 +467,8 @@ EAT_ABLE	[\ \t\b\r]
465 465
 <INITIAL>{STRIP_TAIL}	{ count(); yylval.strval=yytext; return STRIP_TAIL; }
466 466
 <INITIAL>{APPEND_BRANCH}	{ count(); yylval.strval=yytext;
467 467
 								return APPEND_BRANCH; }
468
+<INITIAL>{SET_USERPHONE}	{ count(); yylval.strval=yytext;
469
+								return SET_USERPHONE; }
468 470
 <INITIAL>{FORCE_RPORT}	{ count(); yylval.strval=yytext; return FORCE_RPORT; }
469 471
 <INITIAL>{FORCE_TCP_ALIAS}	{ count(); yylval.strval=yytext;
470 472
 								return FORCE_TCP_ALIAS; }
... ...
@@ -88,6 +88,7 @@
88 88
  * 2007-11-28  added TCP_OPT_{FD_CACHE, DEFER_ACCEPT, DELAYED_ACK, SYNCNT,
89 89
  *              LINGER2, KEEPALIVE, KEEPIDLE, KEEPINTVL, KEEPCNT} (andrei)
90 90
  * 2008-01-24  added cfg_var definition (Miklos)
91
+ * 2009-03-10  added SET_USERPHONE action (Miklos)
91 92
 */
92 93
 
93 94
 %{
... ...
@@ -238,6 +239,7 @@ static void free_socket_id_lst(struct socket_id* i);
238 238
 %token PREFIX
239 239
 %token STRIP
240 240
 %token STRIP_TAIL
241
+%token SET_USERPHONE
241 242
 %token APPEND_BRANCH
242 243
 %token SET_USER
243 244
 %token SET_USERPASS
... ...
@@ -2312,6 +2314,8 @@ cmd:
2312 2312
 	| STRIP LPAREN NUMBER RPAREN { $$=mk_action(STRIP_T, 1, NUMBER_ST, (void*) $3); }
2313 2313
 	| STRIP error { $$=0; yyerror("missing '(' or ')' ?"); }
2314 2314
 	| STRIP LPAREN error RPAREN { $$=0; yyerror("bad argument, number expected"); }
2315
+	| SET_USERPHONE LPAREN RPAREN { $$=mk_action(SET_USERPHONE_T, 0); }
2316
+	| SET_USERPHONE error { $$=0; yyerror("missing '(' or ')' ?"); }
2315 2317
 	| APPEND_BRANCH LPAREN STRING COMMA STRING RPAREN {
2316 2318
 		qvalue_t q;
2317 2319
 		if (str2q(&q, $5, strlen($5)) < 0) {
... ...
@@ -1431,10 +1431,10 @@ inline int normalize_tel_user(char* res, str* src) {
1431 1431
 }
1432 1432
 
1433 1433
 
1434
-static str	s_sip  = STR_STATIC_INIT("sip");
1435
-static str	s_sips = STR_STATIC_INIT("sips");
1436
-static str	s_tel  = STR_STATIC_INIT("tel");
1437
-static str	s_tels = STR_STATIC_INIT("tels");
1434
+str	s_sip  = STR_STATIC_INIT("sip");
1435
+str	s_sips = STR_STATIC_INIT("sips");
1436
+str	s_tel  = STR_STATIC_INIT("tel");
1437
+str	s_tels = STR_STATIC_INIT("tels");
1438 1438
 static str	s_null = STR_STATIC_INIT("");
1439 1439
 
1440 1440
 inline void uri_type_to_str(uri_type type, str *s) {
... ...
@@ -38,6 +38,7 @@
38 38
 #include "../parser/msg_parser.h"
39 39
 
40 40
 
41
+extern str	s_sip, s_sips, s_tel, s_tels;
41 42
 
42 43
 /* buf= pointer to begining of uri (sip:x@foo.bar:5060;a=b?h=i)
43 44
  * len= len of uri
... ...
@@ -70,7 +70,7 @@ enum { METHOD_O=1, URI_O, FROM_URI_O, TO_URI_O, SRCIP_O, SRCPORT_O,
70 70
 
71 71
 enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T,
72 72
 		SET_HOST_T, SET_HOSTPORT_T, SET_USER_T, SET_USERPASS_T,
73
-		SET_PORT_T, SET_URI_T, SET_HOSTPORTTRANS_T,
73
+		SET_PORT_T, SET_URI_T, SET_HOSTPORTTRANS_T, SET_USERPHONE_T,
74 74
 		IF_T, MODULE_T,
75 75
 		SETFLAG_T, RESETFLAG_T, ISFLAGSET_T ,
76 76
 		AVPFLAG_OPER_T,