int ops_is_avp_set(struct sip_msg* msg, struct fis_param *ap) { struct usr_avp *avp; unsigned short name_type; int avp_name; int_str avp_value; int index; int findex; /* get avp name */ if(avpops_get_aname(msg, ap, &avp_name, &name_type)!=0) { LM_ERR("failed to get AVP name\n"); return -1; } /* get avp index */ if(pv_get_spec_index(msg, &ap->u.sval.pvp, &index, &findex)!=0) { LM_ERR("failed to get AVP index\n"); return -1; } avp=search_first_avp(name_type, avp_name, &avp_value, 0); if(avp==0) return -1; do { /* last index [-1] or all [*] go here as well */ if(index<=0) { if(ap->ops&AVPOPS_FLAG_ALL) return 1; if((ap->ops&AVPOPS_FLAG_CASTS && !(avp->flags&AVP_VAL_STR)) ||(ap->ops&AVPOPS_FLAG_CASTN && avp->flags&AVP_VAL_STR)) return -1; if(ap->ops&AVPOPS_FLAG_EMPTY) { if(avp->flags&AVP_VAL_STR) { if(avp_value.s.s==0 || avp_value.s.len==0) return 1; else return -1; } else { if(avp_value.n==0) return 1; else return -1; } } return 1; } index--; } while ((avp=search_first_avp(name_type, avp_name, &avp_value, avp))!=0); return -1; }
int pv_get_xavp(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) { pv_xavp_name_t *xname=NULL; sr_xavp_t *avp=NULL; int idxf = 0; int idx = 0; int count; char *p, *p_ini; int p_size; if(param==NULL) { LM_ERR("bad parameters\n"); return -1; } xname = (pv_xavp_name_t*)param->pvn.u.dname; if(xname->index.type==PVT_EXTRA) { /* get the index */ if(pv_get_spec_index(msg, &xname->index.pvp, &idx, &idxf)!=0) { LM_ERR("invalid index\n"); return -1; } } /* fix the index */ if(idx<0) { count = xavp_count(&xname->name, NULL); idx = count + idx; } avp = xavp_get_by_index(&xname->name, idx, NULL); if(avp==NULL) return pv_get_null(msg, param, res); if(xname->next==NULL) return pv_xavp_get_value(msg, param, res, avp); if(avp->val.type != SR_XTYPE_XAVP) return pv_get_null(msg, param, res); idx = 0; idxf = 0; if(xname->next->index.type==PVT_EXTRA) { /* get the index */ if(pv_get_spec_index(msg, &xname->next->index.pvp, &idx, &idxf)!=0) { LM_ERR("invalid index\n"); return -1; } } /* fix the index */ if(idx<0) { count = xavp_count(&xname->next->name, &avp->val.v.xavp); idx = count + idx; } avp = xavp_get_by_index(&xname->next->name, idx, &avp->val.v.xavp); if(avp==NULL) return pv_get_null(msg, param, res); /* get all values of second key */ if(idxf==PV_IDX_ALL) { p_ini = pv_get_buffer(); p = p_ini; p_size = pv_get_buffer_size(); do { if(p!=p_ini) { if(p-p_ini+PV_FIELD_DELIM_LEN+1>p_size) { LM_ERR("local buffer length exceeded\n"); return pv_get_null(msg, param, res); } memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN); p += PV_FIELD_DELIM_LEN; } if(pv_xavp_get_value(msg, param, res, avp)<0) { LM_ERR("can get value\n"); return pv_get_null(msg, param, res); } if(p-p_ini+res->rs.len+1>p_size) { LM_ERR("local buffer length exceeded!\n"); return pv_get_null(msg, param, res); } memcpy(p, res->rs.s, res->rs.len); p += res->rs.len; } while ((avp=xavp_get_next(avp))!=0); res->rs.s = p_ini; res->rs.len = p - p_ini; return 0; } return pv_xavp_get_value(msg, param, res, avp); }
/** * $xavp(name1[idx1]=>name2[idx2]) */ int pv_set_xavp(struct sip_msg* msg, pv_param_t *param, int op, pv_value_t *val) { pv_xavp_name_t *xname=NULL; sr_xavp_t *avp=NULL; sr_xavp_t *list=NULL; sr_xval_t xval; int idxf = 0; int idx = 0; int idxf1 = 0; int idx1 = 0; int count; if(param==NULL) { LM_ERR("bad parameters\n"); return -1; } xname = (pv_xavp_name_t*)param->pvn.u.dname; if(xname->index.type==PVT_EXTRA) { /* get the index */ if(pv_get_spec_index(msg, &xname->index.pvp, &idx, &idxf)!=0) { LM_ERR("invalid index\n"); return -1; } } if((val==NULL) || (val->flags&PV_VAL_NULL)) { if(xname->next==NULL) { if(xname->index.type==PVT_EXTRA) { if(idxf==PV_IDX_ALL) { xavp_rm_by_name(&xname->name, 1, NULL); return 0; } } if(idx==0) { xavp_rm_by_name(&xname->name, 0, NULL); return 0; } /* fix the index */ if(idx<0) { count = xavp_count(&xname->name, NULL); idx = count + idx + 1; } xavp_rm_by_index(&xname->name, idx, NULL); return 0; } if(xname->next->index.type==PVT_EXTRA) { /* get the index */ if(pv_get_spec_index(msg,&xname->next->index.pvp,&idx1,&idxf1)!=0) { LM_ERR("invalid index!\n"); return -1; } } if(idxf==PV_IDX_ALL) { /* iterate */ avp = xavp_get(&xname->name, NULL); while(avp) { if(avp->val.type==SR_XTYPE_XAVP) { if(xname->next->index.type==PVT_EXTRA) { if(idxf1==PV_IDX_ALL) { xavp_rm_by_name(&xname->next->name, 1, &avp->val.v.xavp); } else { /* fix the index */ idx = idx1; if(idx<0) { count = xavp_count(&xname->next->name, &avp->val.v.xavp); idx = count + idx1 + 1; } xavp_rm_by_index(&xname->next->name, idx, &avp->val.v.xavp); } } else { xavp_rm_by_name(&xname->next->name, 0, &avp->val.v.xavp); } } avp = xavp_get_next(avp); } return 0; } if(idx==0) { avp = xavp_get(&xname->name, NULL); } else { /* fix the index */ if(idx<0) { count = xavp_count(&xname->name, NULL); idx = count + idx + 1; } avp = xavp_get_by_index(&xname->name, idx, NULL); } if(avp) { if(avp->val.type==SR_XTYPE_XAVP) { if(xname->next->index.type==PVT_EXTRA) { if(idxf1==PV_IDX_ALL) { xavp_rm_by_name(&xname->next->name, 1, &avp->val.v.xavp); } else { /* fix the index */ idx = idx1; if(idx<0) { count = xavp_count(&xname->next->name, &avp->val.v.xavp); idx = count + idx1 + 1; } xavp_rm_by_index(&xname->next->name, idx, &avp->val.v.xavp); } } else { xavp_rm_by_name(&xname->next->name, 0, &avp->val.v.xavp); } } } return 0; } /* NULL assignment */ /* build xavp value */ memset(&xval, 0, sizeof(sr_xval_t)); if(val->flags&PV_TYPE_INT) { xval.type = SR_XTYPE_INT; xval.v.i = val->ri; } else { xval.type = SR_XTYPE_STR; xval.v.s = val->rs; } /* where to add */ if(xname->next==NULL) { /* xavp with single value */ if(xname->index.type==PVT_EXTRA) { if(idxf==PV_IDX_ALL) { /* ignore: should iterate and set same value to all xavps * with same name?!?! */ return -1; } /* fix the index */ if(idx<0) { count = xavp_count(&xname->name, NULL); idx = count + idx + 1; } /* set the value */ if(xavp_set_value(&xname->name, idx, &xval, NULL)==NULL) return -1; return 0; } /* add new value */ if(xavp_add_value(&xname->name, &xval, NULL)==NULL) return -1; return 0; } /* xavp with xavp list value */ if(xname->next->index.type==PVT_EXTRA) { /* get the index */ if(pv_get_spec_index(msg,&xname->next->index.pvp,&idx1,&idxf1)!=0) { LM_ERR("invalid index!\n"); return -1; } } if(xname->index.type==PVT_EXTRA) { /* set the value */ if(idxf==PV_IDX_ALL) { /* ignore: should iterate and set same value to all xavps * with same name?!?! */ return 0; } if(idx==0) { avp = xavp_get(&xname->name, NULL); } else { /* fix the index */ if(idx<0) { count = xavp_count(&xname->name, NULL); idx = count + idx + 1; } avp = xavp_get_by_index(&xname->name, idx, NULL); } if(avp==NULL) return 0; if(avp->val.type!=SR_XTYPE_XAVP) return -1; if(xname->next->index.type==PVT_EXTRA) { if(idxf1==PV_IDX_ALL) { /* ignore: should iterate and set same value to all xavps * with same name?!?! */ return 0; } /* fix the index */ idx = idx1; if(idx<0) { count = xavp_count(&xname->next->name, &avp->val.v.xavp); idx = count + idx1 + 1; } /* set value */ xavp_set_value(&xname->next->name, idx, &xval, &avp->val.v.xavp); return 0; } /* add new value in sublist */ if(xavp_add_value(&xname->next->name, &xval, &avp->val.v.xavp)==NULL) return -1; return 0; } /* add new xavp with xavp list */ if(xavp_add_value(&xname->next->name, &xval, &list)==NULL) return -1; /* build xavp value */ memset(&xval, 0, sizeof(sr_xval_t)); xval.type = SR_XTYPE_XAVP; xval.v.xavp = list; xavp_add_value(&xname->name, &xval, NULL); return 0; }
int pv_get_ulc(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) { regpv_name_t *rp; regpv_profile_t *rpp; ucontact_t *c; int idx; int i; if(param==NULL) { LM_ERR("invalid params\n"); return -1; } rp = (regpv_name_t*)param->pvn.u.dname; if(rp==NULL || rp->rp==NULL) { LM_DBG("no profile in params\n"); return pv_get_null(msg, param, res); } rpp = rp->rp; if(rpp->flags==0 || rpp->contacts==NULL) { LM_DBG("profile not set or no contacts there\n"); return pv_get_null(msg, param, res); } /* get index */ if(pv_get_spec_index(msg, param, &idx, &i)!=0) { LM_ERR("invalid index\n"); return -1; } /* work only with positive indexes by now */ if(idx<0) idx = 0; /* get contact */ i = 0; c = rpp->contacts; while(rpp) { if(i == idx) break; i++; c = c->next; } if(c==NULL) return pv_get_null(msg, param, res); switch(rp->attr) { case 0: /* aor */ return pv_get_strval(msg, param, res, &rpp->aor); break; case 1: /* domain */ return pv_get_strval(msg, param, res, &rpp->domain); break; case 2: /* aorhash */ return pv_get_uintval(msg, param, res, rpp->aorhash); break; case 3: /* addr */ return pv_get_strval(msg, param, res, &c->c); break; case 4: /* path */ return pv_get_strval(msg, param, res, &c->path); break; case 5: /* received */ return pv_get_strval(msg, param, res, &c->received); break; case 6: /* expires */ return pv_get_uintval(msg, param, res, (unsigned int)c->expires); break; case 7: /* callid */ return pv_get_strval(msg, param, res, &c->callid); break; case 8: /* q */ return pv_get_sintval(msg, param, res, (int)c->q); break; case 9: /* cseq */ return pv_get_sintval(msg, param, res, c->cseq); break; case 10: /* flags */ return pv_get_uintval(msg, param, res, c->flags); break; case 11: /* cflags */ return pv_get_uintval(msg, param, res, c->cflags); break; case 12: /* user agent */ return pv_get_strval(msg, param, res, &c->user_agent); break; case 14: /* socket */ if(c->sock==NULL) return pv_get_null(msg, param, res); return pv_get_strval(msg, param, res, &c->sock->sock_str); break; case 15: /* modified */ return pv_get_uintval(msg, param, res, (unsigned int)c->last_modified); break; case 16: /* methods */ return pv_get_uintval(msg, param, res, c->methods); break; case 17: /* count */ return pv_get_sintval(msg, param, res, rpp->nrc); break; } return pv_get_null(msg, param, res); }
int pv_get_branchx_helper(sip_msg_t *msg, pv_param_t *param, pv_value_t *res, int btype) { int idx = 0; int idxf = 0; branch_t *br; if(btype==1) { br = &_pv_sbranch; } else { /* get the index */ if(pv_get_spec_index(msg, param, &idx, &idxf)!=0) { LM_ERR("invalid index\n"); return pv_get_null(msg, param, res); } br = get_sip_branch(idx); if(br==NULL) { return pv_get_null(msg, param, res); } } /* branch(count) doesn't need a valid branch, everything else does */ if(br->len == 0 && ( param->pvn.u.isname.name.n != 5/* count*/ )) { LM_ERR("error accessing branch [%d]\n", idx); return pv_get_null(msg, param, res); } switch(param->pvn.u.isname.name.n) { case 1: /* dst uri */ if(br->dst_uri_len==0) return pv_get_null(msg, param, res); return pv_get_strlval(msg, param, res, br->dst_uri, br->dst_uri_len); case 2: /* path */ if(br->path_len==0) return pv_get_null(msg, param, res); return pv_get_strlval(msg, param, res, br->path, br->path_len); case 3: /* Q */ if(br->q == Q_UNSPECIFIED) return pv_get_null(msg, param, res); return pv_get_sintval(msg, param, res, br->q); case 4: /* send socket */ if(br->force_send_socket!=0) return pv_get_strval(msg, param, res, &br->force_send_socket->sock_str); return pv_get_null(msg, param, res); case 5: /* count */ return pv_get_uintval(msg, param, res, nr_branches); case 6: /* flags */ return pv_get_uintval(msg, param, res, br->flags); case 7: /* ruid */ if(br->ruid_len==0) return pv_get_null(msg, param, res); return pv_get_strlval(msg, param, res, br->ruid, br->ruid_len); case 8: /* location_ua */ if(br->location_ua_len==0) return pv_get_null(msg, param, res); return pv_get_strlval(msg, param, res, br->location_ua, br->location_ua_len); default: /* 0 - uri */ return pv_get_strlval(msg, param, res, br->uri, br->len); } return 0; }
int pv_set_branchx_helper(sip_msg_t *msg, pv_param_t *param, int op, pv_value_t *val, int btype) { int idx = 0; int idxf = 0; branch_t *br; struct socket_info *si; int port, proto; str host; char backup; if(msg==NULL || param==NULL) { LM_ERR("bad parameters\n"); return -1; } if(btype==1) { br = &_pv_sbranch; } else { /* get the index */ if(pv_get_spec_index(msg, param, &idx, &idxf)!=0) { LM_ERR("invalid index\n"); return -1; } if(idx<0) { if((int)nr_branches + idx >= 0) { idx += nr_branches; } else { LM_ERR("index too low: %d (%u)\n", idx, nr_branches); return -1; } } LM_DBG("managing branch index %d (%u)\n", idx, nr_branches); br = get_sip_branch(idx); } if(br==NULL) { LM_DBG("no branch to operate on\n"); return -1; } switch(param->pvn.u.isname.name.n) { case 1: /* dst uri */ if(val==NULL || (val->flags&PV_VAL_NULL)) { br->dst_uri[0] = '\0'; br->dst_uri_len = 0; break; } if(!(val->flags&PV_VAL_STR)) { LM_ERR("str value required to set branch dst uri\n"); return -1; } if(val->rs.len<=0) { br->dst_uri[0] = '\0'; br->dst_uri_len = 0; break; } if (unlikely(val->rs.len > MAX_URI_SIZE - 1)) { LM_ERR("too long dst uri: %.*s\n", val->rs.len, val->rs.s); return -1; } memcpy(br->dst_uri, val->rs.s, val->rs.len); br->dst_uri[val->rs.len] = 0; br->dst_uri_len = val->rs.len; break; case 2: /* path */ if(val==NULL || (val->flags&PV_VAL_NULL)) { br->path[0] = '\0'; br->path_len = 0; break; } if(!(val->flags&PV_VAL_STR)) { LM_ERR("str value required to set branch path\n"); return -1; } if(val->rs.len<=0) { br->path[0] = '\0'; br->path_len = 0; break; } if (unlikely(val->rs.len > MAX_PATH_SIZE - 1)) { LM_ERR("path too long: %.*s\n", val->rs.len, val->rs.s); return -1; } memcpy(br->path, val->rs.s, val->rs.len); br->path[val->rs.len] = 0; br->path_len = val->rs.len; break; case 3: /* Q */ if(val==NULL || (val->flags&PV_VAL_NULL)) { br->q = Q_UNSPECIFIED; break; } if(!(val->flags&PV_VAL_INT)) { LM_ERR("int value required to set branch q\n"); return -1; } br->q = val->ri; break; case 4: /* send socket */ if(val==NULL || (val->flags&PV_VAL_NULL)) { br->force_send_socket = NULL; break; } if(!(val->flags&PV_VAL_STR)) { LM_ERR("str value required to set branch send sock\n"); return -1; } if(val->rs.len<=0) { br->force_send_socket = NULL; break; } backup = val->rs.s[val->rs.len]; val->rs.s[val->rs.len] = '\0'; if (parse_phostport(val->rs.s, &host.s, &host.len, &port, &proto) < 0) { LM_ERR("invalid socket specification\n"); val->rs.s[val->rs.len] = backup; return -1; } val->rs.s[val->rs.len] = backup; si = grep_sock_info(&host, (unsigned short)port, (unsigned short)proto); if (si!=NULL) { br->force_send_socket = si; } else { LM_WARN("no socket found to match [%.*s]\n", val->rs.len, val->rs.s); br->force_send_socket = NULL; } break; case 5: /* count */ /* do nothing - cannot set the branch counter */ break; case 6: /* flags */ if(val==NULL || (val->flags&PV_VAL_NULL)) { br->flags = 0; break; } if(!(val->flags&PV_VAL_INT)) { LM_ERR("int value required to set branch flags\n"); return -1; } br->flags = val->ri; break; case 7: /* ruid */ /* do nothing - cannot set the ruid */ break; case 8: /* location_ua */ /* do nothing - cannot set the location_ua */ break; default: /* 0 - uri */ if(val==NULL || (val->flags&PV_VAL_NULL)) { if(btype==1) { memset(br, 0, sizeof(branch_t)); } else { drop_sip_branch(idx); } } else { if(!(val->flags&PV_VAL_STR)) { LM_ERR("str value required to set branch uri\n"); return -1; } if(val->rs.len<=0) { if(btype==1) { memset(br, 0, sizeof(branch_t)); } else { drop_sip_branch(idx); } } else { if (unlikely(val->rs.len > MAX_URI_SIZE - 1)) { LM_ERR("too long r-uri: %.*s\n", val->rs.len, val->rs.s); return -1; } memcpy(br->uri, val->rs.s, val->rs.len); br->uri[val->rs.len] = 0; br->len = val->rs.len; } } } return 0; }
int pv_set_tm_branch_avp(struct sip_msg *msg, pv_param_t *param, int op, pv_value_t *val) { int avp_name; int_str avp_val; int flags, res=0; unsigned short name_type; int idx, idxf; struct usr_avp **old_list=NULL; struct usr_avp **avp_list=NULL; if (!msg || !val) goto error; avp_list = get_bavp_list(); if (!avp_list) { pv_get_null(msg, param, val); goto success; } if (!param) { LM_ERR("bad parameters\n"); goto error; } if (pv_get_avp_name(msg, param, &avp_name, &name_type)) { LM_ALERT("BUG in getting bavp name\n"); goto error; } /* get the index */ if(pv_get_spec_index(msg, param, &idx, &idxf)!=0) { LM_ERR("invalid index\n"); goto error; } /* setting the avp head */ old_list = set_avp_list(avp_list); if (!old_list) { LM_CRIT("no bavp head list found\n"); goto error; } if(val == NULL) { if(op == COLONEQ_T || idxf == PV_IDX_ALL) destroy_avps(name_type, avp_name, 1); else { if(idx < 0) { LM_ERR("index with negative value\n"); goto error; } destroy_index_avp(name_type, avp_name, idx); } /* restoring head */ goto success; } if(op == COLONEQ_T || idxf == PV_IDX_ALL) destroy_avps(name_type, avp_name, 1); flags = name_type; if(val->flags&PV_TYPE_INT) { avp_val.n = val->ri; } else { avp_val.s = val->rs; flags |= AVP_VAL_STR; } if(idxf == PV_IDX_INT || idxf == PV_IDX_PVAR) { if(replace_avp(flags, avp_name, avp_val, idx)< 0) { LM_ERR("failed to replace bavp\n"); goto error; } } else { if (add_avp(flags, avp_name, avp_val)<0) { LM_ERR("error - cannot add bavp\n"); goto error; } } goto success; error: res = -1; success: if (old_list) set_avp_list(old_list); return res; }
int pv_get_tm_branch_avp(struct sip_msg *msg, pv_param_t *param, pv_value_t *val) { int avp_name; int_str avp_value; unsigned short name_type; int idx, idxf, res=0; struct usr_avp **old_list=NULL; struct usr_avp **avp_list=NULL; struct usr_avp *avp; int_str avp_value0; struct usr_avp *avp0; int n=0; char *p; if (!msg || !val) goto error; avp_list = get_bavp_list(); if (!avp_list) { pv_get_null(msg, param, val); goto success; } if (!param) { LM_ERR("bad parameters\n"); goto error; } if (pv_get_avp_name(msg, param, &avp_name, &name_type)) { LM_ALERT("BUG in getting bavp name\n"); goto error; } /* get the index */ if(pv_get_spec_index(msg, param, &idx, &idxf)!=0) { LM_ERR("invalid index\n"); goto error; } /* setting the avp head */ old_list = set_avp_list(avp_list); if (!old_list) { LM_CRIT("no bavp head list found\n"); goto error; } if ((avp=search_first_avp(name_type, avp_name, &avp_value, 0))==0) { pv_get_null(msg, param, val); goto success; } val->flags = PV_VAL_STR; if ( (idxf==0 || idxf==PV_IDX_INT) && idx==0) { if(avp->flags & AVP_VAL_STR) { val->rs = avp_value.s; } else { val->rs.s = sint2str(avp_value.n, &val->rs.len); val->ri = avp_value.n; val->flags |= PV_VAL_INT|PV_TYPE_INT; } goto success; } if(idxf==PV_IDX_ALL) { p = pv_local_buf; do { if(avp->flags & AVP_VAL_STR) { val->rs = avp_value.s; } else { val->rs.s = sint2str(avp_value.n, &val->rs.len); } if(p-pv_local_buf+val->rs.len+1>PV_LOCAL_BUF_SIZE) { LM_ERR("local buffer length exceeded!\n"); pv_get_null(msg, param, val); goto success; } memcpy(p, val->rs.s, val->rs.len); p += val->rs.len; if(p-pv_local_buf+PV_FIELD_DELIM_LEN+1>PV_LOCAL_BUF_SIZE) { LM_ERR("local buffer length exceeded\n"); pv_get_null(msg, param, val); goto success; } memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN); p += PV_FIELD_DELIM_LEN; } while ((avp=search_first_avp(name_type, avp_name, &avp_value, avp))!=0); *p = 0; val->rs.s = pv_local_buf; val->rs.len = p - pv_local_buf; goto success; } /* we have a numeric index */ if(idx<0) { n = 1; avp0 = avp; while ((avp0=search_first_avp(name_type, avp_name, &avp_value0, avp0))!=0) n++; idx = -idx; if(idx>n) { LM_DBG("index out of range\n"); pv_get_null(msg, param, val); goto success; } idx = n - idx; if(idx==0) { if(avp->flags & AVP_VAL_STR) { val->rs = avp_value.s; } else { val->rs.s = sint2str(avp_value.n, &val->rs.len); val->ri = avp_value.n; val->flags |= PV_VAL_INT|PV_TYPE_INT; } goto success; } } n=0; while(n<idx && (avp=search_first_avp(name_type, avp_name, &avp_value, avp))!=0) n++; if(avp!=0) { if(avp->flags & AVP_VAL_STR) { val->rs = avp_value.s; } else { val->rs.s = sint2str(avp_value.n, &val->rs.len); val->ri = avp_value.n; val->flags |= PV_VAL_INT|PV_TYPE_INT; } } goto success; error: res = -1; success: if (old_list) set_avp_list(old_list); return res; }