- still to do action,c
[sip-router] / route.c
1 /*
2  * $Id$
3  *
4  * SIP routing engine
5  *
6  */
7  
8 #include <sys/types.h>
9 #include <regex.h>
10 #include <netdb.h>
11 #include <string.h>
12 #include <sys/socket.h>
13 #include <netinet/in.h>
14 #include <arpa/inet.h>
15 #include <netdb.h>
16
17 #include "route.h"
18 #include "cfg_parser.h"
19 #include "dprint.h"
20
21 /* main routing list */
22 struct route_elem* rlist[RT_NO];
23
24
25
26  void free_re(struct route_elem* r)
27 {
28         int i;
29         if (r){
30                 /*
31                         regfree(&(r->method));
32                         regfree(&(r->uri));
33                         
34                         if (r->host.h_name)      free(r->host.h_name);
35                         if (r->host.h_aliases){
36                                 for (i=0; r->host.h_aliases[i]; i++)
37                                         free(r->host.h_aliases[i]);
38                                 free(r->host.h_aliases);
39                         }
40                         if (r->host.h_addr_list){
41                                 for (i=0; r->host.h_addr_list[i]; i++)
42                                         free(r->host.h_addr_list[i]);
43                                 free(r->host.h_addr_list);
44                         }
45                 */
46                         free(r);
47         }
48 }
49
50
51
52 struct route_elem* init_re()
53 {
54         struct route_elem* r;
55         r=(struct route_elem *) malloc(sizeof(struct route_elem));
56         if (r==0) return 0;
57         memset((void*)r, 0, sizeof (struct route_elem));
58         return r;
59 }
60
61
62
63 void push(struct route_elem* re, struct route_elem** head)
64 {
65         struct route_elem *t;
66         re->next=0;
67         if (*head==0){
68                 *head=re;
69                 return;
70         }
71         for (t=*head; t->next;t=t->next);
72         t->next=re;
73 }
74
75
76
77 void clear_rlist(struct route_elem** rl)
78 {
79         struct route_elem *t, *u;
80
81         if (*rl==0) return;
82         u=0;
83         for (t=*rl; t; u=t, t=t->next){
84                 if (u) free_re(u);
85         }
86         *rl=0;
87 }
88
89
90
91 /* traverses an expr tree and compiles the REs where necessary) 
92  * returns: 0 for ok, <0 if errors */
93 int fix_expr(struct expr* exp)
94 {
95         regex_t* re;
96         int ret;
97         
98         if (exp==0){
99                 LOG(L_CRIT, "BUG: fix_expr: null pointer\n");
100                 return E_BUG;
101         }
102         if (exp->type==EXP_T){
103                 switch(exp->op){
104                         case AND_OP:
105                         case OR_OP:
106                                                 if ((ret=fix_expr(exp->l.expr))!=0)
107                                                         return ret;
108                                                 ret=fix_expr(exp->r.expr);
109                                                 break;
110                         case NOT_OP:
111                                                 ret=fix_expr(exp->l.expr);
112                                                 break;
113                         default:
114                                                 LOG(L_CRIT, "BUG: fix_expr: unknown op %d\n",
115                                                                 exp->op);
116                 }
117         }else if (exp->type==ELEM_T){
118                         if (exp->op==MATCH_OP){
119                                 if (exp->subtype==STRING_ST){
120                                         re=(regex_t*)malloc(sizeof(regex_t));
121                                         if (re==0){
122                                                 LOG(L_CRIT, "ERROR: fix_expr: memory allocation"
123                                                                 " failure\n");
124                                                 return E_OUT_OF_MEM;
125                                         }
126                                         if (regcomp(re, (char*) exp->r.param,
127                                                                 REG_EXTENDED|REG_NOSUB|REG_ICASE) ){
128                                                 LOG(L_CRIT, "ERROR: fix_expr : bad re \"%s\"\n",
129                                                                         (char*) exp->r.param);
130                                                 free(re);
131                                                 return E_BAD_RE;
132                                         }
133                                         /* replace the string with the re */
134                                         free(exp->r.param);
135                                         exp->r.param=re;
136                                         exp->subtype=RE_ST;
137                                 }else if (exp->subtype!=RE_ST){
138                                         LOG(L_CRIT, "BUG: fix_expr : invalid type for match\n");
139                                         return E_BUG;
140                                 }
141                         }
142                         ret=0;
143         }
144         return ret;
145 }
146
147
148
149 /* adds the proxies in the proxy list & resolves the hostnames */
150 int fix_actions(struct action* a)
151 {
152         struct action *t;
153         struct proxy* p;
154         char *tmp;
155         
156         for(t=a; t!=0; t=t->next){
157                 switch(t->type){
158                         case FORWARD_T:
159                         case SEND_T:
160                                         switch(t->p1_type){
161                                                 case NUMBER_ST:
162                                                         tmp=strdup(inet_ntoa(
163                                                                                 *(struct in_addr*)&t->p1.number));
164                                                         if (tmp==0){
165                                                                 LOG(L_CRIT, "ERROR: fix_actions:"
166                                                                                 "memory allocation failure\n");
167                                                                 return E_OUT_OF_MEM;
168                                                         }
169                                                         t->p1_type=STRING_ST;
170                                                         t->p1.string=tmp;
171                                                         /* no break */
172                                                 case STRING_ST:
173                                                         p=add_proxy(t->p1.string, t->p2.number);
174                                                         if (p==0) return E_BAD_ADDRESS;
175                                                         t->p1.data=p;
176                                                         t->p1_type=PROXY_ST;
177                                                         break;
178                                                 default:
179                                                         LOG(L_CRIT, "BUG: fix_actions: invalid type"
180                                                                         " (should be string or number)\n");
181                                                         return E_BUG;
182                                         }
183                                         break;
184                 }
185         }
186         return 0;
187 }
188
189
190
191 /* eval_elem helping function, returns str op param */
192 int comp_str(char* str, void* param, int op, int subtype)
193 {
194         int ret;
195         
196         ret=-1;
197         if (op==EQUAL_OP){
198                 if (subtype!=STRING_ST){
199                         LOG(L_CRIT, "BUG: comp_str: bad type %d, "
200                                         "string expected\n", subtype);
201                         goto error;
202                 }
203                 ret=(strcasecmp(str, (char*)param)==0);
204         }else if (op==MATCH_OP){
205                 if (subtype!=RE_ST){
206                         LOG(L_CRIT, "BUG: comp_str: bad type %d, "
207                                         " RE expected\n", subtype);
208                         goto error;
209                 }
210                 ret=(regexec((regex_t*)param, str, 0, 0, 0)==0);
211         }else{
212                 LOG(L_CRIT, "BUG: comp_str: unknown op %d\n", op);
213                 goto error;
214         }
215         return ret;
216         
217 error:
218         return -1;
219 }
220
221
222
223 /* eval_elem helping function, returns a op param */
224 int comp_ip(unsigned a, void* param, int op, int subtype)
225 {
226         struct hostent* he;
227         char ** h;
228         int ret;
229
230         ret=-1;
231         switch(subtype){
232                 case NET_ST:
233                         ret=(a&((struct net*)param)->mask)==((struct net*)param)->ip;
234                         break;
235                 case STRING_ST:
236                         /* 1: compare with ip2str*/
237                         ret=comp_str(inet_ntoa(*(struct in_addr*)&a), param, op,
238                                                 subtype);
239                         if (ret==1) break;
240                         /* 2: (slow) rev dns the address
241                          * and compare with all the aliases */
242                         he=gethostbyaddr(&a, sizeof(a), AF_INET);
243                         if (he==0){
244                                 LOG(L_DBG, "comp_ip: could not rev_resolve %x\n", a);
245                                 ret=0;
246                         }else{
247                                 /*  compare with primayry host name */
248                                 ret=comp_str(he->h_name, param, op, subtype);
249                                 /* compare with all the aliases */
250                                 for(h=he->h_aliases; (ret!=1) && (*h); h++){
251                                         ret=comp_str(*h, param, op, subtype);
252                                 }
253                         }
254                         break;
255                 default:
256                         LOG(L_CRIT, "BUG: comp_ip: invalid type for "
257                                                 " src_ip or dst_ip (%d)\n", subtype);
258                         ret=-1;
259         }
260         return ret;
261         
262 error:
263         return -1;
264 }
265
266
267
268 /* returns: 0/1 (false/true) or -1 on error */
269 int eval_elem(struct expr* e, struct sip_msg* msg)
270 {
271
272         int ret;
273         
274         if (e->type!=ELEM_T){
275                 LOG(L_CRIT," BUG: eval_elem: invalid type\n");
276                 goto error;
277         }
278         switch(e->l.operand){
279                 case METHOD_O:
280                                 ret=comp_str(msg->first_line.u.request.method, e->r.param,
281                                                                 e->op, e->subtype);
282                                 break;
283                 case URI_O:
284                                 ret=comp_str(msg->first_line.u.request.uri, e->r.param,
285                                                                 e->op, e->subtype);
286                                 break;
287                 case SRCIP_O:
288                                 ret=comp_ip(msg->src_ip, e->r.param, e->op, e->subtype);
289                                 break;
290                 case DSTIP_O:
291                                 ret=comp_ip(msg->dst_ip, e->r.param, e->op, e->subtype);
292                                 break;
293                 case DEFAULT_O:
294                                 ret=1;
295                                 break;
296                 default:
297                                 LOG(L_CRIT, "BUG: eval_elem: invalid operand %d\n",
298                                                         e->l.operand);
299         }
300         return ret;
301 error:
302         return -1;
303 }
304
305
306
307 int eval_expr(struct expr* e, struct sip_msg* msg)
308 {
309         static int rec_lev=0;
310         int ret;
311         
312         rec_lev++;
313         if (rec_lev>MAX_REC_LEV){
314                 LOG(L_CRIT, "ERROR: eval_expr: too many expressions (%d)\n",
315                                 rec_lev);
316                 ret=-1;
317                 goto skip;
318         }
319         
320         if (e->type==ELEM_T){
321                 ret=eval_elem(e, msg);
322         }else if (e->type==EXP_T){
323                 switch(e->op){
324                         case AND_OP:
325                                 ret=eval_expr(e->l.expr, msg);
326                                 /* if error or false stop evaluating the rest */
327                                 if (ret!=1) break;
328                                 ret=eval_expr(e->r.expr, msg); /*ret1 is 1*/
329                                 break;
330                         case OR_OP:
331                                 ret=eval_expr(e->l.expr, msg);
332                                 /* if true or error stop evaluating the rest */
333                                 if (ret!=0) break;
334                                 ret=eval_expr(e->r.expr, msg); /* ret1 is 0 */
335                                 break;
336                         case NOT_OP:
337                                 ret=eval_expr(e->l.expr, msg);
338                                 if (ret<0) break;
339                                 ret= ! ret;
340                                 break;
341                         default:
342                                 LOG(L_CRIT, "BUG: eval_expr: unknown op %d\n", e->op);
343                                 ret=-1;
344                 }
345         }else{
346                 LOG(L_CRIT, "BUG: eval_expr: unknown type %d\n", e->type);
347                 ret=-1;
348         }
349
350 skip:
351         rec_lev--;
352         return ret;
353 }
354
355
356
357
358 int add_rule(struct expr* e, struct action* a, struct route_elem** head)
359 {
360         
361         struct route_elem* re;
362         struct hostent * he;
363         int ret;
364         int i,len, len2;
365
366         re=init_re();
367         if (re==0) return E_OUT_OF_MEM;
368         LOG(L_DBG, "add_rule: fixing expr...\n");
369         if ((ret=fix_expr(e))!=0) goto error;
370         LOG(L_DBG, "add_rule: fixing actions...\n");
371         if ((ret=fix_action(a))!=0) goto error;
372         re->condition=e;
373         re->actions=a;
374         
375         push(re,head);
376         return 0;
377         
378 error:
379         free_re(re);
380         return ret;
381 }
382
383
384
385 struct route_elem* route_match(struct sip_msg* msg, struct route_elem** rl)
386 {
387         struct route_elem* t;
388         if (*rl==0){
389                 LOG(L_ERR, "WARNING: route_match: empty routing table\n");
390                 return 0;
391         }
392         for (t=*rl; t; t=t->next){
393                 if (eval_expr(t->condition, msg)==1) return t;
394         }
395         /* no match :( */
396         return 0;
397 }
398
399
400
401 /* debug function, prints main routing table */
402 void print_rl()
403 {
404         struct route_elem* t;
405         int i,j;
406
407         if (rlist==0){
408                 printf("the routing table is empty\n");
409                 return;
410         }
411         
412         for (t=rlist[0],i=0; t; i++, t=t->next){
413                 printf("%2d.condition: ");
414                 print_expr(t->condition);
415                 printf("\n  -> ");
416                 print_action(t->actions);
417                 printf("\n    Statistics: tx=%d, errors=%d, tx_bytes=%d\n",
418                                 t->tx, t->errors, t->tx_bytes);
419         }
420
421 }
422
423