7ef97069f2e4ede117d7d9c4162409c132688e98
[sip-router] / action.c
1 /*
2  * $Id$
3  */
4
5
6
7 #include "action.h"
8 #include "config.h"
9 #include "error.h"
10 #include "dprint.h"
11 #include "proxy.h"
12 #include "forward.h"
13 #include "udp_server.h"
14 #include "route.h"
15 #include "parser/msg_parser.h"
16 #include "ut.h"
17 #include "sr_module.h"
18 #include "mem/mem.h"
19
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <netdb.h>
23 #include <stdlib.h>
24 #include <netinet/in.h>
25 #include <arpa/inet.h>
26 #include <string.h>
27
28 #ifdef DEBUG_DMALLOC
29 #include <dmalloc.h>
30 #endif
31
32
33 /* ret= 0! if action -> end of list(e.g DROP), 
34       > 0 to continue processing next actions
35    and <0 on error */
36 int do_action(struct action* a, struct sip_msg* msg)
37 {
38         int ret;
39         int v;
40         union sockaddr_union* to;
41         struct socket_info* send_sock;
42         struct proxy_l* p;
43         char* tmp;
44         char *new_uri, *end, *crt;
45         int len;
46         int user;
47         int err;
48         struct sip_uri uri;
49         unsigned short port;
50
51         ret=E_BUG;
52         switch (a->type){
53                 case DROP_T:
54                                 ret=0;
55                         break;
56                 case FORWARD_T:
57                         if (a->p1_type==URIHOST_ST){
58                                 /*parse uri*/
59                                 if (msg->new_uri.s){
60                                                 tmp=msg->new_uri.s;
61                                                 len=msg->new_uri.len;
62                                 }else{
63                                                 tmp=msg->first_line.u.request.uri.s;
64                                                 len=msg->first_line.u.request.uri.len;
65                                 }
66                                 if (parse_uri(tmp, len, &uri)<0){
67                                         LOG(L_ERR, "ERROR: do_action: forward: bad_uri <%s>,"
68                                                                 " dropping packet\n",tmp);
69                                         ret=E_UNSPEC;
70                                         break;
71                                 }
72                                 switch (a->p2_type){
73                                         case URIPORT_ST:
74                                                                         if (uri.port.s){
75                                                                          /*port=strtol(uri.port.s,&end,10);*/
76                                                                                 port=str2s((unsigned char*)uri.port.s, 
77                                                                                                         uri.port.len, &err);
78                                                                                 /*if ((end)&&(*end)){*/
79                                                                                 if (err){
80                                                                                         LOG(L_ERR, "ERROR: do_action: "
81                                                                                                 "forward: bad port in "
82                                                                                                 "uri: <%s>\n", uri.port.s);
83                                                                                         ret=E_UNSPEC;
84                                                                                         goto error_fwd_uri;
85                                                                                 }
86                                                                         }else port=SIP_PORT;
87                                                                         break;
88                                         case NUMBER_ST:
89                                                                         port=a->p2.number;
90                                                                         break;
91                                         default:
92                                                         LOG(L_CRIT, "BUG: do_action bad forward 2nd"
93                                                                                 " param type (%d)\n", a->p2_type);
94                                                         ret=E_UNSPEC;
95                                                         goto error_fwd_uri;
96                                 }
97                                 /* create a temporary proxy*/
98                                 p=mk_proxy(uri.host.s, port);
99                                 if (p==0){
100                                         LOG(L_ERR, "ERROR:  bad host name in uri,"
101                                                         " dropping packet\n");
102                                         ret=E_BAD_ADDRESS;
103                                         goto error_fwd_uri;
104                                 }
105                                 ret=forward_request(msg, p);
106                                 free_uri(&uri);
107                                 free_proxy(p); /* frees only p content, not p itself */
108                                 free(p);
109                                 if (ret>=0) ret=1;
110                         }else if ((a->p1_type==PROXY_ST) && (a->p2_type==NUMBER_ST)){
111                                 ret=forward_request(msg,(struct proxy_l*)a->p1.data);
112                                 if (ret>=0) ret=1;
113                         }else{
114                                 LOG(L_CRIT, "BUG: do_action: bad forward() types %d, %d\n",
115                                                 a->p1_type, a->p2_type);
116                                 ret=E_BUG;
117                         }
118                         break;
119                 case SEND_T:
120                         if ((a->p1_type!= PROXY_ST)|(a->p2_type!=NUMBER_ST)){
121                                 LOG(L_CRIT, "BUG: do_action: bad send() types %d, %d\n",
122                                                 a->p1_type, a->p2_type);
123                                 ret=E_BUG;
124                                 break;
125                         }
126                         to=(union sockaddr_union*) malloc(sizeof(union sockaddr_union));
127                         if (to==0){
128                                 LOG(L_ERR, "ERROR: do_action: "
129                                                         "memory allocation failure\n");
130                                 ret=E_OUT_OF_MEM;
131                                 break;
132                         }
133                         
134                         p=(struct proxy_l*)a->p1.data;
135                         
136                         if (p->ok==0){
137                                 if (p->host.h_addr_list[p->addr_idx+1])
138                                         p->addr_idx++;
139                                 else 
140                                         p->addr_idx=0;
141                                 p->ok=1;
142                         }
143                         ret=hostent2su( to, &p->host, p->addr_idx,
144                                                 (p->port)?htons(p->port):htons(SIP_PORT) );
145                         if (ret==0){
146                                 p->tx++;
147                                 p->tx_bytes+=msg->len;
148                                 send_sock=get_send_socket(to);
149                                 if (send_sock!=0){
150                                         ret=udp_send(send_sock, msg->orig, msg->len, to,
151                                                                         sizeof(union sockaddr_union));
152                                 }else{
153                                         ret=-1;
154                                 }
155                         }
156                         free(to);
157                         if (ret<0){
158                                 p->errors++;
159                                 p->ok=0;
160                         }else ret=1;
161                         
162                         break;
163                 case LOG_T:
164                         if ((a->p1_type!=NUMBER_ST)|(a->p2_type!=STRING_ST)){
165                                 LOG(L_CRIT, "BUG: do_action: bad log() types %d, %d\n",
166                                                 a->p1_type, a->p2_type);
167                                 ret=E_BUG;
168                                 break;
169                         }
170                         LOG(a->p1.number, a->p2.string);
171                         ret=1;
172                         break;
173
174                 /* jku begin: is_length_greater_than */
175                 case LEN_GT_T:
176                         if (a->p1_type!=NUMBER_ST) {
177                                 LOG(L_CRIT, "BUG: do_action: bad len_gt type %d\n",
178                                         a->p1_type );
179                                 ret=E_BUG;
180                                 break;
181                         }
182                         /* DBG("XXX: message length %d, max %d\n", 
183                                 msg->len, a->p1.number ); */
184                         ret = msg->len >= a->p1.number ? 1 : -1;
185                         break;
186                 /* jku end: is_length_greater_than */
187                         
188                 /* jku - begin : flag processing */
189
190                 case SETFLAG_T:
191                         if (a->p1_type!=NUMBER_ST) {
192                                 LOG(L_CRIT, "BUG: do_action: bad setflag() type %d\n",
193                                         a->p1_type );
194                                 ret=E_BUG;
195                                 break;
196                         }
197                         if (!flag_in_range( a->p1.number )) {
198                                 ret=E_CFG;
199                                 break;
200                         }
201                         setflag( msg, a->p1.number );
202                         ret=1;
203                         break;
204
205                 case RESETFLAG_T:
206                         if (a->p1_type!=NUMBER_ST) {
207                                 LOG(L_CRIT, "BUG: do_action: bad resetflag() type %d\n",
208                                         a->p1_type );
209                                 ret=E_BUG;
210                                 break;
211                         }
212                         if (!flag_in_range( a->p1.number )) {
213                                 ret=E_CFG;
214                                 break;
215                         }
216                         resetflag( msg, a->p1.number );
217                         ret=1;
218                         break;
219                         
220                 case ISFLAGSET_T:
221                         if (a->p1_type!=NUMBER_ST) {
222                                 LOG(L_CRIT, "BUG: do_action: bad isflagset() type %d\n",
223                                         a->p1_type );
224                                 ret=E_BUG;
225                                 break;
226                         }
227                         if (!flag_in_range( a->p1.number )) {
228                                 ret=E_CFG;
229                                 break;
230                         }
231                         ret=isflagset( msg, a->p1.number );
232                         break;
233                 /* jku - end : flag processing */
234
235                 case ERROR_T:
236                         if ((a->p1_type!=STRING_ST)|(a->p2_type!=STRING_ST)){
237                                 LOG(L_CRIT, "BUG: do_action: bad error() types %d, %d\n",
238                                                 a->p1_type, a->p2_type);
239                                 ret=E_BUG;
240                                 break;
241                         }
242                         LOG(L_NOTICE, "WARNING: do_action: error(\"%s\", \"%s\") "
243                                         "not implemented yet\n", a->p1.string, a->p2.string);
244                         ret=1;
245                         break;
246                 case ROUTE_T:
247                         if (a->p1_type!=NUMBER_ST){
248                                 LOG(L_CRIT, "BUG: do_action: bad route() type %d\n",
249                                                 a->p1_type);
250                                 ret=E_BUG;
251                                 break;
252                         }
253                         if ((a->p1.number>RT_NO)||(a->p1.number<0)){
254                                 LOG(L_ERR, "ERROR: invalid routing table number in"
255                                                         "route(%d)\n", a->p1.number);
256                                 ret=E_CFG;
257                                 break;
258                         }
259                         ret=((ret=run_actions(rlist[a->p1.number], msg))<0)?ret:1;
260                         break;
261                 case EXEC_T:
262                         if (a->p1_type!=STRING_ST){
263                                 LOG(L_CRIT, "BUG: do_action: bad exec() type %d\n",
264                                                 a->p1_type);
265                                 ret=E_BUG;
266                                 break;
267                         }
268                         LOG(L_NOTICE, "WARNING: exec(\"%s\") not fully implemented,"
269                                                 " using dumb version...\n", a->p1.string);
270                         ret=system(a->p1.string);
271                         if (ret!=0){
272                                 LOG(L_NOTICE, "WARNING: exec() returned %d\n", ret);
273                         }
274                         ret=1;
275                         break;
276                 case SET_HOST_T:
277                 case SET_HOSTPORT_T:
278                 case SET_USER_T:
279                 case SET_USERPASS_T:
280                 case SET_PORT_T:
281                 case SET_URI_T:
282                 case PREFIX_T:
283                 case STRIP_T:
284                                 user=0;
285                                 if (a->type==STRIP_T) {
286                                         if (a->p1_type!=NUMBER_ST) {
287                                                 LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
288                                                         a->p1_type);
289                                                 break;
290                                         }
291                                 } else if (a->p1_type!=STRING_ST){
292                                         LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
293                                                         a->p1_type);
294                                         ret=E_BUG;
295                                         break;
296                                 }
297                                 if (a->type==SET_URI_T){
298                                         if (msg->new_uri.s) {
299                                                         pkg_free(msg->new_uri.s);
300                                                         msg->new_uri.len=0;
301                                         }
302                                         len=strlen(a->p1.string);
303                                         msg->new_uri.s=pkg_malloc(len+1);
304                                         if (msg->new_uri.s==0){
305                                                 LOG(L_ERR, "ERROR: do_action: memory allocation"
306                                                                 " failure\n");
307                                                 ret=E_OUT_OF_MEM;
308                                                 break;
309                                         }
310                                         memcpy(msg->new_uri.s, a->p1.string, len);
311                                         msg->new_uri.s[len]=0;
312                                         msg->new_uri.len=len;
313                                         
314                                         ret=1;
315                                         break;
316                                 }
317                                 if (msg->new_uri.s) {
318                                         tmp=msg->new_uri.s;
319                                         len=msg->new_uri.len;
320                                 }else{
321                                         tmp=msg->first_line.u.request.uri.s;
322                                         len=msg->first_line.u.request.uri.len;
323                                 }
324                                 if (parse_uri(tmp, len, &uri)<0){
325                                         LOG(L_ERR, "ERROR: do_action: bad uri <%s>, dropping"
326                                                                 " packet\n", tmp);
327                                         ret=E_UNSPEC;
328                                         break;
329                                 }
330                                 
331                                 new_uri=pkg_malloc(MAX_URI_SIZE);
332                                 if (new_uri==0){
333                                         LOG(L_ERR, "ERROR: do_action: memory allocation "
334                                                                 " failure\n");
335                                         ret=E_OUT_OF_MEM;
336                                         free_uri(&uri);
337                                         break;
338                                 }
339                                 end=new_uri+MAX_URI_SIZE;
340                                 crt=new_uri;
341                                 /* begin copying */
342                                 len=strlen("sip:"); if(crt+len>end) goto error_uri;
343                                 memcpy(crt,"sip:",len);crt+=len;
344
345                                 /* user */
346
347                                 /* prefix (-jiri) */
348                                 if (a->type==PREFIX_T) {
349                                         tmp=a->p1.string;
350                                         len=strlen(tmp); if(crt+len>end) goto error_uri;
351                                         memcpy(crt,tmp,len);crt+=len;
352                                         /* whateever we had before, with prefix we have username now */
353                                         user=1;
354                                 }
355
356                                 if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) {
357                                         tmp=a->p1.string;
358                                         len=strlen(tmp);
359                                 } else if (a->type==STRIP_T) {
360                                         if (a->p1.number>uri.user.len) {
361                                                 LOG(L_WARN, "Error: too long strip asked; deleting username: "
362                                                         "%d of %s\n", a->p1.number, uri.user.s );
363                                                 len=0;
364                                         } else if (a->p1.number==uri.user.len) {
365                                                 len=0;
366                                         } else {
367                                                 tmp=uri.user.s + a->p1.number;
368                                                 len=uri.user.len - a->p1.number;
369                                         }
370                                 } else {
371                                         tmp=uri.user.s;
372                                         len=uri.user.len;
373                                 }
374
375                                 if (len){
376                                         if(crt+len>end) goto error_uri;
377                                         memcpy(crt,tmp,len);crt+=len;
378                                         user=1; /* we have an user field so mark it */
379                                 }
380
381                                 if (a->type==SET_USERPASS_T) tmp=0;
382                                 else tmp=uri.passwd.s;
383                                 /* passwd */
384                                 if (tmp){
385                                         len=strlen(":"); if(crt+len>end) goto error_uri;
386                                         memcpy(crt,":",len);crt+=len;
387                                         len=strlen(tmp); if(crt+len>end) goto error_uri;
388                                         memcpy(crt,tmp,len);crt+=len;
389                                 }
390                                 /* host */
391                                 if (user || tmp){ /* add @ */
392                                         len=strlen("@"); if(crt+len>end) goto error_uri;
393                                         memcpy(crt,"@",len);crt+=len;
394                                 }
395                                 if ((a->type==SET_HOST_T) ||(a->type==SET_HOSTPORT_T))
396                                         tmp=a->p1.string;
397                                 else
398                                         tmp=uri.host.s;
399                                 if (tmp){
400                                         len=strlen(tmp); if(crt+len>end) goto error_uri;
401                                         memcpy(crt,tmp,len);crt+=len;
402                                 }
403                                 /* port */
404                                 if (a->type==SET_HOSTPORT_T) tmp=0;
405                                 else if (a->type==SET_PORT_T) tmp=a->p1.string;
406                                 else tmp=uri.port.s;
407                                 if (tmp){
408                                         len=strlen(":"); if(crt+len>end) goto error_uri;
409                                         memcpy(crt,":",len);crt+=len;
410                                         len=strlen(tmp); if(crt+len>end) goto error_uri;
411                                         memcpy(crt,tmp,len);crt+=len;
412                                 }
413                                 /* params */
414                                 tmp=uri.params.s;
415                                 if (tmp){
416                                         len=strlen(";"); if(crt+len>end) goto error_uri;
417                                         memcpy(crt,";",len);crt+=len;
418                                         len=strlen(tmp); if(crt+len>end) goto error_uri;
419                                         memcpy(crt,tmp,len);crt+=len;
420                                 }
421                                 /* headers */
422                                 tmp=uri.headers.s;
423                                 if (tmp){
424                                         len=strlen("?"); if(crt+len>end) goto error_uri;
425                                         memcpy(crt,"?",len);crt+=len;
426                                         len=strlen(tmp); if(crt+len>end) goto error_uri;
427                                         memcpy(crt,tmp,len);crt+=len;
428                                 }
429                                 *crt=0; /* null terminate the thing */
430                                 /* copy it to the msg */
431                                 if (msg->new_uri.s) pkg_free(msg->new_uri.s);
432                                 msg->new_uri.s=new_uri;
433                                 msg->new_uri.len=crt-new_uri;
434                                 free_uri(&uri);
435                                 ret=1;
436                                 break;
437                 case IF_T:
438                                 /* if null expr => ignore if? */
439                                 if ((a->p1_type==EXPR_ST)&&a->p1.data){
440                                         v=eval_expr((struct expr*)a->p1.data, msg);
441                                         if (v<0){
442                                                 if (v==EXPR_DROP){ /* hack to quit on DROP*/
443                                                         ret=0;
444                                                         break;
445                                                 }else{
446                                                         LOG(L_WARN,"WARNING: do_action:"
447                                                                                 "error in expression\n");
448                                                 }
449                                         }
450                                         
451                                         ret=1;  /*default is continue */
452                                         if (v>0) {
453                                                 if ((a->p2_type==ACTIONS_ST)&&a->p2.data){
454                                                         ret=run_actions((struct action*)a->p2.data, msg);
455                                                 }
456                                         }else if ((a->p3_type==ACTIONS_ST)&&a->p3.data){
457                                                         ret=run_actions((struct action*)a->p3.data, msg);
458                                         }
459                                 }
460                         break;
461                 case MODULE_T:
462                         if ( ((a->p1_type==CMDF_ST)&&a->p1.data)/*&&
463                                         ((a->p2_type==STRING_ST)&&a->p2.data)*/ ){
464                                 ret=((cmd_function)(a->p1.data))(msg, (char*)a->p2.data,
465                                                                                                           (char*)a->p3.data);
466                         }else{
467                                 LOG(L_CRIT,"BUG: do_action: bad module call\n");
468                         }
469                         break;
470                 default:
471                         LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);
472         }
473 /*skip:*/
474         return ret;
475         
476 error_uri:
477         LOG(L_ERR, "ERROR: do_action: set*: uri too long\n");
478         free_uri(&uri);
479         if (new_uri) free(new_uri);
480         return E_UNSPEC;
481 error_fwd_uri:
482         free_uri(&uri);
483         return ret;
484 }
485
486
487
488 /* returns: 0, or 1 on success, <0 on error */
489 /* (0 if drop or break encountered, 1 if not ) */
490 int run_actions(struct action* a, struct sip_msg* msg)
491 {
492         struct action* t;
493         int ret=E_UNSPEC;
494         static int rec_lev=0;
495         struct sr_module *mod;
496
497         rec_lev++;
498         if (rec_lev>ROUTE_MAX_REC_LEV){
499                 LOG(L_ERR, "WARNING: too many recursive routing table lookups (%d)"
500                                         " giving up!\n", rec_lev);
501                 ret=E_UNSPEC;
502                 goto error;
503         }
504                 
505         if (a==0){
506                 LOG(L_ERR, "WARNING: run_actions: null action list (rec_level=%d)\n", 
507                         rec_lev);
508                 ret=0;
509         }
510
511         for (t=a; t!=0; t=t->next){
512                 ret=do_action(t, msg);
513                 if(ret==0) break;
514                 /* ignore errors */
515                 /*else if (ret<0){ ret=-1; goto error; }*/
516         }
517         
518         rec_lev--;
519         /* process module onbreak handlers if present */
520         if (rec_lev==0 && ret==0) 
521                 for (mod=modules;mod;mod=mod->next) 
522                         if (mod->exports && mod->exports->onbreak_f) {
523                                 mod->exports->onbreak_f( msg );
524                                 DBG("DEBUG: %s onbreak handler called\n", mod->exports->name);
525                         }
526         return ret;
527         
528
529 error:
530         rec_lev--;
531         return ret;
532 }
533
534
535