/*! \brief * Insert a new Record-Route header field * And also 2nd one if it is enabled and realm changed so * the 2nd record-route header will be necessary */ int record_route(struct sip_msg* _m, str *params) { struct lump* l, *l2, *lp, *lp2, *ap; str user; struct to_body* from; str* tag; from = 0; /* Makes gcc happy */ user.len = 0; lp = lp2 = NULL; if (add_username) { if (get_username(_m, &user) < 0) { LM_ERR("failed to extract username\n"); return -1; } } if (append_fromtag) { if (parse_from_header(_m) < 0) { LM_ERR("From parsing failed\n"); return -2; } from = (struct to_body*)_m->from->parsed; tag = &from->tag_value; } else { tag = 0; } l = anchor_lump(_m, _m->headers->name.s - _m->buf, HDR_RECORDROUTE_T); l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, HDR_RECORDROUTE_T); if (!l || !l2) { LM_ERR("failed to create an anchor\n"); return -3; } /* look for pending RR params */ for( lp2=NULL,lp=NULL,ap=_m->add_rm ; ap ; ap=ap->next ) { if (ap->type==HDR_RECORDROUTE_T && ap->op==LUMP_NOP && ap->before && ap->before->op==LUMP_ADD_OPT && ap->before->u.cond==COND_FALSE) { /* found our phony anchor lump */ /* jump over the anchor and conditional lumps */ lp = ap->before->before; /* unlink it */ ap->before->before = NULL; ap->type = 0; /* if double routing, make a copy of the buffered lumps for the second route hdr. */ if (enable_double_rr) lp2 = dup_lump_list(lp); break; } } if (build_rr(l, l2, &user, tag, params, lp, OUTBOUND) < 0) { LM_ERR("failed to insert inbound Record-Route\n"); return -4; } if (enable_double_rr) { l = anchor_lump(_m, _m->headers->name.s - _m->buf,HDR_RECORDROUTE_T); l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, HDR_RECORDROUTE_T); if (!l || !l2) { LM_ERR("failed to create an anchor\n"); return -5; } l = insert_cond_lump_after(l, COND_IF_DIFF_REALMS, 0); l2 = insert_cond_lump_before(l2, COND_IF_DIFF_REALMS, 0); if (!l || !l2) { LM_ERR("failed to insert conditional lump\n"); return -6; } if (build_rr(l, l2, &user, tag, params, lp2, INBOUND) < 0) { LM_ERR("failed to insert outbound Record-Route\n"); return -7; } } return 0; }
int record_route_advertised_address(struct sip_msg* _m, str* _data) { str user = {NULL, 0}; str *tag = NULL; struct lump* l; struct lump* l2; int use_ob = rr_obb.use_outbound ? rr_obb.use_outbound(_m) : 0; int sips; int ret = 0; user.len = 0; user.s = 0; if (add_username) { if (get_username(_m, &user) < 0) { LM_ERR("failed to extract username\n"); return -1; } } else if (use_ob == 1) { if (rr_obb.encode_flow_token(&user, _m->rcv) != 0) { LM_ERR("encoding outbound flow-token\n"); return -1; } } else if (use_ob == 2) { if (copy_flow_token(&user, _m) != 0) { LM_ERR("copying outbound flow-token\n"); return -1; } } if (append_fromtag) { if (is_direction(_m, RR_FLOW_UPSTREAM) == 0) { if (parse_to_header(_m) < 0) { LM_ERR("To parsing failed\n"); ret = -2; goto error; } tag = &((struct to_body*)_m->to->parsed)->tag_value; } else { if (parse_from_header(_m) < 0) { LM_ERR("From parsing failed\n"); ret = -2; goto error; } tag = &((struct to_body*)_m->from->parsed)->tag_value; } } else { tag = 0; } sips = rr_is_sips(_m); if (enable_double_rr) { l = anchor_lump(_m, _m->headers->name.s - _m->buf,0,HDR_RECORDROUTE_T); l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0); if (!l || !l2) { LM_ERR("failed to create an anchor\n"); ret = -3; goto error; } l = insert_cond_lump_after(l, (enable_double_rr == 2) ? COND_TRUE : COND_IF_DIFF_PROTO, 0); l2 = insert_cond_lump_before(l2, (enable_double_rr == 2) ? COND_TRUE : COND_IF_DIFF_PROTO, 0); if (!l || !l2) { LM_ERR("failed to insert conditional lump\n"); ret = -4; goto error; } if (build_advertised_rr(l, l2, _data, &user, tag, OUTBOUND, sips) < 0) { LM_ERR("failed to insert outbound Record-Route\n"); ret = -5; goto error; } } l = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, HDR_RECORDROUTE_T); l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0); if (!l || !l2) { LM_ERR("failed to create an anchor\n"); ret = -6; goto error; } if (build_advertised_rr(l, l2, _data, &user, tag, INBOUND, sips) < 0) { LM_ERR("failed to insert outbound Record-Route\n"); ret = -7; goto error; } ret = 1; error: if ((use_ob == 1) || (use_ob == 2)) if (user.s != NULL) pkg_free(user.s); return ret; }
/*! \brief * build a Record-Route header field */ static inline int build_rr(struct lump* _l, struct lump* _l2, str* user, str *tag, str *params, struct lump *lp, int _inbound) { char* prefix, *suffix, *term, *r2; int suffix_len, prefix_len; char *p; prefix_len = RR_PREFIX_LEN + (user->len ? (user->len + 1) : 0); suffix_len = RR_LR_LEN + (params?params->len:0) + ((tag && tag->len) ? (RR_FROMTAG_LEN + tag->len) : 0); prefix = pkg_malloc(prefix_len); suffix = pkg_malloc(suffix_len); term = pkg_malloc(RR_TERM_LEN); r2 = pkg_malloc(RR_R2_LEN); if (!prefix || !suffix || !term || !r2) { LM_ERR("No more pkg memory\n"); if (suffix) pkg_free(suffix); if (prefix) pkg_free(prefix); if (term) pkg_free(term); if (r2) pkg_free(r2); return -3; } memcpy(prefix, RR_PREFIX, RR_PREFIX_LEN); if (user->len) { memcpy(prefix + RR_PREFIX_LEN, user->s, user->len); #ifdef ENABLE_USER_CHECK /* don't add the ignored user into a RR */ if(i_user.len && i_user.len == user->len && !strncmp(i_user.s, user->s, i_user.len)) { if(prefix[RR_PREFIX_LEN]=='x') prefix[RR_PREFIX_LEN]='y'; else prefix[RR_PREFIX_LEN]='x'; } #endif prefix[RR_PREFIX_LEN + user->len] = '@'; } p = suffix; memcpy( p, RR_LR, RR_LR_LEN); p += RR_LR_LEN; if (tag && tag->len) { memcpy(p, RR_FROMTAG, RR_FROMTAG_LEN); p += RR_FROMTAG_LEN; memcpy(p, tag->s, tag->len); p += tag->len; } if (params && params->len) { memcpy(p, params->s, params->len); p += params->len; } memcpy(term, RR_TERM, RR_TERM_LEN); memcpy(r2, RR_R2, RR_R2_LEN); if (!(_l = insert_new_lump_after(_l, prefix, prefix_len, 0))) goto lump_err; prefix = 0; _l = insert_subst_lump_after(_l, _inbound?SUBST_RCV_ALL:SUBST_SND_ALL, 0); if (_l ==0 ) goto lump_err; if (enable_double_rr) { if (!(_l = insert_cond_lump_after(_l, COND_IF_DIFF_REALMS, 0))) goto lump_err; if (!(_l = insert_new_lump_after(_l, r2, RR_R2_LEN, 0))) goto lump_err; r2 = 0; } else { pkg_free(r2); r2 = 0; } _l2 = insert_new_lump_before(_l2, suffix, suffix_len, 0); if (_l2 == 0) goto lump_err; suffix = 0; if ( lp ) { /* link the pending buffered params and go at the end of the list */ for ( _l2->before = lp ; _l2 && _l2->before ; _l2=_l2->before); } if (!(_l2 = insert_new_lump_before(_l2, term, RR_TERM_LEN, 0))) goto lump_err; term = 0; return 0; lump_err: LM_ERR("failed to insert lumps\n"); if (prefix) pkg_free(prefix); if (suffix) pkg_free(suffix); if (r2) pkg_free(r2); if (term) pkg_free(term); return -4; }
static inline int build_advertised_rr(struct lump* _l, struct lump* _l2, str *_data, str* user, str *tag, int _inbound, int _sips) { char *p; char *hdr, *trans, *r2, *suffix, *term; int hdr_len, suffix_len; char *rr_prefix; int rr_prefix_len; if(_sips==0) { rr_prefix = RR_PREFIX_SIP; rr_prefix_len = RR_PREFIX_SIP_LEN; } else { rr_prefix = RR_PREFIX_SIPS; rr_prefix_len = RR_PREFIX_SIPS_LEN; } hdr_len = rr_prefix_len; if (user && user->len) hdr_len += user->len + 1; /* @ */ hdr_len += _data->len; suffix_len = 0; if (tag && tag->len) { suffix_len += RR_FROMTAG_LEN + tag->len; } if (enable_full_lr) { suffix_len += RR_LR_FULL_LEN; } else { suffix_len += RR_LR_LEN; } hdr = pkg_malloc(hdr_len); trans = pkg_malloc(RR_TRANS_LEN); suffix = pkg_malloc(suffix_len); r2 = pkg_malloc(RR_R2_LEN); term = pkg_malloc(RR_TERM_LEN); if (!hdr || !trans || !suffix || !term || !r2) { LM_ERR("no pkg memory left\n"); if (hdr) pkg_free(hdr); if (trans) pkg_free(trans); if (suffix) pkg_free(suffix); if (r2) pkg_free(r2); if (term) pkg_free(term); return -1; } p = hdr; memcpy(p, rr_prefix, rr_prefix_len); p += rr_prefix_len; if (user && user->len) { memcpy(p, user->s, user->len); p += user->len; *p = '@'; p++; } memcpy(p, _data->s, _data->len); p = suffix; if (tag && tag->len) { memcpy(p, RR_FROMTAG, RR_FROMTAG_LEN); p += RR_FROMTAG_LEN; memcpy(p, tag->s, tag->len); p += tag->len; } if (enable_full_lr) { memcpy(p, RR_LR_FULL, RR_LR_FULL_LEN); p += RR_LR_FULL_LEN; } else { memcpy(p, RR_LR, RR_LR_LEN); p += RR_LR_LEN; } memcpy(trans, RR_TRANS, RR_TRANS_LEN); memcpy(term, RR_TERM, RR_TERM_LEN); memcpy(r2, RR_R2, RR_R2_LEN); if (!(_l = insert_new_lump_after(_l, hdr, hdr_len, 0))) { LM_ERR("failed to insert new lump\n"); goto lump_err; } hdr = NULL; if (!(_l = insert_cond_lump_after(_l, (enable_double_rr == 2) ? COND_TRUE : COND_IF_DIFF_PROTO, 0))) goto lump_err; if (!(_l = insert_new_lump_after(_l, trans, RR_TRANS_LEN, 0))) goto lump_err; if (!(_l = insert_subst_lump_after(_l, _inbound?SUBST_RCV_PROTO:SUBST_SND_PROTO, 0))) goto lump_err; if (enable_double_rr) { if (!(_l = insert_cond_lump_after(_l, (enable_double_rr == 2) ? COND_TRUE : COND_IF_DIFF_REALMS, 0))) goto lump_err; if (!(_l = insert_new_lump_after(_l, r2, RR_R2_LEN, 0))) goto lump_err; r2 = 0; } else { pkg_free(r2); r2 = 0; } if (!(_l2 = insert_new_lump_before(_l2, suffix, suffix_len, HDR_RECORDROUTE_T))) goto lump_err; suffix = NULL; if (rr_param_buf.len) { if (!(_l2 = insert_rr_param_lump(_l2, rr_param_buf.s, rr_param_buf.len))) goto lump_err; } if (!(_l2 = insert_new_lump_before(_l2, term, RR_TERM_LEN, 0))) goto lump_err; return 1; lump_err: if (hdr) pkg_free(hdr); if (trans) pkg_free(trans); if (suffix) pkg_free(suffix); if (term) pkg_free(term); if (r2) pkg_free(r2); return -7; }
/*! * \brief Insert a new Record-Route header field with lr parameter * * Insert a new Record-Route header field and also 2nd one if it is enabled * and the realm changed so the 2nd record-route header will be necessary. * \param _m SIP message * \param params RR parameter * \return 0 on success, negative on failure */ int record_route(struct sip_msg* _m, str *params) { struct lump* l, *l2; str user = {NULL, 0}; str* tag; int use_ob = rr_obb.use_outbound ? rr_obb.use_outbound(_m) : 0; int sips; int ret = 0; user.len = 0; if (add_username) { /* check if there is a custom user set */ if (get_custom_user(_m, &user) < 0) { if (get_username(_m, &user) < 0) { LM_ERR("failed to extract username\n"); return -1; } } } else if (use_ob == 1) { if (rr_obb.encode_flow_token(&user, _m->rcv) != 0) { LM_ERR("encoding outbound flow-token\n"); return -1; } } else if (use_ob == 2) { if (copy_flow_token(&user, _m) != 0) { LM_ERR("copying outbound flow-token\n"); return -1; } } if (append_fromtag) { if (is_direction(_m, RR_FLOW_UPSTREAM) == 0) { if (parse_to_header(_m) < 0) { LM_ERR("To parsing failed\n"); ret = -2; goto error; } tag = &((struct to_body*)_m->to->parsed)->tag_value; } else { if (parse_from_header(_m) < 0) { LM_ERR("From parsing failed\n"); ret = -2; goto error; } tag = &((struct to_body*)_m->from->parsed)->tag_value; } } else { tag = 0; } if (rr_param_buf.len && rr_param_msg!=_m->id) { /* rr_params were set for a different message -> reset buffer */ rr_param_buf.len = 0; } sips = rr_is_sips(_m); if (enable_double_rr) { l = anchor_lump(_m, _m->headers->name.s - _m->buf,0,HDR_RECORDROUTE_T); l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0); if (!l || !l2) { LM_ERR("failed to create an anchor\n"); ret = -5; goto error; } l = insert_cond_lump_after(l, (enable_double_rr == 2) ? COND_TRUE : COND_IF_DIFF_REALMS, 0); l2 = insert_cond_lump_before(l2, (enable_double_rr == 2) ? COND_TRUE : COND_IF_DIFF_REALMS, 0); if (!l || !l2) { LM_ERR("failed to insert conditional lump\n"); ret = -6; goto error; } if (build_rr(l, l2, &user, tag, params, OUTBOUND, sips) < 0) { LM_ERR("failed to insert outbound Record-Route\n"); ret = -7; goto error; } } l = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, HDR_RECORDROUTE_T); l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0); if (!l || !l2) { LM_ERR("failed to create an anchor\n"); ret = -3; goto error; } if (build_rr(l, l2, &user, tag, params, INBOUND, sips) < 0) { LM_ERR("failed to insert inbound Record-Route\n"); ret = -4; goto error; } /* reset the rr_param buffer */ rr_param_buf.len = 0; ret = 0; error: if ((use_ob == 1) || (use_ob == 2)) if (user.s != NULL) pkg_free(user.s); return ret; }
/*! * \brief Build a Record-Route header field * * Build a Record-Route header field, allocates new private memory for this. * \param _l first lump * \param _l2 second lump * \param user user parameter * \param tag tag parameter * \param params parameter * \param _inbound inbound request * \return 0 on success, negative on failure */ static inline int build_rr(struct lump* _l, struct lump* _l2, str* user, str *tag, str *params, int _inbound, int _sips) { char* prefix, *suffix, *term, *r2; int suffix_len, prefix_len; char *p; char *rr_prefix; int rr_prefix_len; if(_sips==0) { rr_prefix = RR_PREFIX_SIP; rr_prefix_len = RR_PREFIX_SIP_LEN; } else { rr_prefix = RR_PREFIX_SIPS; rr_prefix_len = RR_PREFIX_SIPS_LEN; } prefix_len = rr_prefix_len + (user->len ? (user->len + 1) : 0); if (enable_full_lr) { suffix_len = RR_LR_FULL_LEN + (params?params->len:0) + ((tag && tag->len) ? (RR_FROMTAG_LEN + tag->len) : 0); } else { suffix_len = RR_LR_LEN + (params?params->len:0) + ((tag && tag->len) ? (RR_FROMTAG_LEN + tag->len) : 0); } prefix = pkg_malloc(prefix_len); suffix = pkg_malloc(suffix_len); term = pkg_malloc(RR_TERM_LEN); r2 = pkg_malloc(RR_R2_LEN); if (!prefix || !suffix || !term || !r2) { LM_ERR("No more pkg memory\n"); if (suffix) pkg_free(suffix); if (prefix) pkg_free(prefix); if (term) pkg_free(term); if (r2) pkg_free(r2); return -3; } memcpy(prefix, rr_prefix, rr_prefix_len); if (user->len) { memcpy(prefix + rr_prefix_len, user->s, user->len); #ifdef ENABLE_USER_CHECK /* don't add the ignored user into a RR */ if(i_user.len && i_user.len == user->len && !strncmp(i_user.s, user->s, i_user.len)) { if(prefix[rr_prefix_len]=='x') prefix[rr_prefix_len]='y'; else prefix[rr_prefix_len]='x'; } #endif prefix[rr_prefix_len + user->len] = '@'; } p = suffix; if (enable_full_lr) { memcpy( p, RR_LR_FULL, RR_LR_FULL_LEN); p += RR_LR_FULL_LEN; } else { memcpy( p, RR_LR, RR_LR_LEN); p += RR_LR_LEN; } if (tag && tag->len) { memcpy(p, RR_FROMTAG, RR_FROMTAG_LEN); p += RR_FROMTAG_LEN; memcpy(p, tag->s, tag->len); p += tag->len; } if (params && params->len) { memcpy(p, params->s, params->len); p += params->len; } memcpy(term, RR_TERM, RR_TERM_LEN); memcpy(r2, RR_R2, RR_R2_LEN); if (!(_l = insert_new_lump_after(_l, prefix, prefix_len, 0))) goto lump_err; prefix = 0; _l = insert_subst_lump_after(_l, _inbound?SUBST_RCV_ALL:SUBST_SND_ALL, 0); if (_l ==0 ) goto lump_err; if (enable_double_rr) { if (!(_l = insert_cond_lump_after(_l, (enable_double_rr == 2) ? COND_TRUE : COND_IF_DIFF_REALMS, 0))) goto lump_err; if (!(_l = insert_new_lump_after(_l, r2, RR_R2_LEN, 0))) goto lump_err; r2 = 0; } else { pkg_free(r2); r2 = 0; } _l2 = insert_new_lump_before(_l2, suffix, suffix_len, HDR_RECORDROUTE_T); if (_l2 == 0) goto lump_err; if (rr_param_buf.len) { _l2 = insert_rr_param_lump(_l2, rr_param_buf.s, rr_param_buf.len); if (_l2 == 0) goto lump_err; } suffix = 0; if (!(_l2 = insert_new_lump_before(_l2, term, RR_TERM_LEN, 0))) goto lump_err; term = 0; return 0; lump_err: LM_ERR("failed to insert lumps\n"); if (prefix) pkg_free(prefix); if (suffix) pkg_free(suffix); if (r2) pkg_free(r2); if (term) pkg_free(term); return -4; }
int record_route_advertised_address(struct sip_msg* _m, str* _data) { str user; str *tag = NULL; struct lump* l; struct lump* l2; int use_ob = rr_obb.use_outbound ? rr_obb.use_outbound(_m) : 0; int sips; user.len = 0; user.s = 0; if (add_username) { if (get_username(_m, &user) < 0) { LM_ERR("failed to extract username\n"); return -1; } } else if (use_ob == 1) { if (rr_obb.encode_flow_token(&user, _m->rcv) != 0) { LM_ERR("encoding outbound flow-token\n"); return -1; } } else if (use_ob == 2) { if (copy_flow_token(&user, _m) != 0) { LM_ERR("copying outbound flow-token\n"); return -1; } } if (append_fromtag) { if (parse_from_header(_m) < 0) { LM_ERR("From parsing failed\n"); return -2; } tag = &((struct to_body*)_m->from->parsed)->tag_value; } sips = rr_is_sips(_m); if (enable_double_rr) { l = anchor_lump(_m, _m->headers->name.s - _m->buf,0,HDR_RECORDROUTE_T); l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0); if (!l || !l2) { LM_ERR("failed to create an anchor\n"); return -3; } l = insert_cond_lump_after(l, COND_IF_DIFF_PROTO, 0); l2 = insert_cond_lump_before(l2, COND_IF_DIFF_PROTO, 0); if (!l || !l2) { LM_ERR("failed to insert conditional lump\n"); return -4; } if (build_advertised_rr(l, l2, _data, &user, tag, OUTBOUND, sips) < 0) { LM_ERR("failed to insert outbound Record-Route\n"); return -5; } } l = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, HDR_RECORDROUTE_T); l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0); if (!l || !l2) { LM_ERR("failed to create an anchor\n"); return -6; } if (build_advertised_rr(l, l2, _data, &user, tag, INBOUND, sips) < 0) { LM_ERR("failed to insert outbound Record-Route\n"); return -7; } return 1; }
/*! * \brief Insert a new Record-Route header field with lr parameter * * Insert a new Record-Route header field and also 2nd one if it is enabled * and the realm changed so the 2nd record-route header will be necessary. * \param _m SIP message * \param params RR parameter * \return 0 on success, negative on failure */ int record_route(struct sip_msg* _m, str *params) { struct lump* l, *l2; str user; struct to_body* from = NULL; str* tag; int use_ob = rr_obb.use_outbound ? rr_obb.use_outbound(_m) : 0; int sips; user.len = 0; if (add_username) { /* check if there is a custom user set */ if (get_custom_user(_m, &user) < 0) { if (get_username(_m, &user) < 0) { LM_ERR("failed to extract username\n"); return -1; } } } else if (use_ob == 1) { if (rr_obb.encode_flow_token(&user, _m->rcv) != 0) { LM_ERR("encoding outbound flow-token\n"); return -1; } } else if (use_ob == 2) { if (copy_flow_token(&user, _m) != 0) { LM_ERR("copying outbound flow-token\n"); return -1; } } if (append_fromtag) { if (parse_from_header(_m) < 0) { LM_ERR("From parsing failed\n"); return -2; } from = (struct to_body*)_m->from->parsed; tag = &from->tag_value; } else { tag = 0; } if (rr_param_buf.len && rr_param_msg!=_m->id) { /* rr_params were set for a different message -> reset buffer */ rr_param_buf.len = 0; } sips = rr_is_sips(_m); if (enable_double_rr) { l = anchor_lump(_m, _m->headers->name.s - _m->buf,0,HDR_RECORDROUTE_T); l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0); if (!l || !l2) { LM_ERR("failed to create an anchor\n"); return -5; } l = insert_cond_lump_after(l, COND_IF_DIFF_REALMS, 0); l2 = insert_cond_lump_before(l2, COND_IF_DIFF_REALMS, 0); if (!l || !l2) { LM_ERR("failed to insert conditional lump\n"); return -6; } if (build_rr(l, l2, &user, tag, params, OUTBOUND, sips) < 0) { LM_ERR("failed to insert outbound Record-Route\n"); return -7; } } l = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, HDR_RECORDROUTE_T); l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0); if (!l || !l2) { LM_ERR("failed to create an anchor\n"); return -3; } if (build_rr(l, l2, &user, tag, params, INBOUND, sips) < 0) { LM_ERR("failed to insert inbound Record-Route\n"); return -4; } /* reset the rr_param buffer */ rr_param_buf.len = 0; return 0; }