void free_duped_lump_list(struct lump* l) { struct lump *r, *foo,*crt; while(l){ crt=l; l=l->next; r=crt->before; while(r){ foo=r; r=r->before; /* (+): if a new item was introduced to the shallow-ly * duped list, remove it completely, preserve it * otherwise (it is still referred by original list) */ if (foo->flags!=LUMPFLAG_DUPED) free_lump(foo); pkg_free(foo); } r=crt->after; while(r){ foo=r; r=r->after; if (foo->flags!=LUMPFLAG_DUPED) /* (+) ... see above */ free_lump(foo); pkg_free(foo); } /*clean current elem*/ if (crt->flags!=LUMPFLAG_DUPED) /* (+) ... see above */ free_lump(crt); pkg_free(crt); } }
void free_lump_list(struct lump* l) { struct lump* t, *r, *foo,*crt; t=l; while(t){ crt=t; t=t->next; /* dangerous recursive clean if (crt->before) free_lump_list(crt->before); if (crt->after) free_lump_list(crt->after); */ /* no more recursion, clean after and before and that's it */ r=crt->before; while(r){ foo=r; r=r->before; free_lump(foo); pkg_free(foo); } r=crt->after; while(r){ foo=r; r=r->after; free_lump(foo); pkg_free(foo); } /*clean current elem*/ free_lump(crt); pkg_free(crt); } }
void del_nonshm_lump( struct lump** lump_list ) { struct lump *r, *foo, *crt, **prev, *prev_r; prev = lump_list; crt = *lump_list; while (crt) { if (crt->flags!=LUMPFLAG_SHMEM) { /* unlink it */ foo = crt; crt = crt->next; foo->next = 0; /* update the 'next' link of the previous lump */ *prev = crt; /* entire before/after list must be removed */ free_lump_list( foo ); } else { /* check on before and prev list for non-shmem lumps */ r = crt->after; prev_r = crt; while(r){ foo=r; r=r->after; if (foo->flags!=LUMPFLAG_SHMEM) { prev_r->after = r; free_lump(foo); pkg_free(foo); } else { prev_r = foo; } } /* before */ r = crt->before; prev_r = crt; while(r){ foo=r; r=r->before; if (foo->flags!=LUMPFLAG_SHMEM) { prev_r->before = r; free_lump(foo); pkg_free(foo); } else { prev_r = foo; } } /* go to next lump */ prev = &(crt->next); crt = crt->next; } } }
static void free_rr_lump(struct lump **list) { struct lump *prev_lump, *lump, *a, *foo, *next; int first_shmem; first_shmem=1; next=0; prev_lump=0; for(lump=*list;lump;lump=next) { next=lump->next; if (lump->type==HDR_RECORDROUTE_T) { /* may be called from railure_route */ /* if (lump->flags & (LUMPFLAG_DUPED|LUMPFLAG_SHMEM)){ LOG(L_CRIT, "BUG: free_rr_lmp: lump %p, flags %x\n", lump, lump->flags); */ /* ty to continue */ /*}*/ a=lump->before; while(a) { foo=a; a=a->before; if (!(foo->flags&(LUMPFLAG_DUPED|LUMPFLAG_SHMEM))) free_lump(foo); if (!(foo->flags&LUMPFLAG_SHMEM)) pkg_free(foo); } a=lump->after; while(a) { foo=a; a=a->after; if (!(foo->flags&(LUMPFLAG_DUPED|LUMPFLAG_SHMEM))) free_lump(foo); if (!(foo->flags&LUMPFLAG_SHMEM)) pkg_free(foo); } if (first_shmem && (lump->flags&LUMPFLAG_SHMEM)) { /* This is the first element of the shmemzied lump list, we can not unlink it! It wound corrupt the list otherwise if we are in failure_route. -- No problem, only the anchor is left in the list */ LOG(L_DBG, "DEBUG: free_rr_lump: lump %p" \ " is left in the list\n", lump); if (lump->len) LOG(L_CRIT, "BUG: free_rr_lump: lump %p" \ " can not be removed, but len=%d\n", lump, lump->len); prev_lump=lump; } else { if (prev_lump) prev_lump->next = lump->next; else *list = lump->next; if (!(lump->flags&(LUMPFLAG_DUPED|LUMPFLAG_SHMEM))) free_lump(lump); if (!(lump->flags&LUMPFLAG_SHMEM)) pkg_free(lump); } } else { /* store previous position */ prev_lump=lump; } if (first_shmem && (lump->flags&LUMPFLAG_SHMEM)) first_shmem=0; } }
int dlg_replace_contact(struct sip_msg* msg, struct dlg_cell* dlg) { struct lump* lump, *crt, *prev_crt =0, *a, *foo; int offset; int len,n; char *prefix=NULL,*suffix=NULL,*p,*p_init,*ct_username=NULL; int prefix_len,suffix_len,ct_username_len=0; struct sip_uri ctu; str contact; if(!msg->contact) { if(parse_headers(msg, HDR_CONTACT_F, 0)< 0) { LM_ERR("Failed to parse headers\n"); return -1; } if(!msg->contact) return 0; } prefix_len = 5; /* <sip: */ if (dlg->flags & DLG_FLAG_TOPH_KEEP_USER) { if ( parse_contact(msg->contact)<0 || ((contact_body_t *)msg->contact->parsed)->contacts==NULL || ((contact_body_t *)msg->contact->parsed)->contacts->next!=NULL ) { LM_ERR("bad Contact HDR\n"); } else { contact = ((contact_body_t *)msg->contact->parsed)->contacts->uri; if(parse_uri(contact.s, contact.len, &ctu) < 0) { LM_ERR("Bad Contact URI\n"); } else { ct_username = ctu.user.s; ct_username_len = ctu.user.len; LM_DBG("Trying to propagate username [%.*s]\n",ct_username_len, ct_username); if (ct_username_len > 0) prefix_len += 1 + /* @ */ + ct_username_len; } } } prefix = pkg_malloc(prefix_len); if (!prefix) { LM_ERR("no more pkg\n"); goto error; } suffix_len = RR_DLG_PARAM_SIZE+1; /* > */ suffix = pkg_malloc(suffix_len); if (!suffix) { LM_ERR("no more pkg\n"); goto error; } memcpy(prefix,"<sip:",prefix_len); if (dlg->flags & DLG_FLAG_TOPH_KEEP_USER && ct_username_len > 0) { memcpy(prefix+5,ct_username,ct_username_len); prefix[prefix_len-1] = '@'; } p_init = p = suffix; *p++ = ';'; memcpy(p,rr_param.s,rr_param.len); p+=rr_param.len; *p++ = '='; n = RR_DLG_PARAM_SIZE - (p-p_init); if (int2reverse_hex( &p, &n, dlg->h_entry)==-1) return -1; *(p++) = DLG_SEPARATOR; n = RR_DLG_PARAM_SIZE - (p-p_init); if (int2reverse_hex( &p, &n, dlg->h_id)==-1) return -1; *p++ = '>'; suffix_len = p - p_init; offset = msg->contact->body.s - msg->buf; len = msg->contact->body.len; for (crt = msg->add_rm;crt;) { if (crt->type == HDR_CONTACT_T && crt->op == LUMP_DEL && crt->u.offset >= offset && crt->u.offset <= offset + len) { lump = crt; crt = crt->next; a=lump->before; while(a) { LM_DBG("before [%p], op=%d\n", a, a->op); if(a->op == LUMP_ADD) LM_DBG("value= %.*s\n", a->len, a->u.value); foo=a; a=a->before; if (!(foo->flags&(LUMPFLAG_DUPED|LUMPFLAG_SHMEM))) free_lump(foo); if (!(foo->flags&LUMPFLAG_SHMEM)) pkg_free(foo); } a=lump->after; while(a) { LM_DBG("after [%p], op=%d\n", a, a->op); if(a->op == LUMP_ADD) LM_DBG("value= %.*s\n", a->len, a->u.value); foo=a; a=a->after; if (!(foo->flags&(LUMPFLAG_DUPED|LUMPFLAG_SHMEM))) free_lump(foo); if (!(foo->flags&LUMPFLAG_SHMEM)) pkg_free(foo); } if(lump == msg->add_rm) msg->add_rm = lump->next; else prev_crt->next = lump->next; if (!(lump->flags&(LUMPFLAG_DUPED|LUMPFLAG_SHMEM))) free_lump(lump); if (!(lump->flags&LUMPFLAG_SHMEM)) pkg_free(lump); continue; } prev_crt = crt; crt= crt->next; } if ((lump = del_lump(msg, msg->contact->body.s - msg->buf, msg->contact->body.len,HDR_CONTACT_T)) == 0) { LM_ERR("del_lump failed\n"); goto error; } if ((lump = insert_new_lump_after(lump,prefix,prefix_len,HDR_CONTACT_T)) == 0) { LM_ERR("failed inserting '<sip:'\n"); goto error; } /* make sure we do not free this string in case of a further error */ prefix = NULL; if ((lump = insert_subst_lump_after(lump, SUBST_SND_ALL, HDR_CONTACT_T)) == 0) { LM_ERR("failed inserting SUBST_SND buf\n"); goto error; } if ((lump = insert_new_lump_after(lump,suffix,suffix_len,HDR_CONTACT_T)) == 0) { LM_ERR("failed inserting '<sip:'\n"); goto error; } return 0; error: if (prefix) pkg_free(prefix); if (suffix) pkg_free(suffix); return -1; }
/* hide via, route sets and contacts */ static int topology_hiding(struct sip_msg *req,int extra_flags) { struct dlg_cell *dlg; struct hdr_field *it; char* buf; struct lump* lump, *crt, *prev_crt =0, *a, *foo; struct cell* t; t = d_tmb.t_gett(); if (t == T_UNDEFINED) t=NULL; dlg = get_current_dialog(); if(!dlg) { if(dlg_create_dialog( t, req, 0) != 0) { LM_ERR("Failed to create dialog\n"); return -1; } /* double check if the dialog can be retrieved */ if (!(dlg = get_current_dialog())) { LM_ERR("failed to get dialog\n"); return -1; } } dlg->flags |= DLG_FLAG_TOPHIDING; dlg->flags |= extra_flags; /* delete also the added record route and the did param */ for(crt=req->add_rm; crt;) { lump = 0; if(crt->type != HDR_RECORDROUTE_T) /* check on before list for parameters */ for( lump=crt->before ; lump ; lump=lump->before ) { /* we are looking for the lump that adds the * suffix of the RR header */ if ( lump->type==HDR_RECORDROUTE_T && lump->op==LUMP_ADD) { LM_DBG("lump before root %p\n", crt); LM_DBG("Found lump = %p, %.*s\n", lump, lump->len,lump->u.value); break; } } if((crt->type==HDR_RECORDROUTE_T) || lump) { /* lump found */ lump = crt; crt = crt->next; a=lump->before; while(a) { LM_DBG("before [%p], op=%d\n", a, a->op); if(a->op == LUMP_ADD) LM_DBG("value= %.*s\n", a->len, a->u.value); foo=a; a=a->before; if (!(foo->flags&(LUMPFLAG_DUPED|LUMPFLAG_SHMEM))) free_lump(foo); if (!(foo->flags&LUMPFLAG_SHMEM)) pkg_free(foo); } a=lump->after; while(a) { LM_DBG("after [%p], op=%d\n", a, a->op); if(a->op == LUMP_ADD) LM_DBG("value= %.*s\n", a->len, a->u.value); foo=a; a=a->after; if (!(foo->flags&(LUMPFLAG_DUPED|LUMPFLAG_SHMEM))) free_lump(foo); if (!(foo->flags&LUMPFLAG_SHMEM)) pkg_free(foo); } if(lump == req->add_rm) req->add_rm = lump->next; else prev_crt->next = lump->next; if (!(lump->flags&(LUMPFLAG_DUPED|LUMPFLAG_SHMEM))) free_lump(lump); if (!(lump->flags&LUMPFLAG_SHMEM)) pkg_free(lump); // goto after_del_rr; // break; continue; } prev_crt = crt; crt= crt->next; } buf = req->buf; /* delete record-route headers */ for (it=req->record_route;it;it=it->sibling) { if (del_lump(req,it->name.s - buf,it->len,HDR_RECORDROUTE_T) == 0) { LM_ERR("del_lump failed - while deleting record-route\n"); return -1; } } /* delete via headers */ if(dlg_del_vias(req) < 0) { LM_ERR("Failed to remove via headers\n"); return -1; } /* replace contact*/ if(dlg_replace_contact(req, dlg) < 0) { LM_ERR("Failed to replace contact\n"); return -1; } return 1; }
int dlg_replace_contact(struct sip_msg* msg, struct dlg_cell* dlg) { // str local_contact; struct lump* lump, *crt, *prev_crt =0, *a, *foo; int offset; int len,n; char *prefix=NULL,*suffix=NULL,*p,*p_init; int prefix_len,suffix_len; if(!msg->contact) { if(parse_headers(msg, HDR_CONTACT_F, 0)< 0) { LM_ERR("Failed to parse headers\n"); return -1; } if(!msg->contact) return 0; } prefix_len = 5; /* <sip: */ prefix = pkg_malloc(prefix_len); if (!prefix) { LM_ERR("no more pkg\n"); goto error; } suffix_len = RR_DLG_PARAM_SIZE+1; /* > */ suffix = pkg_malloc(suffix_len); if (!suffix) { LM_ERR("no more pkg\n"); goto error; } memcpy(prefix,"<sip:",prefix_len); p_init = p = suffix; *p++ = ';'; memcpy(p,"did",3); p+=3; *p++ = '='; n = RR_DLG_PARAM_SIZE - (p-p_init); if (int2reverse_hex( &p, &n, dlg->h_entry)==-1) return -1; *(p++) = DLG_SEPARATOR; n = RR_DLG_PARAM_SIZE - (p-p_init); if (int2reverse_hex( &p, &n, dlg->h_id)==-1) return -1; *p++ = '>'; suffix_len = p - p_init; offset = msg->contact->body.s - msg->buf; len = msg->contact->body.len; for (crt = msg->add_rm;crt;) { if (crt->type == HDR_CONTACT_T && crt->op == LUMP_DEL && crt->u.offset >= offset && crt->u.offset <= offset + len) { lump = crt; crt = crt->next; a=lump->before; while(a) { LM_DBG("before [%p], op=%d\n", a, a->op); if(a->op == LUMP_ADD) LM_DBG("value= %.*s\n", a->len, a->u.value); foo=a; a=a->before; if (!(foo->flags&(LUMPFLAG_DUPED|LUMPFLAG_SHMEM))) free_lump(foo); if (!(foo->flags&LUMPFLAG_SHMEM)) pkg_free(foo); } a=lump->after; while(a) { LM_DBG("after [%p], op=%d\n", a, a->op); if(a->op == LUMP_ADD) LM_DBG("value= %.*s\n", a->len, a->u.value); foo=a; a=a->after; if (!(foo->flags&(LUMPFLAG_DUPED|LUMPFLAG_SHMEM))) free_lump(foo); if (!(foo->flags&LUMPFLAG_SHMEM)) pkg_free(foo); } if(lump == msg->add_rm) msg->add_rm = lump->next; else prev_crt->next = lump->next; if (!(lump->flags&(LUMPFLAG_DUPED|LUMPFLAG_SHMEM))) free_lump(lump); if (!(lump->flags&LUMPFLAG_SHMEM)) pkg_free(lump); continue; } prev_crt = crt; crt= crt->next; } if ((lump = del_lump(msg, msg->contact->body.s - msg->buf, msg->contact->body.len,HDR_CONTACT_T)) == 0) { LM_ERR("del_lump failed \n"); goto error; } if ((lump = insert_new_lump_after(lump,prefix,prefix_len,HDR_CONTACT_T)) == 0) { LM_ERR("failed inserting '<sip:'\n"); goto error; } if ((lump = insert_subst_lump_after(lump, SUBST_SND_ALL, HDR_CONTACT_T)) == 0) { LM_ERR("failed inserting SUBST_SND buf\n"); goto error; } if ((lump = insert_new_lump_after(lump,suffix,suffix_len,HDR_CONTACT_T)) == 0) { LM_ERR("failed inserting '<sip:'\n"); goto error; } // LM_DBG("Replaced contact with [%.*s]\n", local_contact.len, local_contact.s); return 0; error: if (prefix) pkg_free(prefix); if (suffix) pkg_free(suffix); return -1; }