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