void add_dlg_data_to_contact(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params) { struct impu_data *impu_data; impurecord_t* implicit_impurecord = 0; struct ucontact* ucontact; str callid = {0, 0}; str path = {0, 0}; LM_DBG("dialog [%p] confirmed, lets add dlg data to contact\n", dlg); if(_params && _params->param){ impu_data = (struct impu_data*)*_params->param; if (!impu_data) { LM_ERR("IMPU data object is NULL...... aborting\n"); return; } LM_DBG("IMPU data is present, contact: <%.*s> identity <%.*s>", impu_data->contact.len, impu_data->contact.s, impu_data->identity.len, impu_data->identity.s); LM_DBG("IMPU data domain <%.*s>", impu_data->d->name->len, impu_data->d->name->s); ul.lock_udomain(impu_data->d, &impu_data->identity); if (ul.get_impurecord(impu_data->d, &impu_data->identity, &implicit_impurecord) != 0) { LM_DBG("usrloc does not have imprecord for implicity IMPU, ignore\n"); }else { if (ul.get_ucontact(implicit_impurecord, &impu_data->contact, &callid, &path, 0/*cseq*/, &ucontact) != 0) { //contact does not exist LM_DBG("This contact: <%.*s> is not in usrloc, ignore - NOTE: You need S-CSCF usrloc set to match_mode CONTACT_PORT_IP_ONLY\n", impu_data->contact.len, impu_data->contact.s); } else {//contact exists so add dialog data to it ul.add_dialog_data_to_contact(ucontact, dlg->h_entry, dlg->h_id); } } ul.unlock_udomain(impu_data->d, &impu_data->identity); } }
/*! \brief * Lookup contact in the database and rewrite Request-URI * \return: 1 : contacts found and returned * -1 : not found * -2 : error */ int lookup_transport(struct sip_msg* _m, udomain_t* _d, str* _uri) { str uri; pcontact_t* pcontact; char tmp[MAX_URI_SIZE]; char srcip[20]; str received_host; str tmp_s; int ret = 1; if (_m->new_uri.s) uri = _m->new_uri; else uri = _m->first_line.u.request.uri; received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip)); received_host.s = srcip; //now lookup in usrloc ul.lock_udomain(_d, &uri, &received_host, _m->rcv.src_port); if (ul.get_pcontact(_d, &uri, &received_host, _m->rcv.src_port, &pcontact) != 0) { //need to insert new contact LM_WARN("received request for contact that we don't know about\n"); ret = -1; goto done; } if (pcontact->received_proto != _m->rcv.proto) { reset_dst_uri(_m); memset(tmp, 0, MAX_URI_SIZE); switch (pcontact->received_proto) { case PROTO_TCP: snprintf(tmp, MAX_URI_SIZE, "%.*s;transport=tcp", pcontact->aor.len, pcontact->aor.s); break; case PROTO_UDP: snprintf(tmp, MAX_URI_SIZE, "%.*s;transport=udp", pcontact->aor.len, pcontact->aor.s); break; default: LM_WARN("unsupported transport [%d]\n", pcontact->received_proto); ret = -2; goto done; } tmp_s.s = tmp; tmp_s.len = strlen(tmp); if (set_dst_uri(_m, &tmp_s) < 0) { LM_ERR("failed to set dst_uri for terminating UE\n"); ret = -2; goto done; } LM_DBG("Changed dst URI transport for UE to [%.*s]\n", tmp_s.len, tmp_s.s); } done: ul.unlock_udomain(_d, &uri, &received_host, _m->rcv.src_port); return ret; }
static void natping(unsigned int ticks, void *param) { int rval; void *buf, *cp; str c; struct dest_info dst; buf = NULL; if (cblen > 0) { buf = pkg_malloc(cblen); if (buf == NULL) { LOG(L_ERR, "ERROR: nathelper::natping: out of memory\n"); return; } } rval = ul.get_all_ucontacts(buf, cblen, (ping_nated_only ? FL_NAT : 0)); if (rval > 0) { if (buf != NULL) pkg_free(buf); cblen = rval * 2; buf = pkg_malloc(cblen); if (buf == NULL) { LOG(L_ERR, "ERROR: nathelper::natping: out of memory\n"); return; } rval = ul.get_all_ucontacts(buf, cblen, (ping_nated_only ? FL_NAT : 0)); if (rval != 0) { pkg_free(buf); return; } } if (buf == NULL) return; cp = buf; while (1) { memcpy(&(c.len), cp, sizeof(c.len)); if (c.len == 0) break; c.s = (char *)cp + sizeof(c.len); cp = (char *)cp + sizeof(c.len) + c.len; init_dest_info(&dst); memcpy(&dst.send_sock, cp, sizeof(dst.send_sock)); cp += sizeof(dst.send_sock); natping_contact(c, &dst); } pkg_free(buf); }
/** * checked if passed identity is an asserted identity */ int assert_identity(struct sip_msg* _m, udomain_t* _d, str identity) { // Public identities of this contact struct ppublic * p; //remove <> braces if there are if(identity.s[0]=='<' && identity.s[identity.len-1]=='>') { identity.s++; identity.len -= 2; } LM_DBG("Identity to assert: %.*s\n", identity.len, identity.s); if (getContactP(_m, _d, PCONTACT_REGISTERED|PCONTACT_REG_PENDING_AAR|PCONTACT_REG_PENDING, 0, 0) != NULL) { for (p = c->head; p; p = p->next) { LM_DBG("Public identity: %.*s\n", p->public_identity.len, p->public_identity.s); /* Check length: */ if (identity.len == p->public_identity.len) { /* Check contents: */ if (strncasecmp(identity.s, p->public_identity.s, identity.len) == 0) { LM_DBG("Match!\n"); return 1; } } else LM_DBG("Length does not match.\n"); } } LM_INFO("Contact not found based on Contact, trying IP/Port/Proto\n"); str received_host = {0, 0}; char srcip[50]; received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip)); received_host.s = srcip; if (ul.assert_identity(_d, &received_host, _m->rcv.src_port, _m->rcv.proto, &identity) == 0) return -1; else return 1; }
/** * get PContact-Structure for message * (search only once per Request) */ pcontact_t * getContactP(struct sip_msg* _m, udomain_t* _d) { ppublic_t * p; str received_host = {0, 0}; char srcip[50]; if (_m->id != current_msg_id) { current_msg_id = _m->id; c = NULL; received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip)); received_host.s = srcip; if (ul.get_pcontact_by_src(_d, &received_host, _m->rcv.src_port, _m->rcv.proto, &c) == 1) LM_WARN("No entry in usrloc for %.*s:%i (Proto %i) found!\n", received_host.len, received_host.s, _m->rcv.src_port, _m->rcv.proto); } asserted_identity = NULL; if (c) { p = c->head; while (p) { if (p->is_default == 1) asserted_identity = &p->public_identity; p = p->next; } } return c; }
pcontact_t * getContactP_from_via(struct sip_msg* _m, udomain_t* _d) { ppublic_t * p; struct via_body *vb; vb = cscf_get_ue_via(_m); if (!vb) { LM_WARN("no via header.....strange!\n"); return NULL; } if (vb->port == 0) vb->port = 5060; if (_m->id != current_msg_id) { current_msg_id = _m->id; c = NULL; LM_DBG("Looking for <%d://%.*s:%d>\n", vb->proto, vb->host.len, vb->host.s, vb->port); if (ul.get_pcontact_by_src(_d, &vb->host, vb->port, vb->proto, &c) == 1) LM_WARN("No entry in usrloc for %.*s:%i (Proto %i) found!\n", vb->host.len, vb->host.s, vb->port, vb->proto); } asserted_identity = NULL; if (c) { p = c->head; while (p) { if (p->is_default == 1) asserted_identity = &p->public_identity; p = p->next; } } return c; }
int pcscf_unregister(udomain_t* _d, str * uri, str * received_host, int received_port) { int result = -1; struct pcontact * pcontact; struct pcontact_info ci; memset(&ci, 0, sizeof (struct pcontact_info)); pcontact_info_t search_ci; memset(&ci, 0, sizeof(struct pcontact_info)); sip_uri_t contact_uri; if (parse_uri(uri->s, uri->len, &contact_uri) != 0) { LM_WARN("Failed to parse aor [%.*s]\n", uri->len, uri->s); return -1; } search_ci.received_host.s = received_host->s; search_ci.received_host.len = received_host->len; search_ci.received_port = received_port; search_ci.received_proto = contact_uri.proto? contact_uri.proto : PROTO_UDP; search_ci.searchflag = SEARCH_RECEIVED; search_ci.via_host.s = received_host->s; search_ci.via_host.len = received_host->len; search_ci.via_port = received_port; search_ci.via_prot = search_ci.received_proto; search_ci.aor.s = uri->s; search_ci.aor.len = uri->len; search_ci.reg_state = PCONTACT_ANY; if (ul.get_pcontact(_d, &search_ci, &pcontact) == 0) { /* Lock this record while working with the data: */ ul.lock_udomain(_d, &pcontact->via_host, pcontact->via_port, pcontact->via_proto); LM_DBG("Updating contact [%.*s]: setting state to PCONTACT_DEREG_PENDING_PUBLISH\n", pcontact->aor.len, pcontact->aor.s); ci.reg_state = PCONTACT_DEREG_PENDING_PUBLISH; ci.num_service_routes = 0; if (ul.update_pcontact(_d, &ci, pcontact) == 0) result = 1; /* Unlock domain */ ul.unlock_udomain(_d, &pcontact->via_host, pcontact->via_port, pcontact->via_proto); } return result; }
/* PSEUDOCODE/NOTES * 1. What mode are we in - terminating or originating * 2. check request type - IEC - Immediate Event Charging * ECUR - Event Charging with Unit Reservation * SCUR - Session Charging with Unit Reservation * 3. probably only do SCUR in this module for now - can see event based charging in another component instead (AS for SMS for example, etc) * 4. Check a dialog exists for call, if not we fail * 5. make sure we dont already have an Ro Session for this dialog * 6. create new Ro Session * 7. register for DLG callback passing new Ro session as parameter - (if dlg torn down we know which Ro session it is associated with) * * */ int ret = RO_RETURN_TRUE; int dir = 0; str identity = {0, 0}, contact = {0, 0}; struct hdr_field *h=0; cfg_action_t* cfg_action; tm_cell_t *t; unsigned int tindex = 0, tlabel = 0; struct impu_data *impu_data; udomain_t* domain_t = (udomain_t*) _d; char *p; struct dlg_cell* dlg; unsigned int len; struct ro_session *ro_session = 0; int free_contact = 0; LM_DBG("Ro CCR initiated: direction:%.*s, charge_type:%.*s, unit_type:%.*s, reservation_units:%i, route_name:%.*s", direction->len, direction->s, charge_type->len, charge_type->s, unit_type->len, unit_type->s, reservation_units, route_name->len, route_name->s); if (msg->first_line.type != SIP_REQUEST) { LM_ERR("Ro_CCR() called from SIP reply."); return RO_RETURN_ERROR;; } //make sure we can get the dialog! if not, we can't continue dlg = dlgb.get_dlg(msg); if (!dlg) { LM_ERR("Unable to find dialog and cannot do Ro charging without it\n"); return RO_RETURN_ERROR; } dir = get_direction_as_int(direction); if (dir == RO_ORIG_DIRECTION) { //get caller IMPU from asserted identity if ((identity = cscf_get_asserted_identity(msg, 0)).len == 0) { LM_DBG("No P-Asserted-Identity hdr found. Using From hdr for asserted_identity"); identity = dlg->from_uri; } //get caller contact from contact header - if not present then skip this if ((contact = cscf_get_contact(msg)).len == 0) { LM_WARN("Can not get contact from message - will not get callbacks if this IMPU is removed to terminate call"); goto send_ccr; } } else if (dir == RO_TERM_DIRECTION){ //get callee IMPU from called part id - if not present then skip this if ((identity = cscf_get_public_identity_from_called_party_id(msg, &h)).len == 0) { LM_WARN("No P-Called-Identity hdr found - will not get callbacks if this IMPU is removed to terminate call"); goto send_ccr; } //get callee contact from request URI contact = cscf_get_contact_from_requri(msg); free_contact = 1; } else { LM_CRIT("don't know what to do in unknown mode - should we even get here\n"); ret = RO_RETURN_ERROR; goto done; } LM_DBG("IMPU data to pass to usrloc: contact <%.*s> identity <%.*s>\n", contact.len, contact.s, identity.len, identity.s); //create impu_data_parcel len = identity.len + contact.len + sizeof (struct impu_data); impu_data = (struct impu_data*) shm_malloc(len); if (!impu_data) { LM_ERR("Unable to allocate memory for impu_data, trying to send CCR\n"); ret = RO_RETURN_ERROR; goto done; } memset(impu_data, 0, len); p = (char*) (impu_data + 1); impu_data->identity.s = p; impu_data->identity.len = identity.len; memcpy(p, identity.s, identity.len); p += identity.len; impu_data->contact.s = p; impu_data->contact.len = contact.len; memcpy(p, contact.s, contact.len); p += contact.len; impu_data->d = domain_t; if (p != (((char*) impu_data) + len)) { LM_ERR("buffer overflow creating impu data, trying to send CCR\n"); shm_free(impu_data); ret = RO_RETURN_ERROR; goto done; } //reg for callbacks on confirmed and terminated if (dlgb.register_dlgcb(dlg, /* DLGCB_RESPONSE_FWDED */ DLGCB_CONFIRMED, add_dlg_data_to_contact, (void*)impu_data ,NULL ) != 0) { LM_CRIT("cannot register callback for dialog confirmation\n"); ret = RO_RETURN_ERROR; goto done; } if (dlgb.register_dlgcb(dlg, DLGCB_TERMINATED | DLGCB_FAILED | DLGCB_EXPIRED /*| DLGCB_DESTROY */, remove_dlg_data_from_contact, (void*)impu_data, NULL ) != 0) { LM_CRIT("cannot register callback for dialog termination\n"); ret = RO_RETURN_ERROR; goto done; } send_ccr: //check if we need to send_ccr - //we get the ro_session based on dlg->h_id and dlg->h_entry and direction 0 (so get any ro_session) //if it already exists then we go to done if (single_ro_session_per_dialog && (ro_session = lookup_ro_session(dlg->h_entry, &dlg->callid, 0, 0))) { LM_DBG("single_ro_session_per_dialog = 1 and ro_session already exists for this dialog -so we don't need to send another one\n"); unref_ro_session(ro_session,1);//for the lookup ro session ref goto done; } LM_DBG("Looking for route block [%.*s]\n", route_name->len, route_name->s); int ri = route_get(&main_rt, route_name->s); if (ri < 0) { LM_ERR("unable to find route block [%.*s]\n", route_name->len, route_name->s); ret = RO_RETURN_ERROR; goto done; } cfg_action = main_rt.rlist[ri]; if (!cfg_action) { LM_ERR("empty action lists in route block [%.*s]\n", route_name->len, route_name->s); ret = RO_RETURN_ERROR; goto done; } //before we send lets suspend the transaction t = tmb.t_gett(); if (t == NULL || t == T_UNDEFINED) { if (tmb.t_newtran(msg) < 0) { LM_ERR("cannot create the transaction for CCR async\n"); ret = RO_RETURN_ERROR; goto done; } t = tmb.t_gett(); if (t == NULL || t == T_UNDEFINED) { LM_ERR("cannot lookup the transaction\n"); ret = RO_RETURN_ERROR; goto done; } } LM_DBG("Suspending SIP TM transaction\n"); if (tmb.t_suspend(msg, &tindex, &tlabel) < 0) { LM_ERR("failed to suspend the TM processing\n"); ret = RO_RETURN_ERROR; goto done; } ret = Ro_Send_CCR(msg, dlg, dir, charge_type, unit_type, reservation_units, cfg_action, tindex, tlabel); if(ret < 0){ LM_ERR("Failed to send CCR\n"); tmb.t_cancel_suspend(tindex, tlabel); } done: if(free_contact) shm_free(contact.s);// shm_malloc in cscf_get_public_identity_from_requri return ret; } ///* fixups */ static int domain_fixup(void** param) { udomain_t* d; if (ul.register_udomain((char*)*param, &d) < 0) { LM_ERR("failed to register domain\n"); return E_UNSPEC; } *param = (void*)d; return 0; }
/** * Add proper asserted identies based on registration */ int assert_identity(struct sip_msg* _m, udomain_t* _d, str identity) { str received_host = {0, 0}; char srcip[50]; received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip)); received_host.s = srcip; if (ul.assert_identity(_d, &received_host, _m->rcv.src_port, _m->rcv.proto, &identity) == 0) return -1; else return 1; }
/*! \brief * Convert char* parameter to udomain_t* pointer */ static int domain_fixup(void** param, int param_no) { udomain_t* d; if (param_no == 2) { if (isc_ulb.register_udomain((char*) *param, &d) < 0) { LM_ERR("failed to register domain\n"); return E_UNSPEC; } *param = (void*) d; } return 0; }
int unregister(udomain_t* _d, str * uri, str * received_host, int received_port) { int result = -1; struct pcontact * pcontact; struct pcontact_info ci; memset(&ci, 0, sizeof (struct pcontact_info)); if (ul.get_pcontact(_d, uri, received_host, received_port, &pcontact) == 0) { /* Lock this record while working with the data: */ ul.lock_udomain(_d, &pcontact->aor, received_host, received_port); LM_DBG("Updating contact [%.*s]: setting state to PCONTACT_DEREG_PENDING_PUBLISH\n", pcontact->aor.len, pcontact->aor.s); ci.reg_state = PCONTACT_DEREG_PENDING_PUBLISH; ci.num_service_routes = 0; if (ul.update_pcontact(_d, &ci, pcontact) == 0) result = 1; // if (ul.delete_pcontact(_d, &pc->aor, received_host, received_port, pcontact) == 0) result = 1; /* Unlock domain */ ul.unlock_udomain(_d, &pcontact->aor, received_host, received_port); } return result; }
/* * Convert char* parameter to udomain_t* pointer */ static int domain_fixup(void** param, int param_no) { udomain_t* d; if (param_no == 1) { if (ul.register_udomain((char*)*param, &d) < 0) { LOG(L_ERR, "domain_fixup(): Error while registering domain\n"); return E_UNSPEC; } *param = (void*)d; } return 0; }
/** * Add proper asserted identies based on registration */ int assert_identity(struct sip_msg* _m, udomain_t* _d, str identity) { // Get the contact: pcontact_t * c = getContactP(_m, _d); // Public identities of this contact ppublic_t * p; // Contact not found => Identity not asserted. if (c == NULL) return -2; /* Lock this record while working with the data: */ ul.lock_udomain(_d, &c->aor); LM_DBG("Checking identity: %.*s\n", identity.len, identity.s); LM_DBG("AOR of contact: %.*s\n", c->aor.len, c->aor.s); for (p = c->head; p; p = p->next) { LM_DBG("Public identity: %.*s\n", p->public_identity.len, p->public_identity.s); /* Check length: */ if (identity.len == p->public_identity.len) { /* Check contents: */ if (strncasecmp(identity.s, p->public_identity.s, identity.len) != 0) { LM_DBG("Match!\n"); goto success; } } else LM_DBG("Length does not match.\n"); } // We should only get here, if we failed: /* Unlock domain */ ul.unlock_udomain(_d, &c->aor); return -1; success: /* Unlock domain */ ul.unlock_udomain(_d, &c->aor); return 1; }
static int fixup_aar_register(void** param, int param_no) { // udomain_t* d; // aar_param_t *ap; // // if (param_no != 1) // return 0; // ap = (aar_param_t*) pkg_malloc(sizeof (aar_param_t)); // if (ap == NULL) { // LM_ERR("no more pkg\n"); // return -1; // } // memset(ap, 0, sizeof (aar_param_t)); // ap->paction = get_action_from_param(param, param_no); // // if (ul.register_udomain((char*) *param, &d) < 0) { // LM_ERR("failed to register domain\n"); // return E_UNSPEC; // } // ap->domain = d; // // *param = (void*) ap; // return 0; if (strlen((char*) *param) <= 0) { LM_ERR("empty parameter %d not allowed\n", param_no); return -1; } if (param_no == 1) { //route name - static or dynamic string (config vars) if (fixup_spve_null(param, param_no) < 0) return -1; return 0; } else if (param_no == 2) { udomain_t* d; if (ul.register_udomain((char*) *param, &d) < 0) { LM_ERR("Error doing fixup on assign save"); return -1; } *param = (void*) d; } return 0; }
void remove_dlg_data_from_contact(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params) { struct impu_data *impu_data; impurecord_t* implicit_impurecord = 0; struct ucontact* ucontact; str callid = {0, 0}; str path = {0, 0}; udomain_t* domain_t; LM_DBG("dialog [%p] terminated, lets remove dlg data from contact\n", dlg); if (ul.register_udomain(domain, &domain_t) < 0) { LM_ERR("Unable to register usrloc domain....aborting\n"); return; } if(_params && _params->param){ impu_data = (struct impu_data*)*_params->param; if (!impu_data) { LM_ERR("IMPU data object is NULL...... aborting\n"); return; } LM_DBG("IMPU data is present, contact: <%.*s> identity <%.*s>", impu_data->contact.len, impu_data->contact.s, impu_data->identity.len, impu_data->identity.s); LM_DBG("IMPU data domain <%.*s>", domain_t->name->len, domain_t->name->s); ul.lock_udomain(domain_t, &impu_data->identity); if (ul.get_impurecord(domain_t, &impu_data->identity, &implicit_impurecord) != 0) { LM_DBG("usrloc does not have imprecord for implicity IMPU, ignore\n"); }else { if (ul.get_ucontact(&impu_data->contact, &callid, &path, 0/*cseq*/, &ucontact) != 0) { //contact does not exist LM_DBG("This contact: <%.*s> is not in usrloc, ignore - NOTE: You need S-CSCF usrloc set to match_mode CONTACT_PORT_IP_ONLY\n", impu_data->contact.len, impu_data->contact.s); } else {//contact exists so add dialog data to it ul.remove_dialog_data_from_contact(ucontact, dlg->h_entry, dlg->h_id); ul.release_ucontact(ucontact); } } ul.unlock_udomain(domain_t, &impu_data->identity); free_impu_data(impu_data); } //we referenced the dialog when we registered for callbacks on it... dlgb.release_dlg(dlg); }
/* * Convert the char* parameters */ static int assign_save_fixup3_async(void** param, int param_no) { if (strlen((char*) *param) <= 0) { LM_ERR("empty parameter %d not allowed\n", param_no); return -1; } if (param_no == 1) { //route name - static or dynamic string (config vars) if (fixup_spve_null(param, param_no) < 0) return -1; return 0; } else if (param_no == 2) { udomain_t* d; if (ul.register_udomain((char*) *param, &d) < 0) { LM_ERR("Error doing fixup on assign save"); return -1; } *param = (void*) d; } return 0; }
void async_aar_reg_callback(int is_timeout, void *param, AAAMessage *aaa, long elapsed_msecs) { struct cell *t = 0; pcontact_t* pcontact; unsigned int cdp_result; struct pcontact_info ci; udomain_t* domain_t; int finalReply = 0; AAASession *auth = 0; rx_authsessiondata_t* p_session_data = 0; int result = CSCF_RETURN_ERROR; pcontact_info_t contact_info; LM_DBG("Received AAR callback\n"); saved_transaction_local_t* local_data = (saved_transaction_local_t*) param; saved_transaction_t* data = local_data->global_data; domain_t = data->domain; int is_rereg = local_data->is_rereg; //before we do anything else, lets decrement the reference counter on replies lock_get(data->lock); data->answers_not_received--; if (data->answers_not_received <= 0) { finalReply = 1; } if (data->ignore_replies) { //there was obv. a subsequent error AFTER we had sent one/more AAR's - so we can ignore these replies and just free memory free_saved_transaction_data(local_data); if (finalReply) { free_saved_transaction_global_data(data); } return; } lock_release(data->lock); LM_DBG("received answer and we are waiting for [%d] answers so far failures flag is [%d]\n", data->answers_not_received, data->failed); if (tmb.t_lookup_ident(&t, data->tindex, data->tlabel) < 0) { LM_ERR("t_continue: transaction not found\n"); goto error; } //we have T, lets restore our state (esp. for AVPs) set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from); set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to); set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from); set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to); set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from); set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to); if (is_timeout != 0) { LM_ERR("Error timeout when sending AAR message via CDP\n"); counter_inc(ims_qos_cnts_h.registration_aar_timeouts); goto error; } if (!aaa) { LM_ERR("Error sending message via CDP\n"); goto error; } counter_inc(ims_qos_cnts_h.registration_aars); counter_add(ims_qos_cnts_h.registration_aar_response_time, elapsed_msecs); counter_inc(ims_qos_cnts_h.registration_aar_replies_received); /* Process the response to AAR, retrieving result code and associated Rx session ID */ if (rx_process_aaa(aaa, &cdp_result) < 0) { LM_ERR("Failed to process AAA from PCRF\n"); //puri.host.len, puri.host.s); goto error; } if (cdp_result >= 2000 && cdp_result < 3000) { counter_inc(ims_qos_cnts_h.successful_registration_aars); if (is_rereg) { LM_DBG("this is a re-registration, therefore we don't need to do anything except know that the the subscription was successful\n"); result = CSCF_RETURN_TRUE; create_return_code(result); goto done; } //need to set Rx auth data to say this session has been successfully opened //This is used elsewhere to prevent acting on termination events when the session has not been opened //getting auth session auth = cdpb.AAAGetAuthSession(aaa->sessionId->data); if (!auth) { LM_DBG("Could not get Auth Session for session id: [%.*s]\n", aaa->sessionId->data.len, aaa->sessionId->data.s); goto error; } //getting session data p_session_data = (rx_authsessiondata_t*) auth->u.auth.generic_data; if (!p_session_data) { LM_DBG("Could not get session data on Auth Session for session id: [%.*s]\n", aaa->sessionId->data.len, aaa->sessionId->data.s); if (auth) cdpb.AAASessionsUnlock(auth->hash); goto error; } p_session_data->session_has_been_opened = 1; counter_inc(ims_qos_cnts_h.active_registration_rx_sessions); if (auth) cdpb.AAASessionsUnlock(auth->hash); LM_DBG("Success, received code: [%i] from PCRF for AAR request (contact: [%.*s]), (auth session id: %.*s)\n", cdp_result, local_data->contact.len, local_data->contact.s, local_data->auth_session_id.len, local_data->auth_session_id.s); LM_DBG("Registering for Usrloc callbacks on DELETE\n"); ul.lock_udomain(domain_t, &local_data->via_host, local_data->via_port, local_data->via_proto); contact_info.received_host = local_data->recv_host; contact_info.received_port = local_data->recv_port; contact_info.received_proto = local_data->recv_proto; contact_info.searchflag = (1 << SEARCH_RECEIVED); contact_info.aor = local_data->contact; contact_info.via_host = local_data->via_host; contact_info.via_port = local_data->via_port; contact_info.via_prot = local_data->via_proto; if (ul.get_pcontact(domain_t, &contact_info, &pcontact) != 0) { LM_ERR("Shouldn't get here, can't find contact....\n"); ul.unlock_udomain(domain_t, &local_data->via_host, local_data->via_port, local_data->via_proto); goto error; } //at this point we have the contact /*set the contact state to say we have succesfully done ARR for register and that we dont need to do it again * for the duration of the registration. * */ if (ul.update_rx_regsession(domain_t, &local_data->auth_session_id, pcontact) != 0) { LM_ERR("unable to update pcontact......\n"); ul.unlock_udomain(domain_t, &local_data->via_host, local_data->via_port, local_data->via_proto); goto error; } memset(&ci, 0, sizeof (struct pcontact_info)); ci.reg_state = PCONTACT_REG_PENDING_AAR; ci.num_service_routes = 0; ci.num_public_ids = 0; LM_DBG("impu: [%.*s] updating status to PCONTACT_REG_PENDING\n", pcontact->aor.len, pcontact->aor.s); ul.update_pcontact(domain_t, &ci, pcontact); //register for callbacks on contact ul.register_ulcb(pcontact, PCSCF_CONTACT_DELETE | PCSCF_CONTACT_EXPIRE, callback_pcscf_contact_cb, NULL); ul.unlock_udomain(domain_t, &local_data->via_host, local_data->via_port, local_data->via_proto); result = CSCF_RETURN_TRUE; } else { LM_DBG("Received negative reply from PCRF for AAR Request\n"); counter_inc(ims_qos_cnts_h.failed_registration_aars); result = CSCF_RETURN_FALSE; goto error; } //set success response code AVP create_return_code(result); goto done; error: //set failure response code create_return_code(result); done: if (t) tmb.unref_cell(t); //free memory if (aaa) cdpb.AAAFreeMessage(&aaa); if (finalReply) { tmb.t_continue(data->tindex, data->tlabel, data->act); free_saved_transaction_global_data(data); } free_saved_transaction_data(local_data); }
/** * init module function */ static int mod_init(void) { bind_usrloc_t bind_usrloc; bind_pua_t bind_pua; LM_DBG("initializing module ...\n"); if(default_domain.s == NULL ) { LM_ERR("default domain parameter not set\n"); return -1; } default_domain.len= strlen(default_domain.s); if(pres_prefix.s == NULL ) { LM_DBG("No pres_prefix configured\n"); } else pres_prefix.len= strlen(pres_prefix.s); if(presence_server.s) { presence_server.len= strlen(presence_server.s); } bind_usrloc = (bind_usrloc_t)find_export("ul_bind_usrloc", 1, 0); if (!bind_usrloc) { LM_ERR("Can't bind usrloc\n"); return -1; } if (bind_usrloc(&ul) < 0) { LM_ERR("Can't bind usrloc\n"); return -1; } if(ul.register_ulcb == NULL) { LM_ERR("Could not import ul_register_ulcb\n"); return -1; } if(ul.register_ulcb(UL_CONTACT_INSERT, ul_publish, 0)< 0) { LM_ERR("can not register callback for" " insert\n"); return -1; } if(ul.register_ulcb(UL_CONTACT_EXPIRE, ul_publish, 0)< 0) { LM_ERR("can not register callback for" " expire\n"); return -1; } if(ul.register_ulcb(UL_CONTACT_UPDATE, ul_publish, 0)< 0) { LM_ERR("can not register callback for update\n"); return -1; } if(ul.register_ulcb(UL_CONTACT_DELETE, ul_publish, 0)< 0) { LM_ERR("can not register callback for delete\n"); return -1; } bind_pua= (bind_pua_t)find_export("bind_pua", 1,0); if (!bind_pua) { LM_ERR("Can't bind pua\n"); return -1; } if (bind_pua(&pua) < 0) { LM_ERR("Can't bind pua\n"); return -1; } if(pua.send_publish == NULL) { LM_ERR("Could not import send_publish\n"); return -1; } pua_send_publish= pua.send_publish; if(pua.send_subscribe == NULL) { LM_ERR("Could not import send_subscribe\n"); return -1; } pua_send_subscribe= pua.send_subscribe; /* register post-script pua_unset_publish unset function */ if(register_script_cb(pua_unset_publish, POST_SCRIPT_CB|REQ_TYPE_CB, 0)<0) { LM_ERR("failed to register POST request callback\n"); return -1; } return 0; }
int ipsec_forward(struct sip_msg* m, udomain_t* d) { struct pcontact_info ci; pcontact_t* pcontact = NULL; int ret = IPSEC_CMD_FAIL; // FAIL by default // // Find the contact // if(fill_contact(&ci, m) != 0) { LM_ERR("Error filling in contact data\n"); return ret; } ul.lock_udomain(d, &ci.via_host, ci.via_port, ci.via_prot); if (ul.get_pcontact(d, &ci, &pcontact) != 0) { LM_ERR("Contact doesn't exist\n"); goto cleanup; } if(pcontact->security_temp == NULL) { LM_ERR("No security parameters found in contact\n"); goto cleanup; } //get security parameters if(pcontact->security_temp->type != SECURITY_IPSEC ) { LM_ERR("Unsupported security type: %d\n", pcontact->security_temp->type); goto cleanup; } ipsec_t* s = pcontact->security_temp->data.ipsec; // Update the destination // // from sec-agree // v // sip:host:port // ^ // from URI //int uri_len = 4 /* strlen("sip:") */ + ci.via_host.len + 5 /* max len of port number */ ; if(m->dst_uri.s) { pkg_free(m->dst_uri.s); m->dst_uri.s = NULL; m->dst_uri.len = 0; } char buf[1024]; int buf_len = snprintf(buf, sizeof(buf) - 1, "sip:%.*s:%d", ci.via_host.len, ci.via_host.s, s->port_us); if((m->dst_uri.s = pkg_malloc(buf_len)) == NULL) { LM_ERR("Error allocating memory for dst_uri\n"); goto cleanup; } memcpy(m->dst_uri.s, buf, buf_len); m->dst_uri.len = buf_len; // Set send socket struct socket_info * client_sock = grep_sock_info(&ipsec_listen_addr, ipsec_client_port, PROTO_UDP); if(!client_sock) { LM_ERR("Error calling grep_sock_info() for ipsec client port in ipsec_forward\n"); return -1; } m->force_send_socket = client_sock; // Set destination info struct dest_info dst_info; dst_info.send_sock = client_sock; #ifdef USE_DNS_FAILOVER if (!uri2dst(NULL, &dst_info, m, &m->dst_uri, PROTO_UDP)) { #else if (!uri2dst(&dst_info, m, &m->dst_uri, PROTO_UDP)) { #endif LM_ERR("Error converting dst_uri (%.*s) to struct dst_info\n", m->dst_uri.len, m->dst_uri.s); goto cleanup; } // Update dst_info in message if(m->first_line.type == SIP_REPLY) { struct cell *t = tmb.t_gett(); if (!t) { LM_ERR("Error getting transaction\n"); goto cleanup; } t->uas.response.dst = dst_info; } LM_DBG("Destination changed to %.*s\n", m->dst_uri.len, m->dst_uri.s); ret = IPSEC_CMD_SUCCESS; // all good, return SUCCESS if(add_supported_secagree_header(m) != 0) { goto cleanup; } if(add_security_server_header(m, s) != 0) { goto cleanup; } ret = IPSEC_CMD_SUCCESS; // all good, set ret to SUCCESS, and exit cleanup: ul.unlock_udomain(d, &ci.via_host, ci.via_port, ci.via_prot); pkg_free(ci.received_host.s); return ret; } int ipsec_destroy(struct sip_msg* m, udomain_t* d) { struct pcontact_info ci; pcontact_t* pcontact = NULL; int ret = IPSEC_CMD_FAIL; // FAIL by default // // Find the contact // if(fill_contact(&ci, m) != 0) { LM_ERR("Error filling in contact data\n"); return ret; } ul.lock_udomain(d, &ci.via_host, ci.via_port, ci.via_prot); if (ul.get_pcontact(d, &ci, &pcontact) != 0) { LM_ERR("Contact doesn't exist\n"); goto cleanup; } if(pcontact->security_temp == NULL) { LM_ERR("No security parameters found in contact\n"); goto cleanup; } //get security parameters if(pcontact->security_temp->type != SECURITY_IPSEC ) { LM_ERR("Unsupported security type: %d\n", pcontact->security_temp->type); goto cleanup; } destroy_ipsec_tunnel(ci.received_host, pcontact->security_temp->data.ipsec); ret = IPSEC_CMD_SUCCESS; // all good, set ret to SUCCESS, and exit cleanup: ul.unlock_udomain(d, &ci.via_host, ci.via_port, ci.via_prot); pkg_free(ci.received_host.s); return ret; } int ipsec_cleanall() { struct mnl_socket* nlsock = init_mnl_socket(); if(!nlsock) { return -1; } if(clean_sa(nlsock) != 0) { LM_WARN("Error cleaning IPSec Security associations during startup.\n"); } if(clean_policy(nlsock) != 0) { LM_WARN("Error cleaning IPSec Policies during startup.\n"); } close_mnl_socket(nlsock); return 0; }
/** * Check, if a user-agent follows the indicated service-routes */ int check_service_routes(struct sip_msg* _m, udomain_t* _d) { struct sip_uri uri; int i; struct hdr_field *hdr; rr_t *r; char routes[MAXROUTES][MAXROUTESIZE]; unsigned int num_routes = 0; struct via_body * vb; unsigned short port; unsigned short proto; /* Contact not found => not following service-routes */ // if (c == NULL) return -1; /* Search for the first Route-Header: */ if (find_first_route(_m) < 0) return -1; // LM_DBG("Got %i Route-Headers.\n", c->num_service_routes); vb = cscf_get_ue_via(_m); port = vb->port?vb->port:5060; proto = vb->proto; /* Lock this record while working with the data: */ ul.lock_udomain(_d, &vb->host, port, proto); if (_m->route) { hdr = _m->route; r = (rr_t*)hdr->parsed; //get rid of ourselves from route header if (r) { LM_DBG("Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s); while (r && (parse_uri(r->nameaddr.uri.s, r->nameaddr.uri.len, &uri) == 0) && check_self(&uri.host,uri.port_no?uri.port_no:SIP_PORT,0)) { LM_DBG("Self\n"); /* Check for more headers and fail, if it was the last one Check, if service-routes are indicated. If yes, request is not following service-routes */ if (find_next_route(_m, &hdr) != 0) r = NULL; else r = (rr_t*)hdr->parsed; LM_DBG("hdr is %p\n", hdr); LM_DBG("r is %p\n", r); if (r) LM_DBG("Next Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s); } int i = 0; while (r) { memset(routes[i],0,MAXROUTESIZE); memcpy(routes[i], r->nameaddr.uri.s, r->nameaddr.uri.len); if (find_next_route(_m, &hdr) != 0) r = NULL; else r = (rr_t*)hdr->parsed; i += 1; num_routes += 1; } LM_DBG("num_routes is %d\n", num_routes); for (i=0; i<num_routes; i++) { LM_DBG("route %d for checking is %s\n", i, routes[i]); } pcontact_t * c = getContactP(_m, _d, PCONTACT_REGISTERED, routes, num_routes); if (!c) { LM_DBG("no contact found in usrloc when checking for service route\n"); goto error; } LM_DBG("we have a contact which satisifes the routes...\n"); ul.unlock_udomain(_d, &vb->host, port, proto); return 1; } } else { LM_DBG("Request doesn't have any route headers to check service-route...ignoring\n"); goto error; } pcontact_t * c = getContactP(_m, _d, PCONTACT_REGISTERED, 0, 0); if (!c) { LM_DBG("no contact found in usrloc when checking for service route\n"); goto error; } /* Check the route-set: */ if (_m->route) { hdr = _m->route; LM_DBG("hdr is %p\n", hdr); /* Check, if the first host is ourself: */ r = (rr_t*)hdr->parsed; if (r) { LM_DBG("Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s); /* Skip first headers containing myself: */ while (r && (parse_uri(r->nameaddr.uri.s, r->nameaddr.uri.len, &uri) == 0) && check_self(&uri.host,uri.port_no?uri.port_no:SIP_PORT,0)) { LM_DBG("Self\n"); /* Check for more headers and fail, if it was the last one Check, if service-routes are indicated. If yes, request is not following service-routes */ if (find_next_route(_m, &hdr) != 0) r = NULL; else r = (rr_t*)hdr->parsed; if (!r && (c->num_service_routes > 0)) { LM_DBG("Not enough route-headers in Message\n"); goto error; } LM_DBG("hdr is %p\n", hdr); LM_DBG("r is %p\n", r); if (r) LM_DBG("Next Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s); } LM_DBG("We have %d service-routes\n", c->num_service_routes); /* Then check the following headers: */ for (i=0; i< c->num_service_routes; i++) { LM_DBG("Route must be: %.*s\n", c->service_routes[i].len, c->service_routes[i].s); /* No more Route-Headers? Not following service-routes */ if (!r) { LM_DBG("No more route headers in message.\n"); goto error; } LM_DBG("Route is: %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s); /* Check length: */ if (r->nameaddr.uri.len != c->service_routes[i].len) { LM_DBG("Length does not match.\n"); goto error; } /* Check contents: */ if (strncasecmp(r->nameaddr.uri.s, c->service_routes[i].s, c->service_routes[i].len) != 0) { LM_DBG("String comparison failed.\n"); goto error; } if (find_next_route(_m, &hdr) != 0) r = NULL; else r = (rr_t*)hdr->parsed; } /* Check, if it was the last route-header in the message: */ if (r) { LM_DBG("Too many route headers in message.\n"); goto error; } } else { LM_WARN("Strange: Route-Header is present, but not parsed?!?"); if (c->num_service_routes > 0) goto error; } } else { LM_DBG("No route header in Message.\n"); /* No route-header? Check, if service-routes are indicated. If yes, request is not following service-routes */ if (c->num_service_routes > 0) 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; }
/** * 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; }
pcontact_t * getContactP(struct sip_msg* _m, udomain_t* _d, enum pcontact_reg_states reg_state, char service_routes[][MAXROUTESIZE], int num_service_routes) { ppublic_t * p; contact_body_t *b = 0; contact_t *ct; pcontact_info_t search_ci; str received_host = {0, 0}; char srcip[50]; struct via_body *vb; unsigned short port, proto; str host; sip_uri_t contact_uri; int mustRetryViaSearch = 0; int mustRetryReceivedSearch = 0; LM_DBG("number of service routes to look for is %d\n", num_service_routes); b = cscf_parse_contacts(_m); if (_m->first_line.type == SIP_REPLY && _m->contact && _m->contact->parsed && b->contacts) { mustRetryViaSearch = 1; mustRetryReceivedSearch = 1; LM_DBG("This is a reply - to look for contact we favour the contact header above the via (b2bua)... if no contact we will use last via\n"); ct = b->contacts; host = ct->uri; if (parse_uri(ct->uri.s, ct->uri.len, &contact_uri) != 0) { LM_WARN("Failed to parse contact [%.*s]\n", ct->uri.len, ct->uri.s); return NULL; } host = contact_uri.host; port = contact_uri.port_no ? contact_uri.port_no : 5060; proto = contact_uri.proto; if (proto == 0) { LM_DBG("Contact protocol not specified - using received\n"); proto = _m->rcv.proto; } } else { if (_m->first_line.type == SIP_REPLY) LM_DBG("This is a reply but we are forced to use the via header\n"); else LM_DBG("This is a request - using first via to find contact\n"); vb = cscf_get_ue_via(_m); host = vb->host; port = vb->port ? vb->port : 5060; proto = vb->proto; } LM_DBG("searching for contact with host:port:proto contact [%d://%.*s:%d]\n", proto, host.len, host.s, port); received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof (srcip)); received_host.s = srcip; // if (_m->id != current_msg_id) { current_msg_id = _m->id; c = NULL; //search_ci.reg_state = PCONTACT_REGISTERED; //we can do this because this function is always called expecting a REGISTERED contact memset(&search_ci, 0, sizeof(struct pcontact_info)); search_ci.reg_state = reg_state; search_ci.received_host.s = received_host.s; search_ci.received_host.len = received_host.len; search_ci.received_port = _m->rcv.src_port; search_ci.received_proto = _m->rcv.proto; search_ci.searchflag = SEARCH_RECEIVED; search_ci.num_service_routes = 0; if (is_registered_fallback2ip == 1) { search_ci.searchflag = SEARCH_NORMAL; } search_ci.via_host = host; search_ci.via_port = port; search_ci.via_prot = proto; search_ci.aor.s = 0; search_ci.aor.len = 0; int size = num_service_routes==0?1:num_service_routes; str s_service_routes[size]; int i; for (i=0;i<num_service_routes;i++) { s_service_routes[i].s = service_routes[i]; s_service_routes[i].len = strlen(service_routes[i]); LM_DBG("Setting service routes str for pos %d to %.*s", i, s_service_routes[i].len, s_service_routes[i].s); } if (num_service_routes > 0) { LM_DBG("asked to search for specific service routes...\n"); search_ci.service_routes = s_service_routes; search_ci.num_service_routes = num_service_routes; search_ci.extra_search_criteria = SEARCH_SERVICE_ROUTES; } // b = cscf_parse_contacts(_m); tryagain: if (b && b->contacts) { for (ct = b->contacts; ct; ct = ct->next) { search_ci.aor = ct->uri; if (ul.get_pcontact(_d, &search_ci, &c) == 0) { if (checkcontact(_m, c) != 0) { c = NULL; } else { break; } } } } else { LM_WARN("No contact-header found...\n"); } if ((c == NULL) && (is_registered_fallback2ip == 1)) { LM_INFO("Contact not found based on Contact-header, trying IP/Port/Proto\n"); // received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip)); // received_host.s = srcip; search_ci.searchflag = SEARCH_RECEIVED; if (ul.get_pcontact(_d, &search_ci, &c) == 1) { LM_DBG("No entry in usrloc for %.*s:%i (Proto %i) found!\n", received_host.len, received_host.s, _m->rcv.src_port, _m->rcv.proto); } else { if (checkcontact(_m, c) != 0) { c = NULL; } } } if ((c == NULL) && (is_registered_fallback2ip == 2)) { LM_INFO("Contact not found based on IP/Port/Proto, trying Contact-header\n"); search_ci.searchflag = SEARCH_NORMAL; if (ul.get_pcontact(_d, &search_ci, &c) == 1) { } else { if (checkcontact(_m, c) != 0) { c = NULL; } } } asserted_identity = NULL; registration_contact = NULL; if (c) { LM_DBG("Trying to set asserted identity field"); registration_contact = &c->contact_user; p = c->head; while (p) { LM_DBG("Checking through contact users"); if (p->is_default == 1) { LM_DBG("Found default contact user so setting asserted identity"); asserted_identity = &p->public_identity; } p = p->next; } } if (asserted_identity != NULL && asserted_identity->len > 0) { LM_DBG("Have set the asserted_identity param to [%.*s]\n", asserted_identity->len, asserted_identity->s); } else { LM_DBG("Asserted identity not set"); } // LM_DBG("pcontact flag is [%d]\n", c->flags); // if (c && (c->flags & (1<<FLAG_READFROMDB)) != 0) { // LM_DBG("we have a contact that was read fresh from the DB....\n"); // } if (!c && mustRetryViaSearch) { LM_DBG("This is a reply so we will search using the last via once more...\n"); vb = cscf_get_ue_via(_m); search_ci.via_host = vb->host; search_ci.via_port = vb->port ? vb->port : 5060; search_ci.via_prot = vb->proto; mustRetryViaSearch = 0; goto tryagain; } if (!c && mustRetryReceivedSearch) { LM_DBG("This is a reply and we still don't have a match - will try src ip/port of message\n"); search_ci.via_host = received_host; search_ci.via_port = _m->rcv.src_port; search_ci.via_prot = _m->rcv.proto; mustRetryReceivedSearch = 0; goto tryagain; } return c; }
int ipsec_create(struct sip_msg* m, udomain_t* d) { pcontact_t* pcontact = NULL; struct pcontact_info ci; int ret = IPSEC_CMD_FAIL; // FAIL by default // Find the contact if(fill_contact(&ci, m) != 0) { LM_ERR("Error filling in contact data\n"); return ret; } ul.lock_udomain(d, &ci.via_host, ci.via_port, ci.via_prot); if (ul.get_pcontact(d, &ci, &pcontact) != 0) { LM_ERR("Contact doesn't exist\n"); goto cleanup; } // Get security parameters if(pcontact->security_temp == NULL) { LM_ERR("No security parameters found in contact\n"); goto cleanup; } if(pcontact->security_temp->type != SECURITY_IPSEC ) { LM_ERR("Unsupported security type: %d\n", pcontact->security_temp->type); goto cleanup; } ipsec_t* s = pcontact->security_temp->data.ipsec; if(update_contact_ipsec_params(s, m) != 0) { goto cleanup; } if(create_ipsec_tunnel(ci.received_host, s) != 0) { goto cleanup; } // TODO: Save security_tmp to security!!!!! if (ul.update_pcontact(d, &ci, pcontact) != 0) { LM_ERR("Error updating contact\n"); goto cleanup; } // Destroy the tunnel, if the contact expires if(ul.register_ulcb(pcontact, PCSCF_CONTACT_EXPIRE|PCSCF_CONTACT_DELETE, on_expire, NULL) != 1) { LM_ERR("Error subscribing for contact\n"); goto cleanup; } if(add_supported_secagree_header(m) != 0) { goto cleanup; } if(add_security_server_header(m, s) != 0) { goto cleanup; } ret = IPSEC_CMD_SUCCESS; // all good, set ret to SUCCESS, and exit cleanup: // Do not free str* sec_header! It will be freed in data_lump.c -> free_lump() ul.unlock_udomain(d, &ci.via_host, ci.via_port, ci.via_prot); pkg_free(ci.received_host.s); return ret; }
/** * get PContact-Structure for message * (search only once per Request) */ pcontact_t * getContactP(struct sip_msg* _m, udomain_t* _d) { ppublic_t * p; contact_body_t *b = 0; str received_host = {0, 0}; contact_t *ct; char srcip[50]; int security_server_port = -1; if (_m->id != current_msg_id) { current_msg_id = _m->id; c = NULL; b = cscf_parse_contacts(_m); if (b && b->contacts) { for (ct = b->contacts; ct; ct = ct->next) { if (ul.get_pcontact(_d, &ct->uri, &c) == 0) { if (c->security) { switch (c->security->type) { case SECURITY_IPSEC: security_server_port = c->security->data.ipsec->port_uc; break; case SECURITY_TLS: case SECURITY_NONE: break; } } else if (c->security_temp) { switch (c->security->type) { case SECURITY_IPSEC: security_server_port = c->security->data.ipsec->port_uc; break; case SECURITY_TLS: case SECURITY_NONE: break; } } if ((c->reg_state == PCONTACT_REGISTERED) && ((c->received_port == _m->rcv.src_port) || (security_server_port == _m->rcv.src_port)) && (c->received_proto == _m->rcv.proto)) { received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip)); received_host.s = srcip; LM_DBG("Received host len %d (search %d)\n", c->received_host.len, received_host.len); // Then check the length: if (c->received_host.len == received_host.len) { LM_DBG("Received host %.*s (search %.*s)\n", c->received_host.len, c->received_host.s, received_host.len, received_host.s); // Finally really compare the "received_host" if (!memcmp(c->received_host.s, received_host.s, received_host.len)) break; c = NULL; } } else { c = NULL; } } } } else { LM_WARN("No contact-header found\n"); } if ((c == NULL) && (is_registered_fallback2ip > 0)) { LM_WARN("Contact not found based on Contact-header, trying IP/Port/Proto\n"); received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip)); received_host.s = srcip; if (ul.get_pcontact_by_src(_d, &received_host, _m->rcv.src_port, _m->rcv.proto, &c) == 1) LM_DBG("No entry in usrloc for %.*s:%i (Proto %i) found!\n", received_host.len, received_host.s, _m->rcv.src_port, _m->rcv.proto); } } asserted_identity = NULL; if (c) { p = c->head; while (p) { if (p->is_default == 1) asserted_identity = &p->public_identity; p = p->next; } } return c; }
/*! \brief * init module function */ static int mod_init(void) { bind_usrloc_t bind_usrloc; bind_pua_t bind_pua; if(!default_domain.s || default_domain.len<=0) { LM_ERR("default domain parameter not set\n"); return -1; } if(!pres_prefix.s || pres_prefix.len<=0) LM_DBG("No pres_prefix configured\n"); bind_usrloc = (bind_usrloc_t)find_export("ul_bind_usrloc", 1, 0); if (!bind_usrloc) { LM_ERR("Can't bind usrloc\n"); return -1; } if (bind_usrloc(&ul) < 0) { LM_ERR("Can't bind usrloc\n"); return -1; } if(ul.register_ulcb == NULL) { LM_ERR("Could not import ul_register_ulcb\n"); return -1; } if(ul.register_ulcb(UL_CONTACT_INSERT, ul_publish, 0)< 0) { LM_ERR("can not register callback for" " insert\n"); return -1; } if(ul.register_ulcb(UL_CONTACT_EXPIRE, ul_publish, 0)< 0) { LM_ERR("can not register callback for" " expire\n"); return -1; } if(ul.register_ulcb(UL_CONTACT_UPDATE, ul_publish, 0)< 0) { LM_ERR("can not register callback for update\n"); return -1; } if(ul.register_ulcb(UL_CONTACT_DELETE, ul_publish, 0)< 0) { LM_ERR("can not register callback for delete\n"); return -1; } bind_pua= (bind_pua_t)find_export("bind_pua", 1,0); if (!bind_pua) { LM_ERR("Can't bind pua\n"); return -1; } if (bind_pua(&_pu_pua) < 0) { LM_ERR("Can't bind pua\n"); return -1; } if(_pu_pua.send_publish == NULL) { LM_ERR("Could not import send_publish\n"); return -1; } if(_pu_pua.send_subscribe == NULL) { LM_ERR("Could not import send_subscribe\n"); return -1; } /* register post-script pua_unset_publish unset function */ if(register_script_cb(pua_unset_publish, POST_SCRIPT_CB|REQUEST_CB, 0)<0) { LM_ERR("failed to register POST request callback\n"); return -1; } if(pua_ul_bflag!=-1) pua_ul_bmask = 1 << pua_ul_bflag; return 0; }
/** * Check, if a user-agent follows the indicated service-routes */ int check_service_routes(struct sip_msg* _m, udomain_t* _d) { struct sip_uri uri; int i; struct hdr_field *hdr; rr_t *r; pcontact_t * c = getContactP(_m, _d); /* Contact not found => not following service-routes */ if (c == NULL) return -1; /* Search for the first Route-Header: */ if (find_first_route(_m) < 0) return -1; LM_DBG("Got %i Route-Headers.\n", c->num_service_routes); /* Lock this record while working with the data: */ ul.lock_udomain(_d, &c->aor); /* Check the route-set: */ if (_m->route) { hdr = _m->route; LM_DBG("hdr is %p\n", hdr); /* Check, if the first host is ourself: */ r = (rr_t*)hdr->parsed; if (r) { LM_DBG("Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s); /* Skip first headers containing myself: */ while (parse_uri(r->nameaddr.uri.s, r->nameaddr.uri.len, &uri) == 0 && check_self(&uri.host,uri.port_no?uri.port_no:SIP_PORT,0)) { LM_DBG("Self\n"); /* Check for more headers and fail, if it was the last one Check, if service-routes are indicated. If yes, request is not following service-routes */ if (find_next_route(_m, &hdr) != 0) r = NULL; else r = (rr_t*)hdr->parsed; if (!r && (c->num_service_routes > 0)) { LM_DBG("Not enough route-headers in Message\n"); goto error; } LM_DBG("hdr is %p\n", hdr); LM_DBG("r is %p\n", r); if (r) LM_DBG("Next Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s); } /* Then check the following headers: */ for (i=0; i< c->num_service_routes; i++) { LM_DBG("Route must be: %.*s\n", c->service_routes[i].len, c->service_routes[i].s); /* No more Route-Headers? Not following service-routes */ if (!r) { LM_ERR("No more route headers in message.\n"); goto error; } LM_DBG("Route is: %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s); /* Check length: */ if (r->nameaddr.uri.len != c->service_routes[i].len) { LM_DBG("Length does not match.\n"); goto error; } /* Check contents: */ if (strncasecmp(r->nameaddr.uri.s, c->service_routes[i].s, c->service_routes[i].len) != 0) { LM_DBG("String comparison failed.\n"); goto error; } if (find_next_route(_m, &hdr) != 0) r = NULL; else r = (rr_t*)hdr->parsed; } /* Check, if it was the last route-header in the message: */ if (r) { LM_ERR("Too many route headers in message.\n"); goto error; } } else { LM_WARN("Strange: Route-Header is present, but not parsed?!?"); if (c->num_service_routes > 0) goto error; } } else { LM_ERR("No route header in Message.\n"); /* No route-header? Check, if service-routes are indicated. If yes, request is not following service-routes */ if (c->num_service_routes > 0) goto error; } /* Unlock domain */ ul.unlock_udomain(_d, &c->aor); return 1; error: /* Unlock domain */ ul.unlock_udomain(_d, &c->aor); return -1; }
AAAMessage* cxdx_process_rtr(AAAMessage *rtr) { LM_DBG("Processing RTR"); AAAMessage *rta_msg; AAA_AVP* avp; str public_id; impurecord_t* r; int res = 0; udomain_t* udomain; impu_contact_t *impucontact; rta_msg = cdpb.AAACreateResponse(rtr);//session ID? if (!rta_msg) return 0; avp = cxdx_get_next_public_identity(rtr,0,AVP_IMS_Public_Identity,IMS_vendor_id_3GPP,__FUNCTION__); if(avp==0){ LM_WARN("RTR received with only IMPI (username AVP) - currently S-CSCF does not support this kind of RTR\n"); return 0; //TODO add support for receiving RTR with IMPI //get all impus related to this impu //get all contacts related to each impu //set the contact expire for each contact to now }else{ public_id=avp->data; LM_DBG("RTR received with IMPU [%.*s] in public identity AVP - this is supported\n", public_id.len, public_id.s); //TODO this should be a configurable module param if (ul.register_udomain(domain, &udomain) < 0) { LM_ERR("Unable to register usrloc domain....aborting\n"); return 0; } ul.lock_udomain(udomain, &public_id); res = ul.get_impurecord(udomain, &public_id, &r); if (res != 0) { LM_WARN("Strange, '%.*s' Not found in usrloc\n", public_id.len, public_id.s); ul.unlock_udomain(udomain, &public_id); //no point in continuing return 0; } impucontact = r->linked_contacts.head; while (impucontact) { LM_DBG("Deleting contact with AOR [%.*s]\n", impucontact->contact->aor.len, impucontact->contact->aor.s); ul.lock_contact_slot_i(impucontact->contact->sl); impucontact->contact->state = CONTACT_DELETE_PENDING; if (r->shead) { //send NOTIFY to all subscribers of this IMPU. notify_subscribers(r, 0, 0); } impucontact->contact->state = CONTACT_DELETED; ul.unlock_contact_slot_i(impucontact->contact->sl); impucontact = impucontact->next; } ul.unlock_udomain(udomain, &public_id); while(cdpb.AAAGetNextAVP(avp) && (avp=cxdx_get_next_public_identity(rtr,cdpb.AAAGetNextAVP(avp),AVP_IMS_Public_Identity,IMS_vendor_id_3GPP,__FUNCTION__))!=0){ public_id=avp->data; LM_DBG("RTR also has public id [%.*s]\n", public_id.len, public_id.s); ul.lock_udomain(udomain, &public_id); res = ul.get_impurecord(udomain, &public_id, &r); if (res != 0) { LM_WARN("Strange, '%.*s' Not found in usrloc\n", public_id.len, public_id.s); ul.unlock_udomain(udomain, &public_id); //no point in continuing return 0; } impucontact = r->linked_contacts.head; while (impucontact) { LM_DBG("Deleting contact with AOR [%.*s]\n", impucontact->contact->aor.len, impucontact->contact->aor.s); ul.lock_contact_slot_i(impucontact->contact->sl); impucontact->contact->state = CONTACT_DELETE_PENDING; if (r->shead) { //send NOTIFY to all subscribers of this IMPU. notify_subscribers(r, 0, 0); } impucontact->contact->state = CONTACT_DELETED; ul.unlock_contact_slot_i(impucontact->contact->sl); impucontact = impucontact->next; } ul.unlock_udomain(udomain, &public_id); } } cxdx_add_vendor_specific_appid(rta_msg,IMS_vendor_id_3GPP,IMS_Cx,0 /*IMS_Cx*/); cxdx_add_auth_session_state(rta_msg,1); /* send an RTA back to the HSS */ cxdx_add_result_code(rta_msg,DIAMETER_SUCCESS); return rta_msg; }
static int mod_init(void) { pv_spec_t avp_spec; str s; bind_usrloc_t bind_usrloc; qvalue_t dq; callback_singleton = shm_malloc(sizeof (int)); *callback_singleton = 0; /*build the required strings */ scscf_serviceroute_uri_str.s = (char*) pkg_malloc(orig_prefix.len + scscf_name_str.len); if (!scscf_serviceroute_uri_str.s) { LM_ERR("Unable to allocate memory for service route uri\n"); return -1; } if (contact_expires_buffer_percentage < 0 || contact_expires_buffer_percentage > 90) { LM_ERR("contact expires percentage not valid, must be >0 and <=90"); return -1; } memcpy(scscf_serviceroute_uri_str.s, orig_prefix.s, orig_prefix.len); scscf_serviceroute_uri_str.len = orig_prefix.len; if (scscf_name_str.len > 4 && strncasecmp(scscf_name_str.s, "sip:", 4) == 0) { memcpy(scscf_serviceroute_uri_str.s + scscf_serviceroute_uri_str.len, scscf_name_str.s + 4, scscf_name_str.len - 4); scscf_serviceroute_uri_str.len += scscf_name_str.len - 4; } else { memcpy(scscf_serviceroute_uri_str.s + scscf_serviceroute_uri_str.len, scscf_name_str.s, scscf_name_str.len); scscf_serviceroute_uri_str.len += scscf_name_str.len; } pv_tmx_data_init(); /* </build required strings> */ #ifdef STATISTICS /* register statistics */ if (register_module_stats(exports.name, mod_stats) != 0) { LM_ERR("failed to register core statistics\n"); return -1; } if (!register_stats()) { LM_ERR("Unable to register statistics\n"); return -1; } #endif /*register space for notification processors*/ register_procs(notification_processes); cfg_register_child(notification_processes); /* bind the SL API */ if (sl_load_api(&slb) != 0) { LM_ERR("cannot bind to SL API\n"); return -1; } /* load the TM API */ if (load_tm_api(&tmb) != 0) { LM_ERR("can't load TM API\n"); return -1; } /* load the CDP API */ if (load_cdp_api(&cdpb) != 0) { LM_ERR("can't load CDP API\n"); return -1; } cdp_avp = load_cdp_avp(); if (!cdp_avp) { LM_ERR("can't load CDP_AVP API\n"); return -1; } if (cfg_declare("registrar", registrar_cfg_def, &default_registrar_cfg, cfg_sizeof(registrar), ®istrar_cfg)) { LM_ERR("Fail to declare the configuration\n"); return -1; } if (rcv_avp_param && *rcv_avp_param) { s.s = rcv_avp_param; s.len = strlen(s.s); if (pv_parse_spec(&s, &avp_spec) == 0 || avp_spec.type != PVT_AVP) { LM_ERR("malformed or non AVP %s AVP definition\n", rcv_avp_param); return -1; } if (pv_get_avp_name(0, &avp_spec.pvp, &rcv_avp_name, &rcv_avp_type) != 0) { LM_ERR("[%s]- invalid AVP definition\n", rcv_avp_param); return -1; } } else { rcv_avp_name.n = 0; rcv_avp_type = 0; } if (aor_avp_param && *aor_avp_param) { s.s = aor_avp_param; s.len = strlen(s.s); if (pv_parse_spec(&s, &avp_spec) == 0 || avp_spec.type != PVT_AVP) { LM_ERR("malformed or non AVP %s AVP definition\n", aor_avp_param); return -1; } if (pv_get_avp_name(0, &avp_spec.pvp, &aor_avp_name, &aor_avp_type) != 0) { LM_ERR("[%s]- invalid AVP definition\n", aor_avp_param); return -1; } } else { aor_avp_name.n = 0; aor_avp_type = 0; } if (reg_callid_avp_param && *reg_callid_avp_param) { s.s = reg_callid_avp_param; s.len = strlen(s.s); if (pv_parse_spec(&s, &avp_spec) == 0 || avp_spec.type != PVT_AVP) { LM_ERR("malformed or non AVP %s AVP definition\n", reg_callid_avp_param); return -1; } if (pv_get_avp_name(0, &avp_spec.pvp, ®_callid_avp_name, ®_callid_avp_type) != 0) { LM_ERR("[%s]- invalid AVP definition\n", reg_callid_avp_param); return -1; } } else { reg_callid_avp_name.n = 0; reg_callid_avp_type = 0; } bind_usrloc = (bind_usrloc_t) find_export("ul_bind_usrloc", 1, 0); if (!bind_usrloc) { LM_ERR("can't bind usrloc\n"); return -1; } /* Normalize default_q parameter */ dq = cfg_get(registrar, registrar_cfg, default_q); if (dq != Q_UNSPECIFIED) { if (dq > MAX_Q) { LM_DBG("default_q = %d, lowering to MAX_Q: %d\n", dq, MAX_Q); dq = MAX_Q; } else if (dq < MIN_Q) { LM_DBG("default_q = %d, raising to MIN_Q: %d\n", dq, MIN_Q); dq = MIN_Q; } } cfg_get(registrar, registrar_cfg, default_q) = dq; if (bind_usrloc(&ul) < 0) { return -1; } /*Register for callback of URECORD being deleted - so we can send a SAR*/ if (ul.register_ulcb == NULL) { LM_ERR("Could not import ul_register_ulcb\n"); return -1; } if (ul.register_ulcb(0, 0, UL_IMPU_INSERT, ul_impu_inserted, 0) < 0) { LM_ERR("can not register callback for insert\n"); return -1; } if (sock_hdr_name.s) { if (sock_hdr_name.len == 0 || sock_flag == -1) { LM_WARN("empty sock_hdr_name or sock_flag no set -> reseting\n"); sock_hdr_name.len = 0; sock_flag = -1; } } else if (sock_flag != -1) { LM_WARN("sock_flag defined but no sock_hdr_name -> reseting flag\n"); sock_flag = -1; } /* fix the flags */ sock_flag = (sock_flag != -1) ? (1 << sock_flag) : 0; tcp_persistent_flag = (tcp_persistent_flag != -1) ? (1 << tcp_persistent_flag) : 0; /* init the registrar notifications */ if (!notify_init()) return -1; /* register the registrar notifications timer */ //Currently we do not use this - we send notifies immediately //if (register_timer(notification_timer, notification_list, 5) < 0) return -1; return 0; }
/** * init module function */ static int mod_init(void) { LM_DBG("initialize module...\n"); bind_pua_t bind_pua; bind_usrloc_t bind_usrloc; if(server_address.s== NULL) { LM_ERR("compulsory 'server_address' parameter not set!"); return -1; } server_address.len= strlen(server_address.s); if(presence_server.s) { presence_server.len= strlen(presence_server.s); } if(default_domain.s) { default_domain.len= strlen(default_domain.s); } if(header_name.s == NULL ) { LM_ERR("header_name parameter not set\n"); return -1; } header_name.len= strlen(header_name.s); if(bla_outbound_proxy.s == NULL ) { LM_DBG("No outbound proxy set\n"); } else bla_outbound_proxy.len= strlen(bla_outbound_proxy.s); bind_pua= (bind_pua_t)find_export("bind_pua", 1,0); if (!bind_pua) { LM_ERR("Can't bind pua\n"); return -1; } if (bind_pua(&pua) < 0) { LM_ERR("Can't bind pua\n"); return -1; } if(pua.send_publish == NULL) { LM_ERR("Could not import send_publish\n"); return -1; } pua_send_publish= pua.send_publish; if(pua.send_subscribe == NULL) { LM_ERR("Could not import send_subscribe\n"); return -1; } pua_send_subscribe= pua.send_subscribe; if(pua.is_dialog == NULL) { LM_ERR("Could not import send_subscribe\n"); return -1; } pua_is_dialog= pua.is_dialog; if(pua.register_puacb== NULL) { LM_ERR("Could not import register callback\n"); return -1; } bind_usrloc = (bind_usrloc_t)find_export("ul_bind_usrloc", 1, 0); if (!bind_usrloc) { LM_ERR("Can't bind usrloc\n"); return -1; } if (bind_usrloc(&ul) < 0) { LM_ERR("Can't bind usrloc\n"); return -1; } if(ul.register_ulcb == NULL) { LM_ERR("Could not import ul_register_ulcb\n"); return -1; } if(ul.register_ulcb(UL_CONTACT_INSERT, bla_cb , 0)< 0) { LM_ERR("can not register callback for" " insert\n"); return -1; } if(ul.register_ulcb(UL_CONTACT_EXPIRE, bla_cb, 0)< 0) { LM_ERR("can not register callback for" " insert\n"); return -1; } if(ul.register_ulcb(UL_CONTACT_UPDATE, bla_cb, 0)< 0) { LM_ERR("can not register callback for" " update\n"); return -1; } if(ul.register_ulcb(UL_CONTACT_DELETE, bla_cb, 0)< 0) { LM_ERR("can not register callback for" " delete\n"); return -1; } return 0; }
int process_contact(udomain_t * _d, int expires, str contact_uri, int contact_state) { char bufport[5], *rest, *sep, *val, *port, *trans; pcontact_t* pcontact; struct pcontact_info ci; struct sip_uri puri, uri; unsigned int received_proto, received_port_len; int local_time_now, rest_len, val_len, has_alias; int ret = RESULT_CONTACTS_FOUND; pcscf_act_time(); local_time_now = time_now; has_alias = 0; //get contact //if does not exist then add it //if it does exist check if state it terminated - if so delete it, if not update it memset(&ci, 0, sizeof (struct pcontact_info)); ci.num_public_ids = 0; ci.num_service_routes = 0; LM_DBG("Processing contact using contact from NOTIFY [%.*s]\n", contact_uri.len, contact_uri.s); if (parse_uri(contact_uri.s, contact_uri.len, &puri) < 0) { LM_DBG("Error parsing Contact URI <%.*s>\n", contact_uri.len, contact_uri.s); return RESULT_ERROR; } expires = local_time_now + expires; //turn expires into correct time since epoch format LM_DBG("Changed expires to format time since the epoch: %d", expires); ci.expires = expires; ci.reg_state = PCONTACT_REGISTERED; ul.lock_udomain(_d, &puri.host, puri.port_no, puri.proto); ci.aor = contact_uri; ci.via_host = puri.host; ci.via_prot = puri.proto; ci.via_port = puri.port_no; /* parse the uri in the NOTIFY */ if (parse_uri(contact_uri.s, contact_uri.len, &uri) != 0) { LM_ERR("Unable to parse contact in SIP notify [%.*s]\n", contact_uri.len, contact_uri.s); return RESULT_ERROR; } /*check for alias - NAT */ rest = uri.sip_params.s; rest_len = uri.sip_params.len; while (rest_len >= ALIAS_LEN) { if (strncmp(rest, ALIAS, ALIAS_LEN) == 0) { has_alias = 1; break; } sep = memchr(rest, 59 /* ; */, rest_len); if (sep == NULL) { LM_DBG("no alias param\n"); break; } else { rest_len = rest_len - (sep - rest + 1); rest = sep + 1; } } if (has_alias) { val = rest + ALIAS_LEN; val_len = rest_len - ALIAS_LEN; port = memchr(val, 126 /* ~ */, val_len); if (port == NULL) { LM_ERR("no '~' in alias param value\n"); return RESULT_ERROR; } port++; // received_port = atoi(port); trans = memchr(port, 126 /* ~ */, val_len - (port - val)); if (trans == NULL) { LM_ERR("no second '~' in alias param value\n"); return RESULT_ERROR; } received_port_len = trans - port; trans = trans + 1; received_proto = *trans - 48 /* char 0 */; memcpy(bufport, port, received_port_len); bufport[received_port_len]=0; ci.received_host.s = val; ci.received_host.len = port - val - 1; LM_DBG("Setting received host in search to [%.*s]\n", ci.received_host.len, ci.received_host.s); ci.received_port = atoi(bufport); LM_DBG("Setting received port in search to %d\n", ci.received_port); ci.received_proto = received_proto; LM_DBG("Setting received proto in search to %d\n", ci.received_proto); ci.searchflag = SEARCH_RECEIVED; } else { LM_DBG("Contact in NOTIFY does not have an alias....\n"); } if (ul.get_pcontact(_d, &ci, &pcontact) != 0) { //contact does not exist if (contact_state == STATE_TERMINATED) { LM_DBG("This contact: <%.*s> is in state terminated and is not in usrloc, ignore\n", contact_uri.len, contact_uri.s); ret = RESULT_CONTACTS_FOUND; goto done; } LM_WARN("This contact: <%.*s> is in state active and is not in usrloc - must be another contact on a different P so going to ignore\n", contact_uri.len, contact_uri.s); // LM_DBG("This contact: <%.*s> is in state active and is not in usrloc so adding it to usrloc, expires: %d which is in %d seconds\n", contact_uri.len, contact_uri.s, expires, expires-local_time_now); // if (ul.insert_pcontact(_d, &contact_uri, &ci, &pcontact) != 0) { // LM_ERR("Failed inserting new pcontact\n"); // ret = RESULT_ERROR; // goto done; // } else { // //register for callbacks on this contact so we can send PUBLISH to SCSCF should status change // LM_DBG("registering for UL callback\n"); // ul.register_ulcb(pcontact, PCSCF_CONTACT_DELETE | PCSCF_CONTACT_EXPIRE, callback_pcscf_contact_cb, NULL); // } } else {//contact exists if (contact_state == STATE_TERMINATED) { //delete contact LM_DBG("This contact <%.*s> is in state terminated and is in usrloc so removing it from usrloc\n", contact_uri.len, contact_uri.s); if (ul.delete_pcontact(_d, pcontact) != 0) { LM_DBG("failed to delete pcscf contact <%.*s> - not a problem this may have been removed by de registration", contact_uri.len, contact_uri.s); } /*TODO_LATEST - put this back */ } else {//state is active //update this contact LM_DBG("This contact: <%.*s> is in state active and is in usrloc so just updating - old expires: %li, new expires: %i which is in %i seconds\n", contact_uri.len, contact_uri.s, pcontact->expires, expires, expires - local_time_now); if (ul.update_pcontact(_d, &ci, pcontact) != 0) { LM_ERR("failed to update pcscf contact\n"); ret = RESULT_ERROR; goto done; } pcontact->expires = expires; } } done: ul.unlock_udomain(_d, &puri.host, puri.port_no, puri.proto); return ret; }