static int alter_mediaip(struct sip_msg *msg, str *body, str *oldip, str *newip, int *clendelta, int preserve) { char *buf; int offset; struct lump* anchor; /* check that updating mediaip is really necessary */ if (7 == oldip->len && memcmp("0.0.0.0", oldip->s, 7) == 0) return 0; if (newip->len == oldip->len && memcmp(newip->s, oldip->s, newip->len) == 0) return 0; if (preserve != 0) { anchor = anchor_lump(&(msg->add_rm), body->s + body->len - msg->buf, 0, 0); if (anchor == NULL) { LOG(L_ERR, "ERROR: alter_mediaip: anchor_lump failed\n"); return -1; } buf = pkg_malloc(AOLDMEDIAIP_LEN + oldip->len + CRLF_LEN); if (buf == NULL) { LOG(L_ERR, "ERROR: alter_mediaip: out of memory\n"); return -1; } memcpy(buf, AOLDMEDIAIP, AOLDMEDIAIP_LEN); memcpy(buf + AOLDMEDIAIP_LEN, oldip->s, oldip->len); memcpy(buf + AOLDMEDIAIP_LEN + oldip->len, CRLF, CRLF_LEN); if (insert_new_lump_after(anchor, buf, AOLDMEDIAIP_LEN + oldip->len + CRLF_LEN, 0) == NULL) { LOG(L_ERR, "ERROR: alter_mediaip: insert_new_lump_after failed\n"); pkg_free(buf); return -1; } *clendelta += AOLDMEDIAIP_LEN + oldip->len + CRLF_LEN; } buf = pkg_malloc(newip->len); if (buf == NULL) { LOG(L_ERR, "ERROR: alter_mediaip: out of memory\n"); return -1; } offset = oldip->s - msg->buf; anchor = del_lump(&msg->add_rm, offset, oldip->len, 0); if (anchor == NULL) { LOG(L_ERR, "ERROR: alter_mediaip: del_lump failed\n"); pkg_free(buf); return -1; } memcpy(buf, newip->s, newip->len); if (insert_new_lump_after(anchor, buf, newip->len, 0) == 0) { LOG(L_ERR, "ERROR: alter_mediaip: insert_new_lump_after failed\n"); pkg_free(buf); return -1; } *clendelta += newip->len - oldip->len; return 0; }
static int do_replace_body_f(struct sip_msg* msg, char* key, char* str2, int nobol) { struct lump* l; regmatch_t pmatch; char* s; int len; char* begin; int off; int ret; int eflags; str body; if ( get_body(msg,&body)!=0 || body.len==0) { LM_DBG("message body has zero length\n"); return -1; } begin=body.s; ret=-1; /* pessimist: we will not find any */ len=strlen(str2); eflags=0; /* match ^ at the beginning of the string*/ while (begin<msg->buf+msg->len && regexec((regex_t*) key, begin, 1, &pmatch, eflags)==0) { off=begin-msg->buf; if (pmatch.rm_so==-1){ LM_ERR("offset unknown\n"); return -1; } if (pmatch.rm_so==pmatch.rm_eo){ LM_ERR("matched string is empty... invalid regexp?\n"); return -1; } if ((l=del_lump(msg, pmatch.rm_so+off, pmatch.rm_eo-pmatch.rm_so, 0))==0) { LM_ERR("del_lump failed\n"); return -1; } 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; } /* new cycle */ begin=begin+pmatch.rm_eo; /* is it still a string start */ if (nobol && (*(begin-1)=='\n' || *(begin-1)=='\r')) eflags&=~REG_NOTBOL; else eflags|=REG_NOTBOL; ret=1; } /* while found ... */ return ret; }
static int insert_header_lump(struct sip_msg* msg, char* msg_position, int lump_before, str* hname, str *val) { struct lump* anchor; char *s; int len; anchor = anchor_lump(msg, msg_position - msg->buf, 0, 0); if (anchor == 0) { LOG(L_ERR, "ERROR: textops: insert_header_lump(): Can't get anchor\n"); return -1; } len=hname->len+2+val->len+2; s = (char*)pkg_malloc(len); if (!s) { LOG(L_ERR, "ERROR: textops: insert_header_lump(): not enough memory\n"); return -1; } memcpy(s, hname->s, hname->len); s[hname->len] = ':'; s[hname->len+1] = ' '; memcpy(s+hname->len+2, val->s, val->len); s[hname->len+2+val->len] = '\r'; s[hname->len+2+val->len+1] = '\n'; if ( (lump_before?insert_new_lump_before(anchor, s, len, 0):insert_new_lump_after(anchor, s, len, 0)) == 0) { LOG(L_ERR, "ERROR: textops: insert_header_lump(): Can't insert lump\n"); pkg_free(s); return -1; } return 1; }
static Bool replaceElement(struct sip_msg *msg, str *oldElem, str *newElem) { struct lump* anchor; char *buf; if (newElem->len==oldElem->len && memcmp(newElem->s, oldElem->s, newElem->len)==0) { return True; } buf = pkg_malloc(newElem->len); if (!buf) { LOG(L_ERR, "error: mediaproxy/replaceElement(): out of memory\n"); return False; } anchor = del_lump(msg, oldElem->s - msg->buf, oldElem->len, 0); if (!anchor) { LOG(L_ERR, "error: mediaproxy/replaceElement(): failed to delete old element\n"); pkg_free(buf); return False; } memcpy(buf, newElem->s, newElem->len); if (insert_new_lump_after(anchor, buf, newElem->len, 0)==0) { LOG(L_ERR, "error: mediaproxy/replaceElement(): failed to insert new element\n"); pkg_free(buf); return False; } return True; }
static int search_append_f(struct sip_msg* msg, char* key, char* str) { struct lump* l; regmatch_t pmatch; char* s; int len; char *begin; int off; begin=get_header(msg); /* msg->orig/buf previously .. uri problems */ off=begin-msg->buf; if (regexec((regex_t*) key, begin, 1, &pmatch, 0)!=0) return -1; if (pmatch.rm_so!=-1){ if ((l=anchor_lump(msg, off+pmatch.rm_eo, 0, 0))==0) return -1; len=strlen(str); s=pkg_malloc(len); if (s==0){ LOG(L_ERR, "ERROR: search_append_f: mem. allocation failure\n"); return -1; } memcpy(s, str, len); if (insert_new_lump_after(l, s, len, 0)==0){ LOG(L_ERR, "ERROR: could not insert new lump\n"); pkg_free(s); return -1; } return 1; } return -1; }
/* Creates the necessary lumps in order to push the new header value. * The whole change/update value process (for the header) is based on a * anchoring lump tree that deletes the header and adds the future new values. * A chain of "DEL-> SKIP->" is fix and the the new values will be chained * on the "after" SKIP branch * This works as a multi-time full hdr header replacement (covering hdr name * and CRLF) */ static inline struct lump* _push_changes_into_lumps(struct sip_msg *msg, struct lump *l, struct hdr_field *hdr, str *body) { struct lump *l1; /* is this the first change ? */ if (l==NULL) { /* first change, so build on the static anchoring lump tree (where * all the future changes will be attached ) */ l = del_lump(msg, hdr->name.s-msg->buf, hdr->len, hdr->type); if (l==NULL) { LM_ERR("failed to insert del lump\n"); return NULL; } l->flags |= LUMP_FLAG_LISTHDR; l = insert_skip_lump_after( l ); if (l==NULL) { LM_ERR("failed to insert new skip lump after del\n"); return NULL; } } /* add the new value to the existing anchoring lump tree */ l1 = insert_new_lump_after( l, body->s, body->len, hdr->type); if (l1==NULL) { LM_ERR("failed to insert new lump after skip\n"); return NULL; } return l1; }
static int clone_codec_lumps(void) { struct lump *l; int i; char *s; LM_DBG("cloning %d streams\n",lumps_len); for( i=0 ; i<lumps_len ; i++ ) { /* get last lump for stream */ for( l=lumps[i] ; l->after ; l=l->after ); s = pkg_malloc( l->len+1 ); if (s==NULL) { LM_ERR("failed to alloc new lump pkg buffer\n"); return -1; } memcpy( s, l->u.value, l->len); if (insert_new_lump_after( l, s, l->len, 0)==NULL) { LM_ERR("failed to create new lump\n"); return -1; } } return 0; }
int replace_sdp_stream_port(struct sip_msg *msg, struct sdp_stream_cell *stream, unsigned int transcoder_port) { struct lump *lump; char *p; lump = del_lump(msg, stream->port.s - msg->buf, stream->port.len, HDR_OTHER_T); if (!lump) { LM_ERR("failed to add del lump\n"); return -1; } p = pkg_malloc(6); if (!p) { LM_ERR("no more pkg mem\n"); return -1; } sprintf(p, "%d", transcoder_port); if (!insert_new_lump_after(lump, p, strlen(p), HDR_OTHER_T)) { LM_ERR("no more pkg mem\n"); return -1; } return 0; }
int patch (struct sip_msg *msg, char *oldstr, unsigned int oldlen, char *newstr, unsigned int newlen) { int off; struct lump *anchor; if (oldstr == NULL) return -1; if (newstr == NULL) return -2; off = oldstr - msg->buf; if (off < 0) return -3; if ((anchor = del_lump (msg, off, oldlen, 0)) == 0) { LM_ERR("lumping with del_lump\n"); return -4; } if ((insert_new_lump_after (anchor, newstr, newlen, 0)) == 0) { LM_ERR("lumping with insert_new_lump_after\n"); return -5; } return 0; }
static int replace_f(struct sip_msg* msg, regex_t* key, str* str2) { struct lump* l; regmatch_t pmatch; char* s; char* begin; int off; begin=get_header(msg); /* 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; s=pkg_malloc(str2->len); if (s==0){ LM_ERR("memory allocation failure\n"); return -1; } memcpy(s, str2->s, str2->len); if (insert_new_lump_after(l, s, str2->len, 0)==0){ LM_ERR("could not insert new lump\n"); pkg_free(s); return -1; } return 1; } return -1; }
static int search_append_body_f(struct sip_msg* msg, regex_t* key, str* str2) { struct lump* l; regmatch_t pmatch; char* s; int off; str body; if ( get_body(msg,&body)!=0 || body.len==0) { LM_DBG("message body has zero length\n"); return -1; } off=body.s-msg->buf; if (regexec(key, body.s, 1, &pmatch, 0)!=0) return -1; if (pmatch.rm_so!=-1){ if ((l=anchor_lump(msg, off+pmatch.rm_eo, 0))==0) return -1; s=pkg_malloc(str2->len); if (s==0){ LM_ERR("memory allocation failure\n"); return -1; } memcpy(s, str2->s, str2->len); if (insert_new_lump_after(l, s, str2->len, 0)==0){ LM_ERR("could not insert new lump\n"); pkg_free(s); return -1; } return 1; } return -1; }
int th_unmask_ruri(sip_msg_t *msg) { str eval; struct lump* l; str out; if(th_get_uri_param_value(&REQ_LINE(msg).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-uri\n"); return -1; } LM_DBG("+decoded: %d: [%.*s]\n", out.len, out.len, out.s); l=del_lump(msg, REQ_LINE(msg).uri.s-msg->buf, REQ_LINE(msg).uri.len, 0); if (l==0) { LM_ERR("failed deleting r-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; }
static int update_clen(struct sip_msg* msg, int newlen) { char *buf; int len, offset; struct lump* anchor; buf = pkg_malloc(CLEN_LEN * sizeof(char)); if (buf == NULL) { LOG(L_ERR, "ERROR: update_clen: out of memory\n"); return -1; } offset = msg->content_length->body.s - msg->buf; len = msg->content_length->body.len; anchor = del_lump(&msg->add_rm, offset, len, HDR_CONTENTLENGTH); if (anchor == NULL) { LOG(L_ERR, "ERROR: update_clen: del_lump failed\n"); pkg_free(buf); return -1; } len = snprintf(buf, CLEN_LEN, "%d", newlen); if (len >= CLEN_LEN) len = CLEN_LEN - 1; if (insert_new_lump_after(anchor, buf, len, HDR_CONTENTLENGTH) == NULL) { LOG(L_ERR, "ERROR: update_clen: insert_new_lump_after failed\n"); pkg_free(buf); return -1; } return 1; }
/* * Replaces ip:port pair in the Contact: field with the source address * of the packet and/or adds direction=active option to the SDP. */ static int fix_nated_contact_f(struct sip_msg* msg, char* str1, char* str2) { int offset, len, len1; char *cp, *buf, temp[2]; contact_t* c; struct lump* anchor; struct sip_uri uri; if ((parse_headers(msg, HDR_CONTACT, 0) == -1) || !msg->contact) return -1; if (!msg->contact->parsed && parse_contact(msg->contact) < 0) { LOG(L_ERR, "fix_nated_contact: Error while parsing Contact body\n"); return -1; } c = ((contact_body_t*)msg->contact->parsed)->contacts; if (!c) { LOG(L_ERR, "fix_nated_contact: Error while parsing Contact body\n"); return -1; } if (parse_uri(c->uri.s, c->uri.len, &uri) < 0 || uri.host.len <= 0) { LOG(L_ERR, "fix_nated_contact: Error while parsing Contact URI\n"); return -1; } if (uri.proto != PROTO_UDP && uri.proto != PROTO_NONE) return 0; if (uri.port.len == 0) uri.port.s = uri.host.s + uri.host.len; offset = c->uri.s - msg->buf; anchor = del_lump(&msg->add_rm, offset, c->uri.len, HDR_CONTACT); if (anchor == 0) return -1; cp = ip_addr2a(&msg->rcv.src_ip); len = c->uri.len + strlen(cp) + 6 /* :port */ - (uri.port.s + uri.port.len - uri.host.s) + 1; buf = pkg_malloc(len); if (buf == NULL) { LOG(L_ERR, "ERROR: fix_nated_contact: out of memory\n"); return -1; } temp[0] = uri.host.s[0]; temp[1] = c->uri.s[c->uri.len]; c->uri.s[c->uri.len] = uri.host.s[0] = '\0'; len1 = snprintf(buf, len, "%s%s:%d%s", c->uri.s, cp, msg->rcv.src_port, uri.port.s + uri.port.len); if (len1 < len) len = len1; uri.host.s[0] = temp[0]; c->uri.s[c->uri.len] = temp[1]; if (insert_new_lump_after(anchor, buf, len, HDR_CONTACT) == 0) { pkg_free(buf); return -1; } c->uri.s = buf; c->uri.len = len; return 1; }
static int change_reply_status_f(struct sip_msg* msg, char* _code, char* _reason) { int code; str reason; struct lump *l; char *ch; if (get_int_fparam(&code, msg, (fparam_t*)_code) || get_str_fparam(&reason, msg, (fparam_t*)_reason) || (reason.len == 0) ) { LOG(L_ERR, "ERROR: textops: cannot get parameter\n"); return -1; } if ((code < 100) || (code > 699)) { LOG(L_ERR, "ERROR: textops: wrong status code: %d\n", code); return -1; } if (((code < 300) || (msg->REPLY_STATUS < 300)) && (code/100 != msg->REPLY_STATUS/100) ) { LOG(L_ERR, "ERROR: textops: the class of provisional or " "positive final replies cannot be changed\n"); return -1; } /* rewrite the status code directly in the message buffer */ msg->first_line.u.reply.statuscode = code; msg->first_line.u.reply.status.s[2] = code % 10 + '0'; code /= 10; msg->first_line.u.reply.status.s[1] = code % 10 + '0'; code /= 10; msg->first_line.u.reply.status.s[0] = code + '0'; l = del_lump(msg, msg->first_line.u.reply.reason.s - msg->buf, msg->first_line.u.reply.reason.len, 0); if (!l) { LOG(L_ERR, "ERROR: textops(): Failed to add del lump\n"); return -1; } /* clone the reason phrase, the lumps need to be pkg allocated */ ch = (char *)pkg_malloc(reason.len); if (!ch) { LOG(L_ERR, "ERROR: textops: Not enough memory\n"); return -1; } memcpy(ch, reason.s, reason.len); if (insert_new_lump_after(l, ch, reason.len, 0)==0){ LOG(L_ERR, "ERROR: textops: failed to add new lump: %.*s\n", reason.len, ch); pkg_free(ch); return -1; } return 1; }
/* * Replaces ip:port pair in the Contact: field with the source address * of the packet. */ static int fix_nated_contact_f(struct sip_msg* msg, char* str1, char* str2) { int offset, len, len1; char *cp, *buf, temp[2]; contact_t *c; struct lump *anchor; struct sip_uri uri; str hostport; if (get_contact_uri(msg, &uri, &c) == -1) return -1; /* for UAs behind NAT we have to hope that they will reuse the * TCP connection, otherwise they are lost any way. So this check * does not make too much sense. if (uri.proto != PROTO_UDP && uri.proto != PROTO_NONE) return -1; */ if ((c->uri.s < msg->buf) || (c->uri.s > (msg->buf + msg->len))) { LOG(L_ERR, "ERROR: you can't call fix_nated_contact twice, " "check your config!\n"); return -1; } offset = c->uri.s - msg->buf; anchor = del_lump(msg, offset, c->uri.len, HDR_CONTACT_T); if (anchor == 0) return -1; hostport = uri.host; if (uri.port.len > 0) hostport.len = uri.port.s + uri.port.len - uri.host.s; cp = ip_addr2a(&msg->rcv.src_ip); len = c->uri.len + strlen(cp) + 6 /* :port */ - hostport.len + 1; buf = pkg_malloc(len); if (buf == NULL) { LOG(L_ERR, "ERROR: fix_nated_contact: out of memory\n"); return -1; } temp[0] = hostport.s[0]; temp[1] = c->uri.s[c->uri.len]; c->uri.s[c->uri.len] = hostport.s[0] = '\0'; len1 = snprintf(buf, len, "%s%s:%d%s", c->uri.s, cp, msg->rcv.src_port, hostport.s + hostport.len); if (len1 < len) len = len1; hostport.s[0] = temp[0]; c->uri.s[c->uri.len] = temp[1]; if (insert_new_lump_after(anchor, buf, len, HDR_CONTACT_T) == 0) { pkg_free(buf); return -1; } c->uri.s = buf; c->uri.len = len; return 1; }
int th_unmask_refer_to(sip_msg_t *msg) { str eval; str *uri; int ulen; struct lump* l; str out; if(!((get_cseq(msg)->method_id)&(METHOD_REFER))) return 0; if(parse_refer_to_header(msg)==-1) { LM_DBG("no Refer-To header\n"); return 0; } if(msg->refer_to==NULL || get_refer_to(msg)==NULL) { LM_DBG("Refer-To header not found\n"); return 0; } uri = &(get_refer_to(msg)->uri); if(th_get_uri_param_value(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-uri\n"); return -1; } LM_DBG("+decoded: %d: [%.*s]\n", out.len, out.len, out.s); for(ulen=0; ulen<uri->len; ulen++) { if(uri->s[ulen]=='?') break; } l=del_lump(msg, uri->s-msg->buf, ulen, 0); if (l==0) { LM_ERR("failed deleting r-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; }
int th_mask_record_route(sip_msg_t *msg) { hdr_field_t *hdr; struct lump* l; int i; rr_t *rr; str out; if(msg->record_route==NULL) { LM_DBG("no record route header\n"); return 0; } hdr = msg->record_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) { 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; } 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; }
static int replace_all_f(struct sip_msg* msg, regex_t* key, str* str2) { struct lump* l; regmatch_t pmatch; char* s; char* begin; int off; int ret; int eflags; begin = get_header(msg); ret=-1; /* pessimist: we will not find any */ eflags=0; /* match ^ at the beginning of the string*/ while (begin<msg->buf+msg->len && regexec(key, begin, 1, &pmatch, eflags)==0) { off=begin-msg->buf; if (pmatch.rm_so==-1){ LM_ERR("offset unknown\n"); return -1; } if (pmatch.rm_so==pmatch.rm_eo){ LM_ERR("matched string is empty... invalid regexp?\n"); return -1; } if ((l=del_lump(msg, pmatch.rm_so+off, pmatch.rm_eo-pmatch.rm_so, 0))==0) { LM_ERR("del_lump failed\n"); return -1; } s=pkg_malloc(str2->len); if (s==0){ LM_ERR("memory allocation failure\n"); return -1; } memcpy(s, str2->s, str2->len); if (insert_new_lump_after(l, s, str2->len, 0)==0){ LM_ERR("could not insert new lump\n"); pkg_free(s); return -1; } /* new cycle */ begin=begin+pmatch.rm_eo; /* is it still a string start */ if (*(begin-1)=='\n' || *(begin-1)=='\r') eflags&=~REG_NOTBOL; else eflags|=REG_NOTBOL; ret=1; } /* while found ... */ return ret; }
int dlg_th_encode_callid(struct sip_msg *msg) { struct lump *del; str new_callid; int i; if (msg->callid == NULL) { LM_ERR("Message with no callid\n"); return -1; } new_callid.len = calc_base64_encode_len(msg->callid->body.len); new_callid.len += topo_hiding_prefix.len; new_callid.s = pkg_malloc(new_callid.len); if (new_callid.s==NULL) { LM_ERR("Failed to allocate callid len\n"); return -1; } if (new_callid.s == NULL) { LM_ERR("Failed to encode callid\n"); return -1; } memcpy(new_callid.s,topo_hiding_prefix.s,topo_hiding_prefix.len); for (i=0;i<msg->callid->body.len;i++) msg->callid->body.s[i] ^= topo_hiding_seed.s[i%topo_hiding_seed.len]; base64encode((unsigned char *)(new_callid.s+topo_hiding_prefix.len), (unsigned char *)(msg->callid->body.s),msg->callid->body.len); /* reset the callid back to original value - some might still need it ( eg. post script ) FIXME : use bigger buffer here ? mem vs cpu */ for (i=0;i<msg->callid->body.len;i++) msg->callid->body.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; }
/* sed-perl style re: s/regular expression/replacement/flags */ static int subst_body_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; int nmatches; str body; if ( get_body(msg,&body)!=0 || body.len==0) { LM_DBG("message body has zero length\n"); return -1; } se=(struct subst_expr*)subst; begin=body.s; off=begin-msg->buf; ret=-1; if ((lst=subst_run(se, begin, msg, &nmatches))==0) goto error; /* not found */ for (rpl=lst; rpl; rpl=rpl->next){ LM_DBG("%s 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){ LM_ERR("%s 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: LM_DBG("lst was %p\n", lst); if (lst) replace_lst_free(lst); if (nmatches<0) LM_ERR("%s subst_run failed\n", exports.name); return ret; }
int th_unmask_ruri(sip_msg_t *msg) { str eval; struct lump* l; str out; /* Do nothing if ruri is not encoded */ if (th_uri_prefix_checks && ((REQ_LINE(msg).uri.len<th_uri_prefix.len) || (strncasecmp(REQ_LINE(msg).uri.s, th_uri_prefix.s, th_uri_prefix.len)!=0))) { LM_DBG("ruri [%.*s] is not encoded",REQ_LINE(msg).uri.len,REQ_LINE(msg).uri.s); return 0; } if(th_get_uri_param_value(&REQ_LINE(msg).uri, &th_uparam_name, &eval)<0 || eval.len<=0) { LM_DBG("no uri param [%.*s] in [%.*s]\n", th_uparam_name.len, th_uparam_name.s, REQ_LINE(msg).uri.len,REQ_LINE(msg).uri.s); 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-uri [%.*s]\n", REQ_LINE(msg).uri.len,REQ_LINE(msg).uri.s); return -1; } LM_DBG("+decoded: %d: [%.*s]\n", out.len, out.len, out.s); l=del_lump(msg, REQ_LINE(msg).uri.s-msg->buf, REQ_LINE(msg).uri.len, 0); if (l==0) { LM_ERR("failed deleting r-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; }
static int replace_all_f(struct sip_msg* msg, char* key, char* str) { struct lump* l; regmatch_t pmatch; char* s; int len; char* begin; int off; int ret; int eflags; begin=get_header(msg); /* msg->orig previously .. uri problems */ ret=-1; /* pessimist: we will not find any */ len=strlen(str); eflags=0; /* match ^ at the beginning of the string*/ while (begin<msg->buf+msg->len && regexec((regex_t*) key, begin, 1, &pmatch, eflags)==0) { off=begin-msg->buf; /* change eflags, not to match any more at string start */ eflags|=REG_NOTBOL; if (pmatch.rm_so==-1){ LOG(L_ERR, "ERROR: replace_all_f: offset unknown\n"); return -1; } if ((l=del_lump(msg, pmatch.rm_so+off, pmatch.rm_eo-pmatch.rm_so, 0))==0) { LOG(L_ERR, "ERROR: replace_all_f: del_lump failed\n"); return -1; } s=pkg_malloc(len); if (s==0){ LOG(L_ERR, "ERROR: replace_f: mem. allocation failure\n"); return -1; } memcpy(s, str, len); if (insert_new_lump_after(l, s, len, 0)==0){ LOG(L_ERR, "ERROR: could not insert new lump\n"); pkg_free(s); return -1; } /* new cycle */ begin=begin+pmatch.rm_eo; ret=1; } /* while found ... */ return ret; }
int th_mask_via(sip_msg_t *msg) { hdr_field_t *hdr; struct via_body *via; 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) { out.s = th_mask_encode(via->name.s, vlen, &th_via_prefix, &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); 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; }
static int insert_via_lump(struct sip_msg* msg, char* via, int via_len) { struct lump* anchor; anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0, HDR_VIA_T); if (anchor == 0) { ERR("Unable to create anchor\n"); return -1; } if (insert_new_lump_after(anchor, via, via_len, HDR_VIA_T) == 0) { ERR("Unable to insert via lump\n"); return -1; } return 0; }
/* * Create an AVP to be used by registrar with the source IP and port * of the REGISTER */ static int fix_nated_register_f(struct sip_msg* msg, char* str1, char* str2) { contact_t* c; struct lump* anchor; char* param; str uri; if (create_rcv_uri(&uri, msg) < 0) { return -1; } if (contact_iterator(&c, msg, 0) < 0) { return -1; } while(c) { param = (char*)pkg_malloc(RECEIVED_LEN + 2 + uri.len); if (!param) { ERR("No memory left\n"); return -1; } memcpy(param, RECEIVED, RECEIVED_LEN); param[RECEIVED_LEN] = '\"'; memcpy(param + RECEIVED_LEN + 1, uri.s, uri.len); param[RECEIVED_LEN + 1 + uri.len] = '\"'; anchor = anchor_lump(msg, c->name.s + c->len - msg->buf, 0, 0); if (anchor == NULL) { ERR("anchor_lump failed\n"); return -1; } if (insert_new_lump_after(anchor, param, RECEIVED_LEN + 1 + uri.len + 1, 0) == 0) { ERR("insert_new_lump_after failed\n"); pkg_free(param); return -1; } if (contact_iterator(&c, msg, c) < 0) { return -1; } } return 1; }
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; } /* Do nothing if call-id is not encoded */ if ((msg->callid->body.len<th_callid_prefix.len) || (strncasecmp(msg->callid->body.s,th_callid_prefix.s,th_callid_prefix.len)!=0)) { LM_DBG("call-id [%.*s] not encoded",msg->callid->body.len,msg->callid->body.s); return 0; } 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; }
/* 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; int nmatches; 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, &nmatches))==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); if (nmatches<0) LOG(L_ERR, "ERROR: %s: subst_run failed\n", exports.name); return ret; }
int th_add_via_cookie(sip_msg_t *msg, struct via_body *via) { struct lump* l; int viap; str out; if (via->params.s) { viap = via->params.s - via->hdr.s - 1; } else { if (via->host.s) { viap = via->host.s - via->hdr.s + via->host.len; } else { LM_ERR("no via parameter and no via host, can't insert cookie\n"); return -1; } if (via->port!=0) viap += via->port_str.len + 1; /* +1 for ':'*/ } l = anchor_lump(msg, via->hdr.s - msg->buf + viap, 0, 0); if (l==0) { LM_ERR("failed adding cookie to via [%p]\n", via); return -1; } out.len = 1+th_cookie_name.len+1+th_cookie_value.len+1; out.s = (char*)pkg_malloc(out.len+1); if(out.s==0) { LM_ERR("no pkg memory\n"); return -1; } out.s[0] = ';'; memcpy(out.s+1, th_cookie_name.s, th_cookie_name.len); out.s[th_cookie_name.len+1]='='; memcpy(out.s+th_cookie_name.len+2, th_cookie_value.s, th_cookie_value.len); out.s[out.len-1] = 'v'; out.s[out.len] = '\0'; 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 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; }