int dlg_th_decode_callid(struct sip_msg *msg) { struct lump *del; str new_callid; int i,max_size; if (msg->callid == NULL) { LM_ERR("Message with no callid\n"); return -1; } max_size = calc_max_base64_decode_len(msg->callid->body.len - topo_hiding_prefix.len); new_callid.s = pkg_malloc(max_size); if (new_callid.s==NULL) { LM_ERR("No more pkg\n"); return -1; } new_callid.len = base64decode((unsigned char *)(new_callid.s), (unsigned char *)(msg->callid->body.s + topo_hiding_prefix.len), msg->callid->body.len - topo_hiding_prefix.len); for (i=0;i<new_callid.len;i++) new_callid.s[i] ^= topo_hiding_seed.s[i%topo_hiding_seed.len]; del=del_lump(msg, msg->callid->body.s-msg->buf, msg->callid->body.len, HDR_CALLID_T); if (del==NULL) { LM_ERR("Failed to delete old callid\n"); pkg_free(new_callid.s); return -1; } if (insert_new_lump_after(del,new_callid.s,new_callid.len,HDR_CALLID_T)==NULL) { LM_ERR("Failed to insert new callid\n"); pkg_free(new_callid.s); return -1; } return 0; return 0; }
/* * Logic necessary to forward request to strict routers * * Returns 0 on success, negative number on an error */ static inline int handle_sr(struct sip_msg* _m, struct hdr_field* _hdr, rr_t* _r) { str uri; char* rem_off; int rem_len; /* Next hop is strict router, save R-URI here */ if (save_ruri(_m) < 0) { LM_ERR("failed to save Request-URI\n"); return -1; } /* Put the first Route in Request-URI */ uri = _r->nameaddr.uri; if(get_maddr_uri(&uri, 0)!=0) { LM_ERR("failed to check maddr\n"); return RR_ERROR; } if (set_ruri(_m, &uri) < 0) { LM_ERR("failed to rewrite request URI\n"); return -2; } if (!_r->next) { rem_off = _hdr->name.s; rem_len = _hdr->len; } else { rem_off = _hdr->body.s; rem_len = _r->next->nameaddr.name.s - _hdr->body.s; } if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) { LM_ERR("failed to remove Route HF\n"); return -9; } _r->deleted = 1; return 0; }
static int replace_body_f(struct sip_msg* msg, char* key, char* str2) { struct lump* l; regmatch_t pmatch; char* s; int len; char* begin; int off; str body; if ( get_body(msg,&body)!=0 || body.len==0) { LM_DBG("message body has zero length\n"); return -1; } begin=body.s; /* msg->orig previously .. uri problems */ if (regexec((regex_t*) key, begin, 1, &pmatch, 0)!=0) return -1; off=begin-msg->buf; if (pmatch.rm_so!=-1){ if ((l=del_lump(msg, pmatch.rm_so+off, pmatch.rm_eo-pmatch.rm_so, 0))==0) return -1; len=strlen(str2); s=pkg_malloc(len); if (s==0){ LM_ERR("memory allocation failure\n"); return -1; } memcpy(s, str2, len); if (insert_new_lump_after(l, s, len, 0)==0){ LM_ERR("could not insert new lump\n"); pkg_free(s); return -1; } return 1; } return -1; }
/* sed-perl style re: s/regular expression/replacement/flags */ static int subst_f(struct sip_msg* msg, char* subst, char* ignored) { struct lump* l; struct replace_lst* lst; struct replace_lst* rpl; char* begin; struct subst_expr* se; int off; int ret; se=(struct subst_expr*)subst; begin=get_header(msg); /* start after first line to avoid replacing the uri */ off=begin-msg->buf; ret=-1; if ((lst=subst_run(se, begin, msg))==0) goto error; /* not found */ for (rpl=lst; rpl; rpl=rpl->next){ DBG(" %s: subst_f: replacing at offset %d [%.*s] with [%.*s]\n", exports.name, rpl->offset+off, rpl->size, rpl->offset+off+msg->buf, rpl->rpl.len, rpl->rpl.s); if ((l=del_lump(msg, rpl->offset+off, rpl->size, 0))==0) goto error; /* hack to avoid re-copying rpl, possible because both * replace_lst & lumps use pkg_malloc */ if (insert_new_lump_after(l, rpl->rpl.s, rpl->rpl.len, 0)==0){ LOG(L_ERR, "ERROR: %s: subst_f: could not insert new lump\n", exports.name); goto error; } /* hack continued: set rpl.s to 0 so that replace_lst_free will * not free it */ rpl->rpl.s=0; rpl->rpl.len=0; } ret=1; error: DBG("subst_f: lst was %p\n", lst); if (lst) replace_lst_free(lst); return ret; }
int tps_remove_name_headers(sip_msg_t *msg, str *hname) { hdr_field_t *hf; struct lump* l; for (hf=msg->headers; hf; hf=hf->next) { if (hf->name.len==hname->len && strncasecmp(hf->name.s, hname->s, hname->len)==0) { l=del_lump(msg, hf->name.s-msg->buf, hf->len, 0); if (l==0) { LM_ERR("unable to delete header [%.*s]\n", hname->len, hname->s); return -1; } return 0; } } return 0; }
/** * Remove a header from a message if found. * * @param msg The message to look for the header to remove. * @param header The header name: text. * * @return 0 if the header was not found, >0 is successful, -1 on an * error. */ static int remove_minse_header(struct sip_msg *msg) { struct lump* anchor = NULL; struct hdr_field *hf = NULL; int cnt = 0; /* parse all headers as we want to get all MIN-SE headers*/ if (parse_headers(msg, HDR_EOH_F, 0) == -1) { LM_ERR("failed to parse headers in message.\n"); return(-1); } for (hf = msg->min_se; hf; hf = hf->sibling) { anchor = del_lump(msg, hf->name.s-msg->buf, hf->len, 0); if (anchor == 0) { LM_ERR("no more pkg memory\n"); return -1; } cnt++; } return cnt; }
int gzc_set_msg_body(sip_msg_t *msg, str *obody, str *nbody) { struct lump *anchor; char* buf; /* none should be here - just for safety */ del_nonshm_lump( &(msg->body_lumps) ); msg->body_lumps = NULL; if(del_lump(msg, obody->s - msg->buf, obody->len, 0) == 0) { LM_ERR("cannot delete existing body"); return -1; } anchor = anchor_lump(msg, obody->s - msg->buf, 0, 0); if (anchor == 0) { LM_ERR("failed to get body anchor\n"); return -1; } buf=pkg_malloc(nbody->len * sizeof(char)); if (buf==0) { LM_ERR("out of pkg memory\n"); return -1; } memcpy(buf, nbody->s, nbody->len); if (insert_new_lump_after(anchor, buf, nbody->len, 0) == 0) { LM_ERR("failed to insert body lump\n"); pkg_free(buf); return -1; } return 0; }
static int remove_hf_f(struct sip_msg* msg, char* str_hf, char* foo) { struct hdr_field *hf; struct lump* l; int cnt; cnt=0; /* we need to be sure we have seen all HFs */ parse_headers(msg, HDR_EOH, 0); for (hf=msg->headers; hf; hf=hf->next) { if (hf->name.len!=((str *)str_hf)->len) continue; if (strncasecmp(hf->name.s, ((str *)str_hf)->s, hf->name.len)!=0) continue; l=del_lump(msg, hf->name.s-msg->buf, hf->len, 0); if (l==0) { LOG(L_ERR, "ERROR: remove_hf_f: no memory\n"); return -1; } cnt++; } return cnt==0 ? -1 : 1; }
static int lua_sr_hdr_remove (lua_State *L) { struct lump* anchor; struct hdr_field *hf; char *txt; str hname; sr_lua_env_t *env_L; env_L = sr_lua_env_get(); txt = (char*)lua_tostring(L, -1); if(txt==NULL || env_L->msg==NULL) return 0; LM_DBG("remove hf: %s\n", txt); if (parse_headers(env_L->msg, HDR_EOH_F, 0) == -1) { LM_ERR("error while parsing message\n"); return 0; } hname.s = txt; hname.len = strlen(txt); for (hf=env_L->msg->headers; hf; hf=hf->next) { if (cmp_hdrname_str(&hf->name, &hname)==0) { anchor=del_lump(env_L->msg, hf->name.s - env_L->msg->buf, hf->len, 0); if (anchor==0) { LM_ERR("cannot remove hdr %s\n", txt); return 0; } } } return 0; }
int th_unmask_callid(sip_msg_t *msg) { struct lump* l; str out; if(th_param_mask_callid==0) return 0; if(msg->callid==NULL) { LM_ERR("cannot get Call-Id header\n"); return -1; } out.s = th_mask_decode(msg->callid->body.s, msg->callid->body.len, &th_callid_prefix, 0, &out.len); if(out.s==NULL) { LM_ERR("cannot decode callid\n"); return -1; } l=del_lump(msg, msg->callid->body.s-msg->buf, msg->callid->body.len, 0); if (l==0) { LM_ERR("failed deleting callid\n"); pkg_free(out.s); return -1; } if (insert_new_lump_after(l, out.s, out.len, 0)==0) { LM_ERR("could not insert new lump\n"); pkg_free(out.s); return -1; } return 0; }
static int w_remove_body_f(struct sip_msg *msg, char *p1, char *p2) { str body = {0,0}; body.len = 0; body.s = get_body(msg); if (body.s==0) { LM_DBG("no body in the message\n"); return 1; } body.len = msg->buf + msg->len - body.s; if (body.len<=0) { LM_DBG("empty body in the message\n"); return 1; } if(del_lump(msg, body.s - msg->buf, body.len, 0) == 0) { LM_ERR("cannot remove body\n"); return -1; } return 1; }
int replace_body_segment(struct sdp_mangler * mangler, int offset, int len, unsigned char * new_data, int new_len) { struct lump * l; char *s; l = del_lump(mangler->msg, mangler->body_offset + offset, len, 0); if(l == NULL) { return -1; } s = pkg_malloc(new_len); memcpy(s, new_data, new_len); if(insert_new_lump_after(l, s, new_len, 0) == 0) { pkg_free(s); return -2; } return 0; }
/** * remove_sdp_stream_attrs - removes all attributes from the specified stream * * @return: struct lump * with the removed information */ static struct lump *remove_sdp_stream_attrs(struct sip_msg *msg, struct sdp_stream_cell *stream) { struct lump *lump; char *attrs_end = NULL; LM_DBG("Removing all %d codecs from SDP stream: |%.*s|\n", stream->payloads_num, stream->payloads.len, stream->payloads.s); /* find the last parsed structure of the last attribute */ if (stream->payload_attr->fmtp_string.len > 0) { attrs_end = stream->payload_attr->fmtp_string.s + stream->payload_attr->fmtp_string.len; } else if (stream->payload_attr->rtp_params.len > 0) { attrs_end = stream->payload_attr->rtp_params.s + stream->payload_attr->rtp_params.len; } else if (stream->payload_attr->rtp_clock.len > 0) { attrs_end = stream->payload_attr->rtp_clock.s + stream->payload_attr->rtp_clock.len; } if (!attrs_end) { LM_ERR("invalid SDP stream received\n"); print_sdp_stream(stream, L_ERR); return NULL; } lump = del_lump(msg, stream->payloads.s - msg->buf, attrs_end - stream->payloads.s, HDR_OTHER_T); if (!lump) { LM_ERR("failed to add del lump\n"); return NULL; } return lump; }
/** * Send the request back simulating an AS. * - Inserts a Header with the contents of str2 * - Tries to find the Route: appserver_uri, s-cscf_uri header and removes appserver_uri from it * - It forwards the message to s-scsf_uri, or if none found to str1 * @param msg - The sip message * @param str1 - The uri of the SCSCF to default to if Route header is not found * @param str2 - The Header to add to the message - if empty none will be added * @returns - 0 to cancel further script processing */ int isc_appserver_forward(struct sip_msg *msg,char *str1,char *str2 ) { struct hdr_field *last,*hdr; struct lump* anchor; str header_mark; rr_t *rr; LOG(L_DBG,"DEBUG:"M_NAME":isc_appserver_forward: Forward-back request reached\n"); parse_headers(msg,HDR_EOH_F,0); last = msg->headers; while(last->next) last = last->next; LOG(L_INFO,"INFO:"M_NAME":isc_appserver_forward: New header: [%s]\n%.*s",str2,msg->len,msg->buf); /* Put header marking */ if (strlen(str2)){ header_mark.s = pkg_malloc(256);//36 should be enough sprintf(header_mark.s,"%.*s\n",strlen(str2),str2); header_mark.len =strlen(header_mark.s); anchor = anchor_lump(msg, last->name.s + last->len - msg->buf, 0 , 0); if (anchor == NULL) { LOG(L_ERR, "ERROR:"M_NAME":isc_appserver_forward: anchor_lump failed\n"); } if (!insert_new_lump_before(anchor, header_mark.s,header_mark.len,0)){ LOG( L_ERR, "ERROR:"M_NAME":isc_appserver_forward: error creting lump for header_mark\n" ); } //pkg_free(header_mark.s); } LOG(L_ERR, "INFO:"M_NAME":isc_appserver_forward: Searching Route header to rewrite\n"); /* Search for the Route */ hdr = msg->headers; while(hdr){ if (hdr->type == HDR_ROUTE_T){ if (!hdr->parsed){ if (parse_rr(hdr) < 0) { LOG(L_ERR, "ERROR:"M_NAME":isc_appserver_forward: Error while parsing Route HF\n"); continue; } } rr = (rr_t*)hdr->parsed; while(rr){ if (rr->nameaddr.uri.len >= ISC_MARK_USERNAME_LEN && strncasecmp(rr->nameaddr.uri.s,ISC_MARK_USERNAME,ISC_MARK_USERNAME_LEN)==0) { LOG(L_INFO,"DEBUG:"M_NAME":isc_appserver_forward: Found S-CSCF marking <%.*s> \n",rr->nameaddr.uri.len,rr->nameaddr.uri.s); /* delete the header */ if (!del_lump(msg, hdr->name.s - msg->buf, hdr->len, 0)) { LOG(L_ERR, "ERROR:"M_NAME":isc_appserver_forward: Can't remove Route HF\n"); } /* add the new header */ anchor = anchor_lump(msg, msg->headers->name.s - msg->buf, 0 , 0); header_mark.s = pkg_malloc(256);//36 should be enough sprintf(header_mark.s,"Route: <%.*s>\n",rr->nameaddr.uri.len,rr->nameaddr.uri.s); header_mark.len =strlen(header_mark.s); if (!insert_new_lump_before(anchor, header_mark.s,header_mark.len,0)){ LOG( L_ERR, "ERROR:"M_NAME":isc_appserver_forward: error creting lump for route header\n" ); } /* send the message */ msg->dst_uri.s = pkg_malloc(rr->nameaddr.uri.len); memcpy(msg->dst_uri.s,rr->nameaddr.uri.s,rr->nameaddr.uri.len); msg->dst_uri.len=rr->nameaddr.uri.len; isc_tmb.t_relay(msg,0,0); return 0; } rr = rr->next; } } hdr = hdr->next; } /* In case no suitable route header found, just fwd to the given parameter */ msg->dst_uri.len = strlen(str1); msg->dst_uri.s = str1; isc_tmb.t_relay(msg,0,0); LOG(L_DBG,"DEBUG:"M_NAME":isc_appserver_forward: Mirror request finished\n"); return 0; }
static int assign_hf_do_lumping(struct sip_msg* msg,struct hdr_field* hf, struct hname_data* hname, str* value, int upd_del_fl, str* lump_upd, str* lump_del, char delim) { int len, i; char *s; struct lump* anchor; if (upd_del_fl) { len = value?lump_upd->len:lump_del->len; if (len > 0) { if (!del_lump(msg, (value?lump_upd->s:lump_del->s)-msg->buf, len, 0)) { LOG(L_ERR, "ERROR: textops: assign_hf_do_lumping: not enough memory\n"); return -1; } } if (value && value->len) { anchor = anchor_lump(msg, lump_upd->s - msg->buf, 0, 0); if (anchor == 0) { LOG(L_ERR, "ERROR: textops: assign_hf_do_lumping: Can't get anchor\n"); return -1; } len = 1+value->len; s = pkg_malloc(len); if (!s) { LOG(L_ERR, "ERROR: textops: assign_hf_do_lumping: not enough memory\n"); return -1; } s[0]='='; memcpy(s+1, value->s, value->len); if ( (insert_new_lump_before(anchor, s, len, 0)) == 0) { LOG(L_ERR, "ERROR: textops: assign_hf_do_lumping: Can't insert lump\n"); pkg_free(s); return -1; } } } else { if (!value) return -1; anchor = anchor_lump(msg, lump_del->s - msg->buf, 0, 0); if (anchor == 0) { LOG(L_ERR, "ERROR: textops: assign_hf_do_lumping: Can't get anchor\n"); return -1; } len = 1+hname->param.len+(value->len?value->len+1:0); s = pkg_malloc(len); if (!s) { LOG(L_ERR, "ERROR: textops: assign_hf_do_lumping: not enough memory\n"); return -1; } if (delim) { s[0] = delim; i = 1; } else { i = 0; len--; } memcpy(s+i, hname->param.s, hname->param.len); if (value->len) { s[hname->param.len+i]='='; memcpy(s+i+hname->param.len+1, value->s, value->len); } if ( (insert_new_lump_before(anchor, s, len, 0)) == 0) { LOG(L_ERR, "ERROR: textops: assign_hf_do_lumping: Can't insert lump\n"); pkg_free(s); return -1; } } return 1; }
/** * Force Service routes (upon request) */ int force_service_routes(struct sip_msg* _m, udomain_t* _d) { struct hdr_field *it; int i; str new_route_header; struct lump* lmp = NULL; char * buf; pcontact_t * c = getContactP(_m, _d, PCONTACT_REGISTERED,0 ,0); // char srcip[20]; // str received_host; struct via_body* vb; unsigned short port; unsigned short proto; // Contact not found => not following service-routes if (c == NULL) return -1; /* we need to be sure we have seen all HFs */ parse_headers(_m, HDR_EOH_F, 0); vb = cscf_get_ue_via(_m); port = vb->port?vb->port:5060; proto = vb->proto; /* Save current buffer */ buf = _m->buf; // Delete old Route headers: if (_m->route) { for (it = _m->route; it; it = it->next) { if (it->type == HDR_ROUTE_T) { if ((lmp = del_lump(_m, it->name.s - buf, it->len, HDR_ROUTE_T)) == 0) { LM_ERR("del_lump failed \n"); return -1; } } } } /* Reset dst_uri if previously set either by loose route or manually */ if (_m->dst_uri.s && _m->dst_uri.len) { pkg_free(_m->dst_uri.s); _m->dst_uri.s = NULL; _m->dst_uri.len = 0; } // received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip)); // received_host.s = srcip; /* Lock this record while working with the data: */ ul.lock_udomain(_d, &vb->host, port, proto); if (c->num_service_routes > 0) { /* Create anchor for new Route-Header: */ lmp = anchor_lump(_m, _m->headers->name.s - buf,0,0); if (lmp == 0) { LM_ERR("Failed to get anchor lump\n"); goto error; } /* Calculate the length: */ new_route_header.len = route_start.len + route_end.len + (c->num_service_routes-1) * route_sep.len; for(i=0; i< c->num_service_routes; i++) new_route_header.len+=c->service_routes[i].len; /* Allocate the memory for this new header: */ new_route_header.s = pkg_malloc(new_route_header.len); if (!new_route_header.s) { LM_ERR("Error allocating %d bytes\n", new_route_header.len); goto error; } /* Construct new header */ new_route_header.len = 0; STR_APPEND(new_route_header, route_start); for(i=0; i < c->num_service_routes; i++) { if (i) STR_APPEND(new_route_header, route_sep); STR_APPEND(new_route_header, c->service_routes[i]); } STR_APPEND(new_route_header, route_end); LM_DBG("Setting route header to <%.*s> \n", new_route_header.len, new_route_header.s); if ((lmp = insert_new_lump_after(lmp, new_route_header.s, new_route_header.len, HDR_ROUTE_T)) == 0) { LM_ERR("Error inserting new route set\n"); pkg_free(new_route_header.s); goto error; } LM_DBG("Setting dst_uri to <%.*s> \n", c->service_routes[0].len, c->service_routes[0].s); if (set_dst_uri(_m, &c->service_routes[0]) !=0 ) { LM_ERR("Error setting new dst uri\n"); goto error; } } /* Unlock domain */ ul.unlock_udomain(_d, &vb->host, port, proto); return 1; error: /* Unlock domain */ ul.unlock_udomain(_d, &vb->host, port, proto); return -1; return 1; }
int th_update_hdr_replaces(sip_msg_t *msg) { struct hdr_field *hf = NULL; str replaces; str rcallid; struct lump* l; str out; LM_DBG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); if(th_param_mask_callid==0) return 0; if(!((get_cseq(msg)->method_id)&(METHOD_INVITE))) return 0; for (hf=msg->headers; hf; hf=hf->next) { if (hf->name.len==8 && strncasecmp(hf->name.s, "Replaces", 8)==0) break; } if(hf==NULL) return 0; replaces = hf->body; trim(&replaces); rcallid.s = replaces.s; for(rcallid.len=0; rcallid.len<replaces.len; rcallid.len++) { if(rcallid.s[rcallid.len]==';') break; } if(rcallid.len>th_callid_prefix.len && strncmp(rcallid.s, th_callid_prefix.s, th_callid_prefix.len)==0) { /* value encoded - decode it */ out.s = th_mask_decode(rcallid.s, rcallid.len, &th_callid_prefix, 0, &out.len); } else { /* value decoded - encode it */ out.s = th_mask_encode(rcallid.s, rcallid.len, &th_callid_prefix, &out.len); } if(out.s==NULL) { LM_ERR("cannot update Replaces callid\n"); return -1; } l=del_lump(msg, rcallid.s-msg->buf, rcallid.len, 0); if (l==0) { LM_ERR("failed deleting Replaces callid\n"); pkg_free(out.s); return -1; } if (insert_new_lump_after(l, out.s, out.len, 0)==0) { LM_ERR("could not insert new lump\n"); pkg_free(out.s); return -1; } return 0; }
int th_unmask_route(sip_msg_t *msg) { hdr_field_t *hdr; struct lump* l; int i; rr_t *rr; str out; str eval; if(msg->route==NULL) { LM_DBG("no record route header\n"); return 0; } hdr = msg->route; i = 0; while(hdr!=NULL) { if (parse_rr(hdr) < 0) { LM_ERR("failed to parse RR\n"); return -1; } rr =(rr_t*)hdr->parsed; while(rr) { i++; if(i!=1) { if(th_get_uri_param_value(&rr->nameaddr.uri, &th_uparam_name, &eval)<0 || eval.len<=0) return -1; out.s = th_mask_decode(eval.s, eval.len, &th_uparam_prefix, 0, &out.len); if(out.s==NULL) { LM_ERR("cannot decode R %d\n", i); return -1; } l=del_lump(msg, rr->nameaddr.uri.s-msg->buf, rr->nameaddr.uri.len, 0); if (l==0) { LM_ERR("failed deleting R [%d]\n", i); pkg_free(out.s); return -1; } if (insert_new_lump_after(l, out.s, out.len, 0)==0){ LM_ERR("could not insert new lump\n"); pkg_free(out.s); return -1; } } rr = rr->next; } hdr = next_sibling_hdr(hdr); } return 0; }
int th_flip_record_route(sip_msg_t *msg, int mode) { hdr_field_t *hdr; struct lump* l; int i; rr_t *rr; str out; int utype; str pval; int r2; int act; if(msg->record_route==NULL) { LM_DBG("no record route header\n"); return 0; } hdr = msg->record_route; i = 0; act = 0; if(mode==1) act = 2; while(hdr!=NULL) { if (parse_rr(hdr) < 0) { LM_ERR("failed to parse RR\n"); return -1; } rr =(rr_t*)hdr->parsed; while(rr) { i++; r2 = 0; utype = th_get_uri_type(&rr->nameaddr.uri, &r2, &pval); if(utype==0 && mode==1) { if(r2==1) { act--; if(act==0) return 0; utype = 1; } else { return 0; } } out.s = NULL; switch(utype) { case 1: /* encode */ if(act!=0 && mode==1) { out.s = th_mask_encode(rr->nameaddr.uri.s, rr->nameaddr.uri.len, &th_uri_prefix, &out.len); if(out.s==NULL) { LM_ERR("cannot encode r-r %d\n", i); return -1; } } break; case 2: /* decode */ if(mode==0) { out.s = th_mask_decode(pval.s, pval.len, &th_uparam_prefix, 0, &out.len); if(out.s==NULL) { LM_ERR("cannot decode r-r %d\n", i); return -1; } } break; } if(out.s!=NULL) { l=del_lump(msg, rr->nameaddr.uri.s-msg->buf, rr->nameaddr.uri.len, 0); if (l==0) { LM_ERR("failed deleting r-r [%d]\n", i); pkg_free(out.s); return -1; } if (insert_new_lump_after(l, out.s, out.len, 0)==0){ LM_ERR("could not insert new lump\n"); pkg_free(out.s); return -1; } } rr = rr->next; } hdr = next_sibling_hdr(hdr); } return 0; }
/** * performs the following operations at 200 OK time (early neg <-> late neg): * * - alters the callee's 200 OK message (adds the final decided codec) * - alters the caller's SDP (in memory), so it can be attached @ ACK * - opens transcoding sessions on the card if necessary * * Note: assumes all streams are on corresponding positions in both SDPs */ static int process_session(struct sip_msg *msg, struct sngtc_info *info, str *src, str *dst, struct sdp_session_cell *s1, struct sdp_session_cell *s2) { struct sdp_stream_cell *sm1, *sm2; struct sngtc_session_list *tc_session; struct sngtc_codec_request request; struct sngtc_codec_reply *reply = NULL; struct codec_pair pair; struct lump *lump, *nl; struct in_addr addr; int rc = 0, ret, tc_on = 0; int idx; char buf[INET_ADDRSTRLEN]; str repl; if (s1->next && s2->next) rc = process_session(msg, info, src, dst, s1->next, s2->next); else if (s1->next || s2->next) LM_ERR("endpoints have a different number of SDP sessions" " - choosing min number\n"); if (rc != 0) goto out; tc_session = info->sessions; for (idx = MAX_STREAMS - 1, sm1 = s1->streams, sm2 = s2->streams; sm1 && sm2; sm1 = sm1->next, sm2 = sm2->next, idx--) { ret = match_codecs(sm1, sm2, &pair); codec_matches[idx] = pair; switch (ret) { case SNGTC_OFF: LM_DBG("NO NEED FOR TRANSCODING\n"); /* delete codecs from 200 OK; write endpoint A codec */ /* ip and port stay the same */ lump = remove_sdp_stream_attrs(msg, sm2); if (!lump) { LM_ERR("failed to clear sdp codecs\n"); return SNGTC_SDP_ERR; } LM_DBG("sdp stream:\n"); print_sdp_stream(sm2, L_DBG); ret = write_sdp_stream_attr(msg, lump, pair.att2, NULL); if (ret != 0) { LM_ERR("failed to write sdp stream codec\n"); return ret; } break; case SNGTC_ON: tc_on = 1; if (is_processed(info)) goto use_existing_sessions; LM_DBG("TRANSCODING ([%d] %.*s:%.*s <--> [%d] %.*s:%.*s)\n", pair.tc1, s1->ip_addr.len, s1->ip_addr.s, sm1->port.len, sm1->port.s, pair.tc2, s2->ip_addr.len, s2->ip_addr.s, sm2->port.len, sm2->port.s); memset(&request, 0, sizeof(request)); request.usr_priv = NULL; /* Codec, ms, IP and port for side A */ request.a.codec_id = pair.tc1; request.a.ms = 0; sprintf(buf, "%.*s", s1->ip_addr.len, s1->ip_addr.s); ret = inet_pton(AF_INET, buf, &addr); if (ret != 1) { LM_ERR("failed to convert ip %s to binary form (%d)\n", s1->ip_addr.s, ret); return SNGTC_ERR; } request.a.host_ip = htonl(addr.s_addr); request.a.host_netmask = (unsigned int)-1; if (str2int(&sm1->port, &request.a.host_udp_port) != 0) LM_ERR("Failed to parse integer stored in port str '%.*s'\n", sm1->port.len, sm1->port.s); /* Codec, ms, IP and port for side B */ request.b.codec_id = pair.tc2; request.b.ms = 0; sprintf(buf, "%.*s", s2->ip_addr.len, s2->ip_addr.s); ret = inet_pton(AF_INET, buf, &addr); if (ret != 1) { LM_ERR("failed to convert ip %.*s to binary form (%d)\n", s2->ip_addr.len, s2->ip_addr.s, ret); return SNGTC_ERR; } request.b.host_ip = htonl(addr.s_addr); request.b.host_netmask = (unsigned int)-1; if (str2int(&sm2->port, &request.b.host_udp_port) != 0) LM_ERR("Failed to parse integer stored in port str '%.*s'\n", sm2->port.len, sm2->port.s); LM_DBG("Transcoding request: %d:%d <--> %d:%d\n", request.a.host_ip, request.a.host_udp_port, request.b.host_ip, request.b.host_udp_port); reply = create_transcoding_session(&request, info); if (!reply) { LM_ERR("Failed to create a transcoding session on the card\n"); return SNGTC_TC_ERR; } use_existing_sessions: LM_DBG("NEW TC SESSION!\n"); if (is_processed(info)) { reply = tc_session->reply; tc_session = tc_session->next; } codec_matches[idx].reply = reply; /** * delete codecs from 200 OK * write the common codec * replace IP with ip of Sangoma card * replace port with endpoint A newly opened port on card */ lump = remove_sdp_stream_attrs(msg, sm2); if (!lump) { LM_ERR("failed to clear sdp codecs\n"); return SNGTC_SDP_ERR; } nl = del_lump(msg, s2->ip_addr.s - msg->buf, s2->ip_addr.len, 0); if (!nl) { LM_ERR("failed to add del lump\n"); return SNGTC_ERR; } if (pkg_str_dup(&repl, &card_ip_b) != 0) { LM_ERR("failed to dup in pkg mem\n"); return SNGTC_ERR; } if (!insert_new_lump_after(nl, repl.s, repl.len, HDR_OTHER_T)) { LM_ERR("failed to insert lump with codec result\n"); return SNGTC_ERR; } if (replace_sdp_stream_port(msg, sm2, reply->a.codec_udp_port) != 0) { LM_ERR("failed to rewrite sdp stream port\n"); return SNGTC_ERR; } if (write_sdp_stream_attr(msg, lump, pair.att1, reply) != 0) { LM_ERR("failed to write sdp stream codecs\n"); return SNGTC_ERR; } break; case SNGTC_UNSUP_CODECS: LM_ERR("endpoints have no common codecs and at least one side " "contains only unsupported Sangoma codecs\n"); LM_ERR("caller:\n"); print_sdp_stream(sm1, L_ERR); LM_ERR("callee:\n"); print_sdp_stream(sm2, L_ERR); return SNGTC_SDP_ERR; case SNGTC_BAD_SDP: LM_ERR("received bogus sdp with no attributes\n"); LM_ERR("caller:\n"); print_sdp_stream(sm1, L_ERR); LM_ERR("callee:\n"); print_sdp_stream(sm2, L_ERR); return SNGTC_SDP_ERR; } } if (tc_on) { LM_DBG("transcoding: ON\n"); memcpy(dst->s + dst->len, src->s, s1->ip_addr.s - src->s); dst->len += s1->ip_addr.s - src->s; dst->len += sprintf(dst->s + dst->len, "%.*s", card_ip_a.len, card_ip_a.s); src->s += s1->ip_addr.s - src->s + s1->ip_addr.len; } else LM_DBG("transcoding: OFF\n"); rc |= process_stream(s1->streams, s2->streams, src, dst, MAX_STREAMS - 1); out: return rc; }
/*! * \brief Previous hop was a loose router, handle this case * \param _m SIP message * \param preloaded do we have a preloaded route set * \return -1 on failure, 1 on success */ static inline int after_loose(struct sip_msg* _m, int preloaded) { struct hdr_field* hdr; struct sip_uri puri; rr_t* rt; int res; int status = RR_DRIVEN; str uri; struct socket_info *si; int uri_is_myself, next_is_strict; int use_ob = 0; hdr = _m->route; rt = (rr_t*)hdr->parsed; uri = rt->nameaddr.uri; /* reset rr handling static vars for safety in error case */ routed_msg_id = 0; if (parse_uri(uri.s, uri.len, &puri) < 0) { LM_ERR("failed to parse the first route URI\n"); return RR_ERROR; } next_is_strict = is_strict(&puri.params); routed_params = puri.params; uri_is_myself = is_myself(&puri); /* IF the URI was added by me, remove it */ if (uri_is_myself>0) { LM_DBG("Topmost route URI: '%.*s' is me\n", uri.len, ZSW(uri.s)); /* set the hooks for the params */ routed_msg_id = _m->id; if ((use_ob = process_outbound(_m, puri.user)) < 0) { LM_INFO("failed to process outbound flow-token\n"); return FLOW_TOKEN_BROKEN; } if (!rt->next) { /* No next route in the same header, remove the whole header * field immediately */ if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } res = find_next_route(_m, &hdr); if (res < 0) { LM_ERR("failed to find next route\n"); return RR_ERROR; } if (res > 0) { /* No next route found */ LM_DBG("No next URI found\n"); status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN); goto done; } rt = (rr_t*)hdr->parsed; } else rt = rt->next; if (enable_double_rr && is_2rr(&puri.params)) { /* double route may occure due different IP and port, so force as * send interface the one advertise in second Route */ if (parse_uri(rt->nameaddr.uri.s,rt->nameaddr.uri.len,&puri)<0) { LM_ERR("failed to parse the double route URI\n"); return RR_ERROR; } if (!use_ob) { si = grep_sock_info( &puri.host, puri.port_no, puri.proto); if (si) { set_force_socket(_m, si); } else { if (enable_socket_mismatch_warning) LM_WARN("no socket found for match second RR\n"); } } if (!rt->next) { /* No next route in the same header, remove the whole header * field immediately */ if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } res = find_next_route(_m, &hdr); if (res < 0) { LM_ERR("failed to find next route\n"); return RR_ERROR; } if (res > 0) { /* No next route found */ LM_DBG("no next URI found\n"); status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN); goto done; } rt = (rr_t*)hdr->parsed; } else rt = rt->next; } uri = rt->nameaddr.uri; if (parse_uri(uri.s, uri.len, &puri) < 0) { LM_ERR("failed to parse the first route URI\n"); return RR_ERROR; } } else { #ifdef ENABLE_USER_CHECK /* check if it the ignored user */ if(uri_is_myself < 0) return NOT_RR_DRIVEN; #endif LM_DBG("Topmost URI is NOT myself\n"); routed_params.s = NULL; routed_params.len = 0; } LM_DBG("URI to be processed: '%.*s'\n", uri.len, ZSW(uri.s)); if (next_is_strict) { LM_DBG("Next URI is a strict router\n"); if (handle_sr(_m, hdr, rt) < 0) { LM_ERR("failed to handle strict router\n"); return RR_ERROR; } } else { /* Next hop is loose router */ LM_DBG("Next URI is a loose router\n"); if (!use_ob) { if(get_maddr_uri(&uri, &puri)!=0) { LM_ERR("checking maddr failed\n"); return RR_ERROR; } if (set_dst_uri(_m, &uri) < 0) { LM_ERR("failed to set dst_uri\n"); return RR_ERROR; } /* dst_uri changed, so it makes sense to re-use the current uri for forking */ ruri_mark_new(); /* re-use uri for serial forking */ } /* There is a previous route uri which was 2nd uri of mine * and must be removed here */ if (rt != hdr->parsed) { if (!del_lump(_m, hdr->body.s - _m->buf, rt->nameaddr.name.s - hdr->body.s, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } } } done: if (use_ob == 1) status = RR_OB_DRIVEN; /* run RR callbacks only if we have Route URI parameters */ if(routed_params.len > 0) run_rr_callbacks( _m, &routed_params ); return status; }
int save(struct sip_msg* _m, char* _d, char* _f, char* _s) { struct sip_msg* msg = _m; struct cell* t = NULL; contact_t* _c; contact_t* reply_c = NULL; contact_t* request_c = NULL; int st; int ret; int requested_exp = 0; int enforced_exp = 0; int_str val; struct lump* l; char* p; char forced_binding_buf[MAX_FORCED_BINDING_LEN]; str forced_binding = {NULL, 0}; str *binding_uri; if(_m->first_line.type != SIP_REPLY) return save_aux(_m, NULL, _d, _f, _s); memset(&val, 0, sizeof(int_str)); if(!tmb.t_gett) { LM_ERR("TM module not loaded - can not save on reply\n"); return -1; } t = tmb.t_gett(); if(!t || t==T_UNDEFINED) { LM_ERR("Transaction not created on Register - can not save on reply\n"); return -1; } msg = t->uas.request; if(!msg) { LM_ERR("NULL request - can not save on reply\n"); return -1; } if (parse_message(_m) < 0) return -1; if (check_contacts(_m, &st) > 0) return -1; if (parse_message(msg) < 0) return -1; if (check_contacts(msg, &st) > 0) return -1; /* msg - request _m - reply */ request_c = get_first_contact(msg); if(request_c) { /* For now, we deal only with the first contact * FIXME: implement multiple contact handling - see check_contacts() */ if(!request_c->expires || !request_c->expires->body.len) { if (((exp_body_t*)(msg->expires->parsed))->valid) { requested_exp = ((exp_body_t*)(msg->expires->parsed))->val; } else { LM_WARN("No expired defined\n"); } } else { if (str2int(&(request_c->expires->body), (unsigned int*)&requested_exp)<0) { LM_ERR("unable to get expires from [%.*s]\n", request_c->expires->body.len, request_c->expires->body.s); return -1; } } LM_DBG("Binding received from client [%.*s] with requested expires [%d]\n", request_c->uri.len, request_c->uri.s, requested_exp); /* We will use the Contact from request: * - check if a modified contact was set in avp */ if (mct_avp_name >= 0 && search_first_avp(mct_avp_type,mct_avp_name,&val,0) && val.s.len > 0) { LM_DBG("Binding sent to upper registrar [%.*s]\n", val.s.len, val.s.s); binding_uri = &val.s; } else { binding_uri = &request_c->uri; } if (requested_exp) { /* Let's get the contact from reply */ _c = get_first_contact(_m); while (_c) { if (compare_uris(binding_uri, NULL, &_c->uri, NULL) == 0) { if(_c->expires && _c->expires->body.len) { if(str2int(&(_c->expires->body), (unsigned int*)&enforced_exp)<0) { LM_ERR("unable to get expires from [%.*s]\n", _c->expires->body.len, _c->expires->body.s); return -1; } LM_DBG("Binding received from upper registrar" " [%.*s] with imposed expires [%d]\n", _c->uri.len, _c->uri.s, enforced_exp); reply_c = _c; forced_binding.len = request_c->uri.len + 11 + reply_c->expires->body.len; if (forced_binding.len <= MAX_FORCED_BINDING_LEN) { forced_binding.s = forced_binding_buf; forced_binding_buf[0] = '<'; memcpy(&forced_binding_buf[1], request_c->uri.s, request_c->uri.len); memcpy(&forced_binding_buf[request_c->uri.len + 1], ">;expires=", 10); memcpy(&forced_binding_buf[request_c->uri.len + 11], reply_c->expires->body.s, reply_c->expires->body.len); LM_DBG("forcing binding [%.*s]\n", forced_binding.len, forced_binding.s); break; } else { LM_ERR("forced binding to BIG:" " %d > MAX_FORCED_BINDING_LEN\n", forced_binding.len); return -1; } } } else { LM_DBG("Unmatched binding [%.*s]\n", _c->uri.len, _c->uri.s); } _c = get_next_contact(_c); } } ret = save_aux(msg, forced_binding.s?&forced_binding:NULL, _d, _f, _s); } else { LM_DBG("No Contact in request => this is an interogation\n"); ret = 1; } /* if the contact was changed in register - put the modif value */ if(request_c && requested_exp && val.s.s) { if(reply_c) { LM_DBG("replacing contact uri [%.*s] with [%.*s]\n", reply_c->uri.len, reply_c->uri.s, request_c->uri.len, request_c->uri.s); /* replace with what was received in Register */ /* reply_c->uri - now contains the initial received value */ if((l=del_lump(_m, reply_c->uri.s - _m->buf, reply_c->uri.len, 0))==0) { LM_ERR("Failed to delete contact uri lump\n"); ret = -1; goto done; } p = pkg_malloc( request_c->uri.len); if (p==0) { LM_ERR("no more pkg mem\n"); ret = -1; goto done; } memcpy( p, request_c->uri.s, request_c->uri.len ); if (insert_new_lump_after( l, p, request_c->uri.len, 0)==0) { LM_ERR("insert new lump failed\n"); pkg_free(p); ret =-1; goto done; } } } done: clean_msg_clone(t->uas.request, t->uas.request, t->uas.end_request); return ret; }
/** * sngtc_caller_answer - attaches an SDP body to ACK requests */ static int sngtc_caller_answer(struct sip_msg *msg) { char *p; str body; struct dlg_cell *dlg; struct lump *lump; struct sngtc_info *info; int len; LM_DBG("processing ACK\n"); if (get_body(msg, &body) != 0 || body.len > 0) { LM_ERR("ACK should not contain a SDP body\n"); return SNGTC_ERR; } dlg = dlg_binds.get_dlg(); if (!dlg) { LM_ERR("failed to fetch current dialog\n"); return SNGTC_ERR; } /* get the SDP body from the INVITE which was mangled at 200 OK */ if (dlg_binds.fetch_dlg_value(dlg, &dlg_key_sngtc_info, &body, 0) != 0) { LM_ERR("failed to fetch caller sdp\n"); return SNGTC_ERR; } info = *(struct sngtc_info **)(body.s); /* duplicate the SDP in pkg mem for the lumps mechanism */ if (pkg_str_dup(&body, &info->modified_caller_sdp) != 0) { LM_ERR("failed to dup in pkg mem\n"); return SNGTC_ERR; } LM_DBG("Duplicated SDP: '%.*s'\n", body.len, body.s); lump = anchor_lump(msg, msg->content_length->name.s - msg->buf, 0); if (!lump) { LM_ERR("failed to insert anchor lump\n"); return SNGTC_ERR; } p = pkg_malloc(SDP_CONTENT_TYPE_LEN); if (!p) { LM_ERR("no more pkg memory\n"); return SNGTC_ERR; } /* add the Content-Type header */ memcpy(p, "Content-Type: application/sdp\r\n", SDP_CONTENT_TYPE_LEN); if (!insert_new_lump_before(lump, p, SDP_CONTENT_TYPE_LEN, 0)) { LM_ERR("failed to insert Content-Type lump\n"); return SNGTC_ERR; } LM_DBG("blen: %d\n", msg->content_length->body.len); lump = del_lump(msg, msg->content_length->body.s - msg->buf, msg->content_length->body.len, HDR_OTHER_T); if (!lump) { LM_ERR("failed to insert del lump for the content length\n"); return SNGTC_ERR; } p = pkg_malloc(CONTENT_LEN_DIGITS); if (!p) { LM_ERR("no more pkg memory\n"); return SNGTC_ERR; } LM_DBG("len: %d\n", body.len); len = sprintf(p, "%d", body.len); if (!insert_new_lump_after(lump, p, len, HDR_OTHER_T)) { LM_ERR("failed to insert Content-Length lump\n"); return SNGTC_ERR; } lump = anchor_lump(msg, msg->len - CRLF_LEN, 0); if (!lump) { LM_ERR("failed to insert anchor lump\n"); return SNGTC_ERR; } if (!insert_new_lump_before(lump, body.s, body.len, 0)) { LM_ERR("failed to insert SDP body lump\n"); return SNGTC_ERR; } return 1; }
/** * sngtc_offer - will remove the SDP body of an early negotiation INVITE and * store it in the newly created dialog as a dlg_val. * * @return: 1 on success, negative on failure */ static int sngtc_offer(struct sip_msg *msg) { struct hdr_field *hf; struct lump *lump; struct dlg_cell *dlg; struct sngtc_info *info = NULL; str body, totag, st; if (dlg_binds.create_dlg(msg, 0) < 0) { LM_ERR("failed to create dialog\n"); return SNGTC_ERR; } dlg = dlg_binds.get_dlg(); if (!dlg) { LM_ERR("failed to fetch current dialog\n"); return SNGTC_ERR; } if (get_body(msg, &body) != 0 || body.len <= 0) { LM_ERR("can only do transcoding for early negotiation INVITES\n"); return SNGTC_SDP_ERR; } totag = get_to(msg)->tag_value; /* INVITE retransmissions will skip this part */ if (dlg_binds.fetch_dlg_value(dlg, &dlg_key_sngtc_info, &st, 0) != 0) { if (store_sngtc_info(dlg, &body) != 0) { LM_ERR("failed to create sngtc info struct\n"); return SNGTC_ERR; } /* register a callback to free the above */ if (dlg_binds.register_dlgcb(dlg, DLGCB_EXPIRED|DLGCB_FAILED|DLGCB_TERMINATED, sngtc_dlg_terminated, NULL, NULL) != 0) { LM_ERR("failed to register dialog callback\n"); return SNGTC_ERR; } /* for re-INVITES, just recreate the struct sngtc_info */ } else if (totag.s && totag.len != 0) { info = *(struct sngtc_info **)(st.s); free_transcoding_sessions(info->sessions); if (info->caller_sdp.s) shm_free(info->caller_sdp.s); if (info->modified_caller_sdp.s) shm_free(info->modified_caller_sdp.s); if (store_sngtc_info(dlg, &body) != 0) { LM_ERR("failed to create sngtc info struct\n"); return SNGTC_ERR; } shm_free(info); } LM_DBG("SDP body:\n"); LM_DBG("%.*s\n", body.len, body.s); hf = msg->content_type; /* delete the Content-Type header, we're setting up late negotiation */ lump = del_lump(msg, hf->name.s - msg->buf, hf->len, HDR_OTHER_T); if (!lump) { LM_ERR("no more pkg mem\n"); return SNGTC_ERR; } /* trim the entire SDP body */ lump = del_lump(msg, body.s - msg->buf, body.len, HDR_OTHER_T); if (!lump) { LM_ERR("no more pkg mem\n"); return SNGTC_ERR; } return 1; }
/* * Send a request using data from the dialog structure */ int t_uac(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb, void* cbp,release_tmcb_param release_func) { union sockaddr_union to_su, new_to_su; struct cell *new_cell; struct cell *backup_cell; struct retr_buf *request; static struct sip_msg *req; struct usr_avp **backup; char *buf, *buf1; int buf_len, buf_len1; int ret, flags, sflag_bk; int backup_route_type; int sip_msg_len; unsigned int hi; struct socket_info *new_send_sock; str h_to, h_from, h_cseq, h_callid; struct proxy_l *proxy, *new_proxy; unsigned short dst_changed; ret=-1; /*** added by dcm * - needed by external ua to send a request within a dlg */ if(!dialog->hooks.next_hop && w_calculate_hooks(dialog)<0) goto error3; if(dialog->obp.s) dialog->hooks.next_hop = &dialog->obp; LM_DBG("next_hop=<%.*s>\n",dialog->hooks.next_hop->len, dialog->hooks.next_hop->s); /* calculate the socket corresponding to next hop */ proxy = uri2proxy( dialog->hooks.next_hop, dialog->send_sock ? dialog->send_sock->proto : PROTO_NONE ); if (proxy==0) { ret=E_BAD_ADDRESS; goto error3; } /* use the first address */ hostent2su( &to_su, &proxy->host, proxy->addr_idx, proxy->port ? proxy->port:SIP_PORT); /* check/discover the send socket */ if (dialog->send_sock) { /* if already set, the protocol of send sock must have the the same type as the proto required by destination URI */ if (proxy->proto != dialog->send_sock->proto) dialog->send_sock = NULL; } if (dialog->send_sock==NULL) { /* get the send socket */ dialog->send_sock = get_send_socket( NULL/*msg*/, &to_su, proxy->proto); if (!dialog->send_sock) { LM_ERR("no corresponding socket for af %d\n", to_su.s.sa_family); ser_error = E_NO_SOCKET; goto error2; } } LM_DBG("sending socket is %.*s \n", dialog->send_sock->name.len,dialog->send_sock->name.s); /* ***** Create TRANSACTION and all related ***** */ new_cell = build_cell( NULL/*msg*/, 1/*full UAS clone*/); if (!new_cell) { ret=E_OUT_OF_MEM; LM_ERR("short of cell shmem\n"); goto error2; } /* pass the transaction flags from dialog to transaction */ new_cell->flags |= dialog->T_flags; /* add the callback the transaction for LOCAL_COMPLETED event */ flags = TMCB_LOCAL_COMPLETED; /* Add also TMCB_LOCAL_RESPONSE_OUT if provisional replies are desired */ if (pass_provisional_replies || pass_provisional(new_cell)) flags |= TMCB_LOCAL_RESPONSE_OUT; if(cb && insert_tmcb(&(new_cell->tmcb_hl),flags,cb,cbp,release_func)!=1){ ret=E_OUT_OF_MEM; LM_ERR("short of tmcb shmem\n"); goto error2; } if (method->len==INVITE_LEN && memcmp(method->s, INVITE, INVITE_LEN)==0) new_cell->flags |= T_IS_INVITE_FLAG; new_cell->flags |= T_IS_LOCAL_FLAG; request = &new_cell->uac[0].request; if (dialog->forced_to_su.s.sa_family == AF_UNSPEC) request->dst.to = to_su; else request->dst.to = dialog->forced_to_su; request->dst.send_sock = dialog->send_sock; request->dst.proto = dialog->send_sock->proto; request->dst.proto_reserved1 = 0; hi=dlg2hash(dialog); LOCK_HASH(hi); insert_into_hash_table_unsafe(new_cell, hi); UNLOCK_HASH(hi); /* copy AVPs into transaction */ new_cell->user_avps = dialog->avps; dialog->avps = NULL; /* ***** Create the message buffer ***** */ buf = build_uac_req(method, headers, body, dialog, 0, new_cell, &buf_len); if (!buf) { LM_ERR("failed to build message\n"); ret=E_OUT_OF_MEM; goto error1; } if (local_rlist.a) { LM_DBG("building sip_msg from buffer\n"); req = buf_to_sip_msg(buf, buf_len, dialog); if (req==NULL) { LM_ERR("failed to build sip_msg from buffer\n"); } else { /* set this transaction as active one */ backup_cell = get_t(); set_t( new_cell ); /* set transaction AVP list */ backup = set_avp_list( &new_cell->user_avps ); /* backup script flags */ sflag_bk = getsflags(); /* disable parallel forking */ set_dset_state( 0 /*disable*/); /* run the route */ swap_route_type( backup_route_type, LOCAL_ROUTE); run_top_route( local_rlist.a, req); set_route_type( backup_route_type ); /* transfer current message context back to t */ new_cell->uac[0].br_flags = getb0flags(req); /* restore the prevoius active transaction */ set_t( backup_cell ); set_dset_state( 1 /*enable*/); setsflagsval(sflag_bk); set_avp_list( backup ); /* check for changes - if none, do not regenerate the buffer */ dst_changed = 1; if (req->new_uri.s || req->force_send_socket!=dialog->send_sock || req->dst_uri.len != dialog->hooks.next_hop->len || memcmp(req->dst_uri.s,dialog->hooks.next_hop->s,req->dst_uri.len) || (dst_changed=0)==0 || req->add_rm || req->body_lumps){ new_send_sock = NULL; /* do we also need to change the destination? */ if (dst_changed) { /* calculate the socket corresponding to next hop */ new_proxy = uri2proxy( req->dst_uri.s ? &(req->dst_uri) : &req->new_uri, PROTO_NONE ); if (new_proxy==0) goto abort_update; /* use the first address */ hostent2su( &new_to_su, &new_proxy->host, new_proxy->addr_idx, new_proxy->port ? new_proxy->port:SIP_PORT); /* get the send socket */ new_send_sock = get_send_socket( req, &new_to_su, new_proxy->proto); if (!new_send_sock) { free_proxy( new_proxy ); pkg_free( new_proxy ); LM_ERR("no socket found for the new destination\n"); goto abort_update; } } /* if interface change, we need to re-build the via */ if (new_send_sock && new_send_sock != dialog->send_sock) { LM_DBG("Interface change in local route -> " "rebuilding via\n"); if (!del_lump(req,req->h_via1->name.s - req->buf, req->h_via1->len,0)) { LM_ERR("Failed to remove initial via \n"); goto abort_update; } memcpy(req->add_to_branch_s,req->via1->branch->value.s, req->via1->branch->value.len); req->add_to_branch_len = req->via1->branch->value.len; /* update also info about new destination and send sock */ dialog->send_sock = new_send_sock; free_proxy( proxy ); pkg_free( proxy ); proxy = new_proxy; request->dst.send_sock = new_send_sock; request->dst.proto = new_send_sock->proto; request->dst.proto_reserved1 = 0; /* build the shm buffer now */ set_init_lump_flags(LUMPFLAG_BRANCH); buf1 = build_req_buf_from_sip_req(req, (unsigned int*)&buf_len1, new_send_sock, new_send_sock->proto, MSG_TRANS_SHM_FLAG); reset_init_lump_flags(); del_flaged_lumps( &req->add_rm, LUMPFLAG_BRANCH); } else { LM_DBG("Change in local route -> rebuilding buffer\n"); /* build the shm buffer now */ buf1 = build_req_buf_from_sip_req(req, (unsigned int*)&buf_len1, dialog->send_sock, dialog->send_sock->proto, MSG_TRANS_SHM_FLAG|MSG_TRANS_NOVIA_FLAG); /* now as it used, hide the original VIA header */ del_lump(req,req->h_via1->name.s - req->buf, req->h_via1->len, 0); } if (!buf1) { LM_ERR("no more shm mem\n"); /* keep original buffer */ goto abort_update; } /* update shortcuts */ if(!req->add_rm && !req->new_uri.s) { /* headers are not affected, simply tranlate */ new_cell->from.s = new_cell->from.s - buf + buf1; new_cell->to.s = new_cell->to.s - buf + buf1; new_cell->callid.s = new_cell->callid.s - buf + buf1; new_cell->cseq_n.s = new_cell->cseq_n.s - buf + buf1; } else { /* use heavy artilery :D */ if (extract_ftc_hdrs( buf1, buf_len1, &h_from, &h_to, &h_cseq, &h_callid)!=0 ) { LM_ERR("failed to update shortcut pointers\n"); shm_free(buf1); goto abort_update; } new_cell->from = h_from; new_cell->to = h_to; new_cell->callid = h_callid; new_cell->cseq_n = h_cseq; } /* here we rely on how build_uac_req() builds the first line */ new_cell->uac[0].uri.s = buf1 + req->first_line.u.request.method.len + 1; new_cell->uac[0].uri.len = GET_RURI(req)->len; /* update also info about new destination and send sock */ if (new_send_sock) request->dst.to = new_to_su; shm_free(buf); buf = buf1; buf_len = buf_len1; /* use new buffer */ } else { /* no changes over the message, buffer is already generated, just hide the original VIA for potential further branches */ del_lump(req,req->h_via1->name.s-req->buf,req->h_via1->len,0); } abort_update: /* save the SIP message into transaction */ new_cell->uas.request = sip_msg_cloner( req, &sip_msg_len, 1); if (new_cell->uas.request==NULL) { /* reset any T triggering */ new_cell->on_negative = 0; new_cell->on_reply = 0; } else { new_cell->uas.end_request= ((char*)new_cell->uas.request)+sip_msg_len; } /* no parallel support in UAC transactions */ new_cell->on_branch = 0; free_sip_msg(req); } } /* for DNS based failover, copy the DNS proxy into transaction */ if (!disable_dns_failover) { new_cell->uac[0].proxy = shm_clone_proxy( proxy, 1/*do_free*/); if (new_cell->uac[0].proxy==NULL) LM_ERR("failed to store DNS info -> no DNS based failover\n"); } new_cell->method.s = buf; new_cell->method.len = method->len; request->buffer.s = buf; request->buffer.len = buf_len; new_cell->nr_of_outgoings++; if(last_localT) { *last_localT = new_cell; REF_UNSAFE(new_cell); } if (SEND_BUFFER(request) == -1) { LM_ERR("attempt to send to '%.*s' failed\n", dialog->hooks.next_hop->len, dialog->hooks.next_hop->s); } if (method->len==ACK_LEN && memcmp(method->s, ACK, ACK_LEN)==0 ) { t_release_transaction(new_cell); } else { start_retr(request); } free_proxy( proxy ); pkg_free( proxy ); return 1; error1: LOCK_HASH(hi); remove_from_hash_table_unsafe(new_cell); UNLOCK_HASH(hi); free_cell(new_cell); error2: free_proxy( proxy ); pkg_free( proxy ); error3: return ret; }
static inline int after_loose(struct sip_msg* _m, int preloaded) { struct hdr_field* hdr; struct sip_uri puri; struct sip_uri puri2; rr_t* rt; int res; int status; #ifdef ENABLE_USER_CHECK int ret; #endif str uri; struct socket_info *si; int force_ss = 0; hdr = _m->route; rt = (rr_t*)hdr->parsed; uri = rt->nameaddr.uri; if (parse_uri(uri.s, uri.len, &puri) < 0) { LM_ERR("failed to parse the first route URI\n"); return RR_ERROR; } /* IF the URI was added by me, remove it */ #ifdef ENABLE_USER_CHECK ret=is_myself(&puri.user, &puri.host, puri.port_no); if (ret>0) #else if (is_myself(&puri.host, puri.port_no)) #endif { LM_DBG("Topmost route URI: '%.*s' is me\n", uri.len, ZSW(uri.s)); /* set the hooks for the params -bogdan */ ctx_rrparam_set( &puri.params ); /* if last route in header, gonna get del_lumped now, * if not, it will be taken care of later * Mark it now as deleted */ rt->deleted = 1; if (!rt->next) { /* No next route in the same header, remove the whole header * field immediately */ if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } rt->deleted = 1; res = find_next_route(_m, &hdr); if (res < 0) { LM_ERR("failed to find next route\n"); return RR_ERROR; } if (res > 0) { /* No next route found */ LM_DBG("No next URI found!\n"); status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN); /*same case as LL , if there is no next route*/ ctx_routing_set( ROUTING_LL ); force_ss = 1; goto done; } rt = (rr_t*)hdr->parsed; } else rt = rt->next; if (enable_double_rr && is_2rr(&puri.params)) { force_ss = 0; /* double route may occure due different IP and port, so force as * send interface the one advertise in second Route */ if (parse_uri(rt->nameaddr.uri.s,rt->nameaddr.uri.len,&puri)<0) { LM_ERR("failed to parse the double route URI\n"); return RR_ERROR; } set_sip_defaults( puri.port_no, puri.proto); si = grep_sock_info( &puri.host, puri.port_no, puri.proto); if (si) { _m->force_send_socket = si; } else { if (enable_socket_mismatch_warning) LM_WARN("no socket found to match 2nd RR [%d][%.*s:%d]\n", puri.proto, puri.host.len, puri.host.s, puri.port_no); } rt->deleted = 1; if (!rt->next) { /* No next route in the same header, remove the whole header * field immediately */ if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } res = find_next_route(_m, &hdr); if (res < 0) { LM_ERR("failed to find next route\n"); return RR_ERROR; } if (res > 0) { /* No next route found */ LM_DBG("no next URI found\n"); status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN); /* same case as LL , if there is no next route */ ctx_routing_set( ROUTING_LL ); goto done; } rt = (rr_t*)hdr->parsed; } else rt = rt->next; } else { force_ss = 1; } uri = rt->nameaddr.uri; if (parse_uri(uri.s, uri.len, &puri2) < 0) { LM_ERR("failed to parse the first route URI\n"); return RR_ERROR; } } else { #ifdef ENABLE_USER_CHECK /* check if it the ignored user */ if(ret < 0) return NOT_RR_DRIVEN; #endif LM_DBG("Topmost URI is NOT myself\n"); memcpy(&puri2, &puri, sizeof(struct sip_uri)); } LM_DBG("URI to be processed: '%.*s'\n", uri.len, ZSW(uri.s)); if (is_strict(&puri2.params)) { LM_DBG("Next URI is a strict router\n"); ctx_routing_set( ROUTING_LS ); if (handle_sr(_m, hdr, rt) < 0) { LM_ERR("failed to handle strict router\n"); return RR_ERROR; } } else { /* Next hop is loose router */ LM_DBG("Next URI is a loose router\n"); ctx_routing_set( ROUTING_LL ); if(get_maddr_uri(&uri, &puri2)!=0) { LM_ERR("checking maddr failed\n"); return RR_ERROR; } if (set_dst_uri(_m, &uri) < 0) { LM_ERR("failed to set dst_uri\n"); return RR_ERROR; } /* There is a previous route uri which was 2nd uri of mine * and must be removed here */ if (rt != hdr->parsed) { if (!del_lump(_m, hdr->body.s - _m->buf, rt->nameaddr.name.s - hdr->body.s, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } ((rr_t *)hdr->parsed)->deleted = 1; } } status = RR_DRIVEN; done: if (force_ss && !preloaded) _m->force_send_socket = _m->rcv.bind_address; /* run RR callbacks -bogdan */ run_rr_callbacks( _m, &puri.params ); return status; }
/*! * \brief Previous hop was a strict router, handle this case * \param _m SIP message * \return -1 on error, 1 on success */ static inline int after_strict(struct sip_msg* _m) { int res, rem_len; struct hdr_field* hdr; struct sip_uri puri; rr_t* rt, *prev; char* rem_off; str uri; struct socket_info *si; hdr = _m->route; rt = (rr_t*)hdr->parsed; uri = rt->nameaddr.uri; /* reset rr handling static vars for safety in error case */ routed_msg_id = 0; routed_params.s = NULL; routed_params.len = 0; if (parse_uri(uri.s, uri.len, &puri) < 0) { LM_ERR("failed to parse the first route URI\n"); return RR_ERROR; } if ( enable_double_rr && is_2rr(&puri.params) && is_myself(&puri)) { /* double route may occure due different IP and port, so force as * send interface the one advertise in second Route */ si = grep_sock_info( &puri.host, puri.port_no, puri.proto); if (si) { set_force_socket(_m, si); } else { if (enable_socket_mismatch_warning) LM_WARN("no socket found for match second RR\n"); } if (!rt->next) { /* No next route in the same header, remove the whole header * field immediately */ if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } res = find_next_route(_m, &hdr); if (res < 0) { LM_ERR("searching next route failed\n"); return RR_ERROR; } if (res > 0) { /* No next route found */ LM_DBG("after_strict: No next URI found\n"); return NOT_RR_DRIVEN; } rt = (rr_t*)hdr->parsed; } else rt = rt->next; /* parse the new found uri */ uri = rt->nameaddr.uri; if (parse_uri(uri.s, uri.len, &puri) < 0) { LM_ERR("failed to parse URI\n"); return RR_ERROR; } } /* set the hooks for the param * important note: RURI is already parsed by the above function, so * we just used it without any checking */ routed_msg_id = _m->id; routed_params = _m->parsed_uri.params; if (is_strict(&puri.params)) { LM_DBG("Next hop: '%.*s' is strict router\n", uri.len, ZSW(uri.s)); /* Previous hop was a strict router and the next hop is strict * router too. There is no need to save R-URI again because it * is saved already. In fact, in this case we will behave exactly * like a strict router. */ /* Note: when there is only one Route URI left (endpoint), it will * always be a strict router because endpoints don't use ;lr parameter * In this case we will simply put the URI in R-URI and forward it, * which will work perfectly */ if(get_maddr_uri(&uri, &puri)!=0) { LM_ERR("failed to check maddr\n"); return RR_ERROR; } if (rewrite_uri(_m, &uri) < 0) { LM_ERR("failed to rewrite request URI\n"); return RR_ERROR; } if (rt->next) { rem_off = hdr->body.s; rem_len = rt->next->nameaddr.name.s - hdr->body.s; } else { rem_off = hdr->name.s; rem_len = hdr->len; } if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } } else { LM_DBG("Next hop: '%.*s' is loose router\n", uri.len, ZSW(uri.s)); if(get_maddr_uri(&uri, &puri)!=0) { LM_ERR("failed to check maddr\n"); return RR_ERROR; } if (set_dst_uri(_m, &uri) < 0) { LM_ERR("failed to set dst_uri\n"); return RR_ERROR; } /* Next hop is a loose router - Which means that is is not endpoint yet * In This case we have to recover from previous strict routing, that * means we have to find the last Route URI and put in in R-URI and * remove the last Route URI. */ if (rt != hdr->parsed) { /* There is a previous route uri which was 2nd uri of mine * and must be removed here */ rem_off = hdr->body.s; rem_len = rt->nameaddr.name.s - hdr->body.s; if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } } res = find_rem_target(_m, &hdr, &rt, &prev); if (res < 0) { LM_ERR("searching for last Route URI failed\n"); return RR_ERROR; } else if (res > 0) { /* No remote target is an error */ return RR_ERROR; } uri = rt->nameaddr.uri; if(get_maddr_uri(&uri, 0)!=0) { LM_ERR("checking maddr failed\n"); return RR_ERROR; } if (rewrite_uri(_m, &uri) < 0) { LM_ERR("failed to rewrite R-URI\n"); return RR_ERROR; } /* The first character if uri will be either '<' when it is the * only URI in a Route header field or ',' if there is more than * one URI in the header field */ LM_DBG("The last route URI: '%.*s'\n", rt->nameaddr.uri.len, ZSW(rt->nameaddr.uri.s)); if (prev) { rem_off = prev->nameaddr.name.s + prev->len; rem_len = rt->nameaddr.name.s + rt->len - rem_off; } else { rem_off = hdr->name.s; rem_len = hdr->len; } if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } } /* run RR callbacks only if we have Route URI parameters */ if(routed_params.len > 0) run_rr_callbacks( _m, &routed_params ); return RR_DRIVEN; }
int th_mask_contact(sip_msg_t *msg) { struct lump* l; str out; str in; char *p; contact_t *c; if(msg->contact==NULL) { LM_DBG("no contact header\n"); return 0; } if(parse_contact(msg->contact) < 0) { LM_ERR("failed parsing contact header\n"); return -1; } c = ((contact_body_t*)msg->contact->parsed)->contacts; in = c->uri; out.s = th_mask_encode(in.s, in.len, &th_uri_prefix, &out.len); if(out.s==NULL) { LM_ERR("cannot encode contact uri\n"); return -1; } if(*(in.s-1)!='<') { /* add < > around contact uri if not there */ p = (char*)pkg_malloc(out.len+3); if(p==NULL) { LM_ERR("failed to get more pkg\n"); pkg_free(out.s); return -1; } *p = '<'; strncpy(p+1, out.s, out.len); p[out.len+1] = '>'; p[out.len+2] = '\0'; pkg_free(out.s); out.s = p; out.len += 2; } l=del_lump(msg, in.s-msg->buf, in.len, 0); if (l==0) { LM_ERR("failed deleting contact uri\n"); pkg_free(out.s); return -1; } if (insert_new_lump_after(l, out.s, out.len, 0)==0) { LM_ERR("could not insert new lump\n"); pkg_free(out.s); return -1; } return 0; }
/** * @brief forward SIP reply statelessy with different code and reason text */ static int w_sl_forward_reply(sip_msg_t* msg, str* code, str* reason) { char oldscode[3]; int oldncode; int ret; struct lump *ldel = NULL; struct lump *ladd = NULL; char *rbuf; if(msg->first_line.type!=SIP_REPLY) { LM_ERR("invalid SIP message type\n"); return -1; } if(code!=NULL) { if(code->len!=3) { LM_ERR("invalid reply code value %.*s\n", code->len, code->s); return -1; } if(msg->first_line.u.reply.status.s[0]!=code->s[0]) { LM_ERR("reply code class cannot be changed\n"); return -1; } if(code->s[1]<'0' || code->s[1]>'9' || code->s[2]<'0' || code->s[2]>'9') { LM_ERR("invalid reply code value %.*s!\n", code->len, code->s); return -1; } } if(reason!=NULL && reason->len<=0) { LM_ERR("invalid reply reason value\n"); return -1; } /* backup old values */ oldscode[0] = msg->first_line.u.reply.status.s[0]; oldscode[1] = msg->first_line.u.reply.status.s[1]; oldscode[2] = msg->first_line.u.reply.status.s[2]; oldncode = msg->first_line.u.reply.statuscode; if(code!=NULL) { /* update status code directly in msg buffer */ msg->first_line.u.reply.statuscode = (code->s[0]-'0')*100 + (code->s[1]-'0')*10 + code->s[2]-'0'; msg->first_line.u.reply.status.s[0] = code->s[0]; msg->first_line.u.reply.status.s[1] = code->s[1]; msg->first_line.u.reply.status.s[2] = code->s[2]; } if(reason!=NULL) { ldel = del_lump(msg, msg->first_line.u.reply.reason.s - msg->buf, msg->first_line.u.reply.reason.len, 0); if (ldel==NULL) { LM_ERR("failed to add del lump\n"); ret = -1; goto restore; } rbuf = (char *)pkg_malloc(reason->len); if (rbuf==NULL) { LM_ERR("not enough memory\n"); ret = -1; goto restore; } memcpy(rbuf, reason->s, reason->len); ladd = insert_new_lump_after(ldel, rbuf, reason->len, 0); if (ladd==0) { LOG(L_ERR, "failed to add reason lump: %.*s\n", reason->len, reason->s); pkg_free(rbuf); ret = -1; goto restore; } } ret = forward_reply_nocb(msg); restore: if(reason!=NULL) { if(ldel!=NULL) { remove_lump(msg, ldel); } if(ladd!=NULL) { remove_lump(msg, ladd); } } if(code!=NULL) { msg->first_line.u.reply.statuscode = oldncode; msg->first_line.u.reply.status.s[0] = oldscode[0]; msg->first_line.u.reply.status.s[1] = oldscode[1]; msg->first_line.u.reply.status.s[2] = oldscode[2]; } return (ret==0)?1:ret; }
int th_unmask_via(sip_msg_t *msg, str *cookie) { hdr_field_t *hdr; struct via_body *via; struct via_body *via2; struct via_param *vp; struct lump* l; int i; str out; int vlen; i=0; for(hdr=msg->h_via1; hdr; hdr=next_sibling_hdr(hdr)) { for(via=(struct via_body*)hdr->parsed; via; via=via->next) { i++; LM_DBG("=======via[%d]\n", i); LM_DBG("hdr: [%.*s]\n", via->hdr.len, via->hdr.s); vlen = th_skip_rw(via->name.s, via->bsize); LM_DBG("body: %d: [%.*s]\n", vlen, vlen, via->name.s); if(i!=1) { vp = th_get_via_param(via, &th_vparam_name); if(vp==NULL) { LM_ERR("cannot find param in via %d\n", i); return -1; } if(i==2) out.s = th_mask_decode(vp->value.s, vp->value.len, &th_vparam_prefix, CRLF_LEN+1, &out.len); else out.s = th_mask_decode(vp->value.s, vp->value.len, &th_vparam_prefix, 0, &out.len); if(out.s==NULL) { LM_ERR("cannot encode via %d\n", i); return -1; } LM_DBG("+body: %d: [%.*s]\n", out.len, out.len, out.s); if(i==2) { via2=pkg_malloc(sizeof(struct via_body)); if (via2==0) { LM_ERR("out of memory\n"); pkg_free(out.s); return -1; } memset(via2, 0, sizeof(struct via_body)); memcpy(out.s+out.len, CRLF, CRLF_LEN); out.s[out.len+CRLF_LEN]='X'; if(parse_via(out.s, out.s+out.len+CRLF_LEN+1, via2)==NULL) { LM_ERR("error parsing decoded via2\n"); free_via_list(via2); pkg_free(out.s); return -1; } out.s[out.len] = '\0'; vp = th_get_via_param(via2, &th_cookie_name); if(vp==NULL) { LM_ERR("cannot find cookie in via2\n"); free_via_list(via2); pkg_free(out.s); return -1; } *cookie = vp->value; free_via_list(via2); } l=del_lump(msg, via->name.s-msg->buf, vlen, 0); if (l==0) { LM_ERR("failed deleting via [%d]\n", i); pkg_free(out.s); return -1; } if (insert_new_lump_after(l, out.s, out.len, 0)==0) { LM_ERR("could not insert new lump\n"); pkg_free(out.s); return -1; } } } } return 0; }