68fbebdcff7f0d835ee63e6767ba50dc79382157
[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 "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
27 #ifdef DEBUG_DMALLOC
28 #include <dmalloc.h>
29 #endif
30
31
32 /* ret= 0! if action -> end of list(e.g DROP), 
33       > 0 to continue processing next actions
34    and <0 on error */
35 int do_action(struct action* a, struct sip_msg* msg)
36 {
37         int ret;
38         int v;
39         struct sockaddr_in* to;
40         struct proxy_l* p;
41         char* tmp;
42         char *new_uri, *end, *crt;
43         int len;
44         int user;
45         int err;
46         struct sip_uri uri;
47         unsigned short port;
48
49         ret=E_BUG;
50         switch (a->type){
51                 case DROP_T:
52                                 ret=0;
53                         break;
54                 case FORWARD_T:
55                         if (a->p1_type==URIHOST_ST){
56                                 /*parse uri*/
57                                 if (msg->new_uri.s){
58                                                 tmp=msg->new_uri.s;
59                                                 len=msg->new_uri.len;
60                                 }else{
61                                                 tmp=msg->first_line.u.request.uri.s;
62                                                 len=msg->first_line.u.request.uri.len;
63                                 }
64                                 if (parse_uri(tmp, len, &uri)<0){
65                                         LOG(L_ERR, "ERROR: do_action: forward: bad_uri <%s>,"
66                                                                 " dropping packet\n",tmp);
67                                         ret=E_UNSPEC;
68                                         break;
69                                 }
70                                 switch (a->p2_type){
71                                         case URIPORT_ST:
72                                                                         if (uri.port.s){
73                                                                          /*port=strtol(uri.port.s,&end,10);*/
74                                                                                 port=str2s(uri.port.s, uri.port.len,
75                                                                                                         &err);
76                                                                                 /*if ((end)&&(*end)){*/
77                                                                                 if (err){
78                                                                                         LOG(L_ERR, "ERROR: do_action: "
79                                                                                                         "forward: bad port in "
80                                                                                                         "uri: <%s>\n", uri.port);
81                                                                                         ret=E_UNSPEC;
82                                                                                         goto error_fwd_uri;
83                                                                                 }
84                                                                         }else port=SIP_PORT;
85                                                                         break;
86                                         case NUMBER_ST:
87                                                                         port=a->p2.number;
88                                                                         break;
89                                         default:
90                                                         LOG(L_CRIT, "BUG: do_action bad forward 2nd"
91                                                                                 " param type (%d)\n", a->p2_type);
92                                                         ret=E_UNSPEC;
93                                                         goto error_fwd_uri;
94                                 }
95                                 /* create a temporary proxy*/
96                                 p=mk_proxy(uri.host.s, port);
97                                 if (p==0){
98                                         LOG(L_ERR, "ERROR:  bad host name in uri,"
99                                                         " dropping packet\n");
100                                         ret=E_BAD_ADDRESS;
101                                         goto error_fwd_uri;
102                                 }
103                                 ret=forward_request(msg, p);
104                                 free_uri(&uri);
105                                 free_proxy(p); /* frees only p content, not p itself */
106                                 free(p);
107                                 if (ret>=0) ret=1;
108                         }else if ((a->p1_type==PROXY_ST) && (a->p2_type==NUMBER_ST)){
109                                 ret=forward_request(msg,(struct proxy_l*)a->p1.data);
110                                 if (ret>=0) ret=1;
111                         }else{
112                                 LOG(L_CRIT, "BUG: do_action: bad forward() types %d, %d\n",
113                                                 a->p1_type, a->p2_type);
114                                 ret=E_BUG;
115                         }
116                         break;
117                 case SEND_T:
118                         to=(struct sockaddr_in*) malloc(sizeof(struct sockaddr_in));
119                         if (to==0){
120                                 LOG(L_ERR, "ERROR: do_action: "
121                                                         "memory allocation failure\n");
122                                 ret=E_OUT_OF_MEM;
123                                 break;
124                         }
125                         if ((a->p1_type!= PROXY_ST)|(a->p2_type!=NUMBER_ST)){
126                                 LOG(L_CRIT, "BUG: do_action: bad send() types %d, %d\n",
127                                                 a->p1_type, a->p2_type);
128                                 ret=E_BUG;
129                                 break;
130                         }
131                         
132                         p=(struct proxy_l*)a->p1.data;
133                         
134                         to->sin_family = AF_INET;
135                         to->sin_port=(p->port)?htons(p->port):htons(SIP_PORT);
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                         to->sin_addr.s_addr=*((long*)p->host.h_addr_list[p->addr_idx]);
144                         p->tx++;
145                         p->tx_bytes+=msg->len;
146                         ret=udp_send(msg->orig, msg->len, (struct sockaddr*)to,
147                                         sizeof(struct sockaddr_in));
148                         free(to);
149                         if (ret<0){
150                                 p->errors++;
151                                 p->ok=0;
152                         }else ret=1;
153                         
154                         break;
155                 case LOG_T:
156                         if ((a->p1_type!=NUMBER_ST)|(a->p2_type!=STRING_ST)){
157                                 LOG(L_CRIT, "BUG: do_action: bad log() types %d, %d\n",
158                                                 a->p1_type, a->p2_type);
159                                 ret=E_BUG;
160                                 break;
161                         }
162                         LOG(a->p1.number, a->p2.string);
163                         ret=1;
164                         break;
165                 case ERROR_T:
166                         if ((a->p1_type!=STRING_ST)|(a->p2_type!=STRING_ST)){
167                                 LOG(L_CRIT, "BUG: do_action: bad error() types %d, %d\n",
168                                                 a->p1_type, a->p2_type);
169                                 ret=E_BUG;
170                                 break;
171                         }
172                         LOG(L_NOTICE, "WARNING: do_action: error(\"%s\", \"%s\") "
173                                         "not implemented yet\n", a->p1.string, a->p2.string);
174                         ret=1;
175                         break;
176                 case ROUTE_T:
177                         if (a->p1_type!=NUMBER_ST){
178                                 LOG(L_CRIT, "BUG: do_action: bad route() type %d\n",
179                                                 a->p1_type);
180                                 ret=E_BUG;
181                                 break;
182                         }
183                         if ((a->p1.number>RT_NO)||(a->p1.number<0)){
184                                 LOG(L_ERR, "ERROR: invalid routing table number in"
185                                                         "route(%d)\n", a->p1.number);
186                                 ret=E_CFG;
187                                 break;
188                         }
189                         ret=((ret=run_actions(rlist[a->p1.number], msg))<0)?ret:1;
190                         break;
191                 case EXEC_T:
192                         if (a->p1_type!=STRING_ST){
193                                 LOG(L_CRIT, "BUG: do_action: bad exec() type %d\n",
194                                                 a->p1_type);
195                                 ret=E_BUG;
196                                 break;
197                         }
198                         LOG(L_NOTICE, "WARNING: exec(\"%s\") not fully implemented,"
199                                                 " using dumb version...\n", a->p1.string);
200                         ret=system(a->p1.string);
201                         if (ret!=0){
202                                 LOG(L_NOTICE, "WARNING: exec() returned %d\n", ret);
203                         }
204                         ret=1;
205                         break;
206                 case SET_HOST_T:
207                 case SET_HOSTPORT_T:
208                 case SET_USER_T:
209                 case SET_USERPASS_T:
210                 case SET_PORT_T:
211                 case SET_URI_T:
212                                 user=0;
213                                 if (a->p1_type!=STRING_ST){
214                                         LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
215                                                         a->p1_type);
216                                         ret=E_BUG;
217                                         break;
218                                 }
219                                 if (a->type==SET_URI_T){
220                                         if (msg->new_uri.s) {
221                                                         pkg_free(msg->new_uri.s);
222                                                         msg->new_uri.len=0;
223                                         }
224                                         len=strlen(a->p1.string);
225                                         msg->new_uri.s=pkg_malloc(len+1);
226                                         if (msg->new_uri.s==0){
227                                                 LOG(L_ERR, "ERROR: do_action: memory allocation"
228                                                                 " failure\n");
229                                                 ret=E_OUT_OF_MEM;
230                                                 break;
231                                         }
232                                         memcpy(msg->new_uri.s, a->p1.string, len);
233                                         msg->new_uri.s[len]=0;
234                                         msg->new_uri.len=len;
235                                         
236                                         ret=1;
237                                         break;
238                                 }
239                                 if (msg->new_uri.s) {
240                                         tmp=msg->new_uri.s;
241                                         len=msg->new_uri.len;
242                                 }else{
243                                         tmp=msg->first_line.u.request.uri.s;
244                                         len=msg->first_line.u.request.uri.len;
245                                 }
246                                 if (parse_uri(tmp, len, &uri)<0){
247                                         LOG(L_ERR, "ERROR: do_action: bad uri <%s>, dropping"
248                                                                 " packet\n", tmp);
249                                         ret=E_UNSPEC;
250                                         break;
251                                 }
252                                 
253                                 new_uri=pkg_malloc(MAX_URI_SIZE);
254                                 if (new_uri==0){
255                                         LOG(L_ERR, "ERROR: do_action: memory allocation "
256                                                                 " failure\n");
257                                         ret=E_OUT_OF_MEM;
258                                         free_uri(&uri);
259                                         break;
260                                 }
261                                 end=new_uri+MAX_URI_SIZE;
262                                 crt=new_uri;
263                                 /* begin copying */
264                                 len=strlen("sip:"); if(crt+len>end) goto error_uri;
265                                 memcpy(crt,"sip:",len);crt+=len;
266                                 /* user */
267                                 if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T))
268                                         tmp=a->p1.string;
269                                 else 
270                                         tmp=uri.user.s;
271                                 if (tmp){
272                                         len=strlen(tmp); if(crt+len>end) goto error_uri;
273                                         memcpy(crt,tmp,len);crt+=len;
274                                         user=1; /* we have an user field so mark it */
275                                 }
276                                 if (a->type==SET_USERPASS_T) tmp=0;
277                                 else tmp=uri.passwd.s;
278                                 /* passwd */
279                                 if (tmp){
280                                         len=strlen(":"); if(crt+len>end) goto error_uri;
281                                         memcpy(crt,":",len);crt+=len;
282                                         len=strlen(tmp); if(crt+len>end) goto error_uri;
283                                         memcpy(crt,tmp,len);crt+=len;
284                                 }
285                                 /* host */
286                                 if (user || tmp){ /* add @ */
287                                         len=strlen("@"); if(crt+len>end) goto error_uri;
288                                         memcpy(crt,"@",len);crt+=len;
289                                 }
290                                 if ((a->type==SET_HOST_T) ||(a->type==SET_HOSTPORT_T))
291                                         tmp=a->p1.string;
292                                 else
293                                         tmp=uri.host.s;
294                                 if (tmp){
295                                         len=strlen(tmp); if(crt+len>end) goto error_uri;
296                                         memcpy(crt,tmp,len);crt+=len;
297                                 }
298                                 /* port */
299                                 if (a->type==SET_HOSTPORT_T) tmp=0;
300                                 else if (a->type==SET_PORT_T) tmp=a->p1.string;
301                                 else tmp=uri.port.s;
302                                 if (tmp){
303                                         len=strlen(":"); if(crt+len>end) goto error_uri;
304                                         memcpy(crt,":",len);crt+=len;
305                                         len=strlen(tmp); if(crt+len>end) goto error_uri;
306                                         memcpy(crt,tmp,len);crt+=len;
307                                 }
308                                 /* params */
309                                 tmp=uri.params.s;
310                                 if (tmp){
311                                         len=strlen(";"); if(crt+len>end) goto error_uri;
312                                         memcpy(crt,";",len);crt+=len;
313                                         len=strlen(tmp); if(crt+len>end) goto error_uri;
314                                         memcpy(crt,tmp,len);crt+=len;
315                                 }
316                                 /* headers */
317                                 tmp=uri.headers.s;
318                                 if (tmp){
319                                         len=strlen("?"); if(crt+len>end) goto error_uri;
320                                         memcpy(crt,"?",len);crt+=len;
321                                         len=strlen(tmp); if(crt+len>end) goto error_uri;
322                                         memcpy(crt,tmp,len);crt+=len;
323                                 }
324                                 *crt=0; /* null terminate the thing */
325                                 /* copy it to the msg */
326                                 if (msg->new_uri.s) pkg_free(msg->new_uri.s);
327                                 msg->new_uri.s=new_uri;
328                                 msg->new_uri.len=crt-new_uri;
329                                 free_uri(&uri);
330                                 ret=1;
331                                 break;
332                 case IF_T:
333                                 /* if null expr => ignore if? */
334                                 if ((a->p1_type==EXPR_ST)&&a->p1.data){
335                                         v=eval_expr((struct expr*)a->p1.data, msg);
336                                         if (v<0){
337                                                 LOG(L_WARN,"WARNING: do_action:"
338                                                                         "error in expression\n");
339                                         }
340                                         ret=1; /* default is continue */
341                                         if (v==1){
342                                                 if ((a->p2_type==ACTIONS_ST)&&a->p2.data){
343                                                         ret=run_actions((struct action*)a->p2.data, msg);
344                                                 }
345                                         }else if ((a->p3_type==ACTIONS_ST)&&a->p3.data){
346                                                         ret=run_actions((struct action*)a->p3.data, msg);
347                                         }
348                                 }
349                         break;
350                 case MODULE_T:
351                         if ( ((a->p1_type==CMDF_ST)&&a->p1.data)/*&&
352                                         ((a->p2_type==STRING_ST)&&a->p2.data)*/ ){
353                                 ret=((cmd_function)(a->p1.data))(msg, (char*)a->p2.data,
354                                                                                                           (char*)a->p3.data);
355                         }else{
356                                 LOG(L_CRIT,"BUG: do_action: bad module call\n");
357                         }
358                         break;
359                 default:
360                         LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);
361         }
362 skip:
363         return ret;
364         
365 error_uri:
366         LOG(L_ERR, "ERROR: do_action: set*: uri too long\n");
367         free_uri(&uri);
368         if (new_uri) free(new_uri);
369         return E_UNSPEC;
370 error_fwd_uri:
371         free_uri(&uri);
372         return ret;
373 }
374
375
376
377 /* returns: 0, or 1 on success, <0 on error */
378 /* (0 if drop or break encountered, 1 if not ) */
379 int run_actions(struct action* a, struct sip_msg* msg)
380 {
381         struct action* t;
382         int ret;
383         static int rec_lev=0;
384
385         rec_lev++;
386         if (rec_lev>ROUTE_MAX_REC_LEV){
387                 LOG(L_ERR, "WARNING: too many recursive routing table lookups (%d)"
388                                         " giving up!\n", rec_lev);
389                 ret=E_UNSPEC;
390                 goto error;
391         }
392                 
393         if (a==0){
394                 LOG(L_ERR, "WARNING: run_actions: null action list\n");
395                 ret=0;
396         }
397
398         for (t=a; t!=0; t=t->next){
399                 ret=do_action(t, msg);
400                 if(ret==0) break;
401                 /* ignore errors */
402                 /*else if (ret<0){ ret=-1; goto error; }*/
403         }
404         
405         rec_lev--;
406         return ret;
407         
408
409 error:
410         rec_lev--;
411         return ret;
412 }
413
414
415