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 401
 New features
369 402
 =============
370 403
 - RFC3261 support
371
-	- TCP support and cross-transport forwarding [core]
372
-	- loose routing support [rr module]
404
+    - TCP support and cross-transport forwarding [core]
405
+    - loose routing support [rr module]
373 406
 - 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]
407
+    - vm -- voicemail interface [vm]
408
+    - ENUM support [enum]
409
+    - presence agent [pa]
410
+    - dynamic domain management -- allows to manipulate 
411
+      hosting of multiple domains in run-time [module]
412
+    - flat-text-file database support [dbtext]
413
+    - rich access control lists [permissions]
381 414
 - 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
415
+    - click-to-dial, which is based on improved tm/FIFO 
416
+      that better supports external applications [tm module]
417
+    - web accounting -- acc module can report to serweb
418
+        on placed calls [acc module]
419
+    - improved exec module (header fields passed now
387 420
       as environment variables to scripts) [exec module]
388 421
 - Architectural Improvements
389
-	- powerpc fast locking support
390
-	- netbsd support
391
-	- 64 bits arch. support (e.g. netbsd/sparc64).
422
+    - powerpc fast locking support
423
+    - netbsd support
424
+    - 64 bits arch. support (e.g. netbsd/sparc64).
392 425
 - 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]
426
+    - nathelper utility for Cisco/ATA NAT traversal [nathelper]
427
+    - another NAT traversal utility [mangler]
428
+    - postgress support [postgress]
429
+    - fcp module [fcp]
430
+    - pdt module (prefix2domain) [pdt]
398 431
 
399 432
 Changes to use of ser scripts
400 433
 =============================
... ...
@@ -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 75
 #endif
75 76
 
76 77
 
78
+struct onsend_info* p_onsend=0; /* onsend route send info */
79
+
77 80
 /* ret= 0! if action -> end of list(e.g DROP), 
78 81
       > 0 to continue processing next actions
79 82
    and <0 on error */
... ...
@@ -241,13 +244,20 @@ int do_action(struct action* a, struct sip_msg* msg)
241 244
 			ret=hostent2su(	to, &p->host, p->addr_idx,
242 245
 						(p->port)?p->port:SIP_PORT );
243 246
 			if (ret==0){
247
+				if (p_onsend){
248
+					tmp=p_onsend->buf;
249
+					len=p_onsend->len;
250
+				}else{
251
+					tmp=msg->buf;
252
+					len=msg->len;
253
+				}
244 254
 				p->tx++;
245
-				p->tx_bytes+=msg->len;
255
+				p->tx_bytes+=len;
246 256
 				if (a->type==SEND_T){
247 257
 					/*udp*/
248 258
 					send_sock=get_send_socket(msg, to, PROTO_UDP);
249 259
 					if (send_sock!=0){
250
-						ret=udp_send(send_sock, msg->buf, msg->len, to);
260
+						ret=udp_send(send_sock, tmp, len, to);
251 261
 					}else{
252 262
 						ret=-1;
253 263
 					}
... ...
@@ -255,7 +265,7 @@ int do_action(struct action* a, struct sip_msg* msg)
255 265
 #ifdef USE_TCP
256 266
 					else{
257 267
 					/*tcp*/
258
-					ret=tcp_send(PROTO_TCP, msg->buf, msg->len, to, 0);
268
+					ret=tcp_send(PROTO_TCP, tmp, len, to, 0);
259 269
 				}
260 270
 #endif
261 271
 			}
... ...
@@ -743,9 +753,8 @@ int do_action(struct action* a, struct sip_msg* msg)
743 753
 				break;
744 754
 			}
745 755
 
746
-			     /* If the action is assign then remove the old avp value before adding
747
-			      * new ones
748
-			      */
756
+			/* If the action is assign then remove the old avp value
757
+			 * before adding new ones */
749 758
 			if ((unsigned char)a->type == ASSIGN_T) delete_avp(flags, name);
750 759
 			if (add_avp(flags, name, value) < 0) {
751 760
 				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 117
 ROUTE_FAILURE failure_route
116 118
 ROUTE_ONREPLY onreply_route
117 119
 ROUTE_BRANCH branch_route
120
+ROUTE_SEND onsend_route
118 121
 EXEC	exec
119 122
 FORCE_RPORT		"force_rport"|"add_rport"
120 123
 FORCE_TCP_ALIAS		"force_tcp_alias"|"add_tcp_alias"
... ...
@@ -158,6 +161,12 @@ SRCIP	src_ip
158 161
 SRCPORT	src_port
159 162
 DSTIP	dst_ip
160 163
 DSTPORT	dst_port
164
+SNDIP	snd_ip
165
+SNDPORT	snd_port
166
+SNDPROTO	snd_proto|to_proto
167
+SNDAF		snd_af|to_af
168
+TOIP	to_ip
169
+TOPORT	to_port
161 170
 PROTO	proto
162 171
 AF		af
163 172
 MYSELF	myself
... ...
@@ -328,6 +337,7 @@ EAT_ABLE	[\ \t\b\r]
328 337
 <INITIAL>{ROUTE_FAILURE}	{ count(); yylval.strval=yytext;
329 338
 								return ROUTE_FAILURE; }
330 339
 <INITIAL>{ROUTE_BRANCH} { count(); yylval.strval=yytext; return ROUTE_BRANCH; }
340
+<INITIAL>{ROUTE_SEND} { count(); yylval.strval=yytext; return ROUTE_SEND; }
331 341
 <INITIAL>{EXEC}	{ count(); yylval.strval=yytext; return EXEC; }
332 342
 <INITIAL>{SET_HOST}	{ count(); yylval.strval=yytext; return SET_HOST; }
333 343
 <INITIAL>{SET_HOSTPORT}	{ count(); yylval.strval=yytext; return SET_HOSTPORT; }
... ...
@@ -367,6 +377,12 @@ EAT_ABLE	[\ \t\b\r]
367 377
 <INITIAL>{SRCPORT}	{ count(); yylval.strval=yytext; return SRCPORT; }
368 378
 <INITIAL>{DSTIP}	{ count(); yylval.strval=yytext; return DSTIP; }
369 379
 <INITIAL>{DSTPORT}	{ count(); yylval.strval=yytext; return DSTPORT; }
380
+<INITIAL>{SNDIP}	{ count(); yylval.strval=yytext; return SNDIP; }
381
+<INITIAL>{SNDPORT}	{ count(); yylval.strval=yytext; return SNDPORT; }
382
+<INITIAL>{SNDPROTO}	{ count(); yylval.strval=yytext; return SNDPROTO; }
383
+<INITIAL>{SNDAF}	{ count(); yylval.strval=yytext; return SNDAF; }
384
+<INITIAL>{TOIP}		{ count(); yylval.strval=yytext; return TOIP; }
385
+<INITIAL>{TOPORT}	{ count(); yylval.strval=yytext; return TOPORT; }
370 386
 <INITIAL>{PROTO}	{ count(); yylval.strval=yytext; return PROTO; }
371 387
 <INITIAL>{AF}	{ count(); yylval.strval=yytext; return AF; }
372 388
 <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 105
  with no built in alloca, like icc*/
104 106
 #undef _ALLOCA_H
105 107
 
108
+#define onsend_check(s) \
109
+	do{\
110
+		if (rt!=ONSEND_ROUTE) yyerror( s " allowed only in onsend_routes");\
111
+	}while(0)
106 112
 
107 113
 extern int yylex();
108 114
 static void yyerror(char* s);
... ...
@@ -150,6 +156,7 @@ static struct socket_id* mk_listen_id(char*, int, int);
150 156
 %token ROUTE_FAILURE
151 157
 %token ROUTE_ONREPLY
152 158
 %token ROUTE_BRANCH
159
+%token ROUTE_SEND
153 160
 %token EXEC
154 161
 %token SET_HOST
155 162
 %token SET_HOSTPORT
... ...
@@ -183,6 +190,12 @@ static struct socket_id* mk_listen_id(char*, int, int);
183 190
 %token SRCPORT
184 191
 %token DSTIP
185 192
 %token DSTPORT
193
+%token TOIP
194
+%token TOPORT
195
+%token SNDIP
196
+%token SNDPORT
197
+%token SNDPROTO
198
+%token SNDAF
186 199
 %token PROTO
187 200
 %token AF
188 201
 %token MYSELF
... ...
@@ -310,7 +323,7 @@ static struct socket_id* mk_listen_id(char*, int, int);
310 323
 
311 324
 /*non-terminals */
312 325
 %type <expr> exp exp_elem /*, condition*/
313
-%type <action> action actions cmd if_cmd stm exp_stm assign_action
326
+%type <action> action actions cmd fcmd if_cmd stm exp_stm assign_action
314 327
 %type <ipaddr> ipv4 ipv6 ipv6addr ip
315 328
 %type <ipnet> ipnet
316 329
 %type <strval> host
... ...
@@ -347,6 +360,7 @@ statement:	assign_stm
347 360
 		| {rt=FAILURE_ROUTE;} failure_route_stm
348 361
 		| {rt=ONREPLY_ROUTE;} onreply_route_stm
349 362
 		| {rt=BRANCH_ROUTE;} branch_route_stm
363
+		| {rt=ONSEND_ROUTE;}   send_route_stm
350 364
 		| CR	/* null statement*/
351 365
 	;
352 366
 
... ...
@@ -896,6 +910,19 @@ branch_route_stm: ROUTE_BRANCH LBRACE actions RBRACE {
896 910
 										}
897 911
 		| ROUTE_BRANCH error { yyerror("invalid branch_route statement"); }
898 912
 	;
913
+send_route_stm: ROUTE_SEND LBRACE actions RBRACE {
914
+									push($3, &onsend_rlist[DEFAULT_RT]);
915
+									}
916
+			|   ROUTE_SEND LBRACK NUMBER RBRACK LBRACE actions RBRACE {
917
+									if (($3<ONSEND_RT_NO)&&($3>=1)){
918
+										push($6, &onsend_rlist[$3]);
919
+									} else {
920
+										yyerror("invalid onsend routing"
921
+												"table number");
922
+										YYABORT; }
923
+								}
924
+			| ROUTE_SEND error { yyerror("invalid onsend_route statement"); }
925
+	;
899 926
 /*
900 927
 rules:	rules rule { push($2, &$1); $$=$1; }
901 928
 	| rule {$$=$1; }
... ...
@@ -963,7 +990,7 @@ exp_elem:	METHOD strop STRING	{$$= mk_elem($2, METHOD_O, 0, STRING_ST, $3);}
963 990
 									" == , != or =~ expected");
964 991
 					}
965 992
 		| 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 ); }
993
+		| SRCPORT intop attr_id { $$=mk_elem($2, SRCPORT_O, 0, AVP_ST, (void*)$3 ); }
967 994
 		| SRCPORT intop error { $$=0; yyerror("number expected"); }
968 995
 		| SRCPORT error { $$=0; yyerror("==, !=, <,>, >= or <=  expected"); }
969 996
 
... ...
@@ -972,6 +999,24 @@ exp_elem:	METHOD strop STRING	{$$= mk_elem($2, METHOD_O, 0, STRING_ST, $3);}
972 999
 		| DSTPORT intop error { $$=0; yyerror("number expected"); }
973 1000
 		| DSTPORT error { $$=0; yyerror("==, !=, <,>, >= or <=  expected"); }
974 1001
 
1002
+		| SNDPORT intop NUMBER	{	onsend_check("snd_port");
1003
+									$$=mk_elem($2, SNDPORT_O, 0, NUMBER_ST,
1004
+												(void*)$3 ); }
1005
+		| SNDPORT intop attr_id {	onsend_check("snd_port");
1006
+									$$=mk_elem($2, SNDPORT_O, 0, AVP_ST,
1007
+												(void*)$3 ); }
1008
+		| SNDPORT intop error { $$=0; yyerror("number expected"); }
1009
+		| SNDPORT error { $$=0; yyerror("==, !=, <,>, >= or <=  expected"); }
1010
+
1011
+		| TOPORT intop NUMBER	{	onsend_check("to_port");
1012
+									$$=mk_elem($2, TOPORT_O, 0, NUMBER_ST,
1013
+												(void*)$3 ); }
1014
+		| TOPORT intop attr_id {	onsend_check("to_port");
1015
+									$$=mk_elem($2, TOPORT_O, 0, AVP_ST,
1016
+												(void*)$3 ); }
1017
+		| TOPORT intop error { $$=0; yyerror("number expected"); }
1018
+		| TOPORT error { $$=0; yyerror("==, !=, <,>, >= or <=  expected"); }
1019
+
975 1020
 		| PROTO intop proto	{ $$=mk_elem($2, PROTO_O, 0, NUMBER_ST, (void*)$3 ); }
976 1021
 		| PROTO intop attr_id	{ $$=mk_elem($2, PROTO_O, 0, AVP_ST, (void*)$3 ); }
977 1022
 		| PROTO intop error { $$=0;
... ...
@@ -979,11 +1024,31 @@ exp_elem:	METHOD strop STRING	{$$= mk_elem($2, METHOD_O, 0, STRING_ST, $3);}
979 1024
 							}
980 1025
 		| PROTO error { $$=0; yyerror("equal/!= operator expected"); }
981 1026
 
1027
+		| SNDPROTO intop proto	{	onsend_check("snd_proto");
1028
+									$$=mk_elem($2, SNDPROTO_O, 0, NUMBER_ST,
1029
+										(void*)$3 ); }
1030
+		| SNDPROTO intop attr_id {	onsend_check("snd_proto");
1031
+									$$=mk_elem($2, SNDPROTO_O, 0, AVP_ST,
1032
+										(void*)$3 ); }
1033
+		| SNDPROTO intop error { $$=0;
1034
+								yyerror("protocol expected (udp, tcp or tls)");
1035
+							}
1036
+		| SNDPROTO error { $$=0; yyerror("equal/!= operator expected"); }
1037
+
982 1038
 		| AF intop NUMBER	{ $$=mk_elem($2, AF_O, 0, NUMBER_ST,(void *) $3 ); }
983 1039
 		| AF intop attr_id	{ $$=mk_elem($2, AF_O, 0, AVP_ST,(void *) $3 ); }
984 1040
 		| AF intop error { $$=0; yyerror("number expected"); }
985 1041
 		| AF error { $$=0; yyerror("equal/!= operator expected"); }
986 1042
 
1043
+		| SNDAF intop NUMBER	{	onsend_check("snd_af");
1044
+									$$=mk_elem($2, SNDAF_O, 0, NUMBER_ST,
1045
+										(void *) $3 ); }
1046
+		| SNDAF intop attr_id	{	onsend_check("snd_af");
1047
+									$$=mk_elem($2, SNDAF_O, 0, AVP_ST,
1048
+										(void *) $3 ); }
1049
+		| SNDAF intop error { $$=0; yyerror("number expected"); }
1050
+		| SNDAF error { $$=0; yyerror("equal/!= operator expected"); }
1051
+
987 1052
 		| MSGLEN intop NUMBER	{ $$=mk_elem($2, MSGLEN_O, 0, NUMBER_ST, (void *) $3 ); }
988 1053
 		| MSGLEN intop attr_id	{ $$=mk_elem($2, MSGLEN_O, 0, AVP_ST, (void *) $3 ); }
989 1054
 		| 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 1105
 						 			"expected" ); }
1041 1106
 		| DSTIP error { $$=0; 
1042 1107
 						yyerror("invalid operator, ==, != or =~ expected");}
1108
+		| SNDIP equalop ipnet	{ onsend_check("snd_ip");
1109
+									$$=mk_elem($2, SNDIP_O, 0, NET_ST, $3); }
1110
+		| SNDIP strop STRING	{	onsend_check("snd_ip");
1111
+									s_tmp.s=$3;
1112
+									s_tmp.len=strlen($3);
1113
+									ip_tmp=str2ip(&s_tmp);
1114
+									if (ip_tmp==0)
1115
+										ip_tmp=str2ip6(&s_tmp);
1116
+									if (ip_tmp){
1117
+										$$=mk_elem(	$2, SNDIP_O, 0, NET_ST,
1118
+												mk_net_bitlen(ip_tmp, 
1119
+														ip_tmp->len*8) );
1120
+									}else{
1121
+										$$=mk_elem(	$2, SNDIP_O, 0, STRING_ST,
1122
+												$3);
1123
+									}
1124
+								}
1125
+		| SNDIP strop host	{ 	onsend_check("snd_ip");
1126
+								$$=mk_elem(	$2, SNDIP_O, 0, STRING_ST, $3); }
1127
+		| SNDIP equalop MYSELF  {	onsend_check("snd_ip");
1128
+									$$=mk_elem(	$2, SNDIP_O, 0, MYSELF_ST, 0);
1129
+								}
1130
+		| SNDIP strop error { $$=0; yyerror( "ip address or hostname"
1131
+						 "expected" ); }
1132
+		| SNDIP error  { $$=0; 
1133
+						 yyerror("invalid operator, ==, != or =~ expected");}
1134
+		| TOIP equalop ipnet	{ onsend_check("to_ip");
1135
+									$$=mk_elem($2, TOIP_O, 0, NET_ST, $3); }
1136
+		| TOIP strop STRING	{	onsend_check("to_ip");
1137
+									s_tmp.s=$3;
1138
+									s_tmp.len=strlen($3);
1139
+									ip_tmp=str2ip(&s_tmp);
1140
+									if (ip_tmp==0)
1141
+										ip_tmp=str2ip6(&s_tmp);
1142
+									if (ip_tmp){
1143
+										$$=mk_elem(	$2, TOIP_O, 0, NET_ST,
1144
+												mk_net_bitlen(ip_tmp, 
1145
+														ip_tmp->len*8) );
1146
+									}else{
1147
+										$$=mk_elem(	$2, TOIP_O, 0, STRING_ST,
1148
+												$3);
1149
+									}
1150
+								}
1151
+		| TOIP strop host	{ 	onsend_check("to_ip");
1152
+								$$=mk_elem(	$2, TOIP_O, 0, STRING_ST, $3); }
1153
+		| TOIP equalop MYSELF  {	onsend_check("to_ip");
1154
+									$$=mk_elem(	$2, TOIP_O, 0, MYSELF_ST, 0);
1155
+								}
1156
+		| TOIP strop error { $$=0; yyerror( "ip address or hostname"
1157
+						 "expected" ); }
1158
+		| TOIP error  { $$=0; 
1159
+						 yyerror("invalid operator, ==, != or =~ expected");}
1043 1160
 
1044 1161
 		| MYSELF equalop uri_type	{ $$=mk_elem(	$2, $3, 0, MYSELF_ST,
1045 1162
 												       0);
... ...
@@ -1047,8 +1164,14 @@ exp_elem:	METHOD strop STRING	{$$= mk_elem($2, METHOD_O, 0, STRING_ST, $3);}
1047 1164
 		| MYSELF equalop SRCIP  { $$=mk_elem(	$2, SRCIP_O, 0, MYSELF_ST,
1048 1165
 												0);
1049 1166
 								}
1050
-                | MYSELF equalop DSTIP  { $$=mk_elem(	$2, DSTIP_O, 0, MYSELF_ST,
1051
-							0);
1167
+		| MYSELF equalop DSTIP  { $$=mk_elem(	$2, DSTIP_O, 0, MYSELF_ST,
1168
+												0);
1169
+								}
1170
+		| MYSELF equalop SNDIP  {	onsend_check("snd_ip");
1171
+									$$=mk_elem(	$2, SNDIP_O, 0, MYSELF_ST, 0);
1172
+								}
1173
+		| MYSELF equalop TOIP  {	onsend_check("to_ip");
1174
+									$$=mk_elem(	$2, TOIP_O, 0, MYSELF_ST, 0);
1052 1175
 								}
1053 1176
 		| MYSELF equalop error {	$$=0; 
1054 1177
 									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 1181
 		| exp_stm			{ $$=mk_elem( NO_OP, ACTION_O, 0, ACTIONS_ST, $1);  }
1059 1182
 		| NUMBER		{$$=mk_elem( NO_OP, NUMBER_O, 0, NUMBER_ST, (void*)$1 ); }
1060 1183
 
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); }
1184
+		| attr_id		{$$=mk_elem( NO_OP, AVP_O, (void*)$1, 0, 0); }
1185
+		| attr_id strop STRING	{$$=mk_elem( $2, AVP_O, (void*)$1, STRING_ST, $3); }
1186
+		| attr_id intop NUMBER	{$$=mk_elem( $2, AVP_O, (void*)$1, NUMBER_ST, (void*)$3); }
1187
+		| attr_id binop NUMBER	{$$=mk_elem( $2, AVP_O, (void*)$1, NUMBER_ST, (void*)$3); }
1188
+		| attr_id strop attr_id {$$=mk_elem( $2, AVP_O, (void*)$1, AVP_ST, (void*)$3); }
1066 1189
 ;
1067 1190
 
1068 1191
 
... ...
@@ -1106,8 +1229,33 @@ host:	ID				{ $$=$1; }
1106 1229
 	| host DOT error { $$=0; pkg_free($1); yyerror("invalid hostname"); }
1107 1230
 	;
1108 1231
 
1232
+/* filtered cmd */
1233
+fcmd:	cmd	{ /* check if allowed */
1234
+				if (rt==ONSEND_ROUTE){
1235
+					switch($1->type){
1236
+						case DROP_T:
1237
+						case SEND_T:
1238
+						case SEND_TCP_T:
1239
+						case LOG_T:
1240
+						case SETFLAG_T:
1241
+						case RESETFLAG_T:
1242
+						case ISFLAGSET_T:
1243
+						case IF_T:
1244
+						case MODULE_T:
1245
+							$$=$1;
1246
+							break;
1247
+						default:
1248
+							$$=0;
1249
+							yyerror("command not allowed in onsend_route\n");
1250
+					}
1251
+				}else{
1252
+					$$=$1;
1253
+				}
1254
+			}
1255
+	;
1256
+
1109 1257
 
1110
-exp_stm:	cmd						{ $$=$1; }
1258
+exp_stm:	fcmd						{ $$=$1; }
1111 1259
 		|	if_cmd					{ $$=$1; }
1112 1260
                 |       assign_action { $$ = $1; }
1113 1261
 		|	LBRACE actions RBRACE	{ $$=$2; }
... ...
@@ -1122,11 +1270,11 @@ actions:	actions action	{$$=append_action($1, $2); }
1122 1270
 		| actions error { $$=0; yyerror("bad command"); }
1123 1271
 	;
1124 1272
 
1125
-action:		cmd SEMICOLON {$$=$1;}
1273
+action:		fcmd SEMICOLON {$$=$1;}
1126 1274
 		| if_cmd {$$=$1;}
1127 1275
 		| assign_action SEMICOLON {$$=$1;}
1128 1276
 		| SEMICOLON /* null action */ {$$=0;}
1129
-		| cmd error { $$=0; yyerror("bad command: missing ';'?"); }
1277
+		| fcmd error { $$=0; yyerror("bad command: missing ';'?"); }
1130 1278
 	;
1131 1279
 
1132 1280
 if_cmd:		IF exp stm				{ $$=mk_action3( IF_T,
... ...
@@ -1197,7 +1345,7 @@ assign_op : ADDEQ { $$ = ADD_T; }
1197 1345
 
1198 1346
 assign_action:   attr_id assign_op STRING  { $$=mk_action($2, AVP_ST, STRING_ST, $1, $3); }
1199 1347
                | 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); }
1348
+               | attr_id assign_op fcmd    { $$=mk_action($2, AVP_ST, ACTION_ST, $1, $3); }
1201 1349
                | attr_id assign_op attr_id { $$=mk_action($2, AVP_ST, AVP_ST, $1, $3); }
1202 1350
                | attr_id assign_op LPAREN exp RPAREN { $$ = mk_action($2, AVP_ST, EXPR_ST, $1, $4); }
1203 1351
 ;
... ...
@@ -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 77
 #include "resolve.h"
76 78
 #include "name_alias.h"
77 79
 #include "socket_info.h"
80
+#include "onsend.h"
78 81
 
79 82
 #ifdef DEBUG_DMALLOC
80 83
 #include <dmalloc.h>
... ...
@@ -261,23 +264,14 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p, int proto)
261 264
 {
262 265
 	unsigned int len;
263 266
 	char* buf;
264
-	union sockaddr_union* to;
267
+	union sockaddr_union to;
265 268
 	struct socket_info* send_sock;
266 269
 	char md5[MD5_LEN];
267 270
 	int id; /* used as branch for tcp! */
268 271
 	
269
-	to=0;
270 272
 	buf=0;
271 273
 	id=0;
272 274
 	
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 275
 	/* if error try next ip address if possible */
282 276
 	if (p->ok==0){
283 277
 		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 280
 		p->ok=1;
287 281
 	}
288 282
 	
289
-	hostent2su(to, &p->host, p->addr_idx, 
283
+	hostent2su(&to, &p->host, p->addr_idx, 
290 284
 				(p->port)?p->port:SIP_PORT);
291 285
 	p->tx++;
292 286
 	p->tx_bytes+=len;
293 287
 	
294 288
 
295
-	send_sock=get_send_socket(msg, to, proto);
289
+	send_sock=get_send_socket(msg, &to, proto);
296 290
 	if (send_sock==0){
297 291
 		LOG(L_ERR, "forward_req: ERROR: cannot forward to af %d, proto %d "
298
-				"no corresponding listening socket\n", to->s.sa_family, proto);
292
+				"no corresponding listening socket\n", to.s.sa_family, proto);
299 293
 		ser_error=E_NO_SOCKET;
300
-		goto error1;
294
+		goto error;
301 295
 	}
302 296
 
303 297
 	/* 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 309
 	} else {
316 310
 		if (!char_msg_val( msg, md5 )) 	{ /* parses transaction key */
317 311
 			LOG(L_ERR, "ERROR: forward_request: char_msg_val failed\n");
318
-			goto error1;
312
+			goto error;
319 313
 		}
320 314
 		msg->hash_index=hash( msg->callid->body, get_cseq(msg)->number);
321 315
 		if (!branch_builder( msg->hash_index, 0, md5, id /* 0-th branch */,
322 316
 					msg->add_to_branch_s, &msg->add_to_branch_len )) {
323 317
 			LOG(L_ERR, "ERROR: forward_request: branch_builder failed\n");
324
-			goto error1;
318
+			goto error;
325 319
 		}
326 320
 	}
327 321
 
328 322
 	buf = build_req_buf_from_sip_req( msg, &len, send_sock,  proto);
329 323
 	if (!buf){
330 324
 		LOG(L_ERR, "ERROR: forward_request: building failed\n");
331
-		goto error1;
325
+		goto error;
332 326
 	}
333 327
 	 /* send it! */
334 328
 	DBG("Sending:\n%.*s.\n", (int)len, buf);
335 329
 	DBG("orig. len=%d, new_len=%d, proto=%d\n", msg->len, len, proto );
336 330
 	
337
-	if (msg_send(send_sock, proto, to, 0, buf, len)<0){
331
+	if (run_onsend(msg, send_sock, proto, &to, buf, len)==0){
332
+		LOG(L_INFO, "forward_request: request dropped (onsend_route)\n");
333
+		STATS_TX_DROPS;
334
+		goto error; /* error ? */
335
+	}
336
+	if (msg_send(send_sock, proto, &to, 0, buf, len)<0){
338 337
 		ser_error=E_SEND;
339 338
 		p->errors++;
340 339
 		p->ok=0;
341 340
 		STATS_TX_DROPS;
342
-		goto error1;
341
+		goto error;
343 342
 	}
344 343
 	
345 344
 	/* sent requests stats */
346 345
 	STATS_TX_REQUEST(  msg->first_line.u.request.method_value );
347 346
 	
348 347
 	pkg_free(buf);
349
-	pkg_free(to);
350 348
 	/* received_buf & line_buf will be freed in receive_msg by free_lump_list*/
351 349
 	return 0;
352 350
 
353
-error1:
354
-	pkg_free(to);
355 351
 error:
356 352
 	if (buf) pkg_free(buf);
357 353
 	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 272
 			  	script */
271 273
 				DBG("ERROR: generation of a stateful reply "
272 274
 					"on error succeeded\n");
273
-				ret=0;
275
+				/*ret=0; -- we don't want to stop the script */
274 276
 			}  else {
275 277
 				DBG("ERROR: generation of a stateful reply "
276 278
 					"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 61
 #include "../../dset.h"
61 62
 #include "../../action.h"
62 63
 #include "../../data_lump.h"
64
+#include "../../onsend.h"
63 65
 #include "t_funcs.h"
64 66
 #include "t_hooks.h"
65 67
 #include "t_msgbuilder.h"
... ...
@@ -551,6 +553,13 @@ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg ,
551 553
 	success_branch=0;
552 554
 	for (i=first_branch; i<t->nr_of_outgoings; i++) {
553 555
 		if (added_branches & (1<<i)) {
556
+			if (run_onsend(p_msg,	t->uac[i].request.dst.send_sock,
557
+									t->uac[i].request.dst.proto,
558
+									&t->uac[i].request.dst.to,
559
+									t->uac[i].request.buffer,
560
+									t->uac[i].request.buffer_len)==0)
561
+				continue; /* if onsend drop, try next branch */
562
+			
554 563
 			if (SEND_BUFFER( &t->uac[i].request)==-1) {
555 564
 				LOG(L_ERR, "ERROR: t_forward_nonack: sending request failed\n");
556 565
 				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 75
 struct action* onreply_rlist[ONREPLY_RT_NO];
75 76
 struct action* failure_rlist[FAILURE_RT_NO];
76 77
 struct action* branch_rlist[BRANCH_RT_NO];
78
+struct action* onsend_rlist[ONSEND_RT_NO];
77 79
 
78 80
 static int fix_actions(struct action* a); /*fwd declaration*/
79 81
 
... ...
@@ -643,6 +645,8 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
643 645
 {
644 646
 	struct sip_uri uri;
645 647
 	int ret;
648
+	struct onsend_info* snd_inf;
649
+	struct ip_addr ip;
646 650
 	ret=E_BUG;
647 651
 	
648 652
 	if (e->type!=ELEM_T){
... ...
@@ -727,6 +731,25 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
727 731
 	case DSTIP_O:
728 732
 		ret=comp_ip(e->op, &msg->rcv.dst_ip, e->r_type, &e->r);
729 733
 		break;
734
+	
735
+	case SNDIP_O:
736
+		snd_inf=get_onsend_info();
737
+		if (snd_inf && snd_inf->send_sock){
738
+			ret=comp_ip(e->op, &snd_inf->send_sock->address, e->r_type, &e->r);
739
+		}else{
740
+			BUG("eval_elem: snd_ip unknown (not in a onsend_route?)\n");
741
+		}
742
+		break;
743
+	
744
+	case TOIP_O:
745
+		snd_inf=get_onsend_info();
746
+		if (snd_inf && snd_inf->to){
747
+			su2ip_addr(&ip, snd_inf->to);
748
+			ret=comp_ip(e->op, &ip, e->r_type, &e->r);
749
+		}else{
750
+			BUG("eval_elem: to_ip unknown (not in a onsend_route?)\n");
751
+		}
752
+		break;
730 753
 
731 754
 	case NUMBER_O:
732 755
 		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 771
 			     e->r_type, &e->r);
749 772
 		break;
750 773
 		
774
+	case SNDPORT_O:
775
+		snd_inf=get_onsend_info();
776
+		if (snd_inf && snd_inf->send_sock){
777
+			ret=comp_num(e->op, (int)snd_inf->send_sock->port_no, 
778
+				     e->r_type, &e->r);
779
+		}else{
780
+			BUG("eval_elem: snd_port unknown (not in a onsend_route?)\n");
781
+		}
782
+		break;
783
+		
784
+	case TOPORT_O:
785
+		snd_inf=get_onsend_info();
786
+		if (snd_inf && snd_inf->to){
787
+			ret=comp_num(e->op, (int)su_getport(snd_inf->to), 
788
+				     e->r_type, &e->r);
789
+		}else{
790
+			BUG("eval_elem: to_port unknown (not in a onsend_route?)\n");
791
+		}
792
+		break;
793
+		
751 794
 	case PROTO_O:
752 795
 		ret=comp_num(e->op, msg->rcv.proto, 
753 796
 			     e->r_type, &e->r);
754 797
 		break;
755 798
 		
799
+	case SNDPROTO_O:
800
+		snd_inf=get_onsend_info();
801
+		if (snd_inf && snd_inf->send_sock){
802
+			ret=comp_num(e->op, snd_inf->send_sock->proto, 
803
+				     e->r_type, &e->r);
804
+		}else{
805
+			BUG("eval_elem: snd_proto unknown (not in a onsend_route?)\n");
806
+		}
807
+		break;
808
+		
756 809
 	case AF_O:
757 810
 		ret=comp_num(e->op, (int)msg->rcv.src_ip.af, 
758 811
 			     e->r_type, &e->r);
759 812
 		break;
813
+		
814
+	case SNDAF_O:
815
+		snd_inf=get_onsend_info();
816
+		if (snd_inf && snd_inf->send_sock){
817
+			ret=comp_num(e->op, snd_inf->send_sock->address.af,
818
+							e->r_type, &e->r);
819
+		}else{
820
+			BUG("eval_elem: snd_af unknown (not in a onsend_route?)\n");
821
+		}
822
+		break;
760 823
 
761 824
 	case MSGLEN_O:
762
-		ret=comp_num(e->op, (int)msg->len, 
763
-				e->r_type, &e->r);
825
+		if ((snd_inf=get_onsend_info())!=0){
826
+			ret=comp_num(e->op, (int)snd_inf->len, 
827
+					e->r_type, &e->r);
828
+		}else{
829
+			ret=comp_num(e->op, (int)msg->len, 
830
+					e->r_type, &e->r);
831
+		}
764 832
 		break;
765 833
 
766
-	case AVP_ST:
834
+	case AVP_O:
767 835
 		ret = comp_avp(e->op, e->l.attr, e->r_type, &e->r);
768 836
 		break;
769 837
 		
... ...
@@ -891,6 +959,13 @@ int fix_rls()
891 959
 			}
892 960
 		}
893 961
 	}
962
+	for(i=0;i<ONSEND_RT_NO;i++){
963
+		if(onsend_rlist[i]){
964
+			if ((ret=fix_actions(onsend_rlist[i]))!=0){
965
+				return ret;
966
+			}
967
+		}
968
+	}
894 969
 	return 0;
895 970
 }
896 971
 
... ...
@@ -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 61
 enum { EQUAL_OP=10, MATCH_OP, GT_OP, LT_OP, GTE_OP, LTE_OP, DIFF_OP, NO_OP };
61 62
 enum { METHOD_O=1, URI_O, FROM_URI_O, TO_URI_O, SRCIP_O, SRCPORT_O,
62 63
 	   DSTIP_O, DSTPORT_O, PROTO_O, AF_O, MSGLEN_O, DEFAULT_O, ACTION_O,
63
-	   NUMBER_O, AVP_O};
64
+	   NUMBER_O, AVP_O, SNDIP_O, SNDPORT_O, TOIP_O, TOPORT_O, SNDPROTO_O, 
65
+	   SNDAF_O};
64 66
 
65 67
 enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T,
66 68
 		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 */