modules_s/avp/avp.c

00001 /*
00002  * $Id$
00003  *
00004  * Copyright (C) 2004 FhG Fokus
00005  *
00006  * This file is part of ser, a free SIP server.
00007  *
00008  * ser is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * For a license to use the ser software under conditions
00014  * other than those described here, or to purchase support for this
00015  * software, please contact iptel.org by e-mail at the following addresses:
00016  *    info@iptel.org
00017  *
00018  * ser is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  * GNU General Public License for more details.
00022  *
00023  * You should have received a copy of the GNU General Public License
00024  * along with this program; if not, write to the Free Software
00025  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00026  */
00027 
00028 /*
00029  *  2005-03-28  avp_destination & xlset_destination - handle both nameaddr & uri texts (mma)
00030  *  2005-12-22  merge changes from private branch (mma)
00031  *  2006-01-03  avp_body merged (mma)
00032  */
00033 
00034 #include <string.h>
00035 #include <stdlib.h>
00036 #ifdef EXTRA_DEBUG
00037 #include <assert.h>
00038 #endif
00039 #include "../../sr_module.h"
00040 #include "../../error.h"
00041 #include "../../lump_struct.h"
00042 #include "../../data_lump.h"
00043 #include "../../data_lump_rpl.h"
00044 #include "../../usr_avp.h"
00045 #include "../../mem/mem.h"
00046 #include "../../parser/parse_uri.h"
00047 #include "../../parser/msg_parser.h"
00048 #include "../../parser/parse_nameaddr.h"
00049 #include "../../ut.h"
00050 #include "../../dset.h"
00051 #include "../../trim.h"
00052 #include "../../str.h"
00053 #include "../../dprint.h"
00054 #include "../../re.h"
00055 #include "../../action.h"
00056 
00057 #include "../../parser/parse_hname2.h"
00058 #include "../xlog/xl_lib.h"
00059 #define NO_SCRIPT -1
00060 
00061 MODULE_VERSION
00062 
00063 /* name of attributed used to store flags with command flags2attr */
00064 #define HDR_ID 0
00065 #define HDR_STR 1
00066 
00067 #define PARAM_DELIM '/'
00068 #define VAL_TYPE_INT (1<<0)
00069 #define VAL_TYPE_STR (1<<1)
00070 
00071 struct hdr_name {
00072         enum {hdrId, hdrStr} kind;
00073         union {
00074                 int n;
00075                 str s;
00076         } name;
00077         char field_delimiter;
00078         char array_delimiter;
00079         int val_types;
00080 };
00081 
00082 static int xlbuf_size=256;
00083 static char* xlbuf=NULL;
00084 static str* xl_nul=NULL;
00085 static xl_print_log_f* xl_print=NULL;
00086 static xl_parse_format_f* xl_parse=NULL;
00087 static xl_elog_free_all_f* xl_free=NULL;
00088 static xl_get_nulstr_f* xl_getnul=NULL;
00089 
00090 static int mod_init();
00091 static int set_iattr(struct sip_msg* msg, char* p1, char* p2);
00092 static int set_sattr(struct sip_msg* msg, char* p1, char* p2);
00093 static int print_attr(struct sip_msg* msg, char* p1, char* p2);
00094 static int del_attr(struct sip_msg* msg, char* p1, char* p2);
00095 static int subst_attr(struct sip_msg* msg, char* p1, char* p2);
00096 static int flags2attr(struct sip_msg* msg, char* p1, char* p2);
00097 static int attr2uri(struct sip_msg* msg, char* p1, char* p2);
00098 static int dump_attrs(struct sip_msg* msg, char* p1, char* p2);
00099 static int attr_equals(struct sip_msg* msg, char* p1, char* p2);
00100 static int attr_exists(struct sip_msg* msg, char* p1, char* p2);
00101 static int attr_equals_xl(struct sip_msg* msg, char* p1, char* p2);
00102 static int xlset_attr(struct sip_msg* msg, char* p1, char* p2);
00103 static int xlfix_attr(struct sip_msg* msg, char* p1, char* p2);
00104 static int insert_req(struct sip_msg* msg, char* p1, char* p2);
00105 static int append_req(struct sip_msg* msg, char* p1, char* p2);
00106 static int replace_req(struct sip_msg* msg, char* p1, char* p2);
00107 static int append_reply(struct sip_msg* msg, char* p1, char* p2);
00108 static int attr_destination(struct sip_msg* msg, char* p1, char* p2);
00109 static int xlset_destination(struct sip_msg* msg, char* p1, char* p2);
00110 static int attr_hdr_body2attrs(struct sip_msg* msg, char* p1, char* p2);
00111 static int attr_hdr_body2attrs2(struct sip_msg* msg, char* p1, char* p2);
00112 static int del_attrs(struct sip_msg* msg, char* p1, char* p2);
00113 
00114 static int set_iattr_fixup(void**, int);
00115 static int avpid_fixup(void**, int);
00116 static int subst_attr_fixup(void**, int);
00117 static int fixup_part(void**, int);
00118 static int fixup_xl_1(void**, int);
00119 static int fixup_attr_1_xl_2(void**, int);
00120 static int fixup_str_1_attr_2(void**, int);
00121 static int xlfix_attr_fixup(void** param, int param_no);
00122 static int attr_hdr_body2attrs_fixup(void**, int);
00123 static int attr_hdr_body2attrs2_fixup(void**, int);
00124 static int avpgroup_fixup(void**, int);
00125 
00126 /*
00127  * Exported functions
00128  */
00129 static cmd_export_t cmds[] = {
00130     {"set_iattr",         set_iattr,            2, set_iattr_fixup,            REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
00131     {"set_sattr",         set_sattr,            2, fixup_var_str_12,           REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
00132     {"set_attr",          set_sattr,            2, fixup_var_str_12,           REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
00133     {"print_attr",        print_attr,           1, avpid_fixup,                REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
00134     {"del_attr",          del_attr,             1, avpid_fixup,                REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE}, 
00135     {"del_attrs",         del_attrs,            1, avpgroup_fixup,             REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE}, 
00136     {"subst_attr",        subst_attr,           2, subst_attr_fixup,           REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
00137     {"flags2attr",        flags2attr,           1, avpid_fixup,                REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
00138     {"attr2uri",          attr2uri,             1, fixup_part,                 REQUEST_ROUTE | FAILURE_ROUTE},
00139     {"attr2uri",          attr2uri,             2, fixup_part,                 REQUEST_ROUTE | FAILURE_ROUTE},
00140     {"dump_attrs",        dump_attrs,           0, 0,                          REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
00141     {"dump_attrs",        dump_attrs,           1, avpgroup_fixup,             REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
00142     {"attr_equals",       attr_equals,          2, fixup_var_str_12,           REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
00143     {"attr_exists",       attr_exists,          1 , fixup_var_str_1,           REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
00144     {"attr_equals_xl",    attr_equals_xl,       2, fixup_attr_1_xl_2,          REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
00145     {"xlset_attr",        xlset_attr,           2, fixup_attr_1_xl_2,          REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
00146     {"xlfix_attr",        xlfix_attr,           1, xlfix_attr_fixup,           REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE}, 
00147     {"insert_attr_hf",    insert_req,           2, fixup_str_1_attr_2,         REQUEST_ROUTE | FAILURE_ROUTE},
00148     {"insert_attr_hf",    insert_req,           1, fixup_str_1_attr_2,         REQUEST_ROUTE | FAILURE_ROUTE},
00149     {"append_attr_hf",    append_req,           2, fixup_str_1_attr_2,         REQUEST_ROUTE | FAILURE_ROUTE},
00150     {"append_attr_hf",    append_req,           1, fixup_str_1_attr_2,         REQUEST_ROUTE | FAILURE_ROUTE},
00151     {"replace_attr_hf",   replace_req,          2, fixup_str_1_attr_2,         REQUEST_ROUTE | FAILURE_ROUTE},
00152     {"replace_attr_hf",   replace_req,          1, fixup_str_1_attr_2,         REQUEST_ROUTE | FAILURE_ROUTE},
00153     {"attr_to_reply",     append_reply,         2, fixup_str_1_attr_2,         REQUEST_ROUTE | FAILURE_ROUTE},
00154     {"attr_to_reply",     append_reply,         1, fixup_str_1_attr_2,         REQUEST_ROUTE | FAILURE_ROUTE},
00155     {"attr_destination",  attr_destination,     1, avpid_fixup,                REQUEST_ROUTE | FAILURE_ROUTE}, 
00156     {"xlset_destination", xlset_destination,    1, fixup_xl_1,                 REQUEST_ROUTE},
00157     {"hdr_body2attrs",    attr_hdr_body2attrs,  2, attr_hdr_body2attrs_fixup,  REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
00158     {"hdr_body2attrs2",   attr_hdr_body2attrs2, 2, attr_hdr_body2attrs2_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
00159     {0, 0, 0, 0, 0}
00160 };
00161 
00162 
00163 /*
00164  * Exported parameters
00165  */
00166 static param_export_t params[] = {
00167     {"xlbuf_size", PARAM_INT, &xlbuf_size},
00168     {0, 0, 0}
00169 };
00170 
00171 
00172 struct module_exports exports = {
00173     "avp",
00174     cmds,       /* Exported commands */
00175     0,          /* RPC */
00176     params,     /* Exported parameters */
00177     mod_init,          /* module initialization function */
00178     0,          /* response function*/
00179     0,          /* destroy function */
00180     0,          /* oncancel function */
00181     0           /* per-child init function */
00182 };
00183 
00184 
00185 static int set_iattr_fixup(void** param, int param_no)
00186 {
00187     if (param_no == 1) {
00188         return fixup_var_str_12(param, param_no);
00189     } else {
00190         return fixup_var_int_12(param, param_no);
00191     }
00192 }
00193 
00194 
00195 static int get_avp_id(avp_ident_t* id, fparam_t* p, struct sip_msg* msg)
00196 {
00197     str str_id;
00198     avp_t* avp;
00199     avp_value_t val;
00200     int ret;
00201 
00202     switch(p->type) {
00203     case FPARAM_AVP:
00204         avp = search_avp(p->v.avp, &val, 0);
00205         if (!avp) {
00206             DBG("get_avp_id: AVP %s does not exist\n", p->orig);
00207             return -1;
00208         }
00209         if ((avp->flags & AVP_VAL_STR) == 0) {
00210             DBG("get_avp_id: Not a string AVP\n");
00211             return -1;
00212         }
00213         str_id = val.s;
00214         break;
00215 
00216     case FPARAM_SELECT:
00217         ret = run_select(&str_id, p->v.select, msg);
00218         if (ret < 0 || ret > 0) return -1;
00219         break;
00220 
00221         case FPARAM_STR:
00222         str_id = p->v.str;
00223         break;
00224 
00225     default:
00226         ERR("Invalid parameter type in get_avp_id\n");
00227         return -1;
00228     }
00229 
00230     return parse_avp_ident(&str_id, id);
00231 }
00232 
00233 
00234 static int set_iattr(struct sip_msg* msg, char* p1, char* p2)
00235 {
00236     avp_ident_t avpid;
00237     int_str value;
00238 
00239     if (get_avp_id(&avpid, (fparam_t*)p1, msg) < 0) {
00240         return -1;
00241     }
00242     
00243     if (get_int_fparam(&value.n, msg, (fparam_t*)p2) < 0) {
00244         ERR("Error while obtaining attribute value from '%s'\n", ((fparam_t*)p1)->orig);
00245         return -1;
00246     }
00247     
00248     if (add_avp(avpid.flags | AVP_NAME_STR, avpid.name, value) != 0) {
00249         ERR("add_avp failed\n");
00250         return -1;
00251     }
00252     return 1;
00253 }
00254 
00255 
00256 static int set_sattr(struct sip_msg* msg, char* p1, char* p2)
00257 {
00258     avp_ident_t avpid;
00259     int_str value;
00260     
00261     if (get_avp_id(&avpid, (fparam_t*)p1, msg) < 0) {
00262         return -1;
00263     }
00264 
00265     if (get_str_fparam(&value.s, msg, (fparam_t*)p2) < 0) {
00266         ERR("Error while obtaining attribute value from '%s'\n", ((fparam_t*)p2)->orig);
00267         return -1;
00268     }
00269     
00270     if (add_avp(avpid.flags | AVP_NAME_STR | AVP_VAL_STR, avpid.name, value) != 0) {
00271         ERR("add_avp failed\n");
00272         return -1;
00273     }
00274     
00275     return 1;
00276 }
00277 
00278 
00279 static int avpid_fixup(void** param, int param_no)
00280 {
00281     if (param_no == 1) {
00282                 if (fix_param(FPARAM_AVP, param) == 0) return 0;
00283                 ERR("Invalid AVP identifier: '%s'\n", (char*)*param);
00284                 return -1;
00285     }
00286     return 0;
00287 }
00288 
00289 
00290 static int print_attr(struct sip_msg* msg, char* p1, char* p2)
00291 {
00292     fparam_t* fp;
00293     int_str value;
00294     avp_t *avp;
00295 
00296     fp = (fparam_t*)p1;
00297     
00298     avp = search_avp(fp->v.avp, &value, NULL);
00299     if (avp == 0) {
00300         LOG(L_INFO, "AVP '%s' not found\n", fp->orig);
00301         return -1;
00302     }
00303     
00304     if (avp->flags & AVP_VAL_STR) {
00305         LOG(L_INFO, "AVP: '%s'='%.*s'\n", 
00306             fp->orig, value.s.len, ZSW(value.s.s));
00307     } else {
00308         LOG(L_INFO, "AVP: '%s'=%d\n", fp->orig, value.n);
00309     }
00310     return 1;
00311 }
00312 
00313 
00314 static int del_attr(struct sip_msg* msg, char* p1, char* p2)
00315 {
00316     fparam_t* fp;
00317     avp_t* avp;
00318     struct search_state st;     
00319     
00320     fp = (fparam_t*)p1;
00321     
00322     avp = search_avp(fp->v.avp, 0, &st);
00323     while (avp) {
00324         destroy_avp(avp);
00325         avp = search_next_avp(&st, 0);
00326     }
00327     return 1;
00328 }
00329 
00330 
00331 static int del_attrs(struct sip_msg* msg, char* p1, char* p2)
00332 {
00333     return (reset_avp_list((unsigned long)p1) == 0) ? 1 : -1;
00334 }
00335                         
00336 
00337 static int subst_attr_fixup(void** param, int param_no)
00338 {
00339     if (param_no == 1) {
00340                 return avpid_fixup(param, 1);
00341     }
00342     if (param_no == 2) {
00343                 if (fix_param(FPARAM_SUBST, param) != 0) return -1;
00344     }
00345     return 0;
00346 }
00347 
00348 
00349 static int subst_attr(struct sip_msg* msg, char* p1, char* p2)
00350 {
00351     avp_t* avp;
00352     avp_value_t val;
00353     str *res = NULL;
00354     int count;
00355     avp_ident_t* name = &((fparam_t*)p1)->v.avp;
00356 
00357     if ((avp = search_avp(*name, &val, NULL))) {
00358         if (avp->flags & AVP_VAL_STR) {
00359             res = subst_str(val.s.s, msg, ((fparam_t*)p2)->v.subst, &count);
00360             if (res == NULL) {
00361                 ERR("avp_subst: error while running subst\n");
00362                 goto error;
00363             }
00364 
00365             DBG("avp_subst: %d, result %.*s\n", count, res->len, ZSW(res->s));
00366             val.s = *res;
00367             
00368             if (add_avp_before(avp, name->flags | AVP_VAL_STR, name->name, val)) {
00369                 ERR("avp_subst: error while adding new AVP\n");
00370                 goto error;
00371             }
00372             
00373             destroy_avp(avp);
00374             return 1;
00375         } else {
00376             ERR("avp_subst: AVP has numeric value\n");
00377             goto error;
00378         }
00379     } else {
00380         ERR("avp_subst: AVP[%.*s] index %d, flags %x not found\n", 
00381             name->name.s.len, name->name.s.s,
00382             name->index, name->flags);
00383         goto error;
00384     }
00385 
00386  error:
00387     if (res) pkg_free(res);
00388     return -1;
00389 }
00390 
00391 
00392 static int flags2attr(struct sip_msg* msg, char* p1, char* p2)
00393 {
00394     avp_ident_t* id;
00395     int_str value;
00396     
00397     value.n = msg->flags;
00398     
00399     id = &((fparam_t*)p1)->v.avp;
00400 
00401     if (add_avp(id->flags, id->name, value) != 0) {
00402         ERR("add_avp failed\n");
00403         return -1;
00404     }
00405     
00406     return 1;
00407 }
00408 
00409 
00410 static int fixup_part(void** param, int param_no) 
00411 {
00412     int i;
00413     fparam_t* fp;
00414     
00415     static struct {
00416                 char* s;
00417                 int i;
00418     } fixup_parse[] = {
00419                 {"", SET_URI_T},
00420                 {"prefix", PREFIX_T},
00421                 {"uri", SET_URI_T},
00422                 {"username", SET_USER_T},
00423                 {"user", SET_USER_T},
00424                 {"usernamepassword", SET_USERPASS_T},
00425                 {"userpass", SET_USERPASS_T},
00426                 {"domain", SET_HOST_T},
00427                 {"host", SET_HOST_T},
00428                 {"domainport", SET_HOSTPORT_T},
00429                 {"hostport", SET_HOSTPORT_T},
00430                 {"port", SET_PORT_T},
00431                 {"strip", STRIP_T},
00432                 {"strip_tail", STRIP_TAIL_T},
00433                 {0, 0}
00434     };
00435     
00436     if (param_no == 1) {
00437                 return avpid_fixup(param, 1);
00438     } else if (param_no == 2) {
00439                 /* Create fparam structure */
00440                 if (fix_param(FPARAM_STRING, param) != 0) return -1;
00441                 
00442                 /* We will parse the string now and store the value
00443                  * as int
00444                  */
00445                 fp = (fparam_t*)*param;
00446                 fp->type = FPARAM_INT;
00447                 
00448                 for(i = 0; fixup_parse[i].s; i++) {
00449                         if (!strcasecmp(fp->orig, fixup_parse[i].s)) {
00450                                 fp->v.i = fixup_parse[i].i;
00451                                 return 1;
00452                         }
00453                 }
00454                 
00455                 ERR("Invalid parameter value: '%s'\n", fp->orig);
00456                 return -1;
00457     }
00458     return 0;
00459 }
00460 
00461 
00462 static int attr2uri(struct sip_msg* msg, char* p1, char* p2)
00463 {
00464     int_str value;
00465     avp_t* avp_entry;
00466     struct action act;
00467         struct run_act_ctx ra_ctx;
00468     int pnr;
00469     unsigned int u;
00470     
00471     if (p2) {
00472                 pnr = ((fparam_t*)p2)->v.i;
00473     } else {
00474                 pnr = SET_URI_T;
00475     }
00476     
00477     avp_entry = search_avp(((fparam_t*)p1)->v.avp, &value, NULL);
00478     if (avp_entry == 0) {
00479                 ERR("attr2uri: AVP '%s' not found\n", ((fparam_t*)p1)->orig);
00480                 return -1;
00481     }
00482     
00483     memset(&act, 0, sizeof(act));
00484         
00485     if ((pnr == STRIP_T) || (pnr == STRIP_TAIL_T)) {
00486                 /* we need integer value for these actions */
00487         if (avp_entry->flags & AVP_VAL_STR) {
00488                         if (str2int(&value.s, &u)) {
00489                                 ERR("not an integer value: %.*s\n",
00490                                         value.s.len, value.s.s);
00491                                 return -1;
00492                         }
00493                         act.val[0].u.number = u;
00494                 } else {
00495                         act.val[0].u.number = value.n;
00496                 }
00497                 act.val[0].type = NUMBER_ST;
00498     } else {
00499                 /* we need string value */
00500                 if ((avp_entry->flags & AVP_VAL_STR) == 0) {
00501                         act.val[0].u.string = int2str(value.n, NULL);
00502                 } else {
00503                         act.val[0].u.string = value.s.s;
00504                 }
00505                 act.val[0].type = STRING_ST;
00506     }
00507     act.type = pnr;
00508     init_run_actions_ctx(&ra_ctx);
00509     if (do_action(&ra_ctx, &act, msg) < 0) {
00510                 ERR("failed to change ruri part.\n");
00511                 return -1;
00512     }
00513     return 1;
00514 }
00515 
00516 
00517 /*
00518  * sends avp list to log in readable form
00519  *
00520  */
00521 static void dump_avp_reverse(avp_t* avp)
00522 {
00523     str* name;
00524     int_str val;
00525     
00526     if (avp) {
00527              /* AVPs are added to front of the list, reverse by recursion */
00528         dump_avp_reverse(avp->next);
00529         
00530         name=get_avp_name(avp);
00531         get_avp_val(avp, &val);
00532         switch(avp->flags&(AVP_NAME_STR|AVP_VAL_STR)) {
00533         case 0:
00534                  /* avp type ID, int value */
00535             LOG(L_INFO,"AVP[%d]=%d\n", avp->id, val.n);
00536             break;
00537 
00538         case AVP_NAME_STR:
00539                  /* avp type str, int value */
00540             name=get_avp_name(avp);
00541             LOG(L_INFO,"AVP[\"%.*s\"]=%d\n", name->len, name->s, val.n);
00542             break;
00543 
00544         case AVP_VAL_STR:
00545                  /* avp type ID, str value */
00546             LOG(L_INFO,"AVP[%d]=\"%.*s\"\n", avp->id, val.s.len, val.s.s);
00547             break;
00548 
00549         case AVP_NAME_STR|AVP_VAL_STR:
00550                  /* avp type str, str value */
00551             name=get_avp_name(avp);
00552             LOG(L_INFO,"AVP[\"%.*s\"]=\"%.*s\"\n", name->len, name->s, val.s.len, val.s.s);
00553             break;
00554         }
00555     }
00556 }
00557 
00558 
00559 static int dump_attrs(struct sip_msg* m, char* x, char* y)
00560 {
00561     avp_list_t avp_list;
00562     unsigned long flags;
00563 
00564     if (x) {
00565         flags = (unsigned long)x;
00566     } else {
00567         flags = AVP_CLASS_ALL | AVP_TRACK_ALL;
00568     }
00569 
00570 
00571     if (flags & AVP_CLASS_GLOBAL) {
00572         avp_list = get_avp_list(AVP_CLASS_GLOBAL);
00573         INFO("class=GLOBAL\n");
00574         if (!avp_list) {
00575             LOG(L_INFO,"INFO: No AVP present\n");
00576         } else {
00577             dump_avp_reverse(avp_list);
00578         }
00579     }
00580 
00581     if (flags & AVP_CLASS_DOMAIN && flags & AVP_TRACK_FROM) {
00582         avp_list = get_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_FROM);
00583         INFO("track=FROM class=DOMAIN\n");
00584         if (!avp_list) {
00585             LOG(L_INFO,"INFO: No AVP present\n");
00586         } else {
00587             dump_avp_reverse(avp_list);
00588         }
00589     }
00590 
00591     if (flags & AVP_CLASS_DOMAIN && flags & AVP_TRACK_TO) {
00592         avp_list = get_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_TO);
00593         INFO("track=TO class=DOMAIN\n");
00594         if (!avp_list) {
00595             LOG(L_INFO,"INFO: No AVP present\n");
00596         } else {
00597             dump_avp_reverse(avp_list);
00598         }
00599     }
00600 
00601     if (flags & AVP_CLASS_USER && flags & AVP_TRACK_FROM) {
00602         avp_list = get_avp_list(AVP_CLASS_USER | AVP_TRACK_FROM);
00603         INFO("track=FROM class=USER\n");
00604         if (!avp_list) {
00605             LOG(L_INFO,"INFO: No AVP present\n");
00606         } else {
00607             dump_avp_reverse(avp_list);
00608         }
00609     }
00610 
00611     if (flags & AVP_CLASS_USER && flags & AVP_TRACK_TO) {
00612         avp_list = get_avp_list(AVP_CLASS_USER | AVP_TRACK_TO);
00613         INFO("track=TO class=USER\n");
00614         if (!avp_list) {
00615             LOG(L_INFO,"INFO: No AVP present\n");
00616         } else {
00617             dump_avp_reverse(avp_list);
00618         }
00619     }
00620 
00621     if (flags & AVP_CLASS_URI && flags & AVP_TRACK_FROM) {
00622         avp_list = get_avp_list(AVP_CLASS_URI | AVP_TRACK_FROM);
00623         INFO("track=FROM class=URI\n");
00624         if (!avp_list) {
00625             LOG(L_INFO,"INFO: No AVP present\n");
00626         } else {
00627             dump_avp_reverse(avp_list);
00628         }
00629     }   
00630 
00631     if (flags & AVP_CLASS_URI && flags & AVP_TRACK_TO) {
00632         avp_list = get_avp_list(AVP_CLASS_URI | AVP_TRACK_TO);
00633         INFO("track=TO class=URI\n");
00634         if (!avp_list) {
00635             LOG(L_INFO,"INFO: No AVP present\n");
00636         } else {
00637             dump_avp_reverse(avp_list);
00638         }
00639     }
00640     return 1;
00641 }
00642 
00643 
00644 /*
00645  *  returns 1 if msg contains an AVP with the given name and value,
00646  *  returns -1 otherwise
00647  */
00648 static int attr_equals(struct sip_msg* msg, char* p1, char* p2)
00649 {
00650     avp_ident_t avpid;
00651     int_str value, avp_value;
00652     avp_t* avp;
00653     struct search_state st;
00654 
00655     if (get_avp_id(&avpid, (fparam_t*)p1, msg) < 0) {
00656         return -1;
00657     }
00658 
00659     if (p2 && get_str_fparam(&value.s, msg, (fparam_t*)p2) < 0) {
00660         ERR("Error while obtaining attribute value from '%s'\n", ((fparam_t*)p2)->orig);
00661         return -1;
00662     }
00663 
00664     avp = search_avp(avpid, &avp_value, &st);
00665     if (avp == 0) return -1;
00666 
00667     if (!p2) return 1;
00668     
00669     while (avp != 0) {
00670         if (avp->flags & AVP_VAL_STR) {
00671             if ((avp_value.s.len == value.s.len) &&
00672                 !memcmp(avp_value.s.s, value.s.s, avp_value.s.len)) {
00673                 return 1;
00674             }
00675         } else {
00676             if (avp_value.n == str2s(value.s.s, value.s.len, 0)) {
00677                 return 1;
00678             }
00679         }
00680         avp = search_next_avp(&st, &avp_value);
00681     }
00682     
00683     return -1;
00684 }
00685 
00686 
00687 static int attr_exists(struct sip_msg* msg, char* p1, char* p2)
00688 {
00689         return attr_equals(msg, p1, NULL);
00690 }
00691 
00692 
00693 static int xl_printstr(struct sip_msg* msg, xl_elog_t* format, char** res, int* res_len)
00694 {
00695     int len;
00696     
00697     if (!format || !res) {
00698         LOG(L_ERR, "xl_printstr: Called with null format or res\n");
00699         return -1;
00700     }
00701     
00702     if (!xlbuf) {
00703         xlbuf = pkg_malloc((xlbuf_size+1)*sizeof(char));
00704         if (!xlbuf) {
00705             LOG(L_CRIT, "xl_printstr: No memory left for format buffer\n");
00706             return -1;
00707         }
00708     }
00709     
00710     len = xlbuf_size;
00711     if (xl_print(msg, format, xlbuf, &len)<0) {
00712         LOG(L_ERR, "xl_printstr: Error while formating result\n");
00713         return -1;
00714     }
00715     
00716     if ((xl_nul) && (xl_nul->len == len) && !strncmp(xl_nul->s, xlbuf, len)) {
00717         return 0;
00718     }
00719 
00720     *res = xlbuf;
00721     if (res_len) {
00722         *res_len=len;
00723     }
00724     return len;
00725 }
00726 
00727 
00728 static int attr_equals_xl(struct sip_msg* msg, char* p1, char* format)
00729 {
00730     avp_ident_t* avpid;
00731     avp_value_t avp_val;
00732     struct search_state st;
00733     str xl_val;
00734     avp_t* avp;
00735     
00736     avpid = &((fparam_t*)p1)->v.avp;
00737 
00738     if (xl_printstr(msg, (xl_elog_t*) format, &xl_val.s, &xl_val.len) > 0) {
00739         for (avp = search_avp(*avpid, &avp_val, &st); avp; avp = search_next_avp(&st, &avp_val)) {
00740             if (avp->flags & AVP_VAL_STR) {
00741                 if ((avp_val.s.len == xl_val.len) &&
00742                     !memcmp(avp_val.s.s, xl_val.s, avp_val.s.len)) return 1;
00743             } else {
00744                 if (avp_val.n == str2s(xl_val.s, xl_val.len, 0)) return 1;
00745             }
00746         }
00747         return -1;
00748     }
00749     
00750     ERR("avp_equals_xl:Error while expanding xl_format\n");
00751     return -1;
00752 }
00753 
00754 /* get the pointer to the xl lib functions */
00755 static int get_xl_functions(void)
00756 {
00757     if (!xl_print) {
00758         xl_print=(xl_print_log_f*)find_export("xprint", NO_SCRIPT, 0);
00759         
00760         if (!xl_print) {
00761             LOG(L_CRIT,"ERROR: cannot find \"xprint\", is module xlog loaded?\n");
00762             return -1;
00763         }
00764     }
00765     
00766     if (!xl_parse) {
00767         xl_parse=(xl_parse_format_f*)find_export("xparse", NO_SCRIPT, 0);
00768         
00769         if (!xl_parse) {
00770             LOG(L_CRIT,"ERROR: cannot find \"xparse\", is module xlog loaded?\n");
00771             return -1;
00772         }
00773     }
00774 
00775     if (!xl_free) {
00776         xl_free=(xl_elog_free_all_f*)find_export("xfree", NO_SCRIPT, 0);
00777         
00778         if (!xl_free) {
00779             LOG(L_CRIT,"ERROR: cannot find \"xfree\", is module xlog loaded?\n");
00780             return -1;
00781         }
00782     }
00783 
00784     if (!xl_nul) {
00785         xl_getnul=(xl_get_nulstr_f*)find_export("xnulstr", NO_SCRIPT, 0);
00786         if (xl_getnul) {
00787             xl_nul=xl_getnul();
00788         }
00789         
00790         if (!xl_nul){
00791             LOG(L_CRIT,"ERROR: cannot find \"xnulstr\", is module xlog loaded?\n");
00792             return -1;
00793         } else {
00794             LOG(L_INFO,"INFO: xlog null is \"%.*s\"\n", xl_nul->len, xl_nul->s);
00795         }
00796         
00797     }
00798 
00799     return 0;
00800 }
00801 
00802 /*
00803  * Convert xl format string to xl format description
00804  */
00805 static int fixup_xl_1(void** param, int param_no)
00806 {
00807     xl_elog_t* model;
00808 
00809     if (get_xl_functions()) return -1;
00810 
00811     if (param_no == 1) {
00812         if(*param) {
00813             if(xl_parse((char*)(*param), &model)<0) {
00814                 LOG(L_ERR, "ERROR: xl_fixup: wrong format[%s]\n", (char*)(*param));
00815                 return E_UNSPEC;
00816             }
00817             
00818             *param = (void*)model;
00819             return 0;
00820         } else {
00821             LOG(L_ERR, "ERROR: xl_fixup: null format\n");
00822             return E_UNSPEC;
00823         }
00824     }
00825     
00826     return 0;
00827 }
00828 
00829 static int fixup_attr_1_xl_2(void** param, int param_no)
00830 {
00831     if (param_no == 1) {
00832         return avpid_fixup(param, 1);
00833     } else  if (param_no == 2) {
00834         return fixup_xl_1(param, 1);
00835     }
00836     return 0;
00837 }
00838 
00839 
00840 static int xlset_attr(struct sip_msg* msg, char* p1, char* format)
00841 {
00842     avp_ident_t* avpid;
00843     avp_value_t val;
00844     
00845     avpid = &((fparam_t*)p1)->v.avp;
00846 
00847     if (xl_printstr(msg, (xl_elog_t*)format, &val.s.s, &val.s.len) > 0) {
00848         if (add_avp(avpid->flags | AVP_VAL_STR, avpid->name, val)) {
00849             ERR("xlset_attr:Error adding new AVP\n");
00850             return -1;
00851         }
00852         return 1;
00853     }
00854     
00855     ERR("xlset_attr:Error while expanding xl_format\n");
00856     return -1;
00857 }
00858 
00859 /*
00860  * get the xl function pointers and fix up the AVP parameter
00861  */
00862 static int xlfix_attr_fixup(void** param, int param_no)
00863 {
00864     if (get_xl_functions()) return -1;
00865 
00866     if (param_no == 1)
00867         return avpid_fixup(param, 1);
00868 
00869     return 0;
00870 }
00871 
00872 /* fixes an attribute containing xl formatted string to pure string runtime */
00873 static int xlfix_attr(struct sip_msg* msg, char* p1, char* p2)
00874 {
00875     avp_t* avp;
00876     avp_ident_t* avpid;
00877     avp_value_t val;
00878     xl_elog_t* format=NULL;
00879     int ret=-1;
00880     
00881     avpid = &((fparam_t*)p1)->v.avp;
00882 
00883     /* search the AVP */
00884     avp = search_avp(*avpid, &val, 0);
00885     if (!avp) {
00886         DBG("xlfix_attr: AVP does not exist\n");
00887         goto error;
00888     }
00889     if ((avp->flags & AVP_VAL_STR) == 0) {
00890         DBG("xlfix_attr: Not a string AVP\n");
00891         goto error;
00892     }
00893 
00894     /* parse the xl syntax -- AVP values are always
00895     zero-terminated */
00896     if (xl_parse(val.s.s, &format)<0) {
00897         LOG(L_ERR, "ERROR: xlfix_attr: wrong format[%s]\n", val.s.s);
00898         goto error;
00899     }
00900 
00901     if (xl_printstr(msg, format, &val.s.s, &val.s.len) > 0) {
00902         /* we must delete and re-add the AVP again */
00903         destroy_avp(avp);
00904         if (add_avp(avpid->flags | AVP_VAL_STR, avpid->name, val)) {
00905             ERR("xlfix_attr:Error adding new AVP\n");
00906             goto error;
00907         }
00908         /* everything went OK */
00909         ret = 1;
00910     }
00911 
00912 error:
00913     /* free the parsed xl expression */
00914     if (format) xl_free(format);
00915 
00916     return ret;
00917 }
00918 
00919 
00920 static int request_hf_helper(struct sip_msg* msg, str* hf, avp_ident_t* ident, struct lump* anchor, struct search_state* st, int front, int reverse, int reply)
00921 {
00922     struct lump* new_anchor;
00923     static struct search_state state;
00924     avp_t* avp;
00925     char* s;
00926     str fin_val;
00927     int len, ret;
00928     int_str val;
00929     struct hdr_field* pos, *found = NULL;
00930     
00931     if (!anchor && !reply) {
00932         
00933         if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
00934             LOG(L_ERR, "ERROR: request_hf_helper: Error while parsing message\n");
00935             return -1;
00936         }
00937         
00938         pos = msg->headers;
00939         while (pos && (pos->type != HDR_EOH_T)) {
00940             if ((hf->len == pos->name.len)
00941                 && (!strncasecmp(hf->s, pos->name.s, pos->name.len))) {
00942                 found = pos;
00943                 if (front) {
00944                     break;
00945                 }
00946             }
00947             pos = pos->next;
00948         }
00949         
00950         if (found) {
00951             if (front) {
00952                 len = found->name.s - msg->buf;
00953             } else {
00954                 len = found->name.s + found->len - msg->buf;
00955             }
00956         } else {
00957             len = msg->unparsed - msg->buf;
00958         }
00959         
00960         new_anchor = anchor_lump(msg, len, 0, 0);
00961         if (new_anchor == 0) {
00962             LOG(L_ERR, "ERROR: request_hf_helper: Can't get anchor\n");
00963             return -1;
00964         }
00965     } else {
00966         new_anchor = anchor;
00967     }
00968     
00969     if (!st) {
00970         st = &state;
00971         avp = search_avp(*ident, NULL, st);
00972         ret = -1;
00973     } else {
00974         avp = search_next_avp(st, NULL);
00975         ret = 1;
00976     }
00977     
00978     if (avp) {
00979         if (reverse && (request_hf_helper(msg, hf, ident, new_anchor, st, front, reverse, reply) == -1)) {
00980             return -1;
00981         }
00982         
00983         get_avp_val(avp, &val);
00984         if (avp->flags & AVP_VAL_STR) {
00985             fin_val = val.s;
00986         } else {
00987             fin_val.s = int2str(val.n, &fin_val.len);
00988         }
00989         
00990         len = hf->len + 2 + fin_val.len + 2;
00991         s = (char*)pkg_malloc(len);
00992         if (!s) {
00993             LOG(L_ERR, "ERROR: request_hf_helper: No memory left for data lump\n");
00994             return -1;
00995         }
00996         
00997         memcpy(s, hf->s, hf->len);
00998         memcpy(s + hf->len, ": ", 2 );
00999         memcpy(s + hf->len+2, fin_val.s, fin_val.len );
01000         memcpy(s + hf->len + 2 + fin_val.len, CRLF, CRLF_LEN);
01001         
01002         if (reply) {
01003             if (add_lump_rpl( msg, s, len, LUMP_RPL_HDR | LUMP_RPL_NODUP) == 0) {
01004                 LOG(L_ERR, "ERROR: request_hf_helper: Can't insert RPL lump\n");
01005                 pkg_free(s);
01006                 return -1;
01007             }
01008         } else {
01009             if ((front && (insert_new_lump_before(new_anchor, s, len, 0) == 0))
01010                 || (!front && (insert_new_lump_after(new_anchor, s, len, 0) == 0))) {
01011                 LOG(L_ERR, "ERROR: request_hf_helper: Can't insert lump\n");
01012                 pkg_free(s);
01013                 return -1;
01014             }
01015         }
01016         if (!reverse && (request_hf_helper(msg, hf, ident, new_anchor, st, front, reverse, reply) == -1)) {
01017             return -1;
01018         }
01019         return 1;
01020     };
01021     
01022          /* in case of topmost call (st==NULL) return error */
01023          /* otherwise it's OK, no more AVPs found */
01024     return ret; 
01025 }
01026 
01027 
01028 static int fixup_str_1_attr_2(void** param, int param_no)
01029 {
01030     if (param_no == 1) {
01031         return fixup_var_str_12(param, 1);
01032     } else if (param_no == 2) {
01033         return avpid_fixup(param, 1);
01034     }
01035     return 0;
01036 }
01037 
01038 
01039 static int insert_req(struct sip_msg* msg, char* p1, char* p2)
01040 {
01041     avp_ident_t ident, *avp;
01042     str hf;
01043     
01044     if (get_str_fparam(&hf, msg, (fparam_t*)p1) < 0) {
01045         ERR("Error while obtaining attribute value from '%s'\n", ((fparam_t*)p1)->orig);
01046         return -1;
01047     }
01048 
01049     if (p2) {
01050         avp = &((fparam_t*)p2)->v.avp;
01051     } else {
01052         ident.name.s = hf;
01053         ident.flags = AVP_NAME_STR;
01054         ident.index = 0;
01055         avp = &ident;
01056     }
01057     return (request_hf_helper(msg, &hf, avp, NULL, NULL, 1, 0, 0));
01058 }
01059 
01060 
01061 static int append_req(struct sip_msg* msg, char* p1, char* p2)
01062 {
01063     avp_ident_t ident, *avp;
01064     str hf;
01065 
01066     if (get_str_fparam(&hf, msg, (fparam_t*)p1) < 0) {
01067         ERR("Error while obtaining attribute value from '%s'\n", ((fparam_t*)p1)->orig);
01068         return -1;
01069     }
01070     
01071     if (p2) {
01072         avp = &((fparam_t*)p2)->v.avp;
01073     } else {
01074         ident.name.s = hf;
01075         ident.flags = AVP_NAME_STR;
01076         ident.index = 0;
01077         avp = &ident;
01078     }
01079     return (request_hf_helper(msg, &hf, avp, NULL, NULL, 0, 1, 0));
01080 }
01081 
01082 
01083 static int replace_req(struct sip_msg* msg, char* p1, char* p2)
01084 {
01085     struct hdr_field* pos;
01086     str hf;
01087     
01088     if (get_str_fparam(&hf, msg, (fparam_t*)p1) < 0) {
01089         ERR("Error while obtaining attribute value from '%s'\n", ((fparam_t*)p1)->orig);
01090         return -1;
01091     }
01092     
01093     if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
01094         LOG(L_ERR, "ERROR: replace_req: Error while parsing message\n");
01095         return -1;
01096     }
01097     
01098     pos = msg->headers;
01099     while (pos && (pos->type != HDR_EOH_T)) {
01100         if (hf.len == pos->name.len
01101             && !strncasecmp(hf.s, pos->name.s, pos->name.len)) {
01102             if (del_lump(msg, pos->name.s - msg->buf, pos->len, 0) == 0) {
01103                 LOG(L_ERR,"ERROR: Can't insert del lump\n");
01104                 return -1;
01105             }
01106         }
01107         pos = pos->next;
01108     }
01109     return append_req(msg, p1, p2);
01110 }
01111 
01112 
01113 static int append_reply(struct sip_msg* msg, char* p1, char* p2)
01114 {
01115     avp_ident_t ident, *avp;
01116     str hf;
01117     
01118     if (get_str_fparam(&hf, msg, (fparam_t*)p1) < 0) {
01119         ERR("Error while obtaining attribute value from '%s'\n", ((fparam_t*)p1)->orig);
01120         return -1;
01121     }
01122     
01123     if (p2) {
01124         avp = &((fparam_t*)p2)->v.avp;
01125     } else {
01126         ident.name.s = hf;
01127         ident.flags = AVP_NAME_STR;
01128         ident.index = 0;
01129         avp = &ident;
01130     }
01131     return (request_hf_helper(msg, &hf, avp, NULL, NULL, 0, 1, 1));
01132 }
01133 
01134 
01135 static int set_destination(struct sip_msg* msg, str* dest)
01136 {
01137     name_addr_t nameaddr;
01138     
01139     if (!parse_nameaddr(dest, &nameaddr)) {
01140         return set_dst_uri(msg, &nameaddr.uri);
01141     } else {
01142              /* it is just URI, pass it through */
01143         return set_dst_uri(msg, dest);
01144     }
01145 }
01146 
01147 
01148 static int attr_destination(struct sip_msg* msg, char* p1, char* p2)
01149 {
01150     avp_t* avp;
01151     avp_value_t val;
01152     
01153     if ((avp = search_avp(((fparam_t*)p1)->v.avp, &val, NULL))) {
01154         if (avp->flags & AVP_VAL_STR) {
01155             if (set_destination(msg, &val.s)) {
01156                 LOG(L_ERR, "ERROR: avp_destination: Can't set dst uri\n");
01157                 return -1;
01158             };
01159                 /* dst_uri changed, so it makes sense to re-use the current uri for
01160                         forking */
01161                 ruri_mark_new(); /* re-use uri for serial forking */
01162             return 1;
01163         } else {
01164             ERR("avp_destination:AVP has numeric value\n");
01165             return -1;
01166         }
01167     }
01168     return -1;
01169 }
01170 
01171 
01172 static int xlset_destination(struct sip_msg* msg, char* format, char* p2)
01173 {
01174     str val;
01175     
01176     if (xl_printstr(msg, (xl_elog_t*) format, &val.s, &val.len) > 0) {
01177         DBG("Setting dest to: '%.*s'\n", val.len, val.s);
01178         if (set_destination(msg, &val) == 0) {
01179             return 1;
01180         }
01181     }
01182     
01183     return -1;
01184 }
01185 
01186 
01187 static int attr_hdr_body2attrs(struct sip_msg* m, char* header_, char* prefix_)
01188 {
01189     char name_buf[50];
01190     str *prefix = (str*) prefix_;
01191     struct hdr_name *header = (void*) header_;
01192     struct hdr_field *hf;
01193     str s, name, val;
01194     int_str name2, val2;
01195     int val_type, arr;
01196     if (header->kind == HDR_STR) {
01197         if (parse_headers(m, HDR_EOH_F, 0) == -1) {
01198             LOG(L_ERR, "ERROR: attr_hdr_body2attrs: Error while parsing message\n");
01199             return -1;
01200         }
01201         
01202         for (hf=m->headers; hf; hf=hf->next) {
01203             if ( (header->name.s.len == hf->name.len)
01204                  && (!strncasecmp(header->name.s.s, hf->name.s, hf->name.len)) ) {
01205                 break;
01206             }
01207         }
01208     }
01209     else {
01210         if (parse_headers(m, header->name.n, 0) == -1) {
01211             LOG(L_ERR, "ERROR: attr_hdr_body2attrs: Error while parsing message\n");
01212             return -1;
01213         }
01214         switch (header->name.n) {
01215                  //     HDR_xxx:
01216         default:
01217             hf = NULL;
01218             break;
01219         }
01220     }
01221     if (!hf || !hf->body.len)
01222         return 1;
01223     
01224          // parse body of hf
01225     s = hf->body;
01226     name_buf[0] = '\0';
01227     while (s.len) {
01228         trim_leading(&s);
01229         name.s = s.s;
01230         while ( s.len &&
01231                 ( (s.s[0] >= 'a' && s.s[0] <= 'z') ||
01232                   (s.s[0] >= 'A' && s.s[0] <= 'Z') ||
01233                   (s.s[0] >= '0' && s.s[0] <= '9') ||
01234                   s.s[0] == '_' || s.s[0] == '-'
01235                   ) ) {
01236             s.s++;
01237             s.len--;
01238         }
01239         if (s.s == name.s)
01240             break;
01241         name.len = s.s - name.s;
01242         trim_leading(&s);
01243         if (!s.len)
01244             break;
01245         if (s.s[0] == '=') {
01246             s.s++;
01247             s.len--;
01248             arr = -1;
01249             
01250             while (s.len) {
01251                 trim_leading(&s);
01252                 val_type = 0;
01253                 if (!s.len)
01254                     break;
01255                 if (s.s[0] == '"') {
01256                     s.s++;
01257                     s.len--;
01258                     val.s = s.s;
01259                     
01260                     s.s = q_memchr(s.s, '\"', s.len);
01261                     if (!s.s)
01262                         break;
01263                     val.len = s.s - val.s;
01264                     val_type = AVP_VAL_STR;
01265                     s.s++;
01266                     s.len -= s.s - val.s;
01267                 }
01268                 else {
01269                     int r;
01270                     val.s = s.s;
01271                     if (s.s[0] == '+' || s.s[0] == '-') {
01272                         s.s++;
01273                         s.len--;
01274                     }
01275                     val2.n = 0; r = 0;
01276                     while (s.len) {
01277                         if (s.s[0] == header->field_delimiter || (header->array_delimiter && header->array_delimiter == s.s[0]))
01278                             goto token_end;
01279                         switch (s.s[0]) {
01280                         case ' ':
01281                         case '\t':
01282                         case '\n':
01283                         case '\r':
01284                             goto token_end;
01285                         }
01286                         if (!val_type && s.s[0] >= '0' && s.s[0]<= '9') {
01287                             r++;
01288                             val2.n *= 10;
01289                             val2.n += s.s[0] - '0';
01290                                  // overflow detection ???
01291                         }
01292                         else {
01293                             val_type = AVP_VAL_STR;
01294                         }
01295                         s.s++;
01296                         s.len--;
01297                     }
01298                 token_end:
01299                     if (r == 0) val_type = AVP_VAL_STR;
01300                     if (!val_type && val.s[0] == '-') {
01301                         val2.n = -val2.n;
01302                     }
01303                     val.len = s.s - val.s;
01304                 }
01305                 trim_leading(&s);
01306                 if (arr >= 0 || (s.len && header->array_delimiter && header->array_delimiter == s.s[0])) {
01307                     arr++;
01308                     if (arr == 100)
01309                         LOG(L_ERR, "ERROR: avp index out of limit\n");
01310                 }
01311                 if (val.len && arr < 100) {
01312                     if (prefix != NULL || arr >= 0) {
01313                         if ((prefix?prefix->len:0)+name.len+1+((arr>=0)?3/*#99*/:0) > sizeof(name_buf)) {
01314                             if (arr <= 0)
01315                                 LOG(L_ERR, "ERROR: avp name too long\n");
01316                             goto cont;
01317                         }
01318                         name2.s.len = 0;
01319                         name2.s.s = name_buf;
01320                         if (prefix != NULL) {
01321                             if (name_buf[0] == '\0') {
01322                                 memcpy(&name_buf[0], prefix->s, prefix->len);
01323                             }
01324                             name2.s.len += prefix->len;
01325                         }
01326                         if (arr <= 0) {
01327                             memcpy(&name_buf[name2.s.len], name.s, name.len);
01328                         }
01329                         name2.s.len += name.len;
01330                         if (arr >= 0) {
01331                             name_buf[name2.s.len] = '#';
01332                             name2.s.len++;
01333                             if (arr >= 10) {
01334                                 name_buf[name2.s.len] = '0'+ (arr / 10);
01335                                 name2.s.len++;
01336                             }
01337                             name_buf[name2.s.len] = '0'+ (arr % 10);
01338                             name2.s.len++;
01339                         }
01340                     }
01341                     else {
01342                         name2.s.s = name.s;
01343                         name2.s.len = name.len;
01344                     }
01345                     if ( ((val_type & AVP_VAL_STR) && (header->val_types & VAL_TYPE_STR)) ||
01346                          ((val_type & AVP_VAL_STR) == 0 && (header->val_types & VAL_TYPE_INT))  ) {
01347                         if (val_type) {
01348                             val2.s.s = val.s;
01349                             val2.s.len = val.len;
01350                             DBG("DEBUG: attr_hdr_body2attrs: adding avp '%.*s', sval: '%.*s'\n", name2.s.len, (char*) name2.s.s, val.len, val.s);
01351                         } else {
01352                             DBG("DEBUG: attr_hdr_body2attrs: adding avp '%.*s', ival: '%d'\n", name2.s.len, (char*) name2.s.s, val2.n);
01353                         }
01354                         if ( add_avp(AVP_NAME_STR | val_type, name2, val2)!=0) {
01355                             LOG(L_ERR, "ERROR: attr_hdr_body2attrs: add_avp failed\n");
01356                             return 1;
01357                         }
01358                     }
01359                 }
01360             cont:
01361                 if (s.len && header->array_delimiter && header->array_delimiter == s.s[0]) {
01362                     s.s++;
01363                     s.len--;
01364                 }
01365                 else {
01366                     break;
01367                 }
01368             };
01369         }
01370         if (s.len && s.s[0] == header->field_delimiter) {
01371             s.s++;
01372             s.len--;
01373         }
01374         else {
01375             break;
01376         }
01377     }
01378     return 1;
01379 }
01380 
01381 
01382 static int attr_hdr_body2attrs2(struct sip_msg* msg, char* header_, char* prefix_) 
01383 {
01384     return attr_hdr_body2attrs(msg, header_, prefix_);
01385 }
01386 
01387 
01388 static int attr_hdr_body2attrs_fixup(void** param, int param_no) {
01389     char *c, *params;
01390     struct hdr_name *h;
01391     int n;
01392     str *s;
01393     if (param_no == 1) {
01394         c = *param;
01395         if (*c == '#') {
01396             c++;
01397             n = strtol(c, &params, 10);
01398             switch (*params) {
01399             case PARAM_DELIM:
01400                 break;
01401             case 0:
01402                 params = 0;
01403                 break;
01404             default:
01405                 LOG(L_ERR, "attr_hdr_body2attrs_fixup: bad AVP value\n");
01406                 return E_CFG;
01407             }
01408             switch (n) {
01409                 //                              case HDR_xxx:
01410                 //                              case HDR_xxx:
01411                 //                                      break;
01412             default:
01413                 LOG(L_ERR, "attr_hdr_body2attrs_fixup: header name is not valid and supported HDR_xxx id '%s' resolved as %d\n", c, n);
01414                 return E_CFG;
01415             }
01416             h = pkg_malloc(sizeof(*h));
01417             if (!h) {
01418                 LOG(L_ERR, "attr_hdr_body2attrs_fixup: out of memory\n");
01419                 return E_OUT_OF_MEM;
01420             }
01421             
01422             h->kind = HDR_ID;
01423             h->name.n = n;
01424             pkg_free(*param);
01425             
01426         }
01427         else {
01428             params = strchr(c, PARAM_DELIM);
01429             if (params)
01430                 n = params-c;
01431             else
01432                 n = strlen(c);
01433             if (n == 0) {
01434                 LOG(L_ERR, "attr_hdr_body2attrs_fixup: header name is empty\n");
01435                 return E_CFG;
01436             }
01437             h = pkg_malloc(sizeof(*h)+n+1);
01438             if (!h) {
01439                 LOG(L_ERR, "attr_hdr_body2attrs_fixup: out of memory\n");
01440                 return E_OUT_OF_MEM;
01441             }
01442             h->kind = HDR_STR;
01443             h->name.s.len = n;
01444             h->name.s.s = (char *) h + sizeof(*h);
01445             memcpy(h->name.s.s, c, n+1);
01446         }
01447         if (params) {
01448             h->val_types = 0;
01449             while (*params) {
01450                 switch (*params) {
01451                 case 'i':
01452                 case 'I':
01453                     h->val_types = VAL_TYPE_INT;
01454                     break;
01455                 case 's':
01456                 case 'S':
01457                     h->val_types = VAL_TYPE_STR;
01458                     break;
01459                 case PARAM_DELIM:
01460                     break;
01461                 default:
01462                     LOG(L_ERR, "attr_hdr_body2attrs_fixup: bad field param modifier near '%s'\n", params);
01463                     return E_CFG;
01464                 }
01465                 params++;
01466             }
01467             if (!h->val_types) {
01468                 LOG(L_ERR, "attr_hdr_body2attrs_fixup: no field param modifier specified\n");
01469                 return E_CFG;
01470             }
01471         }
01472         else {
01473             h->val_types = VAL_TYPE_INT|VAL_TYPE_STR;
01474         }
01475         pkg_free(*param);
01476         h->field_delimiter = ',';
01477         h->array_delimiter = '\0';
01478         
01479         *param = h;
01480     }
01481     else if (param_no == 2) {
01482         n = strlen(*param);
01483         if (n == 0) {
01484             s = NULL;
01485         }
01486         else {
01487             s = pkg_malloc(sizeof(*s)+n+1);
01488             if (!s) {
01489                 LOG(L_ERR, "attr_hdr_body2attrs_fixup: out of memory\n");
01490                 return E_OUT_OF_MEM;
01491             }
01492             s->len = n;
01493             s->s = (char *) s + sizeof(*s);
01494             memcpy(s->s, *param, n+1);
01495         }
01496         pkg_free(*param);
01497         *param = s;
01498     }
01499     return 0;
01500 }
01501 
01502 static int attr_hdr_body2attrs2_fixup(void** param, int param_no) 
01503 {
01504     struct hdr_name *h;
01505     int res = attr_hdr_body2attrs_fixup(param, param_no);
01506     if (res == 0 && param_no == 1) {
01507         h = *param;
01508         h->field_delimiter = ';';
01509         h->array_delimiter = ',';
01510     }
01511     return res;
01512 }
01513 
01514 
01515 
01516 static int avpgroup_fixup(void** param, int param_no)
01517 {
01518     unsigned long flags;
01519     char* s;
01520     
01521     if (param_no == 1) {
01522              /* Determine the track and class of attributes to be loaded */
01523         s = (char*)*param;
01524         flags = 0;
01525         if (*s != '$' || (strlen(s) != 3 && strlen(s) != 2)) {
01526             ERR("Invalid parameter value, $xy expected\n");
01527             return -1;
01528         }
01529         switch((s[1] << 8) + s[2]) {
01530         case 0x4655: /* $fu */
01531         case 0x6675:
01532         case 0x4675:
01533         case 0x6655:
01534             flags = AVP_TRACK_FROM | AVP_CLASS_USER;
01535             break;
01536             
01537         case 0x4652: /* $fr */
01538         case 0x6672:
01539         case 0x4672:
01540         case 0x6652:
01541             flags = AVP_TRACK_FROM | AVP_CLASS_URI;
01542             break;
01543             
01544         case 0x5455: /* $tu */
01545         case 0x7475:
01546         case 0x5475:
01547         case 0x7455:
01548             flags = AVP_TRACK_TO | AVP_CLASS_USER;
01549             break;
01550             
01551         case 0x5452: /* $tr */
01552         case 0x7472:
01553         case 0x5472:
01554         case 0x7452:
01555             flags = AVP_TRACK_TO | AVP_CLASS_URI;
01556             break;
01557 
01558         case 0x4644: /* $fd */
01559         case 0x6664:
01560         case 0x4664:
01561         case 0x6644:
01562             flags = AVP_TRACK_FROM | AVP_CLASS_DOMAIN;
01563             break;
01564 
01565         case 0x5444: /* $td */
01566         case 0x7464:
01567         case 0x5464:
01568         case 0x7444:
01569             flags = AVP_TRACK_TO | AVP_CLASS_DOMAIN;
01570             break;
01571 
01572         case 0x6700: /* $td */
01573         case 0x4700:
01574             flags = AVP_CLASS_GLOBAL;
01575             break;
01576             
01577         default:
01578             ERR("Invalid parameter value: '%s'\n", s);
01579             return -1;
01580         }
01581         
01582         pkg_free(*param);
01583         *param = (void*)flags;
01584         return 1;
01585     }
01586     return 0;
01587 }
01588 
01589 
01590 
01591 static int select_attr_fixup(str* res, select_t* s, struct sip_msg* msg)
01592 {
01593         avp_ident_t *avp_ident;
01594 
01595 #define SEL_PARAM_IDX   1
01596 
01597         if (! msg) { /* fixup call */
01598                 str attr_name;
01599                 
01600                 if (s->params[SEL_PARAM_IDX].type != SEL_PARAM_STR) {
01601                         ERR("attribute name expected.\n");
01602                         return -1;
01603                 }
01604 
01605                 attr_name = s->params[SEL_PARAM_IDX].v.s;
01606                 DEBUG("fix up for attribute '%.*s'\n", STR_FMT(&attr_name));
01607 
01608                 if (! (avp_ident = pkg_malloc(sizeof(avp_ident_t)))) {
01609                         ERR("out of mem; requested: %d.\n", (int)sizeof(avp_ident_t));
01610                         return -1;
01611                 }
01612                 memset(avp_ident, 0, sizeof(avp_ident_t));
01613 
01614                 /* skip leading `$' */
01615                 if ((1 < attr_name.len) && (attr_name.s[0] == '$')) {
01616                         attr_name.len --;
01617                         attr_name.s ++;
01618                 }
01619                 if (parse_avp_ident(&attr_name, avp_ident) < 0) {
01620                         ERR("failed to parse attribute name: `%.*s'.\n", STR_FMT(&attr_name));
01621                         pkg_free(avp_ident);
01622                 }
01623                 s->params[SEL_PARAM_IDX].v.p = avp_ident;
01624                 s->params[SEL_PARAM_IDX].type = SEL_PARAM_PTR;
01625         } else { /* run time call */
01626                 avp_t *ret;
01627                 avp_value_t val;
01628 
01629 #ifdef EXTRA_DEBUG
01630                 assert(s->params[SEL_PARAM_IDX].type == SEL_PARAM_PTR);
01631 #endif
01632                 avp_ident = s->params[SEL_PARAM_IDX].v.p;
01633                 ret = search_first_avp(avp_ident->flags, avp_ident->name, &val, NULL);
01634                 if (ret && ret->flags & AVP_VAL_STR)
01635                         *res = val.s;
01636         }
01637 
01638         return 0;
01639 
01640 #undef SEL_PARAM_IDX
01641 }
01642 
01643 SELECT_F(select_any_nameaddr)
01644 ABSTRACT_F(select_attr);
01645 
01646 select_row_t sel_declaration[] = {
01647         { NULL, SEL_PARAM_STR, STR_STATIC_INIT("avp"), select_attr, SEL_PARAM_EXPECTED},
01648         { NULL, SEL_PARAM_STR, STR_STATIC_INIT("attr"), select_attr, SEL_PARAM_EXPECTED},
01649         { NULL, SEL_PARAM_STR, STR_STATIC_INIT("attribute"), select_attr, SEL_PARAM_EXPECTED},
01650         { select_attr, SEL_PARAM_STR, STR_NULL, select_attr_fixup, FIXUP_CALL | CONSUME_NEXT_STR},
01651 
01652         { select_attr_fixup, SEL_PARAM_STR, STR_STATIC_INIT("nameaddr"), select_any_nameaddr, NESTED},
01653 
01654         { NULL, SEL_PARAM_INT, STR_NULL, NULL, 0}
01655 };
01656 
01657 static int mod_init()
01658 {
01659         DBG("%s - initializing\n", exports.name);
01660         return register_select_table(sel_declaration);
01661 }