static int ws_rpc_add_node(rpc_t* rpc, void* ctx, void* ih, ws_connection_t *wsc) { int interval; char *src_proto, *dst_proto, *pong, *sub_protocol; char src_ip[IP6_MAX_STR_SIZE + 1], dst_ip[IP6_MAX_STR_SIZE + 1]; struct tcp_connection *con = tcpconn_get(wsc->id, 0, 0, 0, 0); char rplbuf[512]; if (con) { src_proto = (con->rcv.proto== PROTO_WS) ? "ws" : "wss"; memset(src_ip, 0, IP6_MAX_STR_SIZE + 1); ip_addr2sbuf(&con->rcv.src_ip, src_ip, IP6_MAX_STR_SIZE); dst_proto = (con->rcv.proto == PROTO_WS) ? "ws" : "wss"; memset(dst_ip, 0, IP6_MAX_STR_SIZE + 1); ip_addr2sbuf(&con->rcv.dst_ip, dst_ip, IP6_MAX_STR_SIZE); pong = wsc->awaiting_pong ? "awaiting Pong, " : ""; interval = (int)time(NULL) - wsc->last_used; if (wsc->sub_protocol == SUB_PROTOCOL_SIP) sub_protocol = "sip"; else if (wsc->sub_protocol == SUB_PROTOCOL_MSRP) sub_protocol = "msrp"; else sub_protocol = "**UNKNOWN**"; if (snprintf(rplbuf, 512, "%d: %s:%s:%hu -> %s:%s:%hu (state: %s" ", %s last used %ds ago" ", sub-protocol: %s)", wsc->id, src_proto, strlen(src_ip) ? src_ip : "*", con->rcv.src_port, dst_proto, strlen(dst_ip) ? dst_ip : "*", con->rcv.dst_port, wsconn_state_str[wsc->state], pong, interval, sub_protocol) < 0) { tcpconn_put(con); rpc->fault(ctx, 500, "Failed to print connection details"); return -1; } if (rpc->array_add(ih, "s", rplbuf)<0) { tcpconn_put(con); rpc->fault(ctx, 500, "Failed to add to response"); return -1; } tcpconn_put(con); return 1; } else return 0; }
static int add_node(struct mi_root *tree, ws_connection_t *wsc) { int interval; char *src_proto, *dst_proto, *pong, *sub_protocol; char src_ip[IP6_MAX_STR_SIZE + 1], dst_ip[IP6_MAX_STR_SIZE + 1]; struct tcp_connection *con = tcpconn_get(wsc->id, 0, 0, 0, 0); if (con) { src_proto = (con->rcv.proto== PROTO_WS) ? "ws" : "wss"; memset(src_ip, 0, IP6_MAX_STR_SIZE + 1); ip_addr2sbuf(&con->rcv.src_ip, src_ip, IP6_MAX_STR_SIZE); dst_proto = (con->rcv.proto == PROTO_WS) ? "ws" : "wss"; memset(dst_ip, 0, IP6_MAX_STR_SIZE + 1); ip_addr2sbuf(&con->rcv.dst_ip, dst_ip, IP6_MAX_STR_SIZE); pong = wsc->awaiting_pong ? "awaiting Pong, " : ""; interval = (int)time(NULL) - wsc->last_used; if (wsc->sub_protocol == SUB_PROTOCOL_SIP) sub_protocol = "sip"; else if (wsc->sub_protocol == SUB_PROTOCOL_MSRP) sub_protocol = "msrp"; else sub_protocol = "**UNKNOWN**"; if (addf_mi_node_child(&tree->node, 0, 0, 0, "%d: %s:%s:%hu -> %s:%s:%hu (state: %s" ", %s last used %ds ago" ", sub-protocol: %s)", wsc->id, src_proto, strlen(src_ip) ? src_ip : "*", con->rcv.src_port, dst_proto, strlen(dst_ip) ? dst_ip : "*", con->rcv.dst_port, wsconn_state_str[wsc->state], pong, interval, sub_protocol) == 0) { tcpconn_put(con); return -1; } tcpconn_put(con); return 1; } else return 0; }
/** * 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; }
static void dmq_rpc_list_nodes(rpc_t *rpc, void *c) { void *h; dmq_node_t* cur = node_list->nodes; char ip[IP6_MAX_STR_SIZE + 1]; while(cur) { memset(ip, 0, IP6_MAX_STR_SIZE + 1); ip_addr2sbuf(&cur->ip_address, ip, IP6_MAX_STR_SIZE); if (rpc->add(c, "{", &h) < 0) goto error; if (rpc->struct_add(h, "SSsddd", "host", &cur->uri.host, "port", &cur->uri.port, "resolved_ip", ip, "status", cur->status, "last_notification", cur->last_notification, "local", cur->local) < 0) goto error; cur = cur->next; } return; error: LM_ERR("Failed to add item to RPC response\n"); return; }
/** * 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; }
/** * 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; }
int checkcontact(struct sip_msg* _m, pcontact_t * c) { int security_server_port = -1; str received_host = {0, 0}; char srcip[50]; LM_DBG("Port %d (search %d), Proto %d (search %d), reg_state %s (search %s)\n", c->received_port, _m->rcv.src_port, c->received_proto, _m->rcv.proto, reg_state_to_string(c->reg_state), reg_state_to_string(PCONTACT_REGISTERED) ); 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 ((ignore_reg_state || (c->reg_state == PCONTACT_REGISTERED)) && (ignore_contact_rxport_check || (c->received_port == _m->rcv.src_port) || (security_server_port == _m->rcv.src_port)) && (ignore_contact_rxport_check||(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)) { LM_DBG("check contact passed\n"); return 0; } } } LM_DBG("check contact failed\n"); return 1; }
/*! \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; }
/*! * \brief Perform outbound processing - force local socket and set destination URI * \param _m SIP message * \param flow_token string containing the flow-token extracted from the Route: header * \param dst_uri string to write the destination URI to (extracted from flow-token) * \return -1 on error, 0 when outbound not in use, 1 when outbound in use */ static inline int process_outbound(struct sip_msg *_m, str flow_token) { int ret; struct receive_info *rcv = NULL; struct socket_info *si; str dst_uri; if (!rr_obb.decode_flow_token) return 0; ret = rr_obb.decode_flow_token(_m, &rcv, flow_token); if (ret == -2) { LM_DBG("no flow token found - outbound not in use\n"); return 0; } else if (ret == -1) { LM_INFO("failed to decode flow token\n"); return -1; } else if (!ip_addr_cmp(&rcv->src_ip, &_m->rcv.src_ip) || rcv->src_port != _m->rcv.src_port) { LM_DBG("\"incoming\" request found. Using flow-token for" "routing\n"); /* First, force the local socket */ si = find_si(&rcv->dst_ip, rcv->dst_port, rcv->proto); if (si) set_force_socket(_m, si); else { LM_INFO("cannot find socket from flow-token\n"); return -1; } /* Second, override the destination URI */ dst_uri.s = uri_buf; dst_uri.len = 0; dst_uri.len += snprintf(dst_uri.s + dst_uri.len, MAX_ROUTE_URI_LEN - dst_uri.len, "sip:%s", rcv->src_ip.af == AF_INET6 ? "[" : ""); dst_uri.len += ip_addr2sbuf(&rcv->src_ip, dst_uri.s + dst_uri.len, MAX_ROUTE_URI_LEN - dst_uri.len); dst_uri.len += snprintf(dst_uri.s + dst_uri.len, MAX_ROUTE_URI_LEN - dst_uri.len, "%s:%d;transport=%s", rcv->src_ip.af == AF_INET6 ? "]" : "", rcv->src_port, get_proto_name(rcv->proto)); if (set_dst_uri(_m, &dst_uri) < 0) { LM_ERR("failed to set dst_uri\n"); return -1; } ruri_mark_new(); return 1; } LM_DBG("Not using flow-token for routing\n"); return 0; }
/** * Save contact based on REGISTER request. this will be a pending save, until we receive response * from SCSCF. If no response after pending_timeout seconds, the contacts is removed. Can only be used from REQUEST ROUTE */ int save_pending(struct sip_msg* _m, udomain_t* _d) { contact_body_t* cb = 0; int cexpires = 0; pcontact_t* pcontact; contact_t* c; struct pcontact_info ci; struct via_body* vb; unsigned short port, proto; int_str val; struct sip_uri parsed_received; char srcip[50]; memset(&ci, 0, sizeof(struct pcontact_info)); vb = cscf_get_ue_via(_m); port = vb->port?vb->port:5060; proto = vb->proto; cb = cscf_parse_contacts(_m); if (!cb || (!cb->contacts)) { LM_ERR("No contact headers\n"); goto error; } c = cb->contacts; //TODO: need support for multiple contacts - currently assume one contact //make sure this is not a de-registration int expires_hdr = cscf_get_expires_hdr(_m, 0); if (expires_hdr < 0) { //no global header we have to check the contact expiry if (c && c->expires && c->expires->body.len) { str2int(&(c->expires->body), (unsigned int*) &cexpires); } if (!cexpires){ //assume de-registration LM_DBG("not doing pending reg on de-registration\n"); return 1; } } pcscf_act_time(); int local_time_now = time_now; int expires = calc_contact_expires(c, expires_hdr, local_time_now); if (expires <= 0) { LM_DBG("not doing pending reg on de-registration\n"); return 1; } LM_DBG("Save Pending"); LM_DBG("contact requesting to expire in %d seconds\n", expires-local_time_now); /*populate CI with bare minimum*/ ci.via_host = vb->host; ci.via_port = port; ci.via_prot = proto; ci.aor = c->uri; ci.num_public_ids=0; ci.num_service_routes=0; ci.expires=local_time_now + pending_reg_expires; ci.reg_state=PCONTACT_ANY; ci.searchflag=SEARCH_RECEIVED; //we want to make sure we are very specific with this search to make sure we get the correct contact to put into reg_pending. // Received Info: First try AVP, otherwise simply take the source of the request: memset(&val, 0, sizeof(int_str)); if (rcv_avp_name.n != 0 && search_first_avp(rcv_avp_type, rcv_avp_name, &val, 0) && val.s.len > 0) { if (val.s.len > RECEIVED_MAX_SIZE) { LM_ERR("received too long\n"); goto error; } if (parse_uri(val.s.s, val.s.len, &parsed_received) < 0) { LM_DBG("Error parsing Received URI <%.*s>\n", val.s.len, val.s.s); goto error; } ci.received_host = parsed_received.host; ci.received_port = parsed_received.port_no; ci.received_proto = parsed_received.proto; } else { ci.received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip)); ci.received_host.s = srcip; ci.received_port = _m->rcv.src_port; ci.received_proto = _m->rcv.proto; } // Set to default, if not set: if (ci.received_port == 0) ci.received_port = 5060; ul.lock_udomain(_d, &ci.via_host, ci.via_port, ci.via_prot); if (ul.get_pcontact(_d, &ci, &pcontact) != 0) { //need to insert new contact LM_DBG("Adding pending pcontact: <%.*s>\n", c->uri.len, c->uri.s); ci.reg_state=PCONTACT_REG_PENDING; if (ul.insert_pcontact(_d, &c->uri, &ci, &pcontact) != 0) { LM_ERR("Failed inserting new pcontact\n"); } else { LM_DBG("registering for UL callback\n"); ul.register_ulcb(pcontact, PCSCF_CONTACT_DELETE | PCSCF_CONTACT_EXPIRE | PCSCF_CONTACT_UPDATE, callback_pcscf_contact_cb, NULL); } } else { //contact already exists - update LM_DBG("Contact already exists - not doing anything for now\n"); } ul.unlock_udomain(_d, &ci.via_host, ci.via_port, ci.via_prot); return 1; error: LM_DBG("Error saving pending contact\n"); 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; contact_body_t *b = 0; contact_t *ct; 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 (_m->id != current_msg_id) { current_msg_id = _m->id; c = NULL; if (is_registered_fallback2ip == 2) { LM_DBG("Searching in usrloc for %.*s:%i (Proto %i)\n", received_host.len, received_host.s, _m->rcv.src_port, _m->rcv.proto); 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); } else { if (checkcontact(_m, c) != 0) { c = NULL; } } } if (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, &received_host, _m->rcv.src_port, &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; 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); } else { if (checkcontact(_m, c) != 0) { c = NULL; } } } } asserted_identity = NULL; registration_contact = NULL; if (c) { registration_contact = &c->contact_user; p = c->head; while (p) { if (p->is_default == 1) asserted_identity = &p->public_identity; p = p->next; } } return c; }
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; }
static int fill_contact(struct pcontact_info* ci, struct sip_msg* m) { contact_body_t* cb = NULL; struct via_body* vb = NULL; unsigned short port, proto = 0; struct sip_msg* req = NULL; if(!ci) { LM_ERR("fill_contact() called with null ptr\n"); return -1; } memset(ci, 0, sizeof(struct pcontact_info)); if(m->first_line.type == SIP_REQUEST) { struct sip_uri uri; memset(&uri, 0, sizeof(struct sip_uri)); if(parse_uri(m->first_line.u.request.uri.s, m->first_line.u.request.uri.len, &uri)) { LM_ERR("Can't parse the request URI from first line\n"); return -1; } // populate host,port, aor in CI ci->via_host = uri.host; ci->via_port = uri.port_no ? uri.port_no : 5060; ci->via_prot = proto; ci->aor = m->first_line.u.request.uri; req = m; } else if(m->first_line.type == SIP_REPLY) { cb = cscf_parse_contacts(m); vb = cscf_get_ue_via(m); port = vb->port?vb->port:5060; proto = vb->proto; struct cell *t = tmb.t_gett(); if (!t || t == (void*) -1) { LM_ERR("fill_contact(): Reply without transaction\n"); return -1; } req = t->uas.request; cb = cscf_parse_contacts(req); if (!cb || (!cb->contacts)) { LM_ERR("fill_contact(): No contact headers\n"); return -1; } // populate CI with bare minimum ci->via_host = vb->host; ci->via_port = port; ci->via_prot = proto; ci->aor = cb->contacts->uri; } char* srcip = NULL; if((srcip = pkg_malloc(50)) == NULL) { LM_ERR("Error allocating memory for source IP address\n"); return -1; } ci->received_host.len = ip_addr2sbuf(&req->rcv.src_ip, srcip, 50); ci->received_host.s = srcip; ci->received_port = req->rcv.src_port; ci->received_proto = req->rcv.proto; // Set to default, if not set: if (ci->received_port == 0) ci->received_port = 5060; return 0; }
/** * 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; }
static void tls_list(rpc_t* rpc, void* c) { char buf[128]; char src_ip[IP_ADDR_MAX_STR_SIZE]; char dst_ip[IP_ADDR_MAX_STR_SIZE]; void* handle; char* tls_info; char* state; struct tls_extra_data* tls_d; struct tcp_connection* con; int i, len, timeout; TCPCONN_LOCK; for(i = 0; i < TCP_ID_HASH_SIZE; i++) { for (con = tcpconn_id_hash[i]; con; con = con->id_next) { if (con->rcv.proto != PROTO_TLS) continue; tls_d = con->extra_data; rpc->add(c, "{", &handle); /* tcp data */ if ((len = ip_addr2sbuf(&con->rcv.src_ip, src_ip, sizeof(src_ip))) == 0) BUG("failed to convert source ip"); src_ip[len] = 0; if ((len = ip_addr2sbuf(&con->rcv.dst_ip, dst_ip, sizeof(dst_ip))) == 0) BUG("failed to convert destination ip"); dst_ip[len] = 0; timeout = TICKS_TO_S(con->timeout - get_ticks_raw()); rpc->struct_add(handle, "ddsdsd", "id", con->id, "timeout", timeout, "src_ip", src_ip, "src_port", con->rcv.src_port, "dst_ip", dst_ip, "dst_port", con->rcv.dst_port); if (tls_d) { if(SSL_get_current_cipher(tls_d->ssl)) { tls_info = SSL_CIPHER_description( SSL_get_current_cipher(tls_d->ssl), buf, sizeof(buf)); len = strlen(buf); if (len && buf[len - 1] == '\n') buf[len - 1] = '\0'; } else { tls_info = "unknown"; } /* tls data */ state = "unknown/error"; lock_get(&con->write_lock); switch(tls_d->state) { case S_TLS_NONE: state = "none/init"; break; case S_TLS_ACCEPTING: state = "tls_accept"; break; case S_TLS_CONNECTING: state = "tls_connect"; break; case S_TLS_ESTABLISHED: state = "established"; break; } rpc->struct_add(handle, "sddds", "cipher", tls_info, "ct_wq_size", tls_d->ct_wq? tls_d->ct_wq->queued:0, "enc_rd_buf", tls_d->enc_rd_buf? tls_d->enc_rd_buf->size:0, "flags", tls_d->flags, "state", state ); lock_release(&con->write_lock); } else { rpc->struct_add(handle, "sddds", "cipher", "unknown", "ct_wq_size", 0, "enc_rd_buf", 0, "flags", 0, "state", "pre-init" ); } } } TCPCONN_UNLOCK; }
/** * Updates the registrar with the new values * @param req - the REGISTER request - to extract NAT info * @param rpl - the REGISTER reply - to extract contact info * @param is_star - whether this was a STAR contact header * @param expires_hdr - value of the Expires header * @param public_id - array of public identities attached to this contact * @param public_id_cnt - size of the public_id array * @param service_route - array of Service-Routes * @param service_route_cnt - size of the service_route array * @param requires_nat - if to create pinholes * @returns the maximum expiration time, -1 on error */ static inline int update_contacts(struct sip_msg *req,struct sip_msg *rpl, udomain_t* _d, unsigned char is_star,int expires_hdr, str *public_id,int public_id_cnt,str *service_route,int service_route_cnt, int requires_nat) { int local_time_now, expires=0; struct hdr_field* h; contact_t* c; struct sip_uri puri; struct sip_uri parsed_received; struct pcontact_info ci; pcontact_t* pcontact; char srcip[50]; int_str val; pcscf_act_time(); local_time_now = time_now; if (is_star) { /* first of all, we shouldn't get here... * then, we will update on NOTIFY */ return 0; } // Set the structure to "0", to make sure it's properly initialized memset(&ci, 0, sizeof(struct pcontact_info)); for (h = rpl->contact; h; h = h->next) { if (h->type == HDR_CONTACT_T && h->parsed) for (c = ((contact_body_t*) h->parsed)->contacts; c; c = c->next) { expires = calc_contact_expires(c, expires_hdr, local_time_now); if (parse_uri(c->uri.s, c->uri.len, &puri) < 0) { LM_DBG("Error parsing Contact URI <%.*s>\n", c->uri.len, c->uri.s); continue; } //build contact info ci.expires = expires; ci.public_ids = public_id; ci.num_public_ids = public_id_cnt; ci.service_routes = service_route; ci.num_service_routes = service_route_cnt; ci.reg_state = PCONTACT_REGISTERED; ci.received_host.len = 0; ci.received_host.s = 0; ci.received_port = 0; ci.received_proto = 0; // Received Info: First try AVP, otherwise simply take the source of the request: memset(&val, 0, sizeof(int_str)); if (rcv_avp_name.n!=0 && search_first_avp(rcv_avp_type, rcv_avp_name, &val, 0) && val.s.len > 0) { if (val.s.len>RECEIVED_MAX_SIZE) { LM_ERR("received too long\n"); goto error; } if (parse_uri(val.s.s, val.s.len, &parsed_received) < 0) { LM_DBG("Error parsing Received URI <%.*s>\n", val.s.len, val.s.s); continue; } ci.received_host = parsed_received.host; ci.received_port = parsed_received.port_no; ci.received_proto = parsed_received.proto; } else { ci.received_host.len = ip_addr2sbuf(&req->rcv.src_ip, srcip, sizeof(srcip)); ci.received_host.s = srcip; ci.received_port = req->rcv.src_port; ci.received_proto = req->rcv.proto; } // Set to default, if not set: if (ci.received_port == 0) ci.received_port = 5060; ul.lock_udomain(_d, &c->uri); if (ul.get_pcontact(_d, &c->uri, &pcontact) != 0) { //need to insert new contact if ((expires-local_time_now)<=0) { //remove contact - de-register LM_DBG("This is a de-registration for contact <%.*s> but contact is not in usrloc - ignore\n", c->uri.len, c->uri.s); goto next_contact; } LM_DBG("Adding pcontact: <%.*s>, expires: %d which is in %d seconds\n", c->uri.len, c->uri.s, expires, expires-local_time_now); if (ul.insert_pcontact(_d, &c->uri, &ci, &pcontact) != 0) { LM_ERR("Failed inserting new pcontact\n"); } 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); //we also need to subscribe to reg event of this contact at SCSCF } } else { //contact already exists - update LM_DBG("contact already exists and is in state (%d) : [%s]\n",pcontact->reg_state, reg_state_to_string(pcontact->reg_state)); if ((expires-local_time_now)<=0) { //remove contact - de-register LM_DBG("This is a de-registration for contact <%.*s>\n", c->uri.len, c->uri.s); if (ul.delete_pcontact(_d, &c->uri, pcontact) != 0) { LM_ERR("failed to delete pcscf contact <%.*s>\n", c->uri.len, c->uri.s); } } else { //update contact LM_DBG("Updating contact: <%.*s>, old expires: %li, new expires: %i which is in %i seconds\n", c->uri.len, c->uri.s, pcontact->expires-local_time_now, expires, expires-local_time_now); if (ul.update_pcontact(_d, &ci, pcontact) != 0) { LM_ERR("failed to update pcscf contact\n"); } pcontact->expires = expires; } } next_contact: ul.unlock_udomain(_d, &c->uri); } } return 1; error: return 0; }
static int xcaps_get_directory(struct sip_msg *msg, str *user, str *domain, str *directory) { db_key_t qcols[2]; db_val_t qvals[2], *values; db_key_t rcols[3]; db_row_t *rows; db1_res_t* db_res = NULL; int n_qcols = 0, n_rcols = 0; int i, cur_type = 0, cur_pos = 0; int doc_type_col, doc_uri_col, etag_col; str auid_string = {0, 0}; struct hdr_field *hdr = msg->headers; str server_name = {0, 0}; qcols[n_qcols] = &str_username_col; qvals[n_qcols].type = DB1_STR; qvals[n_qcols].nul = 0; qvals[n_qcols].val.str_val = *user; n_qcols++; qcols[n_qcols] = &str_domain_col; qvals[n_qcols].type = DB1_STR; qvals[n_qcols].nul = 0; qvals[n_qcols].val.str_val = *domain; n_qcols++; rcols[doc_type_col = n_rcols++] = &str_doc_type_col; rcols[doc_uri_col = n_rcols++] = &str_doc_uri_col; rcols[etag_col = n_rcols++] = &str_etag_col; if (xcaps_dbf.use_table(xcaps_db, &xcaps_db_table) < 0) { LM_ERR("in use_table-[table]= %.*s\n", xcaps_db_table.len, xcaps_db_table.s); goto error; } if (xcaps_dbf.query(xcaps_db, qcols, 0, qvals, rcols, n_qcols, n_rcols, &str_doc_type_col, &db_res) < 0) { LM_ERR("in sql query\n"); goto error; } if (db_res == NULL) goto error; directory->s = xcaps_buf.s; directory->len = 0; directory->len += snprintf(directory->s + directory->len, xcaps_buf.len - directory->len, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" "<xcap-directory xmlns=\"urn:oma:xml:xdm:xcap-directory\">\r\n"); rows = RES_ROWS(db_res); for (i = 0; i < RES_ROW_N(db_res); i++) { values = ROW_VALUES(&rows[i]); if (cur_type != VAL_INT(&values[doc_type_col])) { if (cur_type != 0) { directory->len += snprintf(directory->s + directory->len, xcaps_buf.len - directory->len, "</folder>\r\n"); } cur_type = VAL_INT(&values[doc_type_col]); memset(&auid_string, 0, sizeof(str)); while(xcaps_auid_list[cur_pos].auid.s != NULL) { if (xcaps_auid_list[cur_pos].type == cur_type) { auid_string.s = xcaps_auid_list[cur_pos].auid.s; auid_string.len = xcaps_auid_list[cur_pos].auid.len; break; } cur_pos++; } if (auid_string.s == NULL) { goto error; } directory->len += snprintf(directory->s + directory->len, xcaps_buf.len - directory->len, "<folder auid=\"%.*s\">\r\n", auid_string.len, auid_string.s); } switch(xcaps_directory_scheme) { case -1: directory->len += snprintf(directory->s + directory->len, xcaps_buf.len - directory->len, "<entry uri=\"%s://", msg->rcv.proto == PROTO_TLS ? "https" : "http"); break; case 0: directory->len += snprintf(directory->s + directory->len, xcaps_buf.len - directory->len, "<entry uri=\"http://"); break; case 1: directory->len += snprintf(directory->s + directory->len, xcaps_buf.len - directory->len, "<entry uri=\"https://"); break; } if (xcaps_directory_hostname.len > 0) { directory->len += snprintf(directory->s + directory->len, xcaps_buf.len - directory->len, "%.*s", xcaps_directory_hostname.len, xcaps_directory_hostname.s); } else { if (parse_headers(msg, HDR_EOH_F, 0) < 0) { LM_ERR("error parsing headers\n"); goto error; } while (hdr != NULL) { if (cmp_hdrname_strzn(&hdr->name, "Host", 4) == 0) { server_name = hdr->body; break; } hdr = hdr->next; } if (server_name.len > 0) { directory->len += snprintf(directory->s + directory->len, xcaps_buf.len - directory->len, "%.*s", server_name.len, server_name.s); } else { server_name.s = pkg_malloc(IP6_MAX_STR_SIZE + 6); server_name.len = ip_addr2sbuf(&msg->rcv.dst_ip, server_name.s, IP6_MAX_STR_SIZE); directory->len += snprintf(directory->s + directory->len, xcaps_buf.len - directory->len, "%.*s:%d", server_name.len, server_name.s, msg->rcv.dst_port); pkg_free(server_name.s); } } directory->len += snprintf(directory->s + directory->len, xcaps_buf.len - directory->len, "%s\" etag=\"%s\"/>\r\n", VAL_STRING(&values[doc_uri_col]), VAL_STRING(&values[etag_col])); } if (cur_type != 0) { directory->len += snprintf(directory->s + directory->len, xcaps_buf.len - directory->len, "</folder>\r\n"); } directory->len += snprintf(directory->s + directory->len, xcaps_buf.len - directory->len, "</xcap-directory>"); if (db_res != NULL) xcaps_dbf.free_result(xcaps_db, db_res); return 0; error: if (db_res != NULL) xcaps_dbf.free_result(xcaps_db, db_res); 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); char srcip[20]; str received_host; // 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); /* 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, &c->aor, &received_host, _m->rcv.src_port); 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, &c->aor, &received_host, _m->rcv.src_port); return 1; error: /* Unlock domain */ ul.unlock_udomain(_d, &c->aor, &received_host, _m->rcv.src_port); return -1; }
/** * 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 srcip[20]; str received_host; 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); 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, &c->aor, &received_host, _m->rcv.src_port); /* 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, &c->aor, &received_host, _m->rcv.src_port); return 1; error: /* Unlock domain */ ul.unlock_udomain(_d, &c->aor, &received_host, _m->rcv.src_port); return -1; }