5 * Copyright (C) 2001-2003 FhG Fokus
7 * This file is part of ser, a free SIP server.
9 * ser is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version
14 * For a license to use the ser software under conditions
15 * other than those described here, or to purchase support for this
16 * software, please contact iptel.org by e-mail at the following addresses:
19 * ser is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 * 2003-02-28 scratchpad compatibility abandoned (jiri)
31 * 2003-01-29 removed scratchpad (jiri)
32 * 2003-03-19 fixed set* len calculation bug & simplified a little the code
33 * (should be a little faster now) (andrei)
34 * replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
35 * 2003-04-01 Added support for loose routing in forward (janakj)
36 * 2003-04-12 FORCE_RPORT_T added (andrei)
37 * 2003-04-22 strip_tail added (jiri)
38 * 2003-10-02 added SET_ADV_ADDR_T & SET_ADV_PORT_T (andrei)
39 * 2003-10-29 added FORCE_TCP_ALIAS_T (andrei)
40 * 2004-11-30 added FORCE_SEND_SOCKET_T (andrei)
41 * 2005-12-12 return & drop/exit differentiation (andrei)
42 * 2005-12-19 select framework (mma)
43 * 2006-04-12 updated *_send() calls to use a struct dest_info (andrei)
44 * 2006-07-27 dns cache and dns based send address failover support (andrei)
45 * 2006-12-06 on popular request last_retcode set also by module functions
47 * 2007-06-14 run_actions & do_action need a ctx or handle now, no more
48 * static vars (andrei)
49 * 2008-12-17 added UDP_MTU_TRY_PROTO_T (andrei)
53 #include "comp_defs.h"
61 #include "udp_server.h"
63 #include "parser/msg_parser.h"
64 #include "parser/parse_uri.h"
66 #include "sr_module.h"
73 #include "tcp_server.h"
76 #include "sctp_server.h"
79 #include <sys/types.h>
80 #include <sys/socket.h>
83 #include <netinet/in.h>
84 #include <arpa/inet.h>
93 struct onsend_info* p_onsend=0; /* onsend route send info */
95 /* ret= 0! if action -> end of list(e.g DROP),
96 > 0 to continue processing next actions
98 int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
102 struct dest_info dst;
104 char *new_uri, *end, *crt;
107 struct sip_uri uri, next_hop;
110 unsigned short flags;
115 /* reset the value of error to E_UNSPEC so avoid unknowledgable
116 functions to return with error (status<0) and not setting it
117 leaving there previous error; cache the previous value though
118 for functions which want to process it */
119 prev_ser_error=ser_error;
123 switch ((unsigned char)a->type){
125 if (a->val[0].type==RETCODE_ST)
128 ret=(int) a->val[0].u.number;
129 h->run_flags|=(unsigned int)a->val[1].u.number;
143 init_dest_info(&dst);
144 if (a->type==FORWARD_UDP_T) dst.proto=PROTO_UDP;
146 else if (a->type==FORWARD_TCP_T) dst.proto= PROTO_TCP;
149 else if (a->type==FORWARD_TLS_T) dst.proto= PROTO_TLS;
152 else if (a->type==FORWARD_SCTP_T) dst.proto=PROTO_SCTP;
154 else dst.proto=PROTO_NONE;
155 if (a->val[0].type==URIHOST_ST){
158 if (msg->dst_uri.len) {
159 ret = parse_uri(msg->dst_uri.s, msg->dst_uri.len,
163 ret = parse_sip_msg_uri(msg);
164 u = &msg->parsed_uri;
168 LOG(L_ERR, "ERROR: do_action: forward: bad_uri "
169 " dropping packet\n");
173 switch (a->val[1].type){
178 port=a->val[1].u.number;
181 LOG(L_CRIT, "BUG: do_action bad forward 2nd"
182 " param type (%d)\n", a->val[1].type);
186 if (dst.proto == PROTO_NONE){ /* only if proto not set get it
190 /*dst.proto=PROTO_UDP; */
191 /* no proto, try to get it from the dns */
206 LOG(L_ERR,"ERROR: do action: forward: bad uri"
207 " transport %d\n", u->proto);
212 if (u->type==SIPS_URI_T){
213 if (u->proto==PROTO_UDP){
214 LOG(L_ERR, "ERROR: do_action: forward: secure uri"
215 " incompatible with transport %d\n",
226 if (u->maddr_val.s && u->maddr_val.len)
227 dst_host=&u->maddr_val;
234 ret=forward_request(msg, dst_host, port, &dst);
238 }else if ((a->val[0].type==PROXY_ST) && (a->val[1].type==NUMBER_ST)){
239 if (dst.proto==PROTO_NONE)
240 dst.proto=msg->rcv.proto;
241 proxy2su(&dst.to, (struct proxy_l*)a->val[0].u.data);
242 ret=forward_request(msg, 0, 0, &dst);
245 proxy_mark((struct proxy_l*)a->val[0].u.data, ret);
246 }else if (ser_error!=E_OK){
247 proxy_mark((struct proxy_l*)a->val[0].u.data, ret);
250 LOG(L_CRIT, "BUG: do_action: bad forward() types %d, %d\n",
251 a->val[0].type, a->val[1].type);
257 if ((a->val[0].type!= PROXY_ST)|(a->val[1].type!=NUMBER_ST)){
258 LOG(L_CRIT, "BUG: do_action: bad send() types %d, %d\n",
259 a->val[0].type, a->val[1].type);
264 init_dest_info(&dst);
265 ret=proxy2su(&dst.to, (struct proxy_l*)a->val[0].u.data);
274 if (a->type==SEND_T){
276 dst.proto=PROTO_UDP; /* not really needed for udp_send */
277 dst.send_sock=get_send_socket(msg, &dst.to, PROTO_UDP);
278 if (dst.send_sock!=0){
279 ret=udp_send(&dst, tmp, len);
289 ret=tcp_send(&dst, 0, tmp, len);
296 proxy_mark((struct proxy_l*)a->val[0].u.data, ret);
301 if ((a->val[0].type!=NUMBER_ST)|(a->val[1].type!=STRING_ST)){
302 LOG(L_CRIT, "BUG: do_action: bad log() types %d, %d\n",
303 a->val[0].type, a->val[1].type);
307 LOG_(a->val[0].u.number, "<script>: ", "%s", a->val[1].u.string);
311 /* jku -- introduce a new branch */
312 case APPEND_BRANCH_T:
313 if ((a->val[0].type!=STRING_ST)) {
314 LOG(L_CRIT, "BUG: do_action: bad append_branch_t %d\n",
319 ret=append_branch( msg, a->val[0].u.string,
320 a->val[0].u.string ? strlen(a->val[0].u.string):0,
321 0, 0, a->val[1].u.number, 0);
324 /* jku begin: is_length_greater_than */
326 if (a->val[0].type!=NUMBER_ST) {
327 LOG(L_CRIT, "BUG: do_action: bad len_gt type %d\n",
332 /* DBG("XXX: message length %d, max %d\n",
333 msg->len, a->val[0].u.number ); */
334 ret = msg->len >= a->val[0].u.number ? 1 : -1;
336 /* jku end: is_length_greater_than */
338 /* jku - begin : flag processing */
341 if (a->val[0].type!=NUMBER_ST) {
342 LOG(L_CRIT, "BUG: do_action: bad setflag() type %d\n",
347 if (!flag_in_range( a->val[0].u.number )) {
351 setflag( msg, a->val[0].u.number );
356 if (a->val[0].type!=NUMBER_ST) {
357 LOG(L_CRIT, "BUG: do_action: bad resetflag() type %d\n",
362 if (!flag_in_range( a->val[0].u.number )) {
366 resetflag( msg, a->val[0].u.number );
371 if (a->val[0].type!=NUMBER_ST) {
372 LOG(L_CRIT, "BUG: do_action: bad isflagset() type %d\n",
377 if (!flag_in_range( a->val[0].u.number )) {
381 ret=isflagset( msg, a->val[0].u.number );
383 /* jku - end : flag processing */
385 case AVPFLAG_OPER_T: {
386 struct search_state st;
390 flag = a->val[1].u.number;
391 if ((a->val[0].u.attr->type & AVP_INDEX_ALL) == AVP_INDEX_ALL || (a->val[0].u.attr->type & AVP_NAME_RE)!=0) {
392 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)) {
393 switch (a->val[2].u.number) { /* oper: 0..reset, 1..set, -1..no change */
395 avp->flags &= ~(avp_flags_t)a->val[1].u.number;
398 avp->flags |= (avp_flags_t)a->val[1].u.number;
402 ret = ret || ((avp->flags & (avp_flags_t)a->val[1].u.number) != 0);
406 avp = search_avp_by_index(a->val[0].u.attr->type, a->val[0].u.attr->name, NULL, a->val[0].u.attr->index);
408 switch (a->val[2].u.number) { /* oper: 0..reset, 1..set, -1..no change */
410 avp->flags &= ~(avp_flags_t)a->val[1].u.number;
413 avp->flags |= (avp_flags_t)a->val[1].u.number;
417 ret = (avp->flags & (avp_flags_t)a->val[1].u.number) != 0;
425 if ((a->val[0].type!=STRING_ST)|(a->val[1].type!=STRING_ST)){
426 LOG(L_CRIT, "BUG: do_action: bad error() types %d, %d\n",
427 a->val[0].type, a->val[1].type);
431 LOG(L_NOTICE, "WARNING: do_action: error(\"%s\", \"%s\") "
432 "not implemented yet\n", a->val[0].u.string, a->val[1].u.string);
436 if (a->val[0].type!=NUMBER_ST){
437 LOG(L_CRIT, "BUG: do_action: bad route() type %d\n",
442 if ((a->val[0].u.number>=main_rt.idx)||(a->val[0].u.number<0)){
443 LOG(L_ERR, "ERROR: invalid routing table number in"
444 "route(%lu)\n", a->val[0].u.number);
448 /*ret=((ret=run_actions(rlist[a->val[0].u.number], msg))<0)?ret:1;*/
449 ret=run_actions(h, main_rt.rlist[a->val[0].u.number], msg);
451 h->run_flags&=~RETURN_R_F; /* absorb returns */
454 if (a->val[0].type!=STRING_ST){
455 LOG(L_CRIT, "BUG: do_action: bad exec() type %d\n",
460 LOG(L_NOTICE, "WARNING: exec(\"%s\") not fully implemented,"
461 " using dumb version...\n", a->val[0].u.string);
462 ret=system(a->val[0].u.string);
464 LOG(L_NOTICE, "WARNING: exec() returned %d\n", ret);
469 if (msg->new_uri.s) {
470 pkg_free(msg->new_uri.s);
473 msg->parsed_uri_ok=0; /* invalidate current parsed uri*/
479 case SET_HOSTPORTTRANS_T:
487 case SET_USERPHONE_T:
489 if (a->type==STRIP_T || a->type==STRIP_TAIL_T) {
490 if (a->val[0].type!=NUMBER_ST) {
491 LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
496 } else if (a->type!=SET_USERPHONE_T) {
497 if (a->val[0].type!=STRING_ST) {
498 LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
504 if (a->type==SET_URI_T){
505 if (msg->new_uri.s) {
506 pkg_free(msg->new_uri.s);
509 msg->parsed_uri_ok=0;
510 len=strlen(a->val[0].u.string);
511 msg->new_uri.s=pkg_malloc(len+1);
512 if (msg->new_uri.s==0){
513 LOG(L_ERR, "ERROR: do_action: memory allocation"
518 memcpy(msg->new_uri.s, a->val[0].u.string, len);
519 msg->new_uri.s[len]=0;
520 msg->new_uri.len=len;
525 if ((msg->parsed_uri_ok==0) || ((uri.flags & URI_SIP_USER_PHONE)!=0)) {
526 if (msg->new_uri.s) {
528 len=msg->new_uri.len;
530 tmp=msg->first_line.u.request.uri.s;
531 len=msg->first_line.u.request.uri.len;
533 /* don't convert sip:user=phone to tel, otherwise we loose parameters */
536 msg->parsed_uri_ok=0;
537 if (parse_uri(tmp, len, &uri)<0){
539 LOG(L_ERR, "ERROR: do_action: bad uri <%s>, dropping"
549 /* skip SET_USERPHONE_T action if the URI is already
550 * a tel: or tels: URI, or contains the user=phone param */
551 if ((a->type==SET_USERPHONE_T)
552 && ((uri.type==TEL_URI_T) || (uri.type==TELS_URI_T)
553 || ((uri.user_param_val.len==5) && (memcmp(uri.user_param_val.s, "phone", 5)==0)))
558 /* SET_PORT_T does not work with tel: URIs */
559 if ((a->type==SET_PORT_T)
560 && ((uri.type==TEL_URI_T) || (uri.type==TELS_URI_T))
561 && ((uri.flags & URI_SIP_USER_PHONE)==0)
563 LOG(L_ERR, "ERROR: do_action: port number of a tel: URI cannot be set\n");
568 new_uri=pkg_malloc(MAX_URI_SIZE);
570 LOG(L_ERR, "ERROR: do_action: memory allocation "
575 end=new_uri+MAX_URI_SIZE;
578 /* Preserve the URI scheme unless the host part needs
579 * to be rewritten, and the shceme is tel: or tels: */
592 if ((uri.flags & URI_SIP_USER_PHONE)
593 || (a->type==SET_HOST_T)
594 || (a->type==SET_HOSTPORT_T)
595 || (a->type==SET_HOSTPORTTRANS_T)
606 if ((uri.flags & URI_SIP_USER_PHONE)
607 || (a->type==SET_HOST_T)
608 || (a->type==SET_HOSTPORT_T)
609 || (a->type==SET_HOSTPORTTRANS_T)
620 LOG(L_ERR, "ERROR: Unsupported URI scheme (%d), "
621 "reverted to sip:\n",
626 if(crt+len+1 /* colon */ >end) goto error_uri;
627 memcpy(crt,tmp,len);crt+=len;
633 if (a->type==PREFIX_T) {
634 tmp=a->val[0].u.string;
635 len=strlen(tmp); if(crt+len>end) goto error_uri;
636 memcpy(crt,tmp,len);crt+=len;
637 /* whatever we had before, with prefix we have username
642 if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) {
643 tmp=a->val[0].u.string;
645 } else if (a->type==STRIP_T) {
646 if (a->val[0].u.number>uri.user.len) {
647 LOG(L_WARN, "Error: too long strip asked; "
648 " deleting username: %lu of <%.*s>\n",
649 a->val[0].u.number, uri.user.len, uri.user.s );
651 } else if (a->val[0].u.number==uri.user.len) {
654 tmp=uri.user.s + a->val[0].u.number;
655 len=uri.user.len - a->val[0].u.number;
657 } else if (a->type==STRIP_TAIL_T) {
658 if (a->val[0].u.number>uri.user.len) {
659 LOG(L_WARN, "WARNING: too long strip_tail asked; "
660 " deleting username: %lu of <%.*s>\n",
661 a->val[0].u.number, uri.user.len, uri.user.s );
663 } else if (a->val[0].u.number==uri.user.len) {
667 len=uri.user.len - a->val[0].u.number;
675 if(crt+len>end) goto error_uri;
676 memcpy(crt,tmp,len);crt+=len;
677 user=1; /* we have an user field so mark it */
680 if (a->type==SET_USERPASS_T) tmp=0;
681 else tmp=uri.passwd.s;
684 len=uri.passwd.len; if(crt+len+1>end) goto error_uri;
686 memcpy(crt,tmp,len);crt+=len;
689 if ((a->type==SET_HOST_T)
690 || (a->type==SET_HOSTPORT_T)
691 || (a->type==SET_HOSTPORTTRANS_T)
693 tmp=a->val[0].u.string;
694 if (tmp) len = strlen(tmp);
696 } else if ((uri.type==SIP_URI_T)
697 || (uri.type==SIPS_URI_T)
698 || (uri.flags & URI_SIP_USER_PHONE)
706 if (user) { /* add @ */
707 if(crt+1>end) goto error_uri;
710 if(crt+len>end) goto error_uri;
711 memcpy(crt,tmp,len);crt+=len;
714 if ((a->type==SET_HOSTPORT_T)
715 || (a->type==SET_HOSTPORTTRANS_T))
717 else if (a->type==SET_PORT_T) {
718 tmp=a->val[0].u.string;
719 if (tmp) len = strlen(tmp);
726 if(crt+len+1>end) goto error_uri;
728 memcpy(crt,tmp,len);crt+=len;
731 if ((a->type==SET_HOSTPORTTRANS_T) && uri.transport.s) {
732 /* bypass the transport parameter */
733 if (uri.params.s < uri.transport.s) {
734 /* there are parameters before transport */
735 len = uri.transport.s - uri.params.s - 1;
736 /* ignore the ';' at the end */
737 if (crt+len+1>end) goto error_uri;
739 memcpy(crt,uri.params.s,len);crt+=len;
741 len = (uri.params.s + uri.params.len) -
742 (uri.transport.s + uri.transport.len);
744 /* there are parameters after transport */
745 if (crt+len>end) goto error_uri;
746 tmp = uri.transport.s + uri.transport.len;
747 memcpy(crt,tmp,len);crt+=len;
752 len=uri.params.len; if(crt+len+1>end) goto error_uri;
754 memcpy(crt,tmp,len);crt+=len;
757 /* Add the user=phone param if a tel: or tels:
758 * URI was converted to sip: or sips:.
759 * (host part of a tel/tels URI was set.)
760 * Or in case of sip: URI and SET_USERPHONE_T action */
761 if (((((uri.type==TEL_URI_T) || (uri.type==TELS_URI_T))
762 && ((uri.flags & URI_SIP_USER_PHONE)==0))
763 && ((a->type==SET_HOST_T)
764 || (a->type==SET_HOSTPORT_T)
765 || (a->type==SET_HOSTPORTTRANS_T)))
766 || (a->type==SET_USERPHONE_T)
770 if(crt+len>end) goto error_uri;
771 memcpy(crt,tmp,len);crt+=len;
776 len=uri.headers.len; if(crt+len+1>end) goto error_uri;
778 memcpy(crt,tmp,len);crt+=len;
780 *crt=0; /* null terminate the thing */
781 /* copy it to the msg */
782 if (msg->new_uri.s) pkg_free(msg->new_uri.s);
783 msg->new_uri.s=new_uri;
784 msg->new_uri.len=crt-new_uri;
785 msg->parsed_uri_ok=0;
789 /* if null expr => ignore if? */
790 if ((a->val[0].type==EXPR_ST)&&a->val[0].u.data){
791 v=eval_expr(h, (struct expr*)a->val[0].u.data, msg);
794 if (v==EXPR_DROP){ /* hack to quit on DROP*/
798 LOG(L_WARN,"WARNING: do_action:"
799 "error in expression\n");
803 if (h->run_flags & EXIT_R_F){
807 h->run_flags &= ~RETURN_R_F; /* catch returns in expr */
808 ret=1; /*default is continue */
810 if ((a->val[1].type==ACTIONS_ST)&&a->val[1].u.data){
812 (struct action*)a->val[1].u.data, msg);
814 }else if ((a->val[2].type==ACTIONS_ST)&&a->val[2].u.data){
816 (struct action*)a->val[2].u.data, msg);
821 if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && ((cmd_export_t*)a->val[0].u.data)->function ){
822 ret=((cmd_export_t*)a->val[0].u.data)->function(msg,
823 (char*)a->val[2].u.data,
824 (char*)a->val[3].u.data
826 if (ret==0) h->run_flags|=EXIT_R_F;
829 LOG(L_CRIT,"BUG: do_action: bad module call\n");
833 msg->msg_flags|=FL_FORCE_RPORT;
834 ret=1; /* continue processing */
836 case UDP_MTU_TRY_PROTO_T:
837 msg->msg_flags|= (unsigned int)a->val[0].u.number & FL_MTU_FB_MASK;
838 ret=1; /* continue processing */
841 if (a->val[0].type!=STR_ST){
842 LOG(L_CRIT, "BUG: do_action: bad set_advertised_address() "
843 "type %d\n", a->val[0].type);
847 msg->set_global_address=*((str*)a->val[0].u.data);
848 ret=1; /* continue processing */
851 if (a->val[0].type!=STR_ST){
852 LOG(L_CRIT, "BUG: do_action: bad set_advertised_port() "
853 "type %d\n", a->val[0].type);
857 msg->set_global_port=*((str*)a->val[0].u.data);
858 ret=1; /* continue processing */
861 case FORCE_TCP_ALIAS_T:
862 if ( msg->rcv.proto==PROTO_TCP
864 || msg->rcv.proto==PROTO_TLS
868 if (a->val[0].type==NOSUBTYPE) port=msg->via1->port;
869 else if (a->val[0].type==NUMBER_ST) port=(int)a->val[0].u.number;
871 LOG(L_CRIT, "BUG: do_action: bad force_tcp_alias"
872 " port type %d\n", a->val[0].type);
877 if (tcpconn_add_alias(msg->rcv.proto_reserved1, port,
879 LOG(L_ERR, " ERROR: receive_msg: tcp alias failed\n");
885 ret=1; /* continue processing */
887 case FORCE_SEND_SOCKET_T:
888 if (a->val[0].type!=SOCKETINFO_ST){
889 LOG(L_CRIT, "BUG: do_action: bad force_send_socket argument"
890 " type: %d\n", a->val[0].type);
894 msg->force_send_socket=(struct socket_info*)a->val[0].u.data;
895 ret=1; /* continue processing */
901 /* If the left attr was specified without indexing brackets delete
902 * existing AVPs before adding new ones
904 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);
906 if (a->val[1].type == STRING_ST) {
907 value.s = a->val[1].u.str;
908 flags = a->val[0].u.attr->type | AVP_VAL_STR;
909 name = a->val[0].u.attr->name;
911 } else if (a->val[1].type == NUMBER_ST) {
912 value.n = a->val[1].u.number;
913 flags = a->val[0].u.attr->type;
914 name = a->val[0].u.attr->name;
916 } else if (a->val[1].type == ACTION_ST) {
917 flags = a->val[0].u.attr->type;
918 name = a->val[0].u.attr->name;
919 if (a->val[1].u.data) {
920 value.n = run_actions(h, (struct action*)a->val[1].u.data,
926 } else if(a->val[1].type == EXPR_ST && a->val[1].u.data) {
927 v = eval_expr(h, (struct expr*)a->val[1].u.data, msg);
929 if (v == EXPR_DROP){ /* hack to quit on DROP*/
933 LOG(L_WARN,"WARNING: do_action: error in expression\n");
934 v = 0; /* error is treated as false (Miklos) */
938 flags = a->val[0].u.attr->type;
939 name = a->val[0].u.attr->name;
941 } else if (a->val[1].type == AVP_ST) {
942 struct search_state st;
947 if ((a->val[1].u.attr->type & AVP_INDEX_ALL) == AVP_INDEX_ALL) {
948 avp = search_first_avp(a->val[1].u.attr->type, a->val[1].u.attr->name, &value, &st);
950 /* We take only the type of value and name from the source avp
951 * and reset class and track flags
953 flags = (a->val[0].u.attr->type & ~AVP_INDEX_ALL) | (avp->flags & ~(AVP_CLASS_ALL|AVP_TRACK_ALL));
955 if (add_avp_before(avp_mark, flags, a->val[0].u.attr->name, value) < 0) {
956 LOG(L_CRIT, "ERROR: Failed to assign value to attribute\n");
961 /* move the mark, so the next found AVP will come before the one currently added
962 * so they will have the same order as in the source list
965 avp_mark=avp_mark->next;
967 avp_mark=search_first_avp(flags, a->val[0].u.attr->name, NULL, NULL);
970 avp = search_next_avp(&st, &value);
975 avp = search_avp_by_index(a->val[1].u.attr->type, a->val[1].u.attr->name, &value, a->val[1].u.attr->index);
977 flags = a->val[0].u.attr->type | (avp->flags & ~(AVP_CLASS_ALL|AVP_TRACK_ALL));
978 name = a->val[0].u.attr->name;
985 } else if (a->val[1].type == SELECT_ST) {
987 r = run_select(&value.s, a->val[1].u.select, msg);
996 flags = a->val[0].u.attr->type | AVP_VAL_STR;
997 name = a->val[0].u.attr->name;
1000 LOG(L_CRIT, "BUG: do_action: Bad right side of avp assignment\n");
1005 /* If the action is assign then remove the old avp value
1006 * before adding new ones */
1007 /* if ((unsigned char)a->type == ASSIGN_T) delete_avp(flags, name); */
1008 if (add_avp(flags & ~AVP_INDEX_ALL, name, value) < 0) {
1009 LOG(L_CRIT, "ERROR: Failed to assign value to attribute\n");
1016 LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);
1022 LOG(L_ERR, "ERROR: do_action: set*: uri too long\n");
1023 if (new_uri) pkg_free(new_uri);
1026 /*free_uri(&uri); -- not needed anymore, using msg->parsed_uri*/
1032 /* returns: 0, or 1 on success, <0 on error */
1033 /* (0 if drop or break encountered, 1 if not ) */
1034 int run_actions(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
1038 struct sr_module *mod;
1042 if (h->rec_lev>ROUTE_MAX_REC_LEV){
1043 LOG(L_ERR, "WARNING: too many recursive routing table lookups (%d)"
1044 " giving up!\n", h->rec_lev);
1052 if (setjmp(h->jmp_env)){
1054 ret=h->last_retcode;
1061 DBG("DEBUG: run_actions: null action list (rec_level=%d)\n",
1066 for (t=a; t!=0; t=t->next){
1067 ret=do_action(h, t, msg);
1068 if (h->run_flags & (RETURN_R_F|EXIT_R_F)){
1069 if (h->run_flags & EXIT_R_F){
1071 h->last_retcode=ret;
1072 longjmp(h->jmp_env, ret);
1077 /* ignore error returns */
1082 /* process module onbreak handlers if present */
1083 if (h->rec_lev==0 && ret==0)
1084 for (mod=modules;mod;mod=mod->next)
1085 if (mod->exports && mod->exports->onbreak_f) {
1086 mod->exports->onbreak_f( msg );
1087 DBG("DEBUG: %s onbreak handler called\n", mod->exports->name);