Пример #1
0
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;
}
Пример #2
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;
}
Пример #3
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;
}
Пример #4
0
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;

}
Пример #5
0
/**
 * 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;
}
Пример #6
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;
}
Пример #7
0
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;
}
Пример #8
0
/*! \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;
}
Пример #9
0
/*!
 * \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;
}
Пример #10
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;
}
Пример #11
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;
	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;
}
Пример #12
0
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;
}
Пример #13
0
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;
}
Пример #14
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;
}
Пример #15
0
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;
}
Пример #16
0
/**
 * 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;
}
Пример #17
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;
}
Пример #18
0
/**
 * 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;
	
}
Пример #19
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 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;
}