/*! * \brief Appends a new Record-Route parameter * \param msg SIP message * \param rr_param RR parameter * \return 0 on success, -1 on failure */ int add_rr_param(struct sip_msg* msg, str* rr_param) { struct lump *last_param; struct lump *root; root = msg->add_rm; last_param = get_rr_param_lump( &root ); if (last_param) { /* RR was already done -> have to add a new lump before this one */ if (insert_rr_param_lump( last_param, rr_param->s, rr_param->len)==0) { LM_ERR("failed to add lump\n"); goto error; } /* double routing enabled? */ if (enable_double_rr) { if (root==0 || (last_param=get_rr_param_lump(&root))==0) { LM_CRIT("failed to locate double RR lump\n"); goto error; } if (insert_rr_param_lump(last_param,rr_param->s,rr_param->len)==0) { LM_ERR("failed to add 2nd lump\n"); goto error; } } } else { /* RR not done yet -> store the param in the static buffer */ if (rr_param_msg!=msg->id) { /* it's about a different message -> reset buffer */ rr_param_buf.len = 0; rr_param_msg = msg->id; } if (rr_param_buf.len+rr_param->len>RR_PARAM_BUF_SIZE) { LM_ERR("maximum size of rr_param_buf exceeded\n"); goto error; } memcpy( rr_param_buf.s+rr_param_buf.len, rr_param->s, rr_param->len); rr_param_buf.len += rr_param->len; LM_DBG("rr_param_buf=<%.*s>\n",rr_param_buf.len, rr_param_buf.s); } return 0; error: return -1; }
/*! \brief * Appends a new Record-Route parameter */ int add_rr_param(struct sip_msg* msg, str* rr_param) { struct lump *l; struct lump *crt; int rr_found=0; LM_DBG("adding (%.*s)\n",rr_param->len,rr_param->s); for( crt=msg->add_rm ; crt ; crt=crt->next ) { if (crt->type!=HDR_RECORDROUTE_T || crt->op!=LUMP_NOP) continue; /* found a RR-related anchor; we are looking for the * "second RR lump" (having data on "before") or for the * "buffering lump" (having also data on "before") */ if (!crt->before) continue; if (!rr_found && crt->before->op==LUMP_ADD_OPT && crt->before->u.cond==COND_FALSE ) { LM_DBG("buffering lump was found\n"); /* this is the "buffering lump" */ /* RR not done, but some RR params are already buffered -> add a before lump to the existing buffering one */ /* get the last param attached on the anchor */ for( l=crt->before->before ; l && l->before ; l=l->before); /* add the param */ if (insert_rr_param_lump( l, rr_param->s, rr_param->len)==0) { LM_ERR("failed to add buffered lump\n"); goto error; } return 0; } /* this is a "second RR lump" */ LM_DBG("second RR lump found\n"); /* RR was already done -> have to add a new lump before last param */ for (l=crt->before ; l && l->op!=LUMP_ADD ; l=l->before ); if (l==NULL) { LM_CRIT("BUG - second RR anchor has no ADD on before\n"); return -1; } if (insert_rr_param_lump( l, rr_param->s, rr_param->len)==0) { LM_ERR("failed to add lump\n"); goto error; } /* double routing enabled? */ if (!enable_double_rr) /* done */ return 0; /* continue looking for more RR headers */ rr_found = 1; } /* param already added to existing RR headers ? */ if (rr_found) return 0; /* RR not done, no other RR param added so far -> create the phony anchor and add the lump to it */ crt = anchor_lump(msg, msg->headers->name.s-msg->buf, HDR_RECORDROUTE_T); if (crt==NULL) { LM_ERR("cannot create phony lump for buffering params\n"); goto error; } l = insert_cond_lump_before( crt, COND_FALSE, 0); if (l==NULL) { LM_ERR("cannot create conditional lump for buffering params\n"); goto error; } if (insert_rr_param_lump( l, rr_param->s, rr_param->len)==0) { LM_ERR("failed to add buffered lump\n"); goto error; } return 0; error: return -1; }
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 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; }