route_struct.c
c07508e2
 /*
  * $Id$
  *
  * route structures helping functions
7dd0b342
  *
53c7e0f1
  * Copyright (C) 2001-2003 FhG Fokus
7dd0b342
  *
  * This file is part of ser, a free SIP server.
  *
  * ser is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
  * For a license to use the ser software under conditions
  * other than those described here, or to purchase support for this
  * software, please contact iptel.org by e-mail at the following addresses:
  *    info@iptel.org
  *
  * ser is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
f141bc93
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
7dd0b342
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
e3dccdc9
  */
 /* History:
  * --------
  *  2003-01-29  src_port introduced (jiri)
  *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
3e8c3475
  *  2003-04-12  FORCE_RPORT_T added (andrei)
6bfaa042
  *  2003-10-02  added SET_ADV_ADDRESS & SET_ADV_PORT (andrei)
1bee75ad
  *  2004-02-24  added LOAD_AVP_T and AVP_TO_URI_T (bogdan)
a0fb4e8b
  *  2005-12-19  select framework added SELECT_O and SELECT_ST (mma)
c07508e2
  */
 
1d0661db
 /*!
  * \file
  * \brief SIP-router core :: 
  * \ingroup core
  * Module: \ref core
  */
 
c07508e2
 
7dd0b342
 
c07508e2
 #include  "route_struct.h"
 
 #include <stdio.h>
3e429f5c
 #include <stdlib.h>
e22bbdb8
 #include <string.h>
f141bc93
 #include <stdarg.h>
c07508e2
 
7268726e
 #include "dprint.h"
4e2fdd79
 #include "ip_addr.h"
e3dccdc9
 #include "mem/mem.h"
74ce7043
 #include "usr_avp.h"
e03e1211
 #include "ut.h" /* ZSW() */
7268726e
 
03150098
 
33d56025
 
 /** joins to cfg file positions into a new one. */
 void cfg_pos_join(struct cfg_pos* res,
 							struct cfg_pos* pos1, struct cfg_pos* pos2)
 {
 	struct cfg_pos ret;
 	ret=*pos1;
 	if ((ret.s_line == 0) || (ret.s_line > pos2->s_line)){
 		ret.s_line=pos2->s_line;
 		ret.s_col=pos2->s_col;
 	}else if ((ret.s_line == pos2->s_line) && (ret.s_col > pos2->s_col)){
 		ret.s_col=pos2->s_col;
 	}
 	if ((ret.e_line == 0) || (ret.e_line < pos2->e_line)){
 		ret.e_line=pos2->e_line;
 		ret.e_col=pos2->e_col;
 	}else if ((ret.e_line == pos2->e_line) && (ret.e_col < pos2->e_col)){
 		ret.e_col=pos2->e_col;
 	}
 	*res=ret;
 }
 
 
 
c07508e2
 struct expr* mk_exp(int op, struct expr* left, struct expr* right)
 {
 	struct expr * e;
e3dccdc9
 	e=(struct expr*)pkg_malloc(sizeof (struct expr));
c07508e2
 	if (e==0) goto error;
 	e->type=EXP_T;
 	e->op=op;
 	e->l.expr=left;
 	e->r.expr=right;
 	return e;
 error:
7268726e
 	LOG(L_CRIT, "ERROR: mk_exp: memory allocation failure\n");
c07508e2
 	return 0;
 }
 
 
7fa369e3
 struct expr* mk_exp_rve(int op, void* left, void* right)
 {
 	struct expr * e;
 	e=(struct expr*)pkg_malloc(sizeof (struct expr));
 	if (e==0) goto error;
 	e->type=EXP_T;
 	e->op=op;
 	e->l.param=mk_elem(RVEXP_O, RVE_ST, left, 0, 0);
 	e->r.param=mk_elem(RVEXP_O, RVE_ST, right, 0, 0);
 	if (e->l.param==0 || e->r.param==0){
 		if (e->l.param) pkg_free(e->l.param);
 		if (e->r.param) pkg_free(e->r.param);
 		pkg_free(e);
 		goto error;
 	}
 	return e;
 error:
 	LOG(L_CRIT, "ERROR: mk_exp_rve: memory allocation failure\n");
 	return 0;
 }
 
aa9fa735
 struct expr* mk_elem(int op, expr_l_type ltype, void* lparam,
 							 expr_r_type rtype, void* rparam)
c07508e2
 {
 	struct expr * e;
e3dccdc9
 	e=(struct expr*)pkg_malloc(sizeof (struct expr));
c07508e2
 	if (e==0) goto error;
 	e->type=ELEM_T;
 	e->op=op;
74ce7043
 	e->l_type=ltype;
 	e->l.param=lparam;
 	e->r_type = rtype;
 	e->r.param=rparam;
c07508e2
 	return e;
 error:
7268726e
 	LOG(L_CRIT, "ERROR: mk_elem: memory allocation failure\n");
c07508e2
 	return 0;
 }
 
 
aa9fa735
 /** create an action structure (parser use).
  * @param type - type of the action
  * @param count - count of couples {param_type,val}
  * @param ... -   count {param_type, val} pairs, where param_type is
  *                action_param_type.
  * @return  new action structure on success (pkg_malloc'ed) or 0 on error.
  */
 struct action* mk_action(enum action_type type, int count, ...)
 {
f141bc93
 	va_list args;
 	int i;
c07508e2
 	struct action* a;
f141bc93
 
 	a = (struct action*)pkg_malloc(sizeof(struct action));
c07508e2
 	if (a==0) goto  error;
f141bc93
 	memset(a, 0, sizeof(struct action));
c07508e2
 	a->type=type;
f141bc93
 	a->count = (count > MAX_ACTIONS)?MAX_ACTIONS:count;
 
 	va_start(args, count);
 	for (i=0; i<a->count; i++) {
 		a->val[i].type = va_arg(args, int);
 		a->val[i].u.data = va_arg(args, void *);
 
 		DBG("ACTION_#%d #%d/%d: %d(%x)/ %p\n", a->type, i, a->count, a->val[i].type, a->val[i].type, a->val[i].u.data);
 	}
 	va_end(args);
 
c07508e2
 	a->next=0;
 	return a;
f141bc93
 
c07508e2
 error:
7268726e
 	LOG(L_CRIT, "ERROR: mk_action: memory allocation failure\n");
c07508e2
 	return 0;
f20a56a2
 }
 
 
c07508e2
 struct action* append_action(struct action* a, struct action* b)
 {
 	struct action *t;
 	if (b==0) return a;
 	if (a==0) return b;
f141bc93
 
 	for(t=a; t->next; t=t->next);
c07508e2
 	t->next=b;
 	return a;
 }
 
09e52ebb
 
 
c07508e2
 void print_expr(struct expr* exp)
 {
 	if (exp==0){
7268726e
 		LOG(L_CRIT, "ERROR: print_expr: null expression!\n");
c07508e2
 		return;
 	}
 	if (exp->type==ELEM_T){
74ce7043
 		switch(exp->l_type){
c07508e2
 			case METHOD_O:
7268726e
 				DBG("method");
c07508e2
 				break;
 			case URI_O:
7268726e
 				DBG("uri");
c07508e2
 				break;
6b7de230
 			case FROM_URI_O:
 				DBG("from_uri");
 				break;
 			case TO_URI_O:
 				DBG("to_uri");
 				break;
c07508e2
 			case SRCIP_O:
7268726e
 				DBG("srcip");
c07508e2
 				break;
049f64c2
 			case SRCPORT_O:
 				DBG("srcport");
 				break;
c07508e2
 			case DSTIP_O:
7268726e
 				DBG("dstip");
c07508e2
 				break;
646aef6d
 			case DSTPORT_O:
 				DBG("dstport");
 				break;
7fa369e3
 			case PROTO_O:
 				DBG("proto");
 				break;
 			case AF_O:
 				DBG("af");
 				break;
 			case MSGLEN_O:
 				DBG("msglen");
f20a56a2
 				break;
 			case ACTION_O:
 				break;
7fa369e3
 			case NUMBER_O:
 				break;
 			case AVP_O:
 				DBG("avp");
 				break;
 			case SNDIP_O:
 				DBG("sndip");
 				break;
 			case SNDPORT_O:
 				DBG("sndport");
 				break;
 			case TOIP_O:
 				DBG("toip");
 				break;
 			case TOPORT_O:
 				DBG("toport");
 				break;
 			case SNDPROTO_O:
 				DBG("sndproto");
 				break;
 			case SNDAF_O:
 				DBG("sndaf");
 				break;
 			case RETCODE_O:
 				DBG("retcode");
 				break;
 			case SELECT_O:
 				DBG("select");
74ce7043
 				break;
7fa369e3
 			case RVEXP_O:
 				DBG("rval");
3fb428ed
 				break;
f141bc93
 
c07508e2
 			default:
7268726e
 				DBG("UNKNOWN");
c07508e2
 		}
 		switch(exp->op){
 			case EQUAL_OP:
7268726e
 				DBG("==");
c07508e2
 				break;
 			case MATCH_OP:
7268726e
 				DBG("=~");
09e52ebb
 				break;
f20a56a2
 			case NO_OP:
 				break;
646aef6d
 			case GT_OP:
 				DBG(">");
 				break;
 			case GTE_OP:
 				DBG(">=");
 				break;
 			case LT_OP:
 				DBG("<");
 				break;
 			case LTE_OP:
 				DBG("<=");
 				break;
 			case DIFF_OP:
 				DBG("!=");
 				break;
c07508e2
 			default:
7268726e
 				DBG("<UNKNOWN>");
c07508e2
 		}
74ce7043
 		switch(exp->r_type){
f141bc93
 			case NOSUBTYPE:
7268726e
 					DBG("N/A");
c07508e2
 					break;
 			case STRING_ST:
e03e1211
 					DBG("\"%s\"", ZSW((char*)exp->r.param));
c07508e2
 					break;
 			case NET_ST:
09e52ebb
 					print_net((struct net*)exp->r.param);
 					break;
 			case IP_ST:
9c01c860
 					print_ip("", (struct ip_addr*)exp->r.param, "");
c07508e2
 					break;
f20a56a2
 			case ACTIONS_ST:
74ce7043
 					print_actions((struct action*)exp->r.param);
f20a56a2
 					break;
 			case NUMBER_ST:
e9220390
 					DBG("%ld",exp->r.numval);
f20a56a2
 					break;
855c2e68
 			case MYSELF_ST:
 					DBG("_myself_");
 					break;
74ce7043
 		        case AVP_ST:
3fb428ed
 				        DBG("attr");
 			 	        break;
 		        case SELECT_ST:
 				        DBG("select");
 				        break;
c07508e2
 			default:
74ce7043
 					DBG("type<%d>", exp->r_type);
c07508e2
 		}
 	}else if (exp->type==EXP_T){
 		switch(exp->op){
74ce7043
 			case LOGAND_OP:
7268726e
 					DBG("AND( ");
c07508e2
 					print_expr(exp->l.expr);
7268726e
 					DBG(", ");
c07508e2
 					print_expr(exp->r.expr);
7268726e
 					DBG(" )");
c07508e2
 					break;
74ce7043
 			case LOGOR_OP:
7268726e
 					DBG("OR( ");
c07508e2
 					print_expr(exp->l.expr);
7268726e
 					DBG(", ");
c07508e2
 					print_expr(exp->r.expr);
7268726e
 					DBG(" )");
c07508e2
 					break;
f141bc93
 			case NOT_OP:
7268726e
 					DBG("NOT( ");
c07508e2
 					print_expr(exp->l.expr);
7268726e
 					DBG(" )");
c07508e2
 					break;
 			default:
7268726e
 					DBG("UNKNOWN_EXP ");
c07508e2
 		}
f141bc93
 
c07508e2
 	}else{
7268726e
 		DBG("ERROR:print_expr: unknown type\n");
c07508e2
 	}
 }
 
f141bc93
 
 
c07508e2
 
74ce7043
 void print_action(struct action* t)
c07508e2
 {
74ce7043
 	switch(t->type){
f141bc93
 		case FORWARD_T:
 			DBG("forward(");
 			break;
 		case FORWARD_TCP_T:
 			DBG("forward_tcp(");
 			break;
 		case FORWARD_UDP_T:
 			DBG("forward_udp(");
 			break;
 		case DROP_T:
 			DBG("drop(");
 			break;
 		case LOG_T:
 			DBG("log(");
 			break;
 		case ERROR_T:
 			DBG("error(");
 			break;
 		case ROUTE_T:
 			DBG("route(");
 			break;
 		case EXEC_T:
 			DBG("exec(");
 			break;
 		case REVERT_URI_T:
 			DBG("revert_uri(");
 			break;
 		case STRIP_T:
 			DBG("strip(");
 			break;
 		case APPEND_BRANCH_T:
 			DBG("append_branch(");
 			break;
 		case PREFIX_T:
 			DBG("prefix(");
 			break;
 		case LEN_GT_T:
 			DBG("len_gt(");
 			break;
 		case SETFLAG_T:
 			DBG("setflag(");
 			break;
 		case RESETFLAG_T:
 			DBG("resetflag(");
 			break;
 		case ISFLAGSET_T:
 			DBG("isflagset(");
 			break;
85d4627f
 		case AVPFLAG_OPER_T:
 			DBG("avpflagoper(");
 			break;
f141bc93
 		case SET_HOST_T:
 			DBG("sethost(");
 			break;
 		case SET_HOSTPORT_T:
 			DBG("sethostport(");
 			break;
6973e34c
 		case SET_HOSTPORTTRANS_T:
 			DBG("sethostporttrans(");
 			break;
f141bc93
 		case SET_USER_T:
 			DBG("setuser(");
 			break;
 		case SET_USERPASS_T:
 			DBG("setuserpass(");
 			break;
 		case SET_PORT_T:
 			DBG("setport(");
 			break;
 		case SET_URI_T:
 			DBG("seturi(");
 			break;
 		case IF_T:
 			DBG("if (");
 			break;
cad98b04
 		case MODULE0_T:
 		case MODULE1_T:
 		case MODULE2_T:
a2da0c58
 		case MODULE3_T:
 		case MODULE4_T:
 		case MODULE5_T:
 		case MODULE6_T:
 		case MODULEX_T:
cad98b04
 		case MODULE1_RVE_T:
 		case MODULE2_RVE_T:
 		case MODULE3_RVE_T:
 		case MODULE4_RVE_T:
 		case MODULE5_RVE_T:
 		case MODULE6_RVE_T:
 		case MODULEX_RVE_T:
f141bc93
 			DBG(" external_module_call(");
 			break;
 		case FORCE_RPORT_T:
 			DBG("force_rport(");
 			break;
 		case SET_ADV_ADDR_T:
 			DBG("set_advertised_address(");
 			break;
 		case SET_ADV_PORT_T:
 			DBG("set_advertised_port(");
 			break;
 		case FORCE_TCP_ALIAS_T:
 			DBG("force_tcp_alias(");
 			break;
 		case LOAD_AVP_T:
 			DBG("load_avp(");
 			break;
 		case AVP_TO_URI_T:
 			DBG("avp_to_attr");
 			break;
 		case FORCE_SEND_SOCKET_T:
 			DBG("force_send_socket");
 			break;
 		case ASSIGN_T
 	:		DBG("assign(");
 			break;
 		case ADD_T:
 			DBG("assign_add(");
 			break;
 		default:
 			DBG("UNKNOWN(");
74ce7043
 	}
f141bc93
 	switch(t->val[0].type){
 		case STRING_ST:
 			DBG("\"%s\"", ZSW(t->val[0].u.string));
 			break;
 		case NUMBER_ST:
 			DBG("%lu",t->val[0].u.number);
 			break;
 		case IP_ST:
 			print_ip("", (struct ip_addr*)t->val[0].u.data, "");
 			break;
 		case EXPR_ST:
 			print_expr((struct expr*)t->val[0].u.data);
 			break;
 		case ACTIONS_ST:
 			print_actions((struct action*)t->val[0].u.data);
 			break;
 		case MODEXP_ST:
 			DBG("f_ptr<%p>",t->val[0].u.data);
 			break;
 		case SOCKID_ST:
 			DBG("%d:%s:%d",
 			((struct socket_id*)t->val[0].u.data)->proto,
eb321e3f
 			ZSW(((struct socket_id*)t->val[0].u.data)->addr_lst->name),
f141bc93
 			((struct socket_id*)t->val[0].u.data)->port
 			);
 			break;
 		case AVP_ST:
 			DBG("avp(%u,%.*s)", t->val[0].u.attr->type, t->val[0].u.attr->name.s.len, ZSW(t->val[0].u.attr->name.s.s));
 			break;
 		case SELECT_ST:
 			DBG("select");
 			break;
 		default:
 			DBG("type<%d>", t->val[0].type);
c07508e2
 	}
74ce7043
 	if (t->type==IF_T) DBG(") {");
f141bc93
 	switch(t->val[1].type){
 		case NOSUBTYPE:
 			break;
 		case STRING_ST:
 			DBG(", \"%s\"", ZSW(t->val[1].u.string));
 			break;
 		case NUMBER_ST:
 			DBG(", %lu",t->val[1].u.number);
 			break;
 		case EXPR_ST:
 			print_expr((struct expr*)t->val[1].u.data);
 			break;
 		case ACTION_ST:
 		case ACTIONS_ST:
 			print_actions((struct action*)t->val[1].u.data);
 			break;
 
 		case SOCKID_ST:
 			DBG("%d:%s:%d",
 			((struct socket_id*)t->val[0].u.data)->proto,
eb321e3f
 			ZSW(((struct socket_id*)t->val[0].u.data)->addr_lst->name),
f141bc93
 			((struct socket_id*)t->val[0].u.data)->port
 			);
 			break;
 		case AVP_ST:
 			DBG(", avp(%u,%.*s)", t->val[1].u.attr->type, t->val[1].u.attr->name.s.len, ZSW(t->val[1].u.attr->name.s.s));
 			break;
 		case SELECT_ST:
 			DBG("select");
 			break;
 		default:
 			DBG(", type<%d>", t->val[1].type);
74ce7043
 	}
 	if (t->type==IF_T) DBG("} else {");
f141bc93
 	switch(t->val[2].type){
 		case NOSUBTYPE:
 			break;
 		case STRING_ST:
 			DBG(", \"%s\"", ZSW(t->val[2].u.string));
 			break;
 		case NUMBER_ST:
 			DBG(", %lu",t->val[2].u.number);
 			break;
 		case EXPR_ST:
 			print_expr((struct expr*)t->val[2].u.data);
 			break;
 		case ACTIONS_ST:
 			print_actions((struct action*)t->val[2].u.data);
 			break;
 		case SOCKID_ST:
 			DBG("%d:%s:%d",
 			((struct socket_id*)t->val[0].u.data)->proto,
eb321e3f
 			ZSW(((struct socket_id*)t->val[0].u.data)->addr_lst->name),
f141bc93
 			((struct socket_id*)t->val[0].u.data)->port
 			);
 			break;
 		default:
 			DBG(", type<%d>", t->val[2].type);
74ce7043
 	}
 	if (t->type==IF_T) DBG("}; ");
f141bc93
 		else	DBG("); ");
c07508e2
 }
 
74ce7043
 void print_actions(struct action* a)
 {
 	while(a) {
 		print_action(a);
 		a = a->next;
 	}
 }
486ace87
 
 /**
  * get the pointer to action structure from parameter
  */
 struct action *get_action_from_param(void **param, int param_no)
 {
 	struct action *ac, ac2;
 	action_u_t *au, au2;
 	/* param points to au->u.string, get pointer to au */
 	au = (void*) ((char *)param - ((char *)&au2.u.string-(char *)&au2));
 	au = au - 1 - param_no;
 	ac = (void*) ((char *)au - ((char *)&ac2.val-(char *)&ac2));
 	return ac;
 }