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 484
 		case PREFIX_T:
484 485
 		case STRIP_T:
485 486
 		case STRIP_TAIL_T:
487
+		case SET_USERPHONE_T:
486 488
 				user=0;
487 489
 				if (a->type==STRIP_T || a->type==STRIP_TAIL_T) {
488 490
 					if (a->val[0].type!=NUMBER_ST) {
489 491
 						LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
490 492
 							a->val[0].type);
493
+						ret=E_BUG;
491 494
 						break;
492 495
 					}
493
-				} else if (a->val[0].type!=STRING_ST){
494
-					LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
496
+				} else if (a->type!=SET_USERPHONE_T) {
497
+					if (a->val[0].type!=STRING_ST) {
498
+						LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
495 499
 							a->val[0].type);
496
-					ret=E_BUG;
497
-					break;
500
+						ret=E_BUG;
501
+						break;
502
+					}
498 503
 				}
499 504
 				if (a->type==SET_URI_T){
500 505
 					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 522
 					ret=1;
518 523
 					break;
519 524
 				}
520
-				if (msg->parsed_uri_ok==0) {
525
+				if ((msg->parsed_uri_ok==0) || ((uri.flags & URI_SIP_USER_PHONE)!=0)) {
521 526
 					if (msg->new_uri.s) {
522 527
 						tmp=msg->new_uri.s;
523 528
 						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 530
 						tmp=msg->first_line.u.request.uri.s;
526 531
 						len=msg->first_line.u.request.uri.len;
527 532
 					}
533
+					/* don't convert sip:user=phone to tel, otherwise we loose parameters */
534
+					orig_p2t=phone2tel;
535
+					phone2tel=0;
536
+					msg->parsed_uri_ok=0;
528 537
 					if (parse_uri(tmp, len, &uri)<0){
538
+						phone2tel=orig_p2t;
529 539
 						LOG(L_ERR, "ERROR: do_action: bad uri <%s>, dropping"
530 540
 									" packet\n", tmp);
531 541
 						ret=E_UNSPEC;
532 542
 						break;
533 543
 					}
544
+					phone2tel=orig_p2t;
534 545
 				} else {
535 546
 					uri=msg->parsed_uri;
536 547
 				}
537 548
 
549
+				/* skip SET_USERPHONE_T action if the URI is already
550
+				 * a tel: or tels: URI, or contains the user=phone param */
551
+				if ((a->type==SET_USERPHONE_T) 
552
+					&& ((uri.type==TEL_URI_T) || (uri.type==TELS_URI_T)
553
+						|| ((uri.user_param_val.len==5) && (memcmp(uri.user_param_val.s, "phone", 5)==0)))
554
+				) {
555
+					ret=1;
556
+					break;
557
+				}
558
+				/* SET_PORT_T does not work with tel: URIs */
559
+				if ((a->type==SET_PORT_T)
560
+					&& ((uri.type==TEL_URI_T) || (uri.type==TELS_URI_T))
561
+					&& ((uri.flags & URI_SIP_USER_PHONE)==0)
562
+				) {
563
+					LOG(L_ERR, "ERROR: do_action: port number of a tel: URI cannot be set\n");
564
+					ret=E_UNSPEC;
565
+					break;
566
+				}
567
+
538 568
 				new_uri=pkg_malloc(MAX_URI_SIZE);
539 569
 				if (new_uri==0){
540 570
 					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 575
 				end=new_uri+MAX_URI_SIZE;
546 576
 				crt=new_uri;
547 577
 				/* begin copying */
548
-				len=strlen("sip:"); if(crt+len>end) goto error_uri;
549
-				memcpy(crt,"sip:",len);crt+=len;
578
+				/* Preserve the URI scheme unless the host part needs
579
+				 * to be rewritten, and the shceme is tel: or tels: */
580
+				switch (uri.type) {
581
+				case SIP_URI_T:
582
+					len=s_sip.len;
583
+					tmp=s_sip.s;
584
+					break;
585
+
586
+				case SIPS_URI_T:
587
+					len=s_sips.len;
588
+					tmp=s_sips.s;
589
+					break;
590
+
591
+				case TEL_URI_T:
592
+					if ((uri.flags & URI_SIP_USER_PHONE)
593
+						|| (a->type==SET_HOST_T)
594
+						|| (a->type==SET_HOSTPORT_T)
595
+						|| (a->type==SET_HOSTPORTTRANS_T)
596
+					) {
597
+						len=s_sip.len;
598
+						tmp=s_sip.s;
599
+						break;
600
+					}
601
+					len=s_tel.len;
602
+					tmp=s_tel.s;
603
+					break;
604
+
605
+				case TELS_URI_T:
606
+					if ((uri.flags & URI_SIP_USER_PHONE)
607
+						|| (a->type==SET_HOST_T)
608
+						|| (a->type==SET_HOSTPORT_T)
609
+						|| (a->type==SET_HOSTPORTTRANS_T)
610
+					) {
611
+						len=s_sips.len;
612
+						tmp=s_sips.s;
613
+						break;
614
+					}
615
+					len=s_tels.len;
616
+					tmp=s_tels.s;
617
+					break;
618
+
619
+				default:
620
+					LOG(L_ERR, "ERROR: Unsupported URI scheme (%d), "
621
+						"reverted to sip:\n",
622
+						uri.type);
623
+					len=s_sip.len;
624
+					tmp=s_sip.s;
625
+				}
626
+				if(crt+len+1 /* colon */ >end) goto error_uri;
627
+				memcpy(crt,tmp,len);crt+=len;
628
+				*crt=':'; crt++;
550 629
 
551 630
 				/* user */
552 631
 
... ...
@@ -607,21 +686,27 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
607 686
 					memcpy(crt,tmp,len);crt+=len;
608 687
 				}
609 688
 				/* host */
610
-				if (user || tmp){ /* add @ */
611
-					if(crt+1>end) goto error_uri;
612
-					*crt='@'; crt++;
613
-				}
614 689
 				if ((a->type==SET_HOST_T)
615 690
 						|| (a->type==SET_HOSTPORT_T)
616
-						|| (a->type==SET_HOSTPORTTRANS_T)) {
691
+						|| (a->type==SET_HOSTPORTTRANS_T)
692
+				) {
617 693
 					tmp=a->val[0].u.string;
618 694
 					if (tmp) len = strlen(tmp);
619 695
 					else len=0;
620
-				} else {
696
+				} else if ((uri.type==SIP_URI_T)
697
+					|| (uri.type==SIPS_URI_T)
698
+					|| (uri.flags & URI_SIP_USER_PHONE)
699
+				) {
621 700
 					tmp=uri.host.s;
622
-					len = uri.host.len;
701
+					len=uri.host.len;
702
+				} else {
703
+					tmp=0;
623 704
 				}
624 705
 				if (tmp){
706
+					if (user) { /* add @ */
707
+						if(crt+1>end) goto error_uri;
708
+						*crt='@'; crt++;
709
+					}
625 710
 					if(crt+len>end) goto error_uri;
626 711
 					memcpy(crt,tmp,len);crt+=len;
627 712
 				}
... ...
@@ -669,6 +754,22 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
669 754
 						memcpy(crt,tmp,len);crt+=len;
670 755
 					}
671 756
 				}
757
+				/* Add the user=phone param if a tel: or tels:
758
+				 * URI was converted to sip: or sips:.
759
+				 * (host part of a tel/tels URI was set.)
760
+				 * Or in case of sip: URI and SET_USERPHONE_T action */
761
+				if (((((uri.type==TEL_URI_T) || (uri.type==TELS_URI_T))
762
+					&& ((uri.flags & URI_SIP_USER_PHONE)==0))
763
+					&& ((a->type==SET_HOST_T)
764
+						|| (a->type==SET_HOSTPORT_T)
765
+						|| (a->type==SET_HOSTPORTTRANS_T)))
766
+					|| (a->type==SET_USERPHONE_T)
767
+				) {
768
+					tmp=";user=phone";
769
+					len=strlen(tmp);
770
+					if(crt+len>end) goto error_uri;
771
+					memcpy(crt,tmp,len);crt+=len;
772
+				}
672 773
 				/* headers */
673 774
 				tmp=uri.headers.s;
674 775
 				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 165
 PREFIX			"prefix"
165 166
 STRIP			"strip"
166 167
 STRIP_TAIL		"strip_tail"
168
+SET_USERPHONE		"userphone"
167 169
 APPEND_BRANCH	"append_branch"
168 170
 IF				"if"
169 171
 ELSE			"else"
... ...
@@ -465,6 +467,8 @@ EAT_ABLE	[\ \t\b\r]
465 467
 <INITIAL>{STRIP_TAIL}	{ count(); yylval.strval=yytext; return STRIP_TAIL; }
466 468
 <INITIAL>{APPEND_BRANCH}	{ count(); yylval.strval=yytext;
467 469
 								return APPEND_BRANCH; }
470
+<INITIAL>{SET_USERPHONE}	{ count(); yylval.strval=yytext;
471
+								return SET_USERPHONE; }
468 472
 <INITIAL>{FORCE_RPORT}	{ count(); yylval.strval=yytext; return FORCE_RPORT; }
469 473
 <INITIAL>{FORCE_TCP_ALIAS}	{ count(); yylval.strval=yytext;
470 474
 								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 239
 %token PREFIX
239 240
 %token STRIP
240 241
 %token STRIP_TAIL
242
+%token SET_USERPHONE
241 243
 %token APPEND_BRANCH
242 244
 %token SET_USER
243 245
 %token SET_USERPASS
... ...
@@ -2312,6 +2314,8 @@ cmd:
2312 2314
 	| STRIP LPAREN NUMBER RPAREN { $$=mk_action(STRIP_T, 1, NUMBER_ST, (void*) $3); }
2313 2315
 	| STRIP error { $$=0; yyerror("missing '(' or ')' ?"); }
2314 2316
 	| STRIP LPAREN error RPAREN { $$=0; yyerror("bad argument, number expected"); }
2317
+	| SET_USERPHONE LPAREN RPAREN { $$=mk_action(SET_USERPHONE_T, 0); }
2318
+	| SET_USERPHONE error { $$=0; yyerror("missing '(' or ')' ?"); }
2315 2319
 	| APPEND_BRANCH LPAREN STRING COMMA STRING RPAREN {
2316 2320
 		qvalue_t q;
2317 2321
 		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,