int change_media_ports(sip_msg_t *msg, struct socket_info *bind_address) { // parse SDP str sdp = {0, 0}; if (get_msg_body(msg, &sdp) != 0) { ERR("Cannot parse SDP.\n"); return -1; } struct subst_expr *seCreator, *seMedia, *seRtcp; char *pattern; int count = 0; str *newBody, *tmpBody, *cBody; char const *oldBody = (char const *) sdp.s; // Replace Creator IP pattern = get_replace_ip_pattern(bind_address); seCreator = fill_subst_expr(pattern); free(pattern); cBody = subst_str(oldBody, msg, seCreator, &count); if (count > 0) { count = 0; oldBody = (char const *) cBody->s; } // Replace RTCP ports pattern = get_replace_rtcp_pattern(bind_address); seRtcp = fill_subst_expr(pattern); free(pattern); tmpBody = subst_str(oldBody, msg, seRtcp, &count); // Replace RTP ports (if RTCP ports was not found we append them to media attributes) if (count > 0) { pattern = get_replace_rtp_pattern(bind_address); count = 0; oldBody = (char const *) tmpBody->s; } else { pattern = get_replace_rtp_and_add_rtcp_pattern(bind_address); } seMedia = fill_subst_expr(pattern); free(pattern); newBody = subst_str(oldBody, msg, seMedia, &count); ssp_set_body(msg, newBody); return 0; }
/* sed-perl style re: s/regular expression/replacement/flags, like * subst but works on the message uri */ static int subst_uri_f(struct sip_msg* msg, struct subst_expr *se) { char* tmp; int len; char c; str* result; if (msg->new_uri.s){ len=msg->new_uri.len; tmp=msg->new_uri.s; }else{ tmp=msg->first_line.u.request.uri.s; len =msg->first_line.u.request.uri.len; }; /* ugly hack: 0 s[len], and restore it afterward * (our re functions require 0 term strings), we can do this * because we always alloc len+1 (new_uri) and for first_line, the * message will always be > uri.len */ c=tmp[len]; tmp[len]=0; result=subst_str(tmp, msg, se, 0); /* pkg malloc'ed result */ tmp[len]=c; if (result){ LM_DBG("%s match - old uri= [%.*s], new uri= [%.*s]\n", exports.name, len, tmp, (result->len)?result->len:0,(result->s)?result->s:""); if (msg->new_uri.s) pkg_free(msg->new_uri.s); msg->new_uri=*result; msg->parsed_uri_ok=0; /* reset "use cached parsed uri" flag */ pkg_free(result); /* free str* pointer */ return 1; /* success */ } return -1; /* false, no subst. made */ }
static int subst_attr(struct sip_msg* msg, char* p1, char* p2) { avp_t* avp; avp_value_t val; str *res = NULL; int count; avp_ident_t* name = &((fparam_t*)p1)->v.avp; if ((avp = search_avp(*name, &val, NULL))) { if (avp->flags & AVP_VAL_STR) { res = subst_str(val.s.s, msg, ((fparam_t*)p2)->v.subst, &count); if (res == NULL) { ERR("avp_subst: error while running subst\n"); goto error; } DBG("avp_subst: %d, result %.*s\n", count, res->len, ZSW(res->s)); val.s = *res; if (add_avp_before(avp, name->flags | AVP_VAL_STR, name->name, val)) { ERR("avp_subst: error while adding new AVP\n"); goto error; } destroy_avp(avp); return 1; } else { ERR("avp_subst: AVP has numeric value\n"); goto error; } } else { ERR("avp_subst: AVP[%.*s] index %d, flags %x not found\n", name->name.s.len, name->name.s.s, name->index, name->flags); goto error; } error: if (res) pkg_free(res); return -1; }
/* sed-perl style re: s/regular expression/replacement/flags, like * subst but works on the user part of the uri */ static int subst_user_f(struct sip_msg* msg, char* subst, char* ignored) { int rval; str* result; struct subst_expr* se; struct action act; str user; char c; int nmatches; c=0; if (parse_sip_msg_uri(msg)<0){ return -1; /* error, bad uri */ } if (msg->parsed_uri.user.s==0){ /* no user in uri */ user.s=""; user.len=0; }else{ user=msg->parsed_uri.user; c=user.s[user.len]; user.s[user.len]=0; } se=(struct subst_expr*)subst; result=subst_str(user.s, msg, se, &nmatches);/* pkg malloc'ed result */ if (c) user.s[user.len]=c; if (result == NULL) { if (nmatches<0) LM_ERR("subst_user(): subst_str() failed\n"); return -1; } /* result->s[result->len] = '\0'; --subst_str returns 0-term strings */ memset(&act, 0, sizeof(act)); /* be on the safe side */ act.type = SET_USER_T; act.elem[0].type = STR_ST; act.elem[0].u.s = *result; rval = do_action(&act, msg); pkg_free(result->s); pkg_free(result); return rval; }
int tr_txt_eval_re(struct sip_msg *msg, tr_param_t *tp, int subtype, pv_value_t *val) { struct subst_expr *se = NULL; int nmatches; str* result; #define TR_TXT_BUF_SIZE 2048 static char tr_txt_buf[TR_TXT_BUF_SIZE]; pv_value_t v; if(val==NULL || (!(val->flags&PV_VAL_STR)) || val->rs.len<=0) return -1; switch(subtype) { case TR_TXT_RE_SUBST: if (tp->type == TR_PARAM_SUBST) { se = (struct subst_expr*)tp->v.data; if (se==NULL) return 0; } else if (tp->type == TR_PARAM_SPEC) { if (pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0 || (!(v.flags&PV_VAL_STR)) || v.rs.len<=0) { LM_ERR("Can't evaluate regexp\n"); return -1; } se=subst_parser(&v.rs); if (se==0) { LM_ERR("Can't compile regexp\n"); return -1; } } else { LM_ERR("Unknown parameter type\n"); return -1; } if(val->rs.len>=TR_TXT_BUF_SIZE-1) { LM_ERR("PV value too big %d, increase buffer size\n", val->rs.len); goto error; } memcpy(tr_txt_buf, val->rs.s, val->rs.len); tr_txt_buf[val->rs.len] = '\0'; /* pkg malloc'ed result */ result=subst_str(tr_txt_buf, msg, se, &nmatches); if (result == NULL) { if (nmatches==0) { LM_DBG("no match for subst expression\n"); break; } if (nmatches<0) LM_ERR("subst failed\n"); goto error; } if(result->len>=TR_TXT_BUF_SIZE-1) { LM_ERR("subst result too big %d, increase buffer size\n", result->len); goto error; } memcpy(tr_txt_buf, result->s, result->len); tr_txt_buf[result->len] = '\0'; memset(val, 0, sizeof(pv_value_t)); val->flags = PV_VAL_STR; val->rs.s = tr_txt_buf; val->rs.len = result->len; pkg_free(result->s); pkg_free(result); break; default: LM_ERR("unknown subtype %d\n", subtype); goto error; } if (tp->type == TR_PARAM_SPEC) { subst_expr_free(se); } return 0; error: if (tp->type == TR_PARAM_SPEC) { subst_expr_free(se); } return -1; }
int ops_subst(struct sip_msg* msg, struct fis_param** src, struct subst_expr* se) { struct usr_avp *avp; struct usr_avp *prev_avp; int_str avp_val; unsigned short name_type1; unsigned short name_type2; int avp_name1; int avp_name2; int n; int nmatches; str* result; n = 0; prev_avp = 0; /* avp name is known ->search by name */ /* get src avp name */ if(avpops_get_aname(msg, src[0], &avp_name1, &name_type1)!=0) { LM_ERR("failed to get src AVP name\n"); return -1; } avp = search_first_avp(name_type1, avp_name1, &avp_val, 0); if(avp==NULL) return -1; if(src[1]!=0) { /* get dst avp name */ if(avpops_get_aname(msg, src[1], &avp_name2, &name_type2)!=0) { LM_ERR("failed to get dst AVP name\n"); return -1; } } else { name_type2 = name_type1; avp_name2 = avp_name1; } /* TODO: delete? if(name_type2&AVP_NAME_STR) { if(avp_name2.s.len>=STR_BUF_SIZE) { LM_ERR("dst name too long\n"); goto error; } strncpy(str_buf, avp_name2.s.s, avp_name2.s.len); str_buf[avp_name2.s.len] = '\0'; avp_name2.s.s = str_buf; } */ while(avp) { if(!is_avp_str_val(avp)) { prev_avp = avp; avp = search_first_avp(name_type1, avp_name1, &avp_val, prev_avp); continue; } result=subst_str(avp_val.s.s, msg, se, &nmatches); if(result!=NULL) { /* build a new avp with new name */ avp_val.s = *result; if(add_avp(name_type2|AVP_VAL_STR, avp_name2, avp_val)==-1 ) { LM_ERR("failed to create new avp\n"); if(result->s!=0) pkg_free(result->s); pkg_free(result); goto error; } if(result->s!=0) pkg_free(result->s); pkg_free(result); n++; /* copy all avps? */ if (!(src[0]->ops&AVPOPS_FLAG_ALL) ) { /* delete the old one? */ if (src[0]->ops&AVPOPS_FLAG_DELETE || src[1]==0) destroy_avp(avp); break; } else { prev_avp = avp; avp = search_first_avp(name_type1,avp_name1,&avp_val,prev_avp); /* delete the old one? */ if (src[0]->ops&AVPOPS_FLAG_DELETE || src[1]==0) destroy_avp( prev_avp ); } } else { prev_avp = avp; avp = search_first_avp(name_type1, avp_name1, &avp_val, prev_avp); } } LM_DBG("subst to %d avps\n", n); return n?1:-1; error: return -1; }
int ldap_write_result( struct sip_msg* _msg, struct ldap_result_params* _lrp, struct subst_expr* _se) { int dst_avp_name; int_str dst_avp_val; unsigned short dst_avp_type; int nmatches, rc, i, added_avp_count = 0; struct berval **attr_vals; str avp_val_str, *subst_result = NULL; int avp_val_int; /* * get dst AVP name (dst_avp_name) */ if (pv_get_avp_name( _msg, &(_lrp->dst_avp_spec.pvp), &dst_avp_name, &dst_avp_type) != 0) { LM_ERR("error getting dst AVP name\n"); return -2; } /* * get LDAP attr values */ if ((rc = ldap_get_attr_vals(&_lrp->ldap_attr_name, &attr_vals)) != 0) { if (rc > 0) { return -1; } else { return -2; } } /* * add AVPs */ for (i = 0; attr_vals[i] != NULL; i++) { if (_se == NULL) { avp_val_str.s = attr_vals[i]->bv_val; avp_val_str.len = attr_vals[i]->bv_len; } else { subst_result = subst_str(attr_vals[i]->bv_val, _msg, _se, &nmatches); if ((subst_result == NULL) || (nmatches < 1)) { continue; } avp_val_str = *subst_result; } if (_lrp->dst_avp_val_type == 1) { /* try to convert ldap value to integer */ if (!str2sint(&avp_val_str, &avp_val_int)) { dst_avp_val.n = avp_val_int; rc = add_avp(dst_avp_type, dst_avp_name, dst_avp_val); } else { continue; } } else { /* save ldap value as string */ dst_avp_val.s = avp_val_str; rc = add_avp(dst_avp_type|AVP_VAL_STR, dst_avp_name, dst_avp_val); } if (subst_result != NULL) { if (subst_result->s != 0) { pkg_free(subst_result->s); } pkg_free(subst_result); subst_result = NULL; } if (rc < 0) { LM_ERR("failed to create new AVP\n"); ldap_value_free_len(attr_vals); return -2; } added_avp_count++; } ldap_value_free_len(attr_vals); if (added_avp_count > 0) { return added_avp_count; } else { return -1; } }
int ldap_result_check( struct sip_msg* _msg, struct ldap_result_check_params* _lrp, struct subst_expr* _se) { str check_str, *subst_result = NULL; int rc, i, nmatches; char *attr_val; struct berval **attr_vals; /* * do variable substitution for check_str */ if (_lrp->check_str_elem_p) { if (pv_printf_s(_msg, _lrp->check_str_elem_p, &check_str) != 0) { LM_ERR("pv_printf_s failed\n"); return -2; } } else { LM_ERR("empty check string\n"); return -2; } LM_DBG("check_str [%s]\n", check_str.s); /* * get LDAP attr values */ if ((rc = ldap_get_attr_vals(&_lrp->ldap_attr_name, &attr_vals)) != 0) { if (rc > 0) { return -1; } else { return -2; } } /* * loop through attribute values */ for (i = 0; attr_vals[i] != NULL; i++) { if (_se == NULL) { attr_val = attr_vals[i]->bv_val; } else { subst_result = subst_str(attr_vals[i]->bv_val, _msg, _se, &nmatches); if ((subst_result == NULL) || (nmatches < 1)) { continue; } attr_val = subst_result->s; } LM_DBG("attr_val [%s]\n", attr_val); rc = strncmp(check_str.s, attr_val, check_str.len); if (_se != NULL) { pkg_free(subst_result->s); } if (rc == 0) { ldap_value_free_len(attr_vals); return 1; } } ldap_value_free_len(attr_vals); return -1; }