/* * from a token in form of * tag->value extract the tag and the value * @param token * @param tag reference * @param value reference * @return 0 (success) / < 0 (error) * * tag and value must be allocated beforehand */ static int parse_extra_token(str* token, str* tag, str* value) { /* insanity checks */ if (token == NULL || token->len == 0 || token->s == NULL || tag == NULL || value == NULL) { LM_ERR("bad input!\n"); return -1; } /* value will not point exactly where the value is * will point where the - character from the '->' delimiter will be */ if ((value->s = str_strstr(token, &tag_delim)) == NULL) { /* if not found then the value is the same as the token */ str_trim_spaces_lr(*token); *value = *tag = *token; } else { tag->s = token->s; tag->len = value->s - token->s; /* jump over '->' delimiter */ value->s += tag_delim.len; value->len = token->len - (value->s - token->s); str_trim_spaces_lr(*tag); str_trim_spaces_lr(*value); } return 0; }
/** * types: log, aaa, db, diam, evi * case insesitive * */ static inline unsigned long long do_acc_type_parser(str* token) { str_trim_spaces_lr(*token); if (token->len == do_acc_log_s.len && !strncasecmp(token->s, do_acc_log_s.s, token->len)) { return DO_ACC_LOG; } else if (token->len == do_acc_aaa_s.len && !strncasecmp(token->s, do_acc_aaa_s.s, token->len)) { return DO_ACC_AAA; } else if (token->len == do_acc_db_s.len && !strncasecmp(token->s, do_acc_db_s.s, token->len)) { return DO_ACC_DB; } else if (token->len == do_acc_diam_s.len && !strncasecmp(token->s, do_acc_diam_s.s, token->len)) { return DO_ACC_DIAM; } else if (token->len == do_acc_evi_s.len && !strncasecmp(token->s, do_acc_evi_s.s, token->len)) { return DO_ACC_EVI; } else { LM_ERR("Invalid token <%.*s>!\n", token->len, token->s); return -1; } }
int check_addr_param1(str *s, struct part_var *pv) { char *end; unsigned int gid; int ret; str spart, sval; ret=0; spart.s = s->s; end = q_memchr(s->s, ':', s->len); ret = -1; if (end == NULL) { ret = str2int(s, &gid); pv->u.parsed_part.partition.s = NULL; if (0 == ret) pv->u.parsed_part.v.ival = gid; else { pv->u.parsed_part.v.sval.s = s->s; pv->u.parsed_part.v.sval.len = s->len; } } else { spart.len = end - spart.s; sval.s = end + 1; sval.len = (s->s + s->len) - sval.s; str_trim_spaces_lr(sval); str_trim_spaces_lr(spart); pv->u.parsed_part.partition = spart; ret = str2int(&sval, &gid); if (0 == ret) pv->u.parsed_part.v.ival = gid; else pv->u.parsed_part.v.sval = sval; } return 0; }
int pv_parse_acc_leg_index(pv_spec_p sp, str* in) { int idx; pv_spec_p e; if (in == NULL || in->s == NULL || in->len == 0) { LM_ERR("bad index!\n"); return -1; } if (sp == NULL) { LM_ERR("bad pv spec!\n"); return -1; } str_trim_spaces_lr(*in); if (in->s[0] == PV_MARKER) { e=pkg_malloc(sizeof(pv_spec_t)); if (e==NULL) { LM_ERR("no more pkg mem!\n"); return -1; } memset(e, 0, sizeof(pv_spec_t)); if (pv_parse_spec(in, e) == NULL) { LM_ERR("failed to parse index variable!\n"); pv_spec_free(e); return -1; } sp->pvp.pvi.type = PV_IDX_PVAR; sp->pvp.pvi.u.dval = (void *)e; } else { if (str2sint(in, &idx) < 0) { LM_ERR("bad index! not a number! <%.*s>!\n", in->len, in->s); return -1; } sp->pvp.pvi.type = PV_IDX_INT; sp->pvp.pvi.u.ival = idx; } return 0; }
/** * types: cdr, missed * case insesitive * */ static inline unsigned long long do_acc_flags_parser(str* token) { str_trim_spaces_lr(*token); if (token->len == do_acc_cdr_s.len && !strncasecmp(token->s, do_acc_cdr_s.s, token->len)) { if (!is_cdr_enabled) { if (parse_avp_spec( &acc_created_avp_name, &acc_created_avp_id) < 0) { LM_ERR("failed to register AVP name <%s>\n", acc_created_avp_name.s); return -1; } if (load_dlg_api(&dlg_api)!=0) LM_DBG("failed to find dialog API - is dialog module loaded?\n"); if (!dlg_api.get_dlg) { LM_WARN("error loading dialog module - cdrs cannot be generated\n"); return 0; } if (dlg_api.get_dlg && dlg_api.register_dlgcb(NULL, DLGCB_LOADED,acc_loaded_callback, NULL, NULL) < 0) LM_ERR("cannot register callback for dialog loaded - accounting " "for ongoing calls will be lost after restart\n"); is_cdr_enabled=1; } return DO_ACC_CDR; } else if (token->len == do_acc_missed_s.len && !strncasecmp(token->s, do_acc_missed_s.s, token->len)) { /* load dialog module if these are used */ return DO_ACC_MISSED; } else if (token->len == do_acc_failed_s.len && !strncasecmp(token->s, do_acc_failed_s.s, token->len)) { return DO_ACC_FAILED; } else { return -1; } }
/* * set default partition table */ int set_default_table(modparam_t type, void *val) { str db_table; db_table.s = (char *)val; db_table.len = strlen(db_table.s); str_trim_spaces_lr(db_table); if (default_partition == NULL) if (alloc_default_partition() == NULL) goto out_nomem; default_partition->table = db_table; return 0; out_nomem: LM_ERR("no more memory!\n"); return -1; }
/* * set default partition url */ int set_default_db_url(modparam_t type, void *val) { str db_str; db_str.s = (char *)val; db_str.len = strlen(db_str.s); str_trim_spaces_lr(db_str); if (default_partition == NULL) if (alloc_default_partition() == NULL) goto out_nomem; default_partition->url.s = (char *)val; init_db_url( default_partition->url, 1 /* can be null */); return 0; out_nomem: LM_ERR("no more memory!\n"); return -1; }
/* * parse $acc_extra variable name */ int pv_parse_acc_extra_name(pv_spec_p sp, str *in) { int idx; if (sp == NULL || in == NULL || in->s == NULL || in->len == 0) { LM_ERR("bad name!\n"); return -1; } str_trim_spaces_lr(*in); for (idx=0; idx<extra_tgs_len; idx++) { if (in->len == extra_tags[idx].len && !memcmp(in->s, extra_tags[idx].s, extra_tags[idx].len)) { sp->pvp.pvn.u.isname.name.n = idx; return 0; } } LM_ERR("tag <%.*s> not declared in modparam section!\n", in->len, in->s); return -1; }
/* * parse acc extra element in form of * <backend>:<tag1>=<value1>;<tag2>=<value2>[;] * last semicolon may miss * all tags shall be added (if not present) to the tag list * and be linked to all extra structures in acc_extra lists by * the index in the vector * * @param string to be parsed(char*) * @return 0(success) / < 0 (error) */ static int parse_acc_list_generic(void* val, str2bkend str2bk, tag_t** tag_arr, int* tags_len) { str sent={(char*)val, strlen((char*)val)}; str tok_list_s, backend_s; str token, tag, value; struct acc_extra** bkend_list; char* end; if ((end=q_memchr(sent.s, ':', sent.len)) == NULL) { LM_ERR("Missing backend separator ':'!\n"); return -1; } backend_s.s = sent.s; backend_s.len = end-sent.s; str_trim_spaces_lr(backend_s); if ((bkend_list = str2bk(&backend_s)) == NULL) { LM_ERR("Invalid backend <%.*s>\n", backend_s.len, backend_s.s); return -1; } tok_list_s.s = end+1; tok_list_s.len = sent.len - (end - sent.s + 1); do { end=q_memchr(tok_list_s.s, ';', tok_list_s.len); /* get key=value parameter */ token.s = tok_list_s.s; if (end != NULL) { token.len = end-tok_list_s.s; tok_list_s.len = tok_list_s.len - (end - tok_list_s.s + 1); tok_list_s.s = end + 1; } else { token.len = tok_list_s.len; } /* we reached the end or there are probably some trailing spaces * after the last ';' */ str_trim_spaces_lr(token); if (!token.len) break; if (parse_extra_token(&token, &tag, &value) < 0) { LM_ERR("failed to parse token!\n"); return -1; } if (add_extra(&tag, &value, bkend_list, tag_arr, tags_len) < 0) { LM_ERR("failed to add extra!\n"); return -1; } } while (end); return 0; }
/* * parse a partition parameter of type * <part_name> : attr1=val1; attr2=val2; */ int parse_partition(modparam_t t, void *val) { str type, value, token; char *tok_end; struct pm_partition *el, *it; str decl = {(char*)val, strlen((char *)val)}; if (get_partitions() == NULL) { if (alloc_partitions() == NULL) goto out_memfault; el=get_partitions(); } else { el=pkg_malloc(sizeof(struct pm_partition)); if (el == NULL) goto out_memfault; memset(el, 0, sizeof(struct pm_partition)); for (it=get_partitions(); it->next; it=it->next); it->next = el; } tok_end = q_memchr(decl.s, ':', decl.len); if (tok_end == NULL) goto out_invdef; value.s = decl.s; value.len = tok_end - decl.s; str_trim_spaces_lr(value); el->name = value; decl.len = decl.len - (++tok_end - decl.s); decl.s = tok_end; while (decl.len > 0 && decl.s) { tok_end = q_memchr(decl.s, ';', decl.len); if (tok_end == NULL) break; token.s = decl.s; token.len = tok_end - token.s; tok_end = q_memchr(token.s, '=', token.len); if (tok_end == NULL) break; type.s = token.s; type.len = tok_end - type.s; value.s = tok_end + 1; value.len = (token.s + token.len) - value.s; decl.s += token.len + 1; decl.len -= (token.len + 1); str_trim_spaces_lr(type); str_trim_spaces_lr(value); if (!str_strcmp( &type, &part_db_url)) el->url = value; else if (!str_strcmp( &type, &part_table_name)) el->table = value; else goto out_invdef; } if (el->url.s == NULL) { LM_ERR("you should define an URL for this partition %.*s\n", el->name.len, el->name.s); return -1; } return 0; out_invdef: LM_ERR("invalid partition definition!\n"); return -ERR; out_memfault: LM_ERR("no more memory\n"); return -ERR; }
static int dp_create_head(str part_desc) { str tmp; str *partition; str param_type, param_value; char* end, *start; int ulen = strlen(PARAM_URL), tlen = strlen(PARAM_TABLE); tmp.s = part_desc.s; end = q_memchr(part_desc.s, DP_CHAR_COLON, part_desc.len); if (end == NULL) goto out_err; tmp.len = end - tmp.s; str_trim_spaces_lr(tmp); partition = str_n_dup( &tmp, tmp.len); if (partition == NULL) goto mem_err; do { start = ++end; end = q_memchr(start, DP_CHAR_SCOLON, part_desc.s + part_desc.len - start); if (end == NULL) break; param_type.s = start; param_value.s = q_memchr(start, DP_CHAR_EQUAL, part_desc.len + part_desc.s - start); if (param_value.s == 0) goto out_err; param_type.len = (param_value.s - 1) - param_type.s; param_value.len = end - (++param_value.s); str_trim_spaces_lr(param_type); str_trim_spaces_lr(param_value); if ( !memcmp(param_type.s, PARAM_URL, ulen)) { dp_head_insert( DP_TYPE_URL, param_value, *partition); } else if ( !memcmp( param_type.s, PARAM_TABLE, tlen)) { dp_head_insert( DP_TYPE_TABLE, param_value, *partition); } else { LM_ERR("Invalid parameter type\n"); return -1; } } while(1); return 0; out_err: LM_ERR("invalid partition param definition\n"); return -1; mem_err: LM_ERR("no more memory\n"); return -1; }
static int dp_create_head(str part_desc) { str tmp; str partition; str param_type, param_value; char* end, *start; int ulen = strlen(PARAM_URL), tlen = strlen(PARAM_TABLE); tmp.s = part_desc.s; end = q_memchr(part_desc.s, DP_CHAR_COLON, part_desc.len); if (end == NULL) { LM_ERR("[[%s]]\n", tmp.s); goto out_err; } tmp.len = end - tmp.s; str_trim_spaces_lr(tmp); partition = tmp; do { start = ++end; end = q_memchr(start, DP_CHAR_SCOLON, part_desc.s + part_desc.len - start); if (end == NULL) break; param_type.s = start; param_value.s = q_memchr(start, DP_CHAR_EQUAL, part_desc.len + part_desc.s - start); if (param_value.s == 0) { LM_ERR("[[%s]]!\n", param_value.s); goto out_err; } param_type.len = param_value.s - param_type.s; param_value.len = end - (++param_value.s); str_trim_spaces_lr(param_type); str_trim_spaces_lr(param_value); if (param_type.len == ulen && !memcmp(param_type.s, PARAM_URL, ulen)) { dp_head_insert( DP_TYPE_URL, ¶m_value, &partition); } else if ( param_type.len == tlen && !memcmp( param_type.s, PARAM_TABLE, tlen)) { dp_head_insert( DP_TYPE_TABLE, ¶m_value, &partition); } else { LM_ERR("Invalid parameter type definition [[%.*s]]\n", param_type.len, param_type.s); return -1; } } while(1); return 0; out_err: LM_ERR("invalid partition param definition\n"); return -1; }
int get_source_group(struct sip_msg* msg, char *arg) { int group = -1; struct in_addr in; struct ip_addr *ip; str str_ip, partition; pv_value_t pvt; struct part_pvar *ppv; struct pm_part_struct *ps; ppv = (struct part_pvar *)arg; if (ppv->part) { if (fixup_get_svalue(msg, ppv->part, &partition)) { LM_ERR("cannot get partition value\n"); return -1; } str_trim_spaces_lr(partition); ps = get_part_struct(&partition); if (ps == NULL) { LM_ERR("no such partition (%.*s)\n", partition.len, partition.s); return -1; } } else { ps = get_part_struct(&def_part); if (ps == NULL) { LM_ERR("no default partition\n"); return -1; } } LM_DBG("Looking for <%x, %u> in address table\n", msg->rcv.src_ip.u.addr32[0], msg->rcv.src_port); in.s_addr = msg->rcv.src_ip.u.addr32[0]; str_ip.s = inet_ntoa(in); str_ip.len = str_ip.s ? strlen(str_ip.s) : 0; ip = str2ip(&str_ip); group = find_group_in_hash_table(*ps->hash_table, ip, msg->rcv.src_port); group=0; LM_DBG("Found <%d>\n", group); if (group == -1) { LM_DBG("Looking for <%x, %u> in subnet table\n", msg->rcv.src_ip.u.addr32[0], msg->rcv.src_port); /* TODO FIX INPUT PARAMS*/ group = find_group_in_subnet_table(*ps->subnet_table, ip, msg->rcv.src_port); group = 0; LM_DBG("Found <%d>\n", group); } pvt.flags = PV_VAL_INT|PV_TYPE_INT; pvt.rs.s = NULL; pvt.rs.len = 0; pvt.ri = group; if (pv_set_value(msg, ppv->sp, (int)EQ_T, &pvt) < 0) { LM_ERR("setting of pvar failed\n"); return -1; } return 1; }