Browse code

- tm: t_relay will not stop script execution anymore in case of send error - added onsend_route: special route executed before forwarding a message, when the final destination is known. Only a limited number of commands are allowed ( if (expr) {}else{}, drop, flags manipulations, send(), log()). Usefull to catch more easily unauthorized attempts to relay/bounce message to protected destinations (e.g PSTN gateways) - new onsend checks: to_{ip,port}, snd_{ip,port,proto,af}. to= to whom the message will be sent to. snd=how ser will send it (socket ip/port,proto,af). - msg:len in onsend_route will containg the "new" message len - textops: search() onsend_route support (it will use the new, freshly constructed message and not the original one)

Example:
onsend_route{
# allow messages from 10.0.0.0/8 to 1.2.3.4 only if flag 10 was set
# from the script
if (to_ip==1.2.3.4 && src_ip==10.0.0.0/8 && !isflagset(10)){
log("msg dropped\n");
drop;
}
# drop all messages that contain banned_user in from
if (search("From|f[ ]*:.*banned_user")) drop;
}

Andrei Pelinescu-Onciul authored on 11/12/2005 22:46:38
Showing 13 changed files
... ...
@@ -61,7 +61,7 @@ MAIN_NAME=ser
61 61
 VERSION = 0
62 62
 PATCHLEVEL = 10
63 63
 SUBLEVEL =   99
64
-EXTRAVERSION = -dev27-tm-timers
64
+EXTRAVERSION = -dev28-tm-timers
65 65
 
66 66
 RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
67 67
 OS = $(shell uname -s | sed -e s/SunOS/solaris/ | tr "[A-Z]" "[a-z]")
... ...
@@ -34,8 +34,41 @@ modules:
34 34
                          changing the transaction timer from script, even if
35 35
                          the transaction was already created (see tm docs for
36 36
                          more).
37
+            - t_relay will not stop script execution anymore in case of
38
+              send error
39
+ - textops  - search() can be used in the onsend_route where it will search
40
+              on the "new" message (after applying all script changes, adding
41
+              Vias a.s.o) and not on the original message
37 42
  
38 43
 core:
44
+ - onsend_route added: special route executed before a request is sent.
45
+                       Only a limited number of commands are allowed (drop, if
46
+                       + all the checks, msg flag manipulations, send(), log(),
47
+                       textops::search()). In this route the final destination
48
+                       of the message is available an can be checked (with
49
+                       snd_ip, snd_port, to_ip, to_port, snd_proto, snd_af).
50
+                       This route is executed only when forwarding requests.
51
+                       It's not executed for replies, retransmissions, or
52
+                       locally generated messages (e.g. via fifo uac).
53
+      short example:
54
+            onsend_route{  if(to_ip==1.2.3.4 && !isflagset(12)){
55
+                              log(1, "message blocked\n");
56
+                              drop;
57
+                           }
58
+                         }
59
+ - onsend_route specific checks:
60
+     - snd_ip, snd_port - behave like src_ip/src_port, but contain the
61
+       ip/port ser will use to send the message
62
+     - to_ip, to_port - like above, but contain the ip/port the message will
63
+       be sent to (not to be confused with dst_ip/dst-port, which are the
64
+       destination of the original message: ser's ip and port on which the
65
+       message was received)
66
+     - snd_proto, snd_af - behave like proto/af but contain the 
67
+       protocol/address family that ser will use to send the message
68
+     - msg:len - when used in an onsend_route, msg:len will contain the length
69
+       of the message on the wire (after all the changes in the script are
70
+       applied, Vias are added a.s.o) and not the lentgh of the original 
71
+       message
39 72
  - timer: - improved performance/precision, new api, see doc/timers.txt 
40 73
  - tcp: - improved  performance (io event handling), using OS specific
41 74
            optimizations
... ...
@@ -368,33 +401,33 @@ actual workload (malloc is a little bit faster now)
368 368
 New features
369 369
 =============
370 370
 - RFC3261 support
371
-	- TCP support and cross-transport forwarding [core]
372
-	- loose routing support [rr module]
371
+    - TCP support and cross-transport forwarding [core]
372
+    - loose routing support [rr module]
373 373
 - New modules
374
-	- vm -- voicemail interface [vm]
375
-	- ENUM support [enum]
376
-	- presence agent [pa]
377
-	- dynamic domain management -- allows to manipulate 
378
-	  hosting of multiple domains in run-time [module]
379
-	- flat-text-file database support [dbtext]
380
-	- rich access control lists [permissions]
374
+    - vm -- voicemail interface [vm]
375
+    - ENUM support [enum]
376
+    - presence agent [pa]
377
+    - dynamic domain management -- allows to manipulate 
378
+      hosting of multiple domains in run-time [module]
379
+    - flat-text-file database support [dbtext]
380
+    - rich access control lists [permissions]
381 381
 - Feature Improvements
382
-	- click-to-dial, which is based on improved tm/FIFO 
383
-	  that better supports external applications [tm module]
384
-	- web accounting -- acc module can report to serweb
385
-  	  on placed calls [acc module]
386
-	- improved exec module (header fields passed now
382
+    - click-to-dial, which is based on improved tm/FIFO 
383
+      that better supports external applications [tm module]
384
+    - web accounting -- acc module can report to serweb
385
+        on placed calls [acc module]
386
+    - improved exec module (header fields passed now
387 387
       as environment variables to scripts) [exec module]
388 388
 - Architectural Improvements
389
-	- powerpc fast locking support
390
-	- netbsd support
391
-	- 64 bits arch. support (e.g. netbsd/sparc64).
389
+    - powerpc fast locking support
390
+    - netbsd support
391
+    - 64 bits arch. support (e.g. netbsd/sparc64).
392 392
 - New Experimental Features (not tested at all yet)
393
-	- nathelper utility for Cisco/ATA NAT traversal [nathelper]
394
-	- another NAT traversal utility [mangler]
395
-	- postgress support [postgress]
396
-	- fcp module [fcp]
397
-	- pdt module (prefix2domain) [pdt]
393
+    - nathelper utility for Cisco/ATA NAT traversal [nathelper]
394
+    - another NAT traversal utility [mangler]
395
+    - postgress support [postgress]
396
+    - fcp module [fcp]
397
+    - pdt module (prefix2domain) [pdt]
398 398
 
399 399
 Changes to use of ser scripts
400 400
 =============================
... ...
@@ -57,6 +57,7 @@
57 57
 #include "mem/mem.h"
58 58
 #include "globals.h"
59 59
 #include "dset.h"
60
+#include "onsend.h"
60 61
 #ifdef USE_TCP
61 62
 #include "tcp_server.h"
62 63
 #endif
... ...
@@ -74,6 +75,8 @@
74 74
 #endif
75 75
 
76 76
 
77
+struct onsend_info* p_onsend=0; /* onsend route send info */
78
+
77 79
 /* ret= 0! if action -> end of list(e.g DROP), 
78 80
       > 0 to continue processing next actions
79 81
    and <0 on error */
... ...
@@ -241,13 +244,20 @@ int do_action(struct action* a, struct sip_msg* msg)
241 241
 			ret=hostent2su(	to, &p->host, p->addr_idx,
242 242
 						(p->port)?p->port:SIP_PORT );
243 243
 			if (ret==0){
244
+				if (p_onsend){
245
+					tmp=p_onsend->buf;
246
+					len=p_onsend->len;
247
+				}else{
248
+					tmp=msg->buf;
249
+					len=msg->len;
250
+				}
244 251
 				p->tx++;
245
-				p->tx_bytes+=msg->len;
252
+				p->tx_bytes+=len;
246 253
 				if (a->type==SEND_T){
247 254
 					/*udp*/
248 255
 					send_sock=get_send_socket(msg, to, PROTO_UDP);
249 256
 					if (send_sock!=0){
250
-						ret=udp_send(send_sock, msg->buf, msg->len, to);
257
+						ret=udp_send(send_sock, tmp, len, to);
251 258
 					}else{
252 259
 						ret=-1;
253 260
 					}
... ...
@@ -255,7 +265,7 @@ int do_action(struct action* a, struct sip_msg* msg)
255 255
 #ifdef USE_TCP
256 256
 					else{
257 257
 					/*tcp*/
258
-					ret=tcp_send(PROTO_TCP, msg->buf, msg->len, to, 0);
258
+					ret=tcp_send(PROTO_TCP, tmp, len, to, 0);
259 259
 				}
260 260
 #endif
261 261
 			}
... ...
@@ -743,9 +753,8 @@ int do_action(struct action* a, struct sip_msg* msg)
743 743
 				break;
744 744
 			}
745 745
 
746
-			     /* If the action is assign then remove the old avp value before adding
747
-			      * new ones
748
-			      */
746
+			/* If the action is assign then remove the old avp value
747
+			 * before adding new ones */
749 748
 			if ((unsigned char)a->type == ASSIGN_T) delete_avp(flags, name);
750 749
 			if (add_avp(flags, name, value) < 0) {
751 750
 				LOG(L_CRIT, "ERROR: Failed to assign value to attribute\n");
... ...
@@ -56,6 +56,8 @@
56 56
  *               tcp_max_connections (andrei)
57 57
  *  2005-07-11  added dns_retr_{time,no}, dns_servers_no, dns_use_search_list,
58 58
  *              dns_try_ipv6 (andrei)
59
+ *  2005-12-11  added onsend_route, snd_{ip,port,proto,af},
60
+ *              to_{ip,port} (andrei)
59 61
  */
60 62
 
61 63
 
... ...
@@ -115,6 +117,7 @@ ROUTE	route
115 115
 ROUTE_FAILURE failure_route
116 116
 ROUTE_ONREPLY onreply_route
117 117
 ROUTE_BRANCH branch_route
118
+ROUTE_SEND onsend_route
118 119
 EXEC	exec
119 120
 FORCE_RPORT		"force_rport"|"add_rport"
120 121
 FORCE_TCP_ALIAS		"force_tcp_alias"|"add_tcp_alias"
... ...
@@ -158,6 +161,12 @@ SRCIP	src_ip
158 158
 SRCPORT	src_port
159 159
 DSTIP	dst_ip
160 160
 DSTPORT	dst_port
161
+SNDIP	snd_ip
162
+SNDPORT	snd_port
163
+SNDPROTO	snd_proto|to_proto
164
+SNDAF		snd_af|to_af
165
+TOIP	to_ip
166
+TOPORT	to_port
161 167
 PROTO	proto
162 168
 AF		af
163 169
 MYSELF	myself
... ...
@@ -328,6 +337,7 @@ EAT_ABLE	[\ \t\b\r]
328 328
 <INITIAL>{ROUTE_FAILURE}	{ count(); yylval.strval=yytext;
329 329
 								return ROUTE_FAILURE; }
330 330
 <INITIAL>{ROUTE_BRANCH} { count(); yylval.strval=yytext; return ROUTE_BRANCH; }
331
+<INITIAL>{ROUTE_SEND} { count(); yylval.strval=yytext; return ROUTE_SEND; }
331 332
 <INITIAL>{EXEC}	{ count(); yylval.strval=yytext; return EXEC; }
332 333
 <INITIAL>{SET_HOST}	{ count(); yylval.strval=yytext; return SET_HOST; }
333 334
 <INITIAL>{SET_HOSTPORT}	{ count(); yylval.strval=yytext; return SET_HOSTPORT; }
... ...
@@ -367,6 +377,12 @@ EAT_ABLE	[\ \t\b\r]
367 367
 <INITIAL>{SRCPORT}	{ count(); yylval.strval=yytext; return SRCPORT; }
368 368
 <INITIAL>{DSTIP}	{ count(); yylval.strval=yytext; return DSTIP; }
369 369
 <INITIAL>{DSTPORT}	{ count(); yylval.strval=yytext; return DSTPORT; }
370
+<INITIAL>{SNDIP}	{ count(); yylval.strval=yytext; return SNDIP; }
371
+<INITIAL>{SNDPORT}	{ count(); yylval.strval=yytext; return SNDPORT; }
372
+<INITIAL>{SNDPROTO}	{ count(); yylval.strval=yytext; return SNDPROTO; }
373
+<INITIAL>{SNDAF}	{ count(); yylval.strval=yytext; return SNDAF; }
374
+<INITIAL>{TOIP}		{ count(); yylval.strval=yytext; return TOIP; }
375
+<INITIAL>{TOPORT}	{ count(); yylval.strval=yytext; return TOPORT; }
370 376
 <INITIAL>{PROTO}	{ count(); yylval.strval=yytext; return PROTO; }
371 377
 <INITIAL>{AF}	{ count(); yylval.strval=yytext; return AF; }
372 378
 <INITIAL>{MYSELF}	{ count(); yylval.strval=yytext; return MYSELF; }
... ...
@@ -64,6 +64,8 @@
64 64
  *             DNS_TRY_IPV6 (andrei)
65 65
  * 2005-07-12  default onreply route added (andrei)
66 66
  * 2005-11-16  fixed if (cond) cmd; (andrei)
67
+ * 2005-12-11  added onsend_route support, fcmd (filtered cmd),
68
+ *             snd_{ip,port,proto,af}, to_{ip,proto} (andrei)
67 69
  *
68 70
  */
69 71
 
... ...
@@ -103,6 +105,10 @@
103 103
  with no built in alloca, like icc*/
104 104
 #undef _ALLOCA_H
105 105
 
106
+#define onsend_check(s) \
107
+	do{\
108
+		if (rt!=ONSEND_ROUTE) yyerror( s " allowed only in onsend_routes");\
109
+	}while(0)
106 110
 
107 111
 extern int yylex();
108 112
 static void yyerror(char* s);
... ...
@@ -150,6 +156,7 @@ static struct socket_id* mk_listen_id(char*, int, int);
150 150
 %token ROUTE_FAILURE
151 151
 %token ROUTE_ONREPLY
152 152
 %token ROUTE_BRANCH
153
+%token ROUTE_SEND
153 154
 %token EXEC
154 155
 %token SET_HOST
155 156
 %token SET_HOSTPORT
... ...
@@ -183,6 +190,12 @@ static struct socket_id* mk_listen_id(char*, int, int);
183 183
 %token SRCPORT
184 184
 %token DSTIP
185 185
 %token DSTPORT
186
+%token TOIP
187
+%token TOPORT
188
+%token SNDIP
189
+%token SNDPORT
190
+%token SNDPROTO
191
+%token SNDAF
186 192
 %token PROTO
187 193
 %token AF
188 194
 %token MYSELF
... ...
@@ -310,7 +323,7 @@ static struct socket_id* mk_listen_id(char*, int, int);
310 310
 
311 311
 /*non-terminals */
312 312
 %type <expr> exp exp_elem /*, condition*/
313
-%type <action> action actions cmd if_cmd stm exp_stm assign_action
313
+%type <action> action actions cmd fcmd if_cmd stm exp_stm assign_action
314 314
 %type <ipaddr> ipv4 ipv6 ipv6addr ip
315 315
 %type <ipnet> ipnet
316 316
 %type <strval> host
... ...
@@ -347,6 +360,7 @@ statement:	assign_stm
347 347
 		| {rt=FAILURE_ROUTE;} failure_route_stm
348 348
 		| {rt=ONREPLY_ROUTE;} onreply_route_stm
349 349
 		| {rt=BRANCH_ROUTE;} branch_route_stm
350
+		| {rt=ONSEND_ROUTE;}   send_route_stm
350 351
 		| CR	/* null statement*/
351 352
 	;
352 353
 
... ...
@@ -896,6 +910,19 @@ branch_route_stm: ROUTE_BRANCH LBRACE actions RBRACE {
896 896
 										}
897 897
 		| ROUTE_BRANCH error { yyerror("invalid branch_route statement"); }
898 898
 	;
899
+send_route_stm: ROUTE_SEND LBRACE actions RBRACE {
900
+									push($3, &onsend_rlist[DEFAULT_RT]);
901
+									}
902
+			|   ROUTE_SEND LBRACK NUMBER RBRACK LBRACE actions RBRACE {
903
+									if (($3<ONSEND_RT_NO)&&($3>=1)){
904
+										push($6, &onsend_rlist[$3]);
905
+									} else {
906
+										yyerror("invalid onsend routing"
907
+												"table number");
908
+										YYABORT; }
909
+								}
910
+			| ROUTE_SEND error { yyerror("invalid onsend_route statement"); }
911
+	;
899 912
 /*
900 913
 rules:	rules rule { push($2, &$1); $$=$1; }
901 914
 	| rule {$$=$1; }
... ...
@@ -963,7 +990,7 @@ exp_elem:	METHOD strop STRING	{$$= mk_elem($2, METHOD_O, 0, STRING_ST, $3);}
963 963
 									" == , != or =~ expected");
964 964
 					}
965 965
 		| SRCPORT intop NUMBER	{ $$=mk_elem($2, SRCPORT_O, 0, NUMBER_ST, (void*)$3 ); }
966
-                | SRCPORT intop attr_id { $$=mk_elem($2, SRCPORT_O, 0, AVP_ST, (void*)$3 ); }
966
+		| SRCPORT intop attr_id { $$=mk_elem($2, SRCPORT_O, 0, AVP_ST, (void*)$3 ); }
967 967
 		| SRCPORT intop error { $$=0; yyerror("number expected"); }
968 968
 		| SRCPORT error { $$=0; yyerror("==, !=, <,>, >= or <=  expected"); }
969 969
 
... ...
@@ -972,6 +999,24 @@ exp_elem:	METHOD strop STRING	{$$= mk_elem($2, METHOD_O, 0, STRING_ST, $3);}
972 972
 		| DSTPORT intop error { $$=0; yyerror("number expected"); }
973 973
 		| DSTPORT error { $$=0; yyerror("==, !=, <,>, >= or <=  expected"); }
974 974
 
975
+		| SNDPORT intop NUMBER	{	onsend_check("snd_port");
976
+									$$=mk_elem($2, SNDPORT_O, 0, NUMBER_ST,
977
+												(void*)$3 ); }
978
+		| SNDPORT intop attr_id {	onsend_check("snd_port");
979
+									$$=mk_elem($2, SNDPORT_O, 0, AVP_ST,
980
+												(void*)$3 ); }
981
+		| SNDPORT intop error { $$=0; yyerror("number expected"); }
982
+		| SNDPORT error { $$=0; yyerror("==, !=, <,>, >= or <=  expected"); }
983
+
984
+		| TOPORT intop NUMBER	{	onsend_check("to_port");
985
+									$$=mk_elem($2, TOPORT_O, 0, NUMBER_ST,
986
+												(void*)$3 ); }
987
+		| TOPORT intop attr_id {	onsend_check("to_port");
988
+									$$=mk_elem($2, TOPORT_O, 0, AVP_ST,
989
+												(void*)$3 ); }
990
+		| TOPORT intop error { $$=0; yyerror("number expected"); }
991
+		| TOPORT error { $$=0; yyerror("==, !=, <,>, >= or <=  expected"); }
992
+
975 993
 		| PROTO intop proto	{ $$=mk_elem($2, PROTO_O, 0, NUMBER_ST, (void*)$3 ); }
976 994
 		| PROTO intop attr_id	{ $$=mk_elem($2, PROTO_O, 0, AVP_ST, (void*)$3 ); }
977 995
 		| PROTO intop error { $$=0;
... ...
@@ -979,11 +1024,31 @@ exp_elem:	METHOD strop STRING	{$$= mk_elem($2, METHOD_O, 0, STRING_ST, $3);}
979 979
 							}
980 980
 		| PROTO error { $$=0; yyerror("equal/!= operator expected"); }
981 981
 
982
+		| SNDPROTO intop proto	{	onsend_check("snd_proto");
983
+									$$=mk_elem($2, SNDPROTO_O, 0, NUMBER_ST,
984
+										(void*)$3 ); }
985
+		| SNDPROTO intop attr_id {	onsend_check("snd_proto");
986
+									$$=mk_elem($2, SNDPROTO_O, 0, AVP_ST,
987
+										(void*)$3 ); }
988
+		| SNDPROTO intop error { $$=0;
989
+								yyerror("protocol expected (udp, tcp or tls)");
990
+							}
991
+		| SNDPROTO error { $$=0; yyerror("equal/!= operator expected"); }
992
+
982 993
 		| AF intop NUMBER	{ $$=mk_elem($2, AF_O, 0, NUMBER_ST,(void *) $3 ); }
983 994
 		| AF intop attr_id	{ $$=mk_elem($2, AF_O, 0, AVP_ST,(void *) $3 ); }
984 995
 		| AF intop error { $$=0; yyerror("number expected"); }
985 996
 		| AF error { $$=0; yyerror("equal/!= operator expected"); }
986 997
 
998
+		| SNDAF intop NUMBER	{	onsend_check("snd_af");
999
+									$$=mk_elem($2, SNDAF_O, 0, NUMBER_ST,
1000
+										(void *) $3 ); }
1001
+		| SNDAF intop attr_id	{	onsend_check("snd_af");
1002
+									$$=mk_elem($2, SNDAF_O, 0, AVP_ST,
1003
+										(void *) $3 ); }
1004
+		| SNDAF intop error { $$=0; yyerror("number expected"); }
1005
+		| SNDAF error { $$=0; yyerror("equal/!= operator expected"); }
1006
+
987 1007
 		| MSGLEN intop NUMBER	{ $$=mk_elem($2, MSGLEN_O, 0, NUMBER_ST, (void *) $3 ); }
988 1008
 		| MSGLEN intop attr_id	{ $$=mk_elem($2, MSGLEN_O, 0, AVP_ST, (void *) $3 ); }
989 1009
 		| MSGLEN intop MAX_LEN	{ $$=mk_elem($2, MSGLEN_O, 0, NUMBER_ST, (void *) BUF_SIZE); }
... ...
@@ -1040,6 +1105,58 @@ exp_elem:	METHOD strop STRING	{$$= mk_elem($2, METHOD_O, 0, STRING_ST, $3);}
1040 1040
 						 			"expected" ); }
1041 1041
 		| DSTIP error { $$=0; 
1042 1042
 						yyerror("invalid operator, ==, != or =~ expected");}
1043
+		| SNDIP equalop ipnet	{ onsend_check("snd_ip");
1044
+									$$=mk_elem($2, SNDIP_O, 0, NET_ST, $3); }
1045
+		| SNDIP strop STRING	{	onsend_check("snd_ip");
1046
+									s_tmp.s=$3;
1047
+									s_tmp.len=strlen($3);
1048
+									ip_tmp=str2ip(&s_tmp);
1049
+									if (ip_tmp==0)
1050
+										ip_tmp=str2ip6(&s_tmp);
1051
+									if (ip_tmp){
1052
+										$$=mk_elem(	$2, SNDIP_O, 0, NET_ST,
1053
+												mk_net_bitlen(ip_tmp, 
1054
+														ip_tmp->len*8) );
1055
+									}else{
1056
+										$$=mk_elem(	$2, SNDIP_O, 0, STRING_ST,
1057
+												$3);
1058
+									}
1059
+								}
1060
+		| SNDIP strop host	{ 	onsend_check("snd_ip");
1061
+								$$=mk_elem(	$2, SNDIP_O, 0, STRING_ST, $3); }
1062
+		| SNDIP equalop MYSELF  {	onsend_check("snd_ip");
1063
+									$$=mk_elem(	$2, SNDIP_O, 0, MYSELF_ST, 0);
1064
+								}
1065
+		| SNDIP strop error { $$=0; yyerror( "ip address or hostname"
1066
+						 "expected" ); }
1067
+		| SNDIP error  { $$=0; 
1068
+						 yyerror("invalid operator, ==, != or =~ expected");}
1069
+		| TOIP equalop ipnet	{ onsend_check("to_ip");
1070
+									$$=mk_elem($2, TOIP_O, 0, NET_ST, $3); }
1071
+		| TOIP strop STRING	{	onsend_check("to_ip");
1072
+									s_tmp.s=$3;
1073
+									s_tmp.len=strlen($3);
1074
+									ip_tmp=str2ip(&s_tmp);
1075
+									if (ip_tmp==0)
1076
+										ip_tmp=str2ip6(&s_tmp);
1077
+									if (ip_tmp){
1078
+										$$=mk_elem(	$2, TOIP_O, 0, NET_ST,
1079
+												mk_net_bitlen(ip_tmp, 
1080
+														ip_tmp->len*8) );
1081
+									}else{
1082
+										$$=mk_elem(	$2, TOIP_O, 0, STRING_ST,
1083
+												$3);
1084
+									}
1085
+								}
1086
+		| TOIP strop host	{ 	onsend_check("to_ip");
1087
+								$$=mk_elem(	$2, TOIP_O, 0, STRING_ST, $3); }
1088
+		| TOIP equalop MYSELF  {	onsend_check("to_ip");
1089
+									$$=mk_elem(	$2, TOIP_O, 0, MYSELF_ST, 0);
1090
+								}
1091
+		| TOIP strop error { $$=0; yyerror( "ip address or hostname"
1092
+						 "expected" ); }
1093
+		| TOIP error  { $$=0; 
1094
+						 yyerror("invalid operator, ==, != or =~ expected");}
1043 1095
 
1044 1096
 		| MYSELF equalop uri_type	{ $$=mk_elem(	$2, $3, 0, MYSELF_ST,
1045 1097
 												       0);
... ...
@@ -1047,8 +1164,14 @@ exp_elem:	METHOD strop STRING	{$$= mk_elem($2, METHOD_O, 0, STRING_ST, $3);}
1047 1047
 		| MYSELF equalop SRCIP  { $$=mk_elem(	$2, SRCIP_O, 0, MYSELF_ST,
1048 1048
 												0);
1049 1049
 								}
1050
-                | MYSELF equalop DSTIP  { $$=mk_elem(	$2, DSTIP_O, 0, MYSELF_ST,
1051
-							0);
1050
+		| MYSELF equalop DSTIP  { $$=mk_elem(	$2, DSTIP_O, 0, MYSELF_ST,
1051
+												0);
1052
+								}
1053
+		| MYSELF equalop SNDIP  {	onsend_check("snd_ip");
1054
+									$$=mk_elem(	$2, SNDIP_O, 0, MYSELF_ST, 0);
1055
+								}
1056
+		| MYSELF equalop TOIP  {	onsend_check("to_ip");
1057
+									$$=mk_elem(	$2, TOIP_O, 0, MYSELF_ST, 0);
1052 1058
 								}
1053 1059
 		| MYSELF equalop error {	$$=0; 
1054 1060
 									yyerror(" URI, SRCIP or DSTIP expected"); }
... ...
@@ -1058,11 +1181,11 @@ exp_elem:	METHOD strop STRING	{$$= mk_elem($2, METHOD_O, 0, STRING_ST, $3);}
1058 1058
 		| exp_stm			{ $$=mk_elem( NO_OP, ACTION_O, 0, ACTIONS_ST, $1);  }
1059 1059
 		| NUMBER		{$$=mk_elem( NO_OP, NUMBER_O, 0, NUMBER_ST, (void*)$1 ); }
1060 1060
 
1061
-		| attr_id		{$$=mk_elem( NO_OP, AVP_ST, (void*)$1, 0, 0); }
1062
-		| attr_id strop STRING	{$$=mk_elem( $2, AVP_ST, (void*)$1, STRING_ST, $3); }
1063
-		| attr_id intop NUMBER	{$$=mk_elem( $2, AVP_ST, (void*)$1, NUMBER_ST, (void*)$3); }
1064
-		| attr_id binop NUMBER	{$$=mk_elem( $2, AVP_ST, (void*)$1, NUMBER_ST, (void*)$3); }
1065
-                | attr_id strop attr_id {$$=mk_elem( $2, AVP_ST, (void*)$1, AVP_ST, (void*)$3); }
1061
+		| attr_id		{$$=mk_elem( NO_OP, AVP_O, (void*)$1, 0, 0); }
1062
+		| attr_id strop STRING	{$$=mk_elem( $2, AVP_O, (void*)$1, STRING_ST, $3); }
1063
+		| attr_id intop NUMBER	{$$=mk_elem( $2, AVP_O, (void*)$1, NUMBER_ST, (void*)$3); }
1064
+		| attr_id binop NUMBER	{$$=mk_elem( $2, AVP_O, (void*)$1, NUMBER_ST, (void*)$3); }
1065
+		| attr_id strop attr_id {$$=mk_elem( $2, AVP_O, (void*)$1, AVP_ST, (void*)$3); }
1066 1066
 ;
1067 1067
 
1068 1068
 
... ...
@@ -1106,8 +1229,33 @@ host:	ID				{ $$=$1; }
1106 1106
 	| host DOT error { $$=0; pkg_free($1); yyerror("invalid hostname"); }
1107 1107
 	;
1108 1108
 
1109
+/* filtered cmd */
1110
+fcmd:	cmd	{ /* check if allowed */
1111
+				if (rt==ONSEND_ROUTE){
1112
+					switch($1->type){
1113
+						case DROP_T:
1114
+						case SEND_T:
1115
+						case SEND_TCP_T:
1116
+						case LOG_T:
1117
+						case SETFLAG_T:
1118
+						case RESETFLAG_T:
1119
+						case ISFLAGSET_T:
1120
+						case IF_T:
1121
+						case MODULE_T:
1122
+							$$=$1;
1123
+							break;
1124
+						default:
1125
+							$$=0;
1126
+							yyerror("command not allowed in onsend_route\n");
1127
+					}
1128
+				}else{
1129
+					$$=$1;
1130
+				}
1131
+			}
1132
+	;
1133
+
1109 1134
 
1110
-exp_stm:	cmd						{ $$=$1; }
1135
+exp_stm:	fcmd						{ $$=$1; }
1111 1136
 		|	if_cmd					{ $$=$1; }
1112 1137
                 |       assign_action { $$ = $1; }
1113 1138
 		|	LBRACE actions RBRACE	{ $$=$2; }
... ...
@@ -1122,11 +1270,11 @@ actions:	actions action	{$$=append_action($1, $2); }
1122 1122
 		| actions error { $$=0; yyerror("bad command"); }
1123 1123
 	;
1124 1124
 
1125
-action:		cmd SEMICOLON {$$=$1;}
1125
+action:		fcmd SEMICOLON {$$=$1;}
1126 1126
 		| if_cmd {$$=$1;}
1127 1127
 		| assign_action SEMICOLON {$$=$1;}
1128 1128
 		| SEMICOLON /* null action */ {$$=0;}
1129
-		| cmd error { $$=0; yyerror("bad command: missing ';'?"); }
1129
+		| fcmd error { $$=0; yyerror("bad command: missing ';'?"); }
1130 1130
 	;
1131 1131
 
1132 1132
 if_cmd:		IF exp stm				{ $$=mk_action3( IF_T,
... ...
@@ -1197,7 +1345,7 @@ assign_op : ADDEQ { $$ = ADD_T; }
1197 1197
 
1198 1198
 assign_action:   attr_id assign_op STRING  { $$=mk_action($2, AVP_ST, STRING_ST, $1, $3); }
1199 1199
                | attr_id assign_op NUMBER  { $$=mk_action($2, AVP_ST, NUMBER_ST, $1, (void*)$3); }
1200
-               | attr_id assign_op cmd     { $$=mk_action($2, AVP_ST, ACTION_ST, $1, $3); }
1200
+               | attr_id assign_op fcmd    { $$=mk_action($2, AVP_ST, ACTION_ST, $1, $3); }
1201 1201
                | attr_id assign_op attr_id { $$=mk_action($2, AVP_ST, AVP_ST, $1, $3); }
1202 1202
                | attr_id assign_op LPAREN exp RPAREN { $$ = mk_action($2, AVP_ST, EXPR_ST, $1, $4); }
1203 1203
 ;
... ...
@@ -61,6 +61,7 @@
61 61
 #define FAILURE_RT_NO RT_NO /* on_failure routing tables number */
62 62
 #define ONREPLY_RT_NO RT_NO /* on_reply routing tables number */
63 63
 #define BRANCH_RT_NO RT_NO /* branch_route routing tables number */
64
+#define ONSEND_RT_NO 1  /* onsend_route routing tables number */
64 65
 #define DEFAULT_RT 0 /* default routing table */
65 66
 
66 67
 #define MAX_REC_LEV 100 /* maximum number of recursive calls */
... ...
@@ -46,6 +46,8 @@
46 46
  *  2003-10-24  converted to the new socket_info lists (andrei)
47 47
  *  2004-10-10  modified check_self to use grep_sock_info (andrei)
48 48
  *  2004-11-08  added force_send_socket support in get_send_socket (andrei)
49
+ *  2005-12-11  onsend_router support; forward_request to no longer
50
+ *              pkg_malloc'ed (andrei)
49 51
  */
50 52
 
51 53
 
... ...
@@ -75,6 +77,7 @@
75 75
 #include "resolve.h"
76 76
 #include "name_alias.h"
77 77
 #include "socket_info.h"
78
+#include "onsend.h"
78 79
 
79 80
 #ifdef DEBUG_DMALLOC
80 81
 #include <dmalloc.h>
... ...
@@ -261,23 +264,14 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p, int proto)
261 261
 {
262 262
 	unsigned int len;
263 263
 	char* buf;
264
-	union sockaddr_union* to;
264
+	union sockaddr_union to;
265 265
 	struct socket_info* send_sock;
266 266
 	char md5[MD5_LEN];
267 267
 	int id; /* used as branch for tcp! */
268 268
 	
269
-	to=0;
270 269
 	buf=0;
271 270
 	id=0;
272 271
 	
273
-	to=(union sockaddr_union*)pkg_malloc(sizeof(union sockaddr_union));
274
-	if (to==0){
275
-		ser_error=E_OUT_OF_MEM;
276
-		LOG(L_ERR, "ERROR: forward_request: out of memory\n");
277
-		goto error;
278
-	}
279
-	
280
-	
281 272
 	/* if error try next ip address if possible */
282 273
 	if (p->ok==0){
283 274
 		if (p->host.h_addr_list[p->addr_idx+1])
... ...
@@ -286,18 +280,18 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p, int proto)
286 286
 		p->ok=1;
287 287
 	}
288 288
 	
289
-	hostent2su(to, &p->host, p->addr_idx, 
289
+	hostent2su(&to, &p->host, p->addr_idx, 
290 290
 				(p->port)?p->port:SIP_PORT);
291 291
 	p->tx++;
292 292
 	p->tx_bytes+=len;
293 293
 	
294 294
 
295
-	send_sock=get_send_socket(msg, to, proto);
295
+	send_sock=get_send_socket(msg, &to, proto);
296 296
 	if (send_sock==0){
297 297
 		LOG(L_ERR, "forward_req: ERROR: cannot forward to af %d, proto %d "
298
-				"no corresponding listening socket\n", to->s.sa_family, proto);
298
+				"no corresponding listening socket\n", to.s.sa_family, proto);
299 299
 		ser_error=E_NO_SOCKET;
300
-		goto error1;
300
+		goto error;
301 301
 	}
302 302
 
303 303
 	/* calculate branch for outbound request;  if syn_branch is turned off,
... ...
@@ -315,43 +309,45 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p, int proto)
315 315
 	} else {
316 316
 		if (!char_msg_val( msg, md5 )) 	{ /* parses transaction key */
317 317
 			LOG(L_ERR, "ERROR: forward_request: char_msg_val failed\n");
318
-			goto error1;
318
+			goto error;
319 319
 		}
320 320
 		msg->hash_index=hash( msg->callid->body, get_cseq(msg)->number);
321 321
 		if (!branch_builder( msg->hash_index, 0, md5, id /* 0-th branch */,
322 322
 					msg->add_to_branch_s, &msg->add_to_branch_len )) {
323 323
 			LOG(L_ERR, "ERROR: forward_request: branch_builder failed\n");
324
-			goto error1;
324
+			goto error;
325 325
 		}
326 326
 	}
327 327
 
328 328
 	buf = build_req_buf_from_sip_req( msg, &len, send_sock,  proto);
329 329
 	if (!buf){
330 330
 		LOG(L_ERR, "ERROR: forward_request: building failed\n");
331
-		goto error1;
331
+		goto error;
332 332
 	}
333 333
 	 /* send it! */
334 334
 	DBG("Sending:\n%.*s.\n", (int)len, buf);
335 335
 	DBG("orig. len=%d, new_len=%d, proto=%d\n", msg->len, len, proto );
336 336
 	
337
-	if (msg_send(send_sock, proto, to, 0, buf, len)<0){
337
+	if (run_onsend(msg, send_sock, proto, &to, buf, len)==0){
338
+		LOG(L_INFO, "forward_request: request dropped (onsend_route)\n");
339
+		STATS_TX_DROPS;
340
+		goto error; /* error ? */
341
+	}
342
+	if (msg_send(send_sock, proto, &to, 0, buf, len)<0){
338 343
 		ser_error=E_SEND;
339 344
 		p->errors++;
340 345
 		p->ok=0;
341 346
 		STATS_TX_DROPS;
342
-		goto error1;
347
+		goto error;
343 348
 	}
344 349
 	
345 350
 	/* sent requests stats */
346 351
 	STATS_TX_REQUEST(  msg->first_line.u.request.method_value );
347 352
 	
348 353
 	pkg_free(buf);
349
-	pkg_free(to);
350 354
 	/* received_buf & line_buf will be freed in receive_msg by free_lump_list*/
351 355
 	return 0;
352 356
 
353
-error1:
354
-	pkg_free(to);
355 357
 error:
356 358
 	if (buf) pkg_free(buf);
357 359
 	return -1;
... ...
@@ -42,6 +42,8 @@
42 42
  *  2004-02-13  t->is_invite and t->local replaced with flags (bogdan)
43 43
  *  2005-02-16  fr_*_timer acceps full AVP specifications; empty AVP
44 44
  *              desable variable timer feature (bogdan)
45
+ *  2005-12-11  t_relay doesn't return 0 (stop script) on send error 
46
+ *              anymore (andrei)
45 47
  */
46 48
 
47 49
 #include <limits.h>
... ...
@@ -270,7 +272,7 @@ int t_relay_to( struct sip_msg  *p_msg , struct proxy_l *proxy, int proto,
270 270
 			  	script */
271 271
 				DBG("ERROR: generation of a stateful reply "
272 272
 					"on error succeeded\n");
273
-				ret=0;
273
+				/*ret=0; -- we don't want to stop the script */
274 274
 			}  else {
275 275
 				DBG("ERROR: generation of a stateful reply "
276 276
 					"on error failed\n");
... ...
@@ -44,6 +44,7 @@
44 44
  *  2004-02-13: t->is_invite and t->local replaced with flags (bogdan)
45 45
  *  2005-08-04  msg->parsed_uri and parsed_uri_ok are no saved & restored
46 46
  *               before & after handling the branches (andrei)
47
+ *  2005-12-11  onsend_route support added for forwarding (andrei)
47 48
  */
48 49
 
49 50
 #include "defs.h"
... ...
@@ -60,6 +61,7 @@
60 60
 #include "../../dset.h"
61 61
 #include "../../action.h"
62 62
 #include "../../data_lump.h"
63
+#include "../../onsend.h"
63 64
 #include "t_funcs.h"
64 65
 #include "t_hooks.h"
65 66
 #include "t_msgbuilder.h"
... ...
@@ -551,6 +553,13 @@ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg ,
551 551
 	success_branch=0;
552 552
 	for (i=first_branch; i<t->nr_of_outgoings; i++) {
553 553
 		if (added_branches & (1<<i)) {
554
+			if (run_onsend(p_msg,	t->uac[i].request.dst.send_sock,
555
+									t->uac[i].request.dst.proto,
556
+									&t->uac[i].request.dst.to,
557
+									t->uac[i].request.buffer,
558
+									t->uac[i].request.buffer_len)==0)
559
+				continue; /* if onsend drop, try next branch */
560
+			
554 561
 			if (SEND_BUFFER( &t->uac[i].request)==-1) {
555 562
 				LOG(L_ERR, "ERROR: t_forward_nonack: sending request failed\n");
556 563
 				if (proxy) { proxy->errors++; proxy->ok=0; }
... ...
@@ -66,6 +66,7 @@
66 66
 #include "parser/parse_from.h"
67 67
 #include "parser/parse_to.h"
68 68
 #include "mem/mem.h"
69
+#include "onsend.h"
69 70
 
70 71
 
71 72
 /* main routing script table  */
... ...
@@ -74,6 +75,7 @@ struct action* rlist[RT_NO];
74 74
 struct action* onreply_rlist[ONREPLY_RT_NO];
75 75
 struct action* failure_rlist[FAILURE_RT_NO];
76 76
 struct action* branch_rlist[BRANCH_RT_NO];
77
+struct action* onsend_rlist[ONSEND_RT_NO];
77 78
 
78 79
 static int fix_actions(struct action* a); /*fwd declaration*/
79 80
 
... ...
@@ -643,6 +645,8 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
643 643
 {
644 644
 	struct sip_uri uri;
645 645
 	int ret;
646
+	struct onsend_info* snd_inf;
647
+	struct ip_addr ip;
646 648
 	ret=E_BUG;
647 649
 	
648 650
 	if (e->type!=ELEM_T){
... ...
@@ -727,6 +731,25 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
727 727
 	case DSTIP_O:
728 728
 		ret=comp_ip(e->op, &msg->rcv.dst_ip, e->r_type, &e->r);
729 729
 		break;
730
+	
731
+	case SNDIP_O:
732
+		snd_inf=get_onsend_info();
733
+		if (snd_inf && snd_inf->send_sock){
734
+			ret=comp_ip(e->op, &snd_inf->send_sock->address, e->r_type, &e->r);
735
+		}else{
736
+			BUG("eval_elem: snd_ip unknown (not in a onsend_route?)\n");
737
+		}
738
+		break;
739
+	
740
+	case TOIP_O:
741
+		snd_inf=get_onsend_info();
742
+		if (snd_inf && snd_inf->to){
743
+			su2ip_addr(&ip, snd_inf->to);
744
+			ret=comp_ip(e->op, &ip, e->r_type, &e->r);
745
+		}else{
746
+			BUG("eval_elem: to_ip unknown (not in a onsend_route?)\n");
747
+		}
748
+		break;
730 749
 
731 750
 	case NUMBER_O:
732 751
 		ret=!(!e->r.intval); /* !! to transform it in {0,1} */
... ...
@@ -748,22 +771,67 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
748 748
 			     e->r_type, &e->r);
749 749
 		break;
750 750
 		
751
+	case SNDPORT_O:
752
+		snd_inf=get_onsend_info();
753
+		if (snd_inf && snd_inf->send_sock){
754
+			ret=comp_num(e->op, (int)snd_inf->send_sock->port_no, 
755
+				     e->r_type, &e->r);
756
+		}else{
757
+			BUG("eval_elem: snd_port unknown (not in a onsend_route?)\n");
758
+		}
759
+		break;
760
+		
761
+	case TOPORT_O:
762
+		snd_inf=get_onsend_info();
763
+		if (snd_inf && snd_inf->to){
764
+			ret=comp_num(e->op, (int)su_getport(snd_inf->to), 
765
+				     e->r_type, &e->r);
766
+		}else{
767
+			BUG("eval_elem: to_port unknown (not in a onsend_route?)\n");
768
+		}
769
+		break;
770
+		
751 771
 	case PROTO_O:
752 772
 		ret=comp_num(e->op, msg->rcv.proto, 
753 773
 			     e->r_type, &e->r);
754 774
 		break;
755 775
 		
776
+	case SNDPROTO_O:
777
+		snd_inf=get_onsend_info();
778
+		if (snd_inf && snd_inf->send_sock){
779
+			ret=comp_num(e->op, snd_inf->send_sock->proto, 
780
+				     e->r_type, &e->r);
781
+		}else{
782
+			BUG("eval_elem: snd_proto unknown (not in a onsend_route?)\n");
783
+		}
784
+		break;
785
+		
756 786
 	case AF_O:
757 787
 		ret=comp_num(e->op, (int)msg->rcv.src_ip.af, 
758 788
 			     e->r_type, &e->r);
759 789
 		break;
790
+		
791
+	case SNDAF_O:
792
+		snd_inf=get_onsend_info();
793
+		if (snd_inf && snd_inf->send_sock){
794
+			ret=comp_num(e->op, snd_inf->send_sock->address.af,
795
+							e->r_type, &e->r);
796
+		}else{
797
+			BUG("eval_elem: snd_af unknown (not in a onsend_route?)\n");
798
+		}
799
+		break;
760 800
 
761 801
 	case MSGLEN_O:
762
-		ret=comp_num(e->op, (int)msg->len, 
763
-				e->r_type, &e->r);
802
+		if ((snd_inf=get_onsend_info())!=0){
803
+			ret=comp_num(e->op, (int)snd_inf->len, 
804
+					e->r_type, &e->r);
805
+		}else{
806
+			ret=comp_num(e->op, (int)msg->len, 
807
+					e->r_type, &e->r);
808
+		}
764 809
 		break;
765 810
 
766
-	case AVP_ST:
811
+	case AVP_O:
767 812
 		ret = comp_avp(e->op, e->l.attr, e->r_type, &e->r);
768 813
 		break;
769 814
 		
... ...
@@ -891,6 +959,13 @@ int fix_rls()
891 891
 			}
892 892
 		}
893 893
 	}
894
+	for(i=0;i<ONSEND_RT_NO;i++){
895
+		if(onsend_rlist[i]){
896
+			if ((ret=fix_actions(onsend_rlist[i]))!=0){
897
+				return ret;
898
+			}
899
+		}
900
+	}
894 901
 	return 0;
895 902
 }
896 903
 
... ...
@@ -44,9 +44,10 @@
44 44
 /* main "script table" */
45 45
 extern struct action* rlist[RT_NO];
46 46
 /* main reply route table */
47
-extern struct action* onreply_rlist[RT_NO];
48
-extern struct action* failure_rlist[RT_NO];
49
-extern struct action* branch_rlist[RT_NO];
47
+extern struct action* onreply_rlist[ONREPLY_RT_NO];
48
+extern struct action* failure_rlist[FAILURE_RT_NO];
49
+extern struct action* branch_rlist[BRANCH_RT_NO];
50
+extern struct action* onsend_rlist[ONSEND_RT_NO];
50 51
 
51 52
 
52 53
 void push(struct action* a, struct action** head);
... ...
@@ -33,6 +33,7 @@
33 33
  *  2003-10-10  >,<,>=,<=, != and MSGLEN_O added (andrei)
34 34
  *  2003-10-28  FORCE_TCP_ALIAS added (andrei)
35 35
  *  2004-02-24  added LOAD_AVP_T and AVP_TO_URI_T (bogdan)
36
+ *  2005-12-11  added SND{IP,PORT,PROTO,AF}_O & TO{IP,PORT}_O (andrei)
36 37
  */
37 38
 
38 39
 
... ...
@@ -60,7 +61,8 @@ enum { LOGAND_OP=1, LOGOR_OP, NOT_OP, BINAND_OP, BINOR_OP };
60 60
 enum { EQUAL_OP=10, MATCH_OP, GT_OP, LT_OP, GTE_OP, LTE_OP, DIFF_OP, NO_OP };
61 61
 enum { METHOD_O=1, URI_O, FROM_URI_O, TO_URI_O, SRCIP_O, SRCPORT_O,
62 62
 	   DSTIP_O, DSTPORT_O, PROTO_O, AF_O, MSGLEN_O, DEFAULT_O, ACTION_O,
63
-	   NUMBER_O, AVP_O};
63
+	   NUMBER_O, AVP_O, SNDIP_O, SNDPORT_O, TOIP_O, TOPORT_O, SNDPROTO_O, 
64
+	   SNDAF_O};
64 65
 
65 66
 enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T,
66 67
 		SET_HOST_T, SET_HOSTPORT_T, SET_USER_T, SET_USERPASS_T, 
... ...
@@ -70,6 +70,7 @@ typedef int (*param_func_t)( modparam_t type, void* val);
70 70
 #define FAILURE_ROUTE 2  /* Function can be used in reply route blocks */
71 71
 #define ONREPLY_ROUTE 4  /* Function can be used in on_reply */
72 72
 #define BRANCH_ROUTE  8  /* Function can be used in branch_route blocks */
73
+#define ONSEND_ROUTE   16  /* Function can be used in onsend_route blocks */
73 74
 
74 75
 /* Macros - used as rank in child_init function */
75 76
 #define PROC_MAIN      0  /* Main ser process */