OSDN Git Service

Add MS7619SE
[uclinux-h8/uClinux-dist.git] / user / ser / route.c
1 /*
2  * $Id: route.c,v 1.43.2.1 2005/02/18 14:30:44 andrei Exp $
3  *
4  * SIP routing engine
5  *
6  *
7  * Copyright (C) 2001-2003 FhG Fokus
8  *
9  * This file is part of ser, a free SIP server.
10  *
11  * ser is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version
15  *
16  * For a license to use the ser software under conditions
17  * other than those described here, or to purchase support for this
18  * software, please contact iptel.org by e-mail at the following addresses:
19  *    info@iptel.org
20  *
21  * ser is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License 
27  * along with this program; if not, write to the Free Software 
28  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29  *
30  * History:
31  * --------
32  *  2003-01-28  scratchpad removed, src_port introduced (jiri)
33  *  2003-02-28  scratchpad compatibility abandoned (jiri)
34  *  2003-03-10  updated to the new module exports format (andrei)
35  *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
36  *  2003-04-01  added dst_port, proto, af; renamed comp_port to comp_no,
37  *               inlined all the comp_* functions (andrei)
38  *  2003-04-05  s/reply_route/failure_route, onreply_route introduced (jiri)
39  *  2003-05-23  comp_ip fixed, now it will resolve its operand and compare
40  *              the ip with all the addresses (andrei)
41  *  2003-10-10  added more operators support to comp_* (<,>,<=,>=,!=) (andrei)
42  *  2004-10-19  added from_uri & to_uri (andrei)
43  */
44
45  
46 #include <stdlib.h>
47 #include <sys/types.h>
48 #include <regex.h>
49 #include <netdb.h>
50 #include <string.h>
51 #include <sys/socket.h>
52 #include <netinet/in.h>
53 #include <arpa/inet.h>
54 #include <netdb.h>
55
56 #include "route.h"
57 #include "forward.h"
58 #include "dprint.h"
59 #include "proxy.h"
60 #include "action.h"
61 #include "sr_module.h"
62 #include "ip_addr.h"
63 #include "resolve.h"
64 #include "socket_info.h"
65 #include "parser/parse_uri.h"
66 #include "parser/parse_from.h"
67 #include "parser/parse_to.h"
68 #include "mem/mem.h"
69
70
71 /* main routing script table  */
72 struct action* rlist[RT_NO];
73 /* reply routing table */
74 struct action* onreply_rlist[ONREPLY_RT_NO];
75 struct action* failure_rlist[FAILURE_RT_NO];
76
77
78 static int fix_actions(struct action* a); /*fwd declaration*/
79
80
81 /* traverses an expr tree and compiles the REs where necessary) 
82  * returns: 0 for ok, <0 if errors */
83 static int fix_expr(struct expr* exp)
84 {
85         regex_t* re;
86         int ret;
87         
88         ret=E_BUG;
89         if (exp==0){
90                 LOG(L_CRIT, "BUG: fix_expr: null pointer\n");
91                 return E_BUG;
92         }
93         if (exp->type==EXP_T){
94                 switch(exp->op){
95                         case AND_OP:
96                         case OR_OP:
97                                                 if ((ret=fix_expr(exp->l.expr))!=0)
98                                                         return ret;
99                                                 ret=fix_expr(exp->r.expr);
100                                                 break;
101                         case NOT_OP:
102                                                 ret=fix_expr(exp->l.expr);
103                                                 break;
104                         default:
105                                                 LOG(L_CRIT, "BUG: fix_expr: unknown op %d\n",
106                                                                 exp->op);
107                 }
108         }else if (exp->type==ELEM_T){
109                         if (exp->op==MATCH_OP){
110                                 if (exp->subtype==STRING_ST){
111                                         re=(regex_t*)pkg_malloc(sizeof(regex_t));
112                                         if (re==0){
113                                                 LOG(L_CRIT, "ERROR: fix_expr: memory allocation"
114                                                                 " failure\n");
115                                                 return E_OUT_OF_MEM;
116                                         }
117                                         if (regcomp(re, (char*) exp->r.param,
118                                                                 REG_EXTENDED|REG_NOSUB|REG_ICASE) ){
119                                                 LOG(L_CRIT, "ERROR: fix_expr : bad re \"%s\"\n",
120                                                                         (char*) exp->r.param);
121                                                 pkg_free(re);
122                                                 return E_BAD_RE;
123                                         }
124                                         /* replace the string with the re */
125                                         pkg_free(exp->r.param);
126                                         exp->r.param=re;
127                                         exp->subtype=RE_ST;
128                                 }else if (exp->subtype!=RE_ST){
129                                         LOG(L_CRIT, "BUG: fix_expr : invalid type for match\n");
130                                         return E_BUG;
131                                 }
132                         }
133                         if (exp->l.operand==ACTION_O){
134                                 ret=fix_actions((struct action*)exp->r.param);
135                                 if (ret!=0){
136                                         LOG(L_CRIT, "ERROR: fix_expr : fix_actions error\n");
137                                         return ret;
138                                 }
139                         }
140                         ret=0;
141         }
142         return ret;
143 }
144
145
146
147 /* adds the proxies in the proxy list & resolves the hostnames */
148 /* returns 0 if ok, <0 on error */
149 static int fix_actions(struct action* a)
150 {
151         struct action *t;
152         struct proxy_l* p;
153         char *tmp;
154         int ret;
155         cmd_export_t* cmd;
156         struct sr_module* mod;
157         str s;
158         struct hostent* he;
159         struct ip_addr ip;
160         struct socket_info* si;
161         
162         if (a==0){
163                 LOG(L_CRIT,"BUG: fix_actions: null pointer\n");
164                 return E_BUG;
165         }
166         for(t=a; t!=0; t=t->next){
167                 switch(t->type){
168                         case FORWARD_T:
169                         case FORWARD_TLS_T:
170                         case FORWARD_TCP_T:
171                         case FORWARD_UDP_T:
172                         case SEND_T:
173                         case SEND_TCP_T:
174                                         switch(t->p1_type){
175                                                 case IP_ST: 
176                                                         tmp=strdup(ip_addr2a(
177                                                                                 (struct ip_addr*)t->p1.data));
178                                                         if (tmp==0){
179                                                                 LOG(L_CRIT, "ERROR: fix_actions:"
180                                                                                 "memory allocation failure\n");
181                                                                 return E_OUT_OF_MEM;
182                                                         }
183                                                         t->p1_type=STRING_ST;
184                                                         t->p1.string=tmp;
185                                                         /* no break */
186                                                 case STRING_ST:
187                                                         s.s = t->p1.string;
188                                                         s.len = strlen(s.s);
189                                                         p=add_proxy(&s, t->p2.number, 0); /* FIXME proto*/
190                                                         if (p==0) return E_BAD_ADDRESS;
191                                                         t->p1.data=p;
192                                                         t->p1_type=PROXY_ST;
193                                                         break;
194                                                 case URIHOST_ST:
195                                                         break;
196                                                 default:
197                                                         LOG(L_CRIT, "BUG: fix_actions: invalid type"
198                                                                         "%d (should be string or number)\n",
199                                                                                 t->type);
200                                                         return E_BUG;
201                                         }
202                                         break;
203                         case IF_T:
204                                 if (t->p1_type!=EXPR_ST){
205                                         LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
206                                                                 "%d for if (should be expr)\n",
207                                                                 t->p1_type);
208                                         return E_BUG;
209                                 }else if( (t->p2_type!=ACTIONS_ST)&&(t->p2_type!=NOSUBTYPE) ){
210                                         LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
211                                                                 "%d for if() {...} (should be action)\n",
212                                                                 t->p2_type);
213                                         return E_BUG;
214                                 }else if( (t->p3_type!=ACTIONS_ST)&&(t->p3_type!=NOSUBTYPE) ){
215                                         LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
216                                                                 "%d for if() {} else{...}(should be action)\n",
217                                                                 t->p3_type);
218                                         return E_BUG;
219                                 }
220                                 if (t->p1.data){
221                                         if ((ret=fix_expr((struct expr*)t->p1.data))<0)
222                                                 return ret;
223                                 }
224                                 if ( (t->p2_type==ACTIONS_ST)&&(t->p2.data) ){
225                                         if ((ret=fix_actions((struct action*)t->p2.data))<0)
226                                                 return ret;
227                                 }
228                                 if ( (t->p3_type==ACTIONS_ST)&&(t->p3.data) ){
229                                                 if ((ret=fix_actions((struct action*)t->p3.data))<0)
230                                                 return ret;
231                                 }
232                                 break;
233                         case MODULE_T:
234                                 if ((mod=find_module(t->p1.data, &cmd))!=0){
235                                         DBG("fixing %s %s\n", mod->path, cmd->name);
236                                         if (cmd->fixup){
237                                                 if (cmd->param_no>0){
238                                                         ret=cmd->fixup(&t->p2.data, 1);
239                                                         t->p2_type=MODFIXUP_ST;
240                                                         if (ret<0) return ret;
241                                                 }
242                                                 if (cmd->param_no>1){
243                                                         ret=cmd->fixup(&t->p3.data, 2);
244                                                         t->p3_type=MODFIXUP_ST;
245                                                         if (ret<0) return ret;
246                                                 }
247                                         }
248                                 }
249                                 break;
250                         case FORCE_SEND_SOCKET_T:
251                                 if (t->p1_type!=SOCKID_ST){
252                                         LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
253                                                                 "%d for force_send_socket\n",
254                                                                 t->p1_type);
255                                         return E_BUG;
256                                 }
257                                 he=resolvehost(((struct socket_id*)t->p1.data)->name);
258                                 if (he==0){
259                                         LOG(L_ERR, "ERROR: fix_actions: force_send_socket:"
260                                                                 " could not resolve %s\n",
261                                                                 ((struct socket_id*)t->p1.data)->name);
262                                         return E_BAD_ADDRESS;
263                                 }
264                                 hostent2ip_addr(&ip, he, 0);
265                                 si=find_si(&ip, ((struct socket_id*)t->p1.data)->port,
266                                                                 ((struct socket_id*)t->p1.data)->proto);
267                                 if (si==0){
268                                         LOG(L_ERR, "ERROR: fix_actions: bad force_send_socket"
269                                                         " argument: %s:%d (ser doesn't listen on it)\n",
270                                                         ((struct socket_id*)t->p1.data)->name,
271                                                         ((struct socket_id*)t->p1.data)->port);
272                                         return E_BAD_ADDRESS;
273                                 }
274                                 t->p1.data=si;
275                                 t->p1_type=SOCKETINFO_ST;
276                                 break;
277                 }
278         }
279         return 0;
280 }
281
282
283 inline static int comp_no( int port, void *param, int op, int subtype )
284 {
285         
286         if (subtype!=NUMBER_ST) {
287                 LOG(L_CRIT, "BUG: comp_no: number expected: %d\n", subtype );
288                 return E_BUG;
289         }
290         switch (op){
291                 case EQUAL_OP:
292                         return port==(long)param;
293                 case DIFF_OP:
294                         return port!=(long)param;
295                 case GT_OP:
296                         return port>(long)param;
297                 case LT_OP:
298                         return port<(long)param;
299                 case GTE_OP:
300                         return port>=(long)param;
301                 case LTE_OP:
302                         return port<=(long)param;
303                 default:
304                 LOG(L_CRIT, "BUG: comp_no: unknown operator: %d\n", op );
305                 return E_BUG;
306         }
307 }
308
309 /* eval_elem helping function, returns str op param */
310 inline static int comp_strstr(str* str, void* param, int op, int subtype)
311 {
312         int ret;
313         char backup;
314         
315         ret=-1;
316         switch(op){
317                 case EQUAL_OP:
318                         if (subtype!=STRING_ST){
319                                 LOG(L_CRIT, "BUG: comp_str: bad type %d, "
320                                                 "string expected\n", subtype);
321                                 goto error;
322                         }
323                         ret=(strncasecmp(str->s, (char*)param, str->len)==0);
324                         break;
325                 case DIFF_OP:
326                         if (subtype!=STRING_ST){
327                                 LOG(L_CRIT, "BUG: comp_str: bad type %d, "
328                                                 "string expected\n", subtype);
329                                 goto error;
330                         }
331                         ret=(strncasecmp(str->s, (char*)param, str->len)!=0);
332                         break;
333                 case MATCH_OP:
334                         if (subtype!=RE_ST){
335                                 LOG(L_CRIT, "BUG: comp_str: bad type %d, "
336                                                 " RE expected\n", subtype);
337                                 goto error;
338                         }
339                 /* this is really ugly -- we put a temporary zero-terminating
340                  * character in the original string; that's because regexps
341          * take 0-terminated strings and our messages are not
342          * zero-terminated; it should not hurt as long as this function
343                  * is applied to content of pkg mem, which is always the case
344                  * with calls from route{}; the same goes for fline in reply_route{};
345          *
346          * also, the received function should always give us an extra
347          * character, into which we can put the 0-terminator now;
348          * an alternative would be allocating a new piece of memory,
349          * which might be too slow
350          * -jiri
351          */
352                         backup=str->s[str->len];str->s[str->len]=0;
353                         ret=(regexec((regex_t*)param, str->s, 0, 0, 0)==0);
354                         str->s[str->len]=backup;
355                         break;
356                 default:
357                         LOG(L_CRIT, "BUG: comp_str: unknown op %d\n", op);
358                         goto error;
359         }
360         return ret;
361         
362 error:
363         return -1;
364 }
365
366 /* eval_elem helping function, returns str op param */
367 inline static int comp_str(char* str, void* param, int op, int subtype)
368 {
369         int ret;
370         
371         ret=-1;
372         switch(op){
373                 case EQUAL_OP:
374                         if (subtype!=STRING_ST){
375                                 LOG(L_CRIT, "BUG: comp_str: bad type %d, "
376                                                 "string expected\n", subtype);
377                                 goto error;
378                         }
379                         ret=(strcasecmp(str, (char*)param)==0);
380                         break;
381                 case DIFF_OP:
382                         if (subtype!=STRING_ST){
383                                 LOG(L_CRIT, "BUG: comp_str: bad type %d, "
384                                                 "string expected\n", subtype);
385                                 goto error;
386                         }
387                         ret=(strcasecmp(str, (char*)param)!=0);
388                         break;
389                 case MATCH_OP:
390                         if (subtype!=RE_ST){
391                                 LOG(L_CRIT, "BUG: comp_str: bad type %d, "
392                                                 " RE expected\n", subtype);
393                                 goto error;
394                         }
395                         ret=(regexec((regex_t*)param, str, 0, 0, 0)==0);
396                         break;
397                 default:
398                         LOG(L_CRIT, "BUG: comp_str: unknown op %d\n", op);
399                         goto error;
400         }
401         return ret;
402         
403 error:
404         return -1;
405 }
406
407
408 /* check_self wrapper -- it checks also for the op */
409 inline static int check_self_op(int op, str* s, unsigned short p)
410 {
411         int ret;
412         
413         ret=check_self(s, p, 0);
414         switch(op){
415                 case EQUAL_OP:
416                         break;
417                 case DIFF_OP:
418                         if (ret>=0) ret=!ret;
419                         break;
420                 default:
421                         LOG(L_CRIT, "BUG: check_self_op: invalid operator %d\n", op);
422                         ret=-1;
423         }
424         return ret;
425 }
426
427
428 /* eval_elem helping function, returns an op param */
429 inline static int comp_ip(struct ip_addr* ip, void* param, int op, int subtype)
430 {
431         struct hostent* he;
432         char ** h;
433         int ret;
434         str tmp;
435
436         ret=-1;
437         switch(subtype){
438                 case NET_ST:
439                         switch(op){
440                                 case EQUAL_OP:
441                                         ret=(matchnet(ip, (struct net*) param)==1);
442                                         break;
443                                 case DIFF_OP:
444                                         ret=(matchnet(ip, (struct net*) param)!=1);
445                                         break;
446                                 default:
447                                         goto error_op;
448                         }
449                         break;
450                 case STRING_ST:
451                 case RE_ST:
452                         switch(op){
453                                 case EQUAL_OP:
454                                 case MATCH_OP:
455                                         /* 1: compare with ip2str*/
456                                         ret=comp_str(ip_addr2a(ip), param, op, subtype);
457                                         if (ret==1) break;
458                                         /* 2: resolve (name) & compare w/ all the ips */
459                                         if (subtype==STRING_ST){
460                                                 he=resolvehost((char*)param);
461                                                 if (he==0){
462                                                         DBG("comp_ip: could not resolve %s\n",
463                                                                         (char*)param);
464                                                 }else if (he->h_addrtype==ip->af){
465                                                         for(h=he->h_addr_list;(ret!=1)&& (*h); h++){
466                                                                 ret=(memcmp(ip->u.addr, *h, ip->len)==0);
467                                                         }
468                                                         if (ret==1) break;
469                                                 }
470                                         }
471                                         /* 3: (slow) rev dns the address
472                                         * and compare with all the aliases
473                                         * !!??!! review: remove this? */
474                                         he=rev_resolvehost(ip);
475                                         if (he==0){
476                                                 print_ip( "comp_ip: could not rev_resolve ip address:"
477                                                                         " ", ip, "\n");
478                                         ret=0;
479                                         }else{
480                                                 /*  compare with primary host name */
481                                                 ret=comp_str(he->h_name, param, op, subtype);
482                                                 /* compare with all the aliases */
483                                                 for(h=he->h_aliases; (ret!=1) && (*h); h++){
484                                                         ret=comp_str(*h, param, op, subtype);
485                                                 }
486                                         }
487                                         break;
488                                 case DIFF_OP:
489                                         ret=comp_ip(ip, param, EQUAL_OP, subtype);
490                                         if (ret>=0) ret=!ret;
491                                         break;
492                                 default:
493                                         goto error_op;
494                         }
495                         break;
496                 case MYSELF_ST: /* check if it's one of our addresses*/
497                         tmp.s=ip_addr2a(ip);
498                         tmp.len=strlen(tmp.s);
499                         ret=check_self_op(op, &tmp, 0);
500                         break;
501                 default:
502                         LOG(L_CRIT, "BUG: comp_ip: invalid type for "
503                                                 " src_ip or dst_ip (%d)\n", subtype);
504                         ret=-1;
505         }
506         return ret;
507 error_op:
508         LOG(L_CRIT, "BUG: comp_ip: invalid operator %d\n", op);
509         return -1;
510         
511 }
512
513
514
515 /* returns: 0/1 (false/true) or -1 on error, -127 EXPR_DROP */
516 static int eval_elem(struct expr* e, struct sip_msg* msg)
517 {
518
519         struct sip_uri uri;
520         int ret;
521         ret=E_BUG;
522         
523         if (e->type!=ELEM_T){
524                 LOG(L_CRIT," BUG: eval_elem: invalid type\n");
525                 goto error;
526         }
527         switch(e->l.operand){
528                 case METHOD_O:
529                                 ret=comp_strstr(&msg->first_line.u.request.method, e->r.param,
530                                                                 e->op, e->subtype);
531                                 break;
532                 case URI_O:
533                                 if(msg->new_uri.s){
534                                         if (e->subtype==MYSELF_ST){
535                                                 if (parse_sip_msg_uri(msg)<0) ret=-1;
536                                                 else    ret=check_self_op(e->op, &msg->parsed_uri.host,
537                                                                         msg->parsed_uri.port_no?
538                                                                         msg->parsed_uri.port_no:SIP_PORT);
539                                         }else{
540                                                 ret=comp_strstr(&msg->new_uri, e->r.param,
541                                                                                 e->op, e->subtype);
542                                         }
543                                 }else{
544                                         if (e->subtype==MYSELF_ST){
545                                                 if (parse_sip_msg_uri(msg)<0) ret=-1;
546                                                 else    ret=check_self_op(e->op, &msg->parsed_uri.host,
547                                                                         msg->parsed_uri.port_no?
548                                                                         msg->parsed_uri.port_no:SIP_PORT);
549                                         }else{
550                                                 ret=comp_strstr(&msg->first_line.u.request.uri,
551                                                                                  e->r.param, e->op, e->subtype);
552                                         }
553                                 }
554                                 break;
555                 case FROM_URI_O:
556                                 if (parse_from_header(msg)!=0){
557                                         LOG(L_ERR, "ERROR: eval_elem: bad or missing"
558                                                                 " From: header\n");
559                                         goto error;
560                                 }
561                                 if (e->subtype==MYSELF_ST){
562                                         if (parse_uri(get_from(msg)->uri.s, get_from(msg)->uri.len,
563                                                                         &uri) < 0){
564                                                 LOG(L_ERR, "ERROR: eval_elem: bad uri in From:\n");
565                                                 goto error;
566                                         }
567                                         ret=check_self_op(e->op, &uri.host,
568                                                                                 uri.port_no?uri.port_no:SIP_PORT);
569                                 }else{
570                                         ret=comp_strstr(&get_from(msg)->uri,
571                                                         e->r.param, e->op, e->subtype);
572                                 }
573                                 break;
574                 case TO_URI_O:
575                                 if ((msg->to==0) && ((parse_headers(msg, HDR_TO, 0)==-1) ||
576                                                         (msg->to==0))){
577                                         LOG(L_ERR, "ERROR: eval_elem: bad or missing"
578                                                                 " To: header\n");
579                                         goto error;
580                                 }
581                                 /* to content is parsed automatically */
582                                 if (e->subtype==MYSELF_ST){
583                                         if (parse_uri(get_to(msg)->uri.s, get_to(msg)->uri.len,
584                                                                         &uri) < 0){
585                                                 LOG(L_ERR, "ERROR: eval_elem: bad uri in To:\n");
586                                                 goto error;
587                                         }
588                                         ret=check_self_op(e->op, &uri.host,
589                                                                                 uri.port_no?uri.port_no:SIP_PORT);
590                                 }else{
591                                         ret=comp_strstr(&get_to(msg)->uri,
592                                                                                 e->r.param, e->op, e->subtype);
593                                 }
594                                 break;
595                 case SRCIP_O:
596                                 ret=comp_ip(&msg->rcv.src_ip, e->r.param, e->op, e->subtype);
597                                 break;
598                 case DSTIP_O:
599                                 ret=comp_ip(&msg->rcv.dst_ip, e->r.param, e->op, e->subtype);
600                                 break;
601                 case NUMBER_O:
602                                 ret=!(!e->r.intval); /* !! to transform it in {0,1} */
603                                 break;
604                 case ACTION_O:
605                                 ret=run_actions( (struct action*)e->r.param, msg);
606                                 if (ret<=0) ret=(ret==0)?EXPR_DROP:0;
607                                 else ret=1;
608                                 break;
609                 case SRCPORT_O:
610                                 ret=comp_no(msg->rcv.src_port, 
611                                         e->r.param, /* e.g., 5060 */
612                                         e->op, /* e.g. == */
613                                         e->subtype /* 5060 is number */);
614                                 break;
615                 case DSTPORT_O:
616                                 ret=comp_no(msg->rcv.dst_port, e->r.param, e->op, 
617                                                         e->subtype);
618                                 break;
619                 case PROTO_O:
620                                 ret=comp_no(msg->rcv.proto, e->r.param, e->op, e->subtype);
621                                 break;
622                 case AF_O:
623                                 ret=comp_no(msg->rcv.src_ip.af, e->r.param, e->op, e->subtype);
624                                 break;
625                 case MSGLEN_O:
626                                 ret=comp_no(msg->len, e->r.param, e->op, e->subtype);
627                                 break;
628                 default:
629                                 LOG(L_CRIT, "BUG: eval_elem: invalid operand %d\n",
630                                                         e->l.operand);
631         }
632         return ret;
633 error:
634         return -1;
635 }
636
637
638
639 /* ret= 0/1 (true/false) ,  -1 on error or EXPR_DROP (-127)  */
640 int eval_expr(struct expr* e, struct sip_msg* msg)
641 {
642         static int rec_lev=0;
643         int ret;
644         
645         rec_lev++;
646         if (rec_lev>MAX_REC_LEV){
647                 LOG(L_CRIT, "ERROR: eval_expr: too many expressions (%d)\n",
648                                 rec_lev);
649                 ret=-1;
650                 goto skip;
651         }
652         
653         if (e->type==ELEM_T){
654                 ret=eval_elem(e, msg);
655         }else if (e->type==EXP_T){
656                 switch(e->op){
657                         case AND_OP:
658                                 ret=eval_expr(e->l.expr, msg);
659                                 /* if error or false stop evaluating the rest */
660                                 if (ret!=1) break;
661                                 ret=eval_expr(e->r.expr, msg); /*ret1 is 1*/
662                                 break;
663                         case OR_OP:
664                                 ret=eval_expr(e->l.expr, msg);
665                                 /* if true or error stop evaluating the rest */
666                                 if (ret!=0) break;
667                                 ret=eval_expr(e->r.expr, msg); /* ret1 is 0 */
668                                 break;
669                         case NOT_OP:
670                                 ret=eval_expr(e->l.expr, msg);
671                                 if (ret<0) break;
672                                 ret= ! ret;
673                                 break;
674                         default:
675                                 LOG(L_CRIT, "BUG: eval_expr: unknown op %d\n", e->op);
676                                 ret=-1;
677                 }
678         }else{
679                 LOG(L_CRIT, "BUG: eval_expr: unknown type %d\n", e->type);
680                 ret=-1;
681         }
682
683 skip:
684         rec_lev--;
685         return ret;
686 }
687
688
689 /* adds an action list to head; a must be null terminated (last a->next=0))*/
690 void push(struct action* a, struct action** head)
691 {
692         struct action *t;
693         if (*head==0){
694                 *head=a;
695                 return;
696         }
697         for (t=*head; t->next;t=t->next);
698         t->next=a;
699 }
700
701
702
703
704 int add_actions(struct action* a, struct action** head)
705 {
706         int ret;
707
708         LOG(L_DBG, "add_actions: fixing actions...\n");
709         if ((ret=fix_actions(a))!=0) goto error;
710         push(a,head);
711         return 0;
712         
713 error:
714         return ret;
715 }
716
717
718
719 /* fixes all action tables */
720 /* returns 0 if ok , <0 on error */
721 int fix_rls()
722 {
723         int i,ret;
724         for(i=0;i<RT_NO;i++){
725                 if(rlist[i]){
726                         if ((ret=fix_actions(rlist[i]))!=0){
727                                 return ret;
728                         }
729                 }
730         }
731         for(i=0;i<ONREPLY_RT_NO;i++){
732                 if(onreply_rlist[i]){
733                         if ((ret=fix_actions(onreply_rlist[i]))!=0){
734                                 return ret;
735                         }
736                 }
737         }
738         for(i=0;i<FAILURE_RT_NO;i++){
739                 if(failure_rlist[i]){
740                         if ((ret=fix_actions(failure_rlist[i]))!=0){
741                                 return ret;
742                         }
743                 }
744         }
745         return 0;
746 }
747
748
749 /* debug function, prints main routing table */
750 void print_rl()
751 {
752         struct action* t;
753         int i,j;
754
755         for(j=0; j<RT_NO; j++){
756                 if (rlist[j]==0){
757                         if (j==0) DBG("WARNING: the main routing table is empty\n");
758                         continue;
759                 }
760                 DBG("routing table %d:\n",j);
761                 for (t=rlist[j],i=0; t; i++, t=t->next){
762                         print_action(t);
763                 }
764                 DBG("\n");
765         }
766         for(j=0; j<ONREPLY_RT_NO; j++){
767                 if (onreply_rlist[j]==0){
768                         continue;
769                 }
770                 DBG("onreply routing table %d:\n",j);
771                 for (t=onreply_rlist[j],i=0; t; i++, t=t->next){
772                         print_action(t);
773                 }
774                 DBG("\n");
775         }
776         for(j=0; j<FAILURE_RT_NO; j++){
777                 if (failure_rlist[j]==0){
778                         continue;
779                 }
780                 DBG("failure routing table %d:\n",j);
781                 for (t=failure_rlist[j],i=0; t; i++, t=t->next){
782                         print_action(t);
783                 }
784                 DBG("\n");
785         }
786 }
787
788