/** * enforce a response coming from a UE to contain the same Via headers sent in the corresponding request * @param rpl - the SIP reply * @param str1 - not used * @param str2 - not used * @returns true if ok, false if not or error */ int P_enforce_via_list(struct sip_msg *rpl,char *str1, char *str2) { static struct hdr_field * h = NULL; str hdr; cscf_del_all_headers(rpl, HDR_VIA_T); struct sip_msg *req = cscf_get_request_from_reply(rpl); if (!req){ LOG(L_ERR,"ERR:"M_NAME":P_enforce_via_list: No transactional request found.\n"); return CSCF_RETURN_FALSE; } h = cscf_get_next_via_hdr(req,0); while (h) { hdr.len = h->body.len + via_hdr_s.len + via_hdr_e.len; hdr.s = pkg_malloc(hdr.len); if (!hdr.s) { LOG(L_ERR, "ERR:"M_NAME":P_enforce_via_list: cannot alloc bytes : %d", hdr.len); } hdr.len=0; STR_APPEND(hdr, via_hdr_s); STR_APPEND(hdr, h->body); STR_APPEND(hdr, via_hdr_e); cscf_add_header_first(rpl, &hdr, HDR_VIA_T); h = cscf_get_next_via_hdr(req,h); } return CSCF_RETURN_TRUE; }
/** * Inserts the Route header containing the Service-Route to be enforced * @param msg - the SIP message to add to * @param str1 - the value to insert (IBCF URI here) - !!! quoted if needed * @param str2 - not used * @returns #CSCF_RETURN_TRUE if ok or #CSCF_RETURN_ERROR on error */ int P_route_to_IBCF(struct sip_msg *msg,char *str1,char*str2) { str newuri={0,0}; str uri; str x; int add_lr=0; static str lr_param={";lr",3}; /* Get char *str1 into str uri */ uri.s = str1; uri.len = strlen(str1); x.len = route_s.len + uri.len + route_e.len; /* Add ;lr if there's not in the URI */ if (!strstr(str1,";lr")){ add_lr=1; x.len+=lr_param.len; } x.s = pkg_malloc(x.len); if (!x.s){ LOG(L_ERR, "ERR:"M_NAME":P_route_to_IBCF: Error allocating %d bytes\n",x.len); x.len=0; return CSCF_RETURN_ERROR; } /* Get complete Route header into x */ x.len=0; STR_APPEND(x,route_s); STR_APPEND(x,uri); if (add_lr) STR_APPEND(x,lr_param); STR_APPEND(x,route_e); /* Set dst_uri to the topmost Route URI */ newuri.s = pkg_malloc(uri.len); if (!newuri.s){ LOG(L_ERR, "ERR:"M_NAME":P_route_to_IBCF: Error allocating %d bytes\n",uri.len); return CSCF_RETURN_ERROR; } newuri.len = uri.len; memcpy(newuri.s,uri.s,newuri.len); if (msg->dst_uri.s) pkg_free(msg->dst_uri.s); msg->dst_uri = newuri; /* Add those Route header in x into msg */ if (cscf_add_header_first(msg,&x,HDR_ROUTE_T)) return CSCF_RETURN_TRUE; else { LOG(L_ERR,"ERR:"M_NAME":P_route_to_IBCF: Failed to add new Route.\n"); if (x.s) pkg_free(x.s); return CSCF_RETURN_ERROR; } }
/** * Record routes, with given user as parameter. * @param msg - the SIP message to add to * @param str1 - direction - "orig" or "term" * @param str2 - not used * @returns #CSCF_RETURN_TRUE if ok, #CSCF_RETURN_FALSE if not or #CSCF_RETURN_BREAK on error */ int S_record_route(struct sip_msg *msg,char *str1,char *str2) { str rr={0,0}; str u = {0,0},scheme={0,0},scscf={0,0}; enum s_dialog_direction dir = get_dialog_direction(str1); switch (dir){ case DLG_MOBILE_ORIGINATING: STR_PKG_DUP(rr,scscf_record_route_mo,"pkg"); break; case DLG_MOBILE_TERMINATING: STR_PKG_DUP(rr,scscf_record_route_mt,"pkg"); break; default: u.s = str1; u.len = strlen(str1); if (scscf_name_str.len>4 && strncasecmp(scscf_name_str.s,"sip:",4)==0){ scheme.s = scscf_name_str.s; scheme.len = 4; }else if (scscf_name_str.len>5 && strncasecmp(scscf_name_str.s,"sips:",5)==0){ scheme.s = scscf_name_str.s; scheme.len = 4; } scscf.s = scheme.s+scheme.len; scscf.len = scscf_name_str.len - scheme.len; rr.len = s_record_route_s.len+scheme.len+u.len+1+scscf.len+s_record_route_e.len; rr.s = pkg_malloc(rr.len); if (!rr.s){ LOG(L_ERR,"ERR:"M_NAME":S_record_route: error allocating %d bytes!\n",rr.len); return CSCF_RETURN_BREAK; } rr.len = 0; STR_APPEND(rr,s_record_route_s); STR_APPEND(rr,scheme); STR_APPEND(rr,u); rr.s[rr.len++]='@'; STR_APPEND(rr,scscf); STR_APPEND(rr,s_record_route_e); } if (cscf_add_header_first(msg,&rr,HDR_RECORDROUTE_T)) return CSCF_RETURN_TRUE; else{ if (rr.s) pkg_free(rr.s); return CSCF_RETURN_BREAK; } out_of_memory: return CSCF_RETURN_BREAK; }
/** * Enforce a response coming from a UE to contain the same Record Route headers sent in the * corresponding request. * @param msg - the SIP reply * @param str1 - not used * @param str2 - not used * @returns #CSCF_RETURN_TRUE on success, #CSCF_RETURN_ERROR on error */ int P_enforce_record_routes(struct sip_msg *msg,char *str1, char *str2) { str hdr = {0,0}; str rr_req = {0,0}; struct sip_msg *req = cscf_get_request_from_reply(msg); LOG(L_INFO,"INF:"M_NAME":P_enforce_record_routes(): Enforcing RR in %d reply with the request ones\n", msg->first_line.u.reply.statuscode); if (!req){ LOG(L_ERR,"ERR:"M_NAME":P_enforce_record_routes(): No transactional request found.\n"); return CSCF_RETURN_ERROR; } if(!cscf_del_all_headers(msg, HDR_RECORDROUTE_T)){ LOG(L_ERR,"ERR:"M_NAME":P_enforce_record_routes(): error while deleting headers\n"); return CSCF_RETURN_ERROR; } rr_req = cscf_get_record_routes(req); if(rr_req.len){ hdr.len = pcscf_record_route_mt.len + s_record_route_s.len + rr_req.len+s_record_route_e.len; if(!(hdr.s = pkg_malloc(hdr.len))){ LOG(L_ERR,"ERR:"M_NAME":P_enforce_record_routes(): Unable to allocate memory for hdr\n"); goto out_of_memory; } hdr.len = 0; STR_APPEND(hdr,pcscf_record_route_mt); STR_APPEND(hdr,s_record_route_s); STR_APPEND(hdr,rr_req); STR_APPEND(hdr,s_record_route_e); }else{ LOG(L_ERR,"ERR:"M_NAME":P_enforce_record_routes(): Unable to get record routes - the RR should not be empty...\n"); // still, let it continue, maybe it was empty on purpose //return CSCF_RETURN_ERROR; STR_PKG_DUP(hdr,pcscf_record_route_mt,"pkg"); } if(!cscf_add_header_first(msg,&hdr,HDR_RECORDROUTE_T)){ LOG(L_ERR,"ERR:"M_NAME":P_enforce_record_routes(): Unable to add header\n"); if (hdr.s) pkg_free(hdr.s); return CSCF_RETURN_FALSE; } return CSCF_RETURN_TRUE; out_of_memory: return CSCF_RETURN_ERROR; }
int I_scscf_select(struct sip_msg* msg, char* str1, char* str2) { str call_id,scscf_name={0,0}; struct sip_msg *req; int result; str hdr={0,0}; //print_scscf_list(L_ERR); call_id = cscf_get_call_id(msg,0); LOG(L_DBG,"DBG:"M_NAME":I_scscf_select(): <%.*s>\n",call_id.len,call_id.s); if (!call_id.len) return CSCF_RETURN_FALSE; scscf_name = take_scscf_entry(call_id); if (!scscf_name.len){ I_scscf_drop(msg,str1,str2); cscf_reply_transactional(msg,600,MSG_600_FORWARDING_FAILED); return CSCF_RETURN_BREAK; } if (msg->first_line.u.request.method.len==8 && strncasecmp(msg->first_line.u.request.method.s,"REGISTER",8)==0) { /* REGISTER fwding */ if (str1&&str1[0]=='0'){ /* first time */ //LOG(L_CRIT,"rewrite uri\n"); if (rewrite_uri(msg, &(scscf_name)) < 0) { LOG(L_ERR,"ERR:"M_NAME":I_UAR_forward: Unable to Rewrite URI\n"); result = CSCF_RETURN_FALSE; }else result = CSCF_RETURN_TRUE; }else{ /* subsequent */ //LOG(L_CRIT,"append branch\n"); req = msg;//cscf_get_request_from_reply(msg); append_branch(req,scscf_name.s,scscf_name.len,0,0,0,0); result = CSCF_RETURN_TRUE; } }else{ /* Another request */ result = CSCF_RETURN_TRUE; hdr.len = route_hdr_s.len+scscf_name.len+route_hdr_e.len; hdr.s = pkg_malloc(hdr.len); if (!hdr.s){ LOG(L_ERR,"ERR:"M_NAME":Mw_REQUEST_forward: Error allocating %d bytes\n", hdr.len); result = CSCF_RETURN_TRUE; } hdr.len=0; STR_APPEND(hdr,route_hdr_s); STR_APPEND(hdr,scscf_name); STR_APPEND(hdr,route_hdr_e); if (!cscf_add_header_first(msg,&hdr,HDR_ROUTE_T)){ pkg_free(hdr.s); result = CSCF_RETURN_TRUE; } if (msg->dst_uri.s) pkg_free(msg->dst_uri.s); STR_PKG_DUP(msg->dst_uri,scscf_name,"pkg"); } if (scscf_name.s) shm_free(scscf_name.s); return result; out_of_memory: if (scscf_name.s) shm_free(scscf_name.s); return CSCF_RETURN_ERROR; }
/** * Inserts the Route header containing the dialog routes to be enforced * @param msg - the SIP message to add to * @param str1 - the value to insert - !!! quoted if needed * @param str2 - not used * @returns #CSCF_RETURN_TRUE if ok, #CSCF_RETURN_FALSE if not or #CSCF_RETURN_BREAK on error */ int P_enforce_dialog_routes(struct sip_msg *msg,char *str1,char*str2) { int i; str newuri={0,0}; p_dialog *d; str call_id,host; int port,transport; str x; enum p_dialog_direction dir; dir = get_dialog_direction(str1); if (!find_dialog_contact(msg,dir,&host,&port,&transport)){ LOG(L_ERR,"ERR:"M_NAME":P_enforce_dialog_routes(): Error retrieving %s contact\n",str1); return CSCF_RETURN_BREAK; } call_id = cscf_get_call_id(msg,0); if (!call_id.len) return CSCF_RETURN_FALSE; LOG(L_INFO,"DBG:"M_NAME":P_enforce_dialog_routes(%s): Call-ID <%.*s> %d://%.*s:%d\n", str1,call_id.len,call_id.s, transport,host.len,host.s,port); d = get_p_dialog(call_id,host,port,transport,&dir); if (!d) d = get_p_dialog(call_id,host,port,transport,0); if (!d){ LOG(L_ERR,"ERR:"M_NAME":P_enforce_dialog_routes: dialog does not exists!\n"); return CSCF_RETURN_FALSE; } if (!d->routes_cnt){ d_unlock(d->hash); return CSCF_RETURN_TRUE; } x.len = route_s.len + route_e.len + (d->routes_cnt-1)*route_1.len; for(i=0;i<d->routes_cnt;i++) x.len+=d->routes[i].len; x.s = pkg_malloc(x.len); if (!x.s){ LOG(L_ERR, "ERR:"M_NAME":P_enforce_dialog_routes: Error allocating %d bytes\n", x.len); x.len=0; d_unlock(d->hash); return CSCF_RETURN_ERROR; } x.len=0; STR_APPEND(x,route_s); for(i=0;i<d->routes_cnt;i++){ if (i) STR_APPEND(x,route_1); STR_APPEND(x,d->routes[i]); } STR_APPEND(x,route_e); newuri.s = pkg_malloc(d->routes[0].len); if (!newuri.s){ LOG(L_ERR, "ERR:"M_NAME":P_enforce_dialog_routes: Error allocating %d bytes\n", d->routes[0].len); d_unlock(d->hash); return CSCF_RETURN_ERROR; } newuri.len = d->routes[0].len; memcpy(newuri.s,d->routes[0].s,newuri.len); if (msg->dst_uri.s) pkg_free(msg->dst_uri.s); msg->dst_uri = newuri; //LOG(L_ERR,"%.*s",x.len,x.s); d_unlock(d->hash); if (cscf_add_header_first(msg,&x,HDR_ROUTE_T)) { if (cscf_del_all_headers(msg,HDR_ROUTE_T)) return CSCF_RETURN_TRUE; else { LOG(L_ERR,"ERR:"M_NAME":P_enforce_dialog_routes: new Route headers added, but failed to drop old ones.\n"); return CSCF_RETURN_ERROR; } } else { if (x.s) pkg_free(x.s); return CSCF_RETURN_ERROR; } }