| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095 |
- /*
- * $Id$
- *
- * Copyright (C) 2001-2003 FhG Fokus
- *
- * 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:
- * [email protected]
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * History:
- * ---------
- * 2003-02-28 scratchpad compatibility abandoned (jiri)
- * 2003-01-29 removed scratchpad (jiri)
- * 2003-03-19 fixed set* len calculation bug & simplified a little the code
- * (should be a little faster now) (andrei)
- * replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
- * 2003-04-01 Added support for loose routing in forward (janakj)
- * 2003-04-12 FORCE_RPORT_T added (andrei)
- * 2003-04-22 strip_tail added (jiri)
- * 2003-10-02 added SET_ADV_ADDR_T & SET_ADV_PORT_T (andrei)
- * 2003-10-29 added FORCE_TCP_ALIAS_T (andrei)
- * 2004-11-30 added FORCE_SEND_SOCKET_T (andrei)
- * 2005-12-12 return & drop/exit differentiation (andrei)
- * 2005-12-19 select framework (mma)
- * 2006-04-12 updated *_send() calls to use a struct dest_info (andrei)
- * 2006-07-27 dns cache and dns based send address failover support (andrei)
- * 2006-12-06 on popular request last_retcode set also by module functions
- * (andrei)
- * 2007-06-14 run_actions & do_action need a ctx or handle now, no more
- * static vars (andrei)
- * 2008-12-17 added UDP_MTU_TRY_PROTO_T (andrei)
- */
- #include "comp_defs.h"
- #include "action.h"
- #include "config.h"
- #include "error.h"
- #include "dprint.h"
- #include "proxy.h"
- #include "forward.h"
- #include "udp_server.h"
- #include "route.h"
- #include "parser/msg_parser.h"
- #include "parser/parse_uri.h"
- #include "ut.h"
- #include "sr_module.h"
- #include "mem/mem.h"
- #include "globals.h"
- #include "dset.h"
- #include "onsend.h"
- #include "resolve.h"
- #ifdef USE_TCP
- #include "tcp_server.h"
- #endif
- #ifdef USE_SCTP
- #include "sctp_server.h"
- #endif
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netdb.h>
- #include <stdlib.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <string.h>
- #ifdef DEBUG_DMALLOC
- #include <dmalloc.h>
- #endif
- struct onsend_info* p_onsend=0; /* onsend route send info */
- /* ret= 0! if action -> end of list(e.g DROP),
- > 0 to continue processing next actions
- and <0 on error */
- int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
- {
- int ret;
- int v;
- struct dest_info dst;
- char* tmp;
- char *new_uri, *end, *crt;
- int len;
- int user;
- struct sip_uri uri, next_hop;
- struct sip_uri *u;
- unsigned short port;
- unsigned short flags;
- int_str name, value;
- str* dst_host;
- int orig_p2t;
- /* reset the value of error to E_UNSPEC so avoid unknowledgable
- functions to return with error (status<0) and not setting it
- leaving there previous error; cache the previous value though
- for functions which want to process it */
- prev_ser_error=ser_error;
- ser_error=E_UNSPEC;
- ret=E_BUG;
- switch ((unsigned char)a->type){
- case DROP_T:
- if (a->val[0].type==RETCODE_ST)
- ret=h->last_retcode;
- else
- ret=(int) a->val[0].u.number;
- h->run_flags|=(unsigned int)a->val[1].u.number;
- break;
- case FORWARD_T:
- #ifdef USE_TCP
- case FORWARD_TCP_T:
- #endif
- #ifdef USE_TLS
- case FORWARD_TLS_T:
- #endif
- #ifdef USE_SCTP
- case FORWARD_SCTP_T:
- #endif
- case FORWARD_UDP_T:
- /* init dst */
- init_dest_info(&dst);
- if (a->type==FORWARD_UDP_T) dst.proto=PROTO_UDP;
- #ifdef USE_TCP
- else if (a->type==FORWARD_TCP_T) dst.proto= PROTO_TCP;
- #endif
- #ifdef USE_TLS
- else if (a->type==FORWARD_TLS_T) dst.proto= PROTO_TLS;
- #endif
- #ifdef USE_SCTP
- else if (a->type==FORWARD_SCTP_T) dst.proto=PROTO_SCTP;
- #endif
- else dst.proto=PROTO_NONE;
- if (a->val[0].type==URIHOST_ST){
- /*parse uri*/
- if (msg->dst_uri.len) {
- ret = parse_uri(msg->dst_uri.s, msg->dst_uri.len,
- &next_hop);
- u = &next_hop;
- } else {
- ret = parse_sip_msg_uri(msg);
- u = &msg->parsed_uri;
- }
- if (ret<0) {
- LOG(L_ERR, "ERROR: do_action: forward: bad_uri "
- " dropping packet\n");
- break;
- }
- switch (a->val[1].type){
- case URIPORT_ST:
- port=u->port_no;
- break;
- case NUMBER_ST:
- port=a->val[1].u.number;
- break;
- default:
- LOG(L_CRIT, "BUG: do_action bad forward 2nd"
- " param type (%d)\n", a->val[1].type);
- ret=E_UNSPEC;
- goto error_fwd_uri;
- }
- if (dst.proto == PROTO_NONE){ /* only if proto not set get it
- from the uri */
- switch(u->proto){
- case PROTO_NONE:
- /*dst.proto=PROTO_UDP; */
- /* no proto, try to get it from the dns */
- break;
- case PROTO_UDP:
- #ifdef USE_TCP
- case PROTO_TCP:
- #endif
- #ifdef USE_TLS
- case PROTO_TLS:
- #endif
- #ifdef USE_SCTP
- case PROTO_SCTP:
- #endif
- dst.proto=u->proto;
- break;
- default:
- LOG(L_ERR,"ERROR: do action: forward: bad uri"
- " transport %d\n", u->proto);
- ret=E_BAD_PROTO;
- goto error_fwd_uri;
- }
- #ifdef USE_TLS
- if (u->type==SIPS_URI_T){
- if (u->proto==PROTO_UDP){
- LOG(L_ERR, "ERROR: do_action: forward: secure uri"
- " incompatible with transport %d\n",
- u->proto);
- ret=E_BAD_PROTO;
- goto error_fwd_uri;
- }
- dst.proto=PROTO_TLS;
- }
- #endif
- }
- #ifdef HONOR_MADDR
- if (u->maddr_val.s && u->maddr_val.len)
- dst_host=&u->maddr_val;
- else
- #endif
- dst_host=&u->host;
- #ifdef USE_COMP
- dst.comp=u->comp;
- #endif
- ret=forward_request(msg, dst_host, port, &dst);
- if (ret>=0){
- ret=1;
- }
- }else if ((a->val[0].type==PROXY_ST) && (a->val[1].type==NUMBER_ST)){
- if (dst.proto==PROTO_NONE)
- dst.proto=msg->rcv.proto;
- proxy2su(&dst.to, (struct proxy_l*)a->val[0].u.data);
- ret=forward_request(msg, 0, 0, &dst);
- if (ret>=0){
- ret=1;
- proxy_mark((struct proxy_l*)a->val[0].u.data, ret);
- }else if (ser_error!=E_OK){
- proxy_mark((struct proxy_l*)a->val[0].u.data, ret);
- }
- }else{
- LOG(L_CRIT, "BUG: do_action: bad forward() types %d, %d\n",
- a->val[0].type, a->val[1].type);
- ret=E_BUG;
- }
- break;
- case SEND_T:
- case SEND_TCP_T:
- if ((a->val[0].type!= PROXY_ST)|(a->val[1].type!=NUMBER_ST)){
- LOG(L_CRIT, "BUG: do_action: bad send() types %d, %d\n",
- a->val[0].type, a->val[1].type);
- ret=E_BUG;
- break;
- }
- /* init dst */
- init_dest_info(&dst);
- ret=proxy2su(&dst.to, (struct proxy_l*)a->val[0].u.data);
- if (ret==0){
- if (p_onsend){
- tmp=p_onsend->buf;
- len=p_onsend->len;
- }else{
- tmp=msg->buf;
- len=msg->len;
- }
- if (a->type==SEND_T){
- /*udp*/
- dst.proto=PROTO_UDP; /* not really needed for udp_send */
- dst.send_sock=get_send_socket(msg, &dst.to, PROTO_UDP);
- if (dst.send_sock!=0){
- ret=udp_send(&dst, tmp, len);
- }else{
- ret=-1;
- }
- }
- #ifdef USE_TCP
- else{
- /*tcp*/
- dst.proto=PROTO_TCP;
- dst.id=0;
- ret=tcp_send(&dst, 0, tmp, len);
- }
- #endif
- }else{
- ret=E_BUG;
- break;
- }
- proxy_mark((struct proxy_l*)a->val[0].u.data, ret);
- if (ret>=0) ret=1;
- break;
- case LOG_T:
- if ((a->val[0].type!=NUMBER_ST)|(a->val[1].type!=STRING_ST)){
- LOG(L_CRIT, "BUG: do_action: bad log() types %d, %d\n",
- a->val[0].type, a->val[1].type);
- ret=E_BUG;
- break;
- }
- LOG_(a->val[0].u.number, "<script>: ", "%s", a->val[1].u.string);
- ret=1;
- break;
- /* jku -- introduce a new branch */
- case APPEND_BRANCH_T:
- if ((a->val[0].type!=STRING_ST)) {
- LOG(L_CRIT, "BUG: do_action: bad append_branch_t %d\n",
- a->val[0].type );
- ret=E_BUG;
- break;
- }
- ret=append_branch( msg, a->val[0].u.string,
- a->val[0].u.string ? strlen(a->val[0].u.string):0,
- 0, 0, a->val[1].u.number, 0);
- break;
- /* jku begin: is_length_greater_than */
- case LEN_GT_T:
- if (a->val[0].type!=NUMBER_ST) {
- LOG(L_CRIT, "BUG: do_action: bad len_gt type %d\n",
- a->val[0].type );
- ret=E_BUG;
- break;
- }
- /* DBG("XXX: message length %d, max %d\n",
- msg->len, a->val[0].u.number ); */
- ret = msg->len >= a->val[0].u.number ? 1 : -1;
- break;
- /* jku end: is_length_greater_than */
- /* jku - begin : flag processing */
- case SETFLAG_T:
- if (a->val[0].type!=NUMBER_ST) {
- LOG(L_CRIT, "BUG: do_action: bad setflag() type %d\n",
- a->val[0].type );
- ret=E_BUG;
- break;
- }
- if (!flag_in_range( a->val[0].u.number )) {
- ret=E_CFG;
- break;
- }
- setflag( msg, a->val[0].u.number );
- ret=1;
- break;
- case RESETFLAG_T:
- if (a->val[0].type!=NUMBER_ST) {
- LOG(L_CRIT, "BUG: do_action: bad resetflag() type %d\n",
- a->val[0].type );
- ret=E_BUG;
- break;
- }
- if (!flag_in_range( a->val[0].u.number )) {
- ret=E_CFG;
- break;
- }
- resetflag( msg, a->val[0].u.number );
- ret=1;
- break;
- case ISFLAGSET_T:
- if (a->val[0].type!=NUMBER_ST) {
- LOG(L_CRIT, "BUG: do_action: bad isflagset() type %d\n",
- a->val[0].type );
- ret=E_BUG;
- break;
- }
- if (!flag_in_range( a->val[0].u.number )) {
- ret=E_CFG;
- break;
- }
- ret=isflagset( msg, a->val[0].u.number );
- break;
- /* jku - end : flag processing */
- case AVPFLAG_OPER_T: {
- struct search_state st;
- avp_t* avp;
- int flag;
- ret = 0;
- flag = a->val[1].u.number;
- if ((a->val[0].u.attr->type & AVP_INDEX_ALL) == AVP_INDEX_ALL || (a->val[0].u.attr->type & AVP_NAME_RE)!=0) {
- for (avp=search_first_avp(a->val[0].u.attr->type, a->val[0].u.attr->name, NULL, &st); avp; avp = search_next_avp(&st, NULL)) {
- switch (a->val[2].u.number) { /* oper: 0..reset, 1..set, -1..no change */
- case 0:
- avp->flags &= ~(avp_flags_t)a->val[1].u.number;
- break;
- case 1:
- avp->flags |= (avp_flags_t)a->val[1].u.number;
- break;
- default:;
- }
- ret = ret || ((avp->flags & (avp_flags_t)a->val[1].u.number) != 0);
- }
- }
- else {
- avp = search_avp_by_index(a->val[0].u.attr->type, a->val[0].u.attr->name, NULL, a->val[0].u.attr->index);
- if (avp) {
- switch (a->val[2].u.number) { /* oper: 0..reset, 1..set, -1..no change */
- case 0:
- avp->flags &= ~(avp_flags_t)a->val[1].u.number;
- break;
- case 1:
- avp->flags |= (avp_flags_t)a->val[1].u.number;
- break;
- default:;
- }
- ret = (avp->flags & (avp_flags_t)a->val[1].u.number) != 0;
- }
- }
- if (ret==0)
- ret = -1;
- break;
- }
- case ERROR_T:
- if ((a->val[0].type!=STRING_ST)|(a->val[1].type!=STRING_ST)){
- LOG(L_CRIT, "BUG: do_action: bad error() types %d, %d\n",
- a->val[0].type, a->val[1].type);
- ret=E_BUG;
- break;
- }
- LOG(L_NOTICE, "WARNING: do_action: error(\"%s\", \"%s\") "
- "not implemented yet\n", a->val[0].u.string, a->val[1].u.string);
- ret=1;
- break;
- case ROUTE_T:
- if (a->val[0].type!=NUMBER_ST){
- LOG(L_CRIT, "BUG: do_action: bad route() type %d\n",
- a->val[0].type);
- ret=E_BUG;
- break;
- }
- if ((a->val[0].u.number>=main_rt.idx)||(a->val[0].u.number<0)){
- LOG(L_ERR, "ERROR: invalid routing table number in"
- "route(%lu)\n", a->val[0].u.number);
- ret=E_CFG;
- break;
- }
- /*ret=((ret=run_actions(rlist[a->val[0].u.number], msg))<0)?ret:1;*/
- ret=run_actions(h, main_rt.rlist[a->val[0].u.number], msg);
- h->last_retcode=ret;
- h->run_flags&=~RETURN_R_F; /* absorb returns */
- break;
- case EXEC_T:
- if (a->val[0].type!=STRING_ST){
- LOG(L_CRIT, "BUG: do_action: bad exec() type %d\n",
- a->val[0].type);
- ret=E_BUG;
- break;
- }
- LOG(L_NOTICE, "WARNING: exec(\"%s\") not fully implemented,"
- " using dumb version...\n", a->val[0].u.string);
- ret=system(a->val[0].u.string);
- if (ret!=0){
- LOG(L_NOTICE, "WARNING: exec() returned %d\n", ret);
- }
- ret=1;
- break;
- case REVERT_URI_T:
- if (msg->new_uri.s) {
- pkg_free(msg->new_uri.s);
- msg->new_uri.len=0;
- msg->new_uri.s=0;
- msg->parsed_uri_ok=0; /* invalidate current parsed uri*/
- };
- ret=1;
- break;
- case SET_HOST_T:
- case SET_HOSTPORT_T:
- case SET_HOSTPORTTRANS_T:
- case SET_USER_T:
- case SET_USERPASS_T:
- case SET_PORT_T:
- case SET_URI_T:
- case PREFIX_T:
- case STRIP_T:
- case STRIP_TAIL_T:
- case SET_USERPHONE_T:
- user=0;
- if (a->type==STRIP_T || a->type==STRIP_TAIL_T) {
- if (a->val[0].type!=NUMBER_ST) {
- LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
- a->val[0].type);
- ret=E_BUG;
- break;
- }
- } else if (a->type!=SET_USERPHONE_T) {
- if (a->val[0].type!=STRING_ST) {
- LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
- a->val[0].type);
- ret=E_BUG;
- break;
- }
- }
- if (a->type==SET_URI_T){
- if (msg->new_uri.s) {
- pkg_free(msg->new_uri.s);
- msg->new_uri.len=0;
- }
- msg->parsed_uri_ok=0;
- len=strlen(a->val[0].u.string);
- msg->new_uri.s=pkg_malloc(len+1);
- if (msg->new_uri.s==0){
- LOG(L_ERR, "ERROR: do_action: memory allocation"
- " failure\n");
- ret=E_OUT_OF_MEM;
- break;
- }
- memcpy(msg->new_uri.s, a->val[0].u.string, len);
- msg->new_uri.s[len]=0;
- msg->new_uri.len=len;
- ret=1;
- break;
- }
- if ((msg->parsed_uri_ok==0) || ((uri.flags & URI_SIP_USER_PHONE)!=0)) {
- if (msg->new_uri.s) {
- tmp=msg->new_uri.s;
- len=msg->new_uri.len;
- }else{
- tmp=msg->first_line.u.request.uri.s;
- len=msg->first_line.u.request.uri.len;
- }
- /* don't convert sip:user=phone to tel, otherwise we loose parameters */
- orig_p2t=phone2tel;
- phone2tel=0;
- msg->parsed_uri_ok=0;
- if (parse_uri(tmp, len, &uri)<0){
- phone2tel=orig_p2t;
- LOG(L_ERR, "ERROR: do_action: bad uri <%s>, dropping"
- " packet\n", tmp);
- ret=E_UNSPEC;
- break;
- }
- phone2tel=orig_p2t;
- } else {
- uri=msg->parsed_uri;
- }
- /* skip SET_USERPHONE_T action if the URI is already
- * a tel: or tels: URI, or contains the user=phone param */
- if ((a->type==SET_USERPHONE_T)
- && ((uri.type==TEL_URI_T) || (uri.type==TELS_URI_T)
- || ((uri.user_param_val.len==5) && (memcmp(uri.user_param_val.s, "phone", 5)==0)))
- ) {
- ret=1;
- break;
- }
- /* SET_PORT_T does not work with tel: URIs */
- if ((a->type==SET_PORT_T)
- && ((uri.type==TEL_URI_T) || (uri.type==TELS_URI_T))
- && ((uri.flags & URI_SIP_USER_PHONE)==0)
- ) {
- LOG(L_ERR, "ERROR: do_action: port number of a tel: URI cannot be set\n");
- ret=E_UNSPEC;
- break;
- }
- new_uri=pkg_malloc(MAX_URI_SIZE);
- if (new_uri==0){
- LOG(L_ERR, "ERROR: do_action: memory allocation "
- " failure\n");
- ret=E_OUT_OF_MEM;
- break;
- }
- end=new_uri+MAX_URI_SIZE;
- crt=new_uri;
- /* begin copying */
- /* Preserve the URI scheme unless the host part needs
- * to be rewritten, and the shceme is tel: or tels: */
- switch (uri.type) {
- case SIP_URI_T:
- len=s_sip.len;
- tmp=s_sip.s;
- break;
- case SIPS_URI_T:
- len=s_sips.len;
- tmp=s_sips.s;
- break;
- case TEL_URI_T:
- if ((uri.flags & URI_SIP_USER_PHONE)
- || (a->type==SET_HOST_T)
- || (a->type==SET_HOSTPORT_T)
- || (a->type==SET_HOSTPORTTRANS_T)
- ) {
- len=s_sip.len;
- tmp=s_sip.s;
- break;
- }
- len=s_tel.len;
- tmp=s_tel.s;
- break;
- case TELS_URI_T:
- if ((uri.flags & URI_SIP_USER_PHONE)
- || (a->type==SET_HOST_T)
- || (a->type==SET_HOSTPORT_T)
- || (a->type==SET_HOSTPORTTRANS_T)
- ) {
- len=s_sips.len;
- tmp=s_sips.s;
- break;
- }
- len=s_tels.len;
- tmp=s_tels.s;
- break;
- default:
- LOG(L_ERR, "ERROR: Unsupported URI scheme (%d), "
- "reverted to sip:\n",
- uri.type);
- len=s_sip.len;
- tmp=s_sip.s;
- }
- if(crt+len+1 /* colon */ >end) goto error_uri;
- memcpy(crt,tmp,len);crt+=len;
- *crt=':'; crt++;
- /* user */
- /* prefix (-jiri) */
- if (a->type==PREFIX_T) {
- tmp=a->val[0].u.string;
- len=strlen(tmp); if(crt+len>end) goto error_uri;
- memcpy(crt,tmp,len);crt+=len;
- /* whatever we had before, with prefix we have username
- now */
- user=1;
- }
- if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) {
- tmp=a->val[0].u.string;
- len=strlen(tmp);
- } else if (a->type==STRIP_T) {
- if (a->val[0].u.number>uri.user.len) {
- LOG(L_WARN, "Error: too long strip asked; "
- " deleting username: %lu of <%.*s>\n",
- a->val[0].u.number, uri.user.len, uri.user.s );
- len=0;
- } else if (a->val[0].u.number==uri.user.len) {
- len=0;
- } else {
- tmp=uri.user.s + a->val[0].u.number;
- len=uri.user.len - a->val[0].u.number;
- }
- } else if (a->type==STRIP_TAIL_T) {
- if (a->val[0].u.number>uri.user.len) {
- LOG(L_WARN, "WARNING: too long strip_tail asked; "
- " deleting username: %lu of <%.*s>\n",
- a->val[0].u.number, uri.user.len, uri.user.s );
- len=0;
- } else if (a->val[0].u.number==uri.user.len) {
- len=0;
- } else {
- tmp=uri.user.s;
- len=uri.user.len - a->val[0].u.number;
- }
- } else {
- tmp=uri.user.s;
- len=uri.user.len;
- }
- if (len){
- if(crt+len>end) goto error_uri;
- memcpy(crt,tmp,len);crt+=len;
- user=1; /* we have an user field so mark it */
- }
- if (a->type==SET_USERPASS_T) tmp=0;
- else tmp=uri.passwd.s;
- /* passwd */
- if (tmp){
- len=uri.passwd.len; if(crt+len+1>end) goto error_uri;
- *crt=':'; crt++;
- memcpy(crt,tmp,len);crt+=len;
- }
- /* host */
- if ((a->type==SET_HOST_T)
- || (a->type==SET_HOSTPORT_T)
- || (a->type==SET_HOSTPORTTRANS_T)
- ) {
- tmp=a->val[0].u.string;
- if (tmp) len = strlen(tmp);
- else len=0;
- } else if ((uri.type==SIP_URI_T)
- || (uri.type==SIPS_URI_T)
- || (uri.flags & URI_SIP_USER_PHONE)
- ) {
- tmp=uri.host.s;
- len=uri.host.len;
- } else {
- tmp=0;
- }
- if (tmp){
- if (user) { /* add @ */
- if(crt+1>end) goto error_uri;
- *crt='@'; crt++;
- }
- if(crt+len>end) goto error_uri;
- memcpy(crt,tmp,len);crt+=len;
- }
- /* port */
- if ((a->type==SET_HOSTPORT_T)
- || (a->type==SET_HOSTPORTTRANS_T))
- tmp=0;
- else if (a->type==SET_PORT_T) {
- tmp=a->val[0].u.string;
- if (tmp) len = strlen(tmp);
- else len = 0;
- } else {
- tmp=uri.port.s;
- len = uri.port.len;
- }
- if (tmp){
- if(crt+len+1>end) goto error_uri;
- *crt=':'; crt++;
- memcpy(crt,tmp,len);crt+=len;
- }
- /* params */
- if ((a->type==SET_HOSTPORTTRANS_T) && uri.transport.s) {
- /* bypass the transport parameter */
- if (uri.params.s < uri.transport.s) {
- /* there are parameters before transport */
- len = uri.transport.s - uri.params.s - 1;
- /* ignore the ';' at the end */
- if (crt+len+1>end) goto error_uri;
- *crt=';'; crt++;
- memcpy(crt,uri.params.s,len);crt+=len;
- }
- len = (uri.params.s + uri.params.len) -
- (uri.transport.s + uri.transport.len);
- if (len > 0) {
- /* there are parameters after transport */
- if (crt+len>end) goto error_uri;
- tmp = uri.transport.s + uri.transport.len;
- memcpy(crt,tmp,len);crt+=len;
- }
- } else {
- tmp=uri.params.s;
- if (tmp){
- len=uri.params.len; if(crt+len+1>end) goto error_uri;
- *crt=';'; crt++;
- memcpy(crt,tmp,len);crt+=len;
- }
- }
- /* Add the user=phone param if a tel: or tels:
- * URI was converted to sip: or sips:.
- * (host part of a tel/tels URI was set.)
- * Or in case of sip: URI and SET_USERPHONE_T action */
- if (((((uri.type==TEL_URI_T) || (uri.type==TELS_URI_T))
- && ((uri.flags & URI_SIP_USER_PHONE)==0))
- && ((a->type==SET_HOST_T)
- || (a->type==SET_HOSTPORT_T)
- || (a->type==SET_HOSTPORTTRANS_T)))
- || (a->type==SET_USERPHONE_T)
- ) {
- tmp=";user=phone";
- len=strlen(tmp);
- if(crt+len>end) goto error_uri;
- memcpy(crt,tmp,len);crt+=len;
- }
- /* headers */
- tmp=uri.headers.s;
- if (tmp){
- len=uri.headers.len; if(crt+len+1>end) goto error_uri;
- *crt='?'; crt++;
- memcpy(crt,tmp,len);crt+=len;
- }
- *crt=0; /* null terminate the thing */
- /* copy it to the msg */
- if (msg->new_uri.s) pkg_free(msg->new_uri.s);
- msg->new_uri.s=new_uri;
- msg->new_uri.len=crt-new_uri;
- msg->parsed_uri_ok=0;
- ret=1;
- break;
- case IF_T:
- /* if null expr => ignore if? */
- if ((a->val[0].type==EXPR_ST)&&a->val[0].u.data){
- v=eval_expr(h, (struct expr*)a->val[0].u.data, msg);
- #if 0
- if (v<0){
- if (v==EXPR_DROP){ /* hack to quit on DROP*/
- ret=0;
- break;
- }else{
- LOG(L_WARN,"WARNING: do_action:"
- "error in expression\n");
- }
- }
- #endif
- if (h->run_flags & EXIT_R_F){
- ret=0;
- break;
- }
- h->run_flags &= ~RETURN_R_F; /* catch returns in expr */
- ret=1; /*default is continue */
- if (v>0) {
- if ((a->val[1].type==ACTIONS_ST)&&a->val[1].u.data){
- ret=run_actions(h,
- (struct action*)a->val[1].u.data, msg);
- }
- }else if ((a->val[2].type==ACTIONS_ST)&&a->val[2].u.data){
- ret=run_actions(h,
- (struct action*)a->val[2].u.data, msg);
- }
- }
- break;
- case MODULE_T:
- if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && ((cmd_export_t*)a->val[0].u.data)->function ){
- ret=((cmd_export_t*)a->val[0].u.data)->function(msg,
- (char*)a->val[2].u.data,
- (char*)a->val[3].u.data
- );
- if (ret==0) h->run_flags|=EXIT_R_F;
- h->last_retcode=ret;
- } else {
- LOG(L_CRIT,"BUG: do_action: bad module call\n");
- }
- break;
- case FORCE_RPORT_T:
- msg->msg_flags|=FL_FORCE_RPORT;
- ret=1; /* continue processing */
- break;
- case UDP_MTU_TRY_PROTO_T:
- msg->msg_flags|= (unsigned int)a->val[0].u.number & FL_MTU_FB_MASK;
- ret=1; /* continue processing */
- break;
- case SET_ADV_ADDR_T:
- if (a->val[0].type!=STR_ST){
- LOG(L_CRIT, "BUG: do_action: bad set_advertised_address() "
- "type %d\n", a->val[0].type);
- ret=E_BUG;
- break;
- }
- msg->set_global_address=*((str*)a->val[0].u.data);
- ret=1; /* continue processing */
- break;
- case SET_ADV_PORT_T:
- if (a->val[0].type!=STR_ST){
- LOG(L_CRIT, "BUG: do_action: bad set_advertised_port() "
- "type %d\n", a->val[0].type);
- ret=E_BUG;
- break;
- }
- msg->set_global_port=*((str*)a->val[0].u.data);
- ret=1; /* continue processing */
- break;
- #ifdef USE_TCP
- case FORCE_TCP_ALIAS_T:
- if ( msg->rcv.proto==PROTO_TCP
- #ifdef USE_TLS
- || msg->rcv.proto==PROTO_TLS
- #endif
- ){
- if (a->val[0].type==NOSUBTYPE) port=msg->via1->port;
- else if (a->val[0].type==NUMBER_ST) port=(int)a->val[0].u.number;
- else{
- LOG(L_CRIT, "BUG: do_action: bad force_tcp_alias"
- " port type %d\n", a->val[0].type);
- ret=E_BUG;
- break;
- }
- if (tcpconn_add_alias(msg->rcv.proto_reserved1, port,
- msg->rcv.proto)!=0){
- LOG(L_ERR, " ERROR: receive_msg: tcp alias failed\n");
- ret=E_UNSPEC;
- break;
- }
- }
- #endif
- ret=1; /* continue processing */
- break;
- case FORCE_SEND_SOCKET_T:
- if (a->val[0].type!=SOCKETINFO_ST){
- LOG(L_CRIT, "BUG: do_action: bad force_send_socket argument"
- " type: %d\n", a->val[0].type);
- ret=E_BUG;
- break;
- }
- msg->force_send_socket=(struct socket_info*)a->val[0].u.data;
- ret=1; /* continue processing */
- break;
- case ADD_T:
- case ASSIGN_T:
- /* If the left attr was specified without indexing brackets delete
- * existing AVPs before adding new ones
- */
- if ((a->val[0].u.attr->type & AVP_INDEX_ALL) != AVP_INDEX_ALL) delete_avp(a->val[0].u.attr->type, a->val[0].u.attr->name);
- if (a->val[1].type == STRING_ST) {
- value.s = a->val[1].u.str;
- flags = a->val[0].u.attr->type | AVP_VAL_STR;
- name = a->val[0].u.attr->name;
- ret = 1;
- } else if (a->val[1].type == NUMBER_ST) {
- value.n = a->val[1].u.number;
- flags = a->val[0].u.attr->type;
- name = a->val[0].u.attr->name;
- ret = 1;
- } else if (a->val[1].type == ACTION_ST) {
- flags = a->val[0].u.attr->type;
- name = a->val[0].u.attr->name;
- if (a->val[1].u.data) {
- value.n = run_actions(h, (struct action*)a->val[1].u.data,
- msg);
- } else {
- value.n = -1;
- }
- ret = value.n;
- } else if(a->val[1].type == EXPR_ST && a->val[1].u.data) {
- v = eval_expr(h, (struct expr*)a->val[1].u.data, msg);
- if (v < 0) {
- if (v == EXPR_DROP){ /* hack to quit on DROP*/
- ret = 0;
- break;
- } else {
- LOG(L_WARN,"WARNING: do_action: error in expression\n");
- v = 0; /* error is treated as false (Miklos) */
- }
- }
- flags = a->val[0].u.attr->type;
- name = a->val[0].u.attr->name;
- value.n = v;
- } else if (a->val[1].type == AVP_ST) {
- struct search_state st;
- avp_t* avp;
- avp_t* avp_mark;
- avp_mark = NULL;
- if ((a->val[1].u.attr->type & AVP_INDEX_ALL) == AVP_INDEX_ALL) {
- avp = search_first_avp(a->val[1].u.attr->type, a->val[1].u.attr->name, &value, &st);
- while(avp) {
- /* We take only the type of value and name from the source avp
- * and reset class and track flags
- */
- flags = (a->val[0].u.attr->type & ~AVP_INDEX_ALL) | (avp->flags & ~(AVP_CLASS_ALL|AVP_TRACK_ALL));
- if (add_avp_before(avp_mark, flags, a->val[0].u.attr->name, value) < 0) {
- LOG(L_CRIT, "ERROR: Failed to assign value to attribute\n");
- ret=E_UNSPEC;
- break;
- }
- /* move the mark, so the next found AVP will come before the one currently added
- * so they will have the same order as in the source list
- */
- if (avp_mark) {
- avp_mark=avp_mark->next;
- } else {
- avp_mark=search_first_avp(flags, a->val[0].u.attr->name, NULL, NULL);
- }
- avp = search_next_avp(&st, &value);
- }
- ret = 1;
- break;
- } else {
- avp = search_avp_by_index(a->val[1].u.attr->type, a->val[1].u.attr->name, &value, a->val[1].u.attr->index);
- if (avp) {
- flags = a->val[0].u.attr->type | (avp->flags & ~(AVP_CLASS_ALL|AVP_TRACK_ALL));
- name = a->val[0].u.attr->name;
- ret = 1;
- } else {
- ret = E_UNSPEC;
- break;
- }
- }
- } else if (a->val[1].type == SELECT_ST) {
- int r;
- r = run_select(&value.s, a->val[1].u.select, msg);
- if (r < 0) {
- ret=E_UNSPEC;
- break;
- } else if (r > 0) {
- value.s.s = "";
- value.s.len = 0;
- }
- flags = a->val[0].u.attr->type | AVP_VAL_STR;
- name = a->val[0].u.attr->name;
- ret = 1;
- } else {
- LOG(L_CRIT, "BUG: do_action: Bad right side of avp assignment\n");
- ret=E_BUG;
- break;
- }
- /* If the action is assign then remove the old avp value
- * before adding new ones */
- /* if ((unsigned char)a->type == ASSIGN_T) delete_avp(flags, name); */
- if (add_avp(flags & ~AVP_INDEX_ALL, name, value) < 0) {
- LOG(L_CRIT, "ERROR: Failed to assign value to attribute\n");
- ret=E_UNSPEC;
- break;
- }
- break;
- default:
- LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);
- }
- /*skip:*/
- return ret;
- error_uri:
- LOG(L_ERR, "ERROR: do_action: set*: uri too long\n");
- if (new_uri) pkg_free(new_uri);
- return E_UNSPEC;
- error_fwd_uri:
- /*free_uri(&uri); -- not needed anymore, using msg->parsed_uri*/
- return ret;
- }
- /* returns: 0, or 1 on success, <0 on error */
- /* (0 if drop or break encountered, 1 if not ) */
- int run_actions(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
- {
- struct action* t;
- int ret;
- struct sr_module *mod;
- ret=E_UNSPEC;
- h->rec_lev++;
- if (h->rec_lev>ROUTE_MAX_REC_LEV){
- LOG(L_ERR, "WARNING: too many recursive routing table lookups (%d)"
- " giving up!\n", h->rec_lev);
- ret=E_UNSPEC;
- goto error;
- }
- if (h->rec_lev==1){
- h->run_flags=0;
- h->last_retcode=0;
- #ifdef USE_LONGJMP
- if (setjmp(h->jmp_env)){
- h->rec_lev=0;
- ret=h->last_retcode;
- goto end;
- }
- #endif
- }
- if (a==0){
- DBG("DEBUG: run_actions: null action list (rec_level=%d)\n",
- h->rec_lev);
- ret=1;
- }
- for (t=a; t!=0; t=t->next){
- ret=do_action(h, t, msg);
- if (h->run_flags & (RETURN_R_F|EXIT_R_F)){
- if (h->run_flags & EXIT_R_F){
- #ifdef USE_LONGJMP
- h->last_retcode=ret;
- longjmp(h->jmp_env, ret);
- #endif
- }
- break;
- }
- /* ignore error returns */
- }
- h->rec_lev--;
- end:
- /* process module onbreak handlers if present */
- if (h->rec_lev==0 && ret==0)
- for (mod=modules;mod;mod=mod->next)
- if (mod->exports && mod->exports->onbreak_f) {
- mod->exports->onbreak_f( msg );
- DBG("DEBUG: %s onbreak handler called\n", mod->exports->name);
- }
- return ret;
- error:
- h->rec_lev--;
- return ret;
- }
|