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; }
int dlg_validate_dialog( struct sip_msg* req, struct dlg_cell *dlg) { struct dlg_leg *leg; unsigned int n,m; int nr_routes,i,src_leg; str *rr_uri,*route_uris; if (last_dst_leg<0 || last_dst_leg>=dlg->legs_no[DLG_LEGS_USED]) { log_bogus_dst_leg(dlg); LM_ERR("Script error - validate function before having a dialog\n"); return -4; } leg = & dlg->legs[ last_dst_leg ]; /* first check the cseq */ if ( (!req->cseq && parse_headers(req,HDR_CSEQ_F,0)<0) || !req->cseq || !req->cseq->parsed) { LM_ERR("bad sip message or missing CSeq hdr :-/\n"); return -4; } n = m = 0; if (req->first_line.u.request.method_value == METHOD_ACK) { /* ACKs should have the same cseq as INVITEs */ if (last_dst_leg == DLG_CALLER_LEG) src_leg = callee_idx(dlg); else src_leg = DLG_CALLER_LEG; if ( str2int( &((get_cseq(req))->number), &n)!=0 || str2int( &(dlg->legs[src_leg].inv_cseq), &m)!=0 || n!=m ) { LM_DBG("cseq test for ACK falied recv=%d, old=%d\n",n,m); return -1; } } else { if ( str2int( &((get_cseq(req))->number), &n)!=0 || str2int( &(leg->prev_cseq), &m)!=0 || n<=m ) { LM_DBG("cseq test falied recv=%d, old=%d\n",n,m); return -1; } } LM_DBG("CSEQ validation passed\n"); /* because fix_routing was called on the request */ if(dlg->flags & DLG_FLAG_TOPHIDING) return 0; if (dlg->state <= DLG_STATE_EARLY) return 0; if (leg->contact.len) { rr_uri = d_rrb.get_remote_target(req); if (rr_uri == NULL) { LM_ERR("failed fetching remote target from msg\n"); return -4; } if (compare_uris(rr_uri,0,&leg->contact,0)) { LM_ERR("failed to validate remote contact: dlg=[%.*s] , req=[%.*s]\n", leg->contact.len,leg->contact.s,rr_uri->len,rr_uri->s); return -2; } } LM_DBG("Remote contact succesfully validated\n"); /* check the route set - is the the same as in original request */ /* the route set (without the first Route) must be the same as the one stored in the destination leg */ /* extract the RR parts */ if( parse_headers( req, HDR_EOH_F, 0)<0 ) { LM_ERR("failed to parse headers when looking after ROUTEs\n"); return -4; } if ( req->route==NULL) { if ( leg->route_set.len!=0) { LM_DBG("route check failed (req has no route, but dialog has\n"); return -3; } } else { route_uris = d_rrb.get_route_set(req,&nr_routes); if (route_uris == NULL) { LM_ERR("failed fetching route URIs from the msg\n"); return -4; } if (nr_routes != leg->nr_uris) { LM_ERR("Different number of routes found in msg. req=%d, dlg=%d\n", nr_routes,leg->nr_uris); return -3; } for (i=0;i<nr_routes;i++) { LM_DBG("route %d. req=[%.*s],dlg=[%.*s]\n", i,route_uris[i].len,route_uris[i].s,leg->route_uris[i].len, leg->route_uris[i].s); if (compare_uris(&route_uris[i],0,&leg->route_uris[i],0)) { LM_ERR("Check failed for route number %d. req=[%.*s],dlg=[%.*s]\n", i,route_uris[i].len,route_uris[i].s,leg->route_uris[i].len, leg->route_uris[i].s); return -3; } } } LM_DBG("Route Headers succesfully validated\n"); return 0; }