Example #1
0
int dst_is_blacklisted(struct dest_info* si, struct sip_msg* msg)
{
	int ires;
	struct ip_addr ip;
#ifdef DST_BLACKLIST_HOOKS
	unsigned char err_flags;
	int action;
#endif
	su2ip_addr(&ip, &si->to);

#ifdef DST_BLACKLIST_HOOKS
	err_flags=0;
	if (unlikely((action=(blacklist_run_hooks(&blst_search_cb, si, &err_flags, msg))
					) != DST_BLACKLIST_CONTINUE)){
		if (action==DST_BLACKLIST_DENY)
			return 0;
		else  /* if (action==DST_BLACKLIST_ACCEPT) */
			return err_flags;
	}
#endif
	ires=dst_is_blacklisted_ip(si->proto, &ip, su_getport(&si->to));
#ifdef USE_DST_BLACKLIST_STATS
	if (ires)
		dst_blacklist_stats[process_no].bkl_hit_cnt++;
#endif
	return ires;
}
Example #2
0
static int ki_set_source_address(sip_msg_t *msg, str *saddr)
{
	sr_phostp_t rp;
	union sockaddr_union faddr;
	char cproto;
	int ret;

	if(msg==NULL || saddr==NULL || saddr->len<=0) {
		LM_ERR("bad parameters\n");
		return -1;
	}

	if(parse_protohostport(saddr, &rp)<0) {
		LM_ERR("failed to parse the address [%.*s]\n", saddr->len, saddr->s);
		return -1;
	}

	cproto = (char)rp.proto;
	ret = sip_hostport2su(&faddr, &rp.host, (unsigned short)rp.port, &cproto);
	if(ret!=0) {
		LM_ERR("failed to resolve address [%.*s]\n", saddr->len, saddr->s);
		return -1;
	}

	msg->rcv.src_su=faddr;
	su2ip_addr(&msg->rcv.src_ip, &faddr);
	msg->rcv.src_port=rp.port;

	return 1;
}
Example #3
0
/* 
 * process_stun_msg(): 
 * 			buf - incoming message
 * 			len - length of incoming message
 * 			ri  - information about socket that received a message and 
 *                also information about sender (its IP, port, protocol)
 * 
 * This function ensures processing of incoming message. It's common for both
 * TCP and UDP protocol. There is no other function as an interface.
 * 
 * Return value:	0	if there is no environment error
 * 					-1	if there is some enviroment error such as insufficiency
 * 						of memory
 * 
 */
int process_stun_msg(char* buf, unsigned len, struct receive_info* ri)
{
	struct stun_msg 			msg_req;
	struct stun_msg 			msg_res;
	struct dest_info			dst;
	struct stun_unknown_att*	unknown;
	USHORT_T					error_code;
	 
	memset(&msg_req, 0, sizeof(msg_req));
	memset(&msg_res, 0, sizeof(msg_res));
	
	msg_req.msg.buf.s = buf;
	msg_req.msg.buf.len = len;	
	unknown = NULL;
	error_code = RESPONSE_OK;
	
	if (stun_parse_header(&msg_req, &error_code) != 0) {
		goto error;
	}
	
	if (error_code == RESPONSE_OK) {
		if (stun_parse_body(&msg_req, &unknown, &error_code) != 0) {
			goto error;
		}
	}
	
	if (stun_create_response(&msg_req, &msg_res, ri,  
							unknown, error_code) != 0) {
		goto error;
	}
	
	init_dst_from_rcv(&dst, ri);

#ifdef EXTRA_DEBUG	
	struct ip_addr ip;
	su2ip_addr(&ip, &dst.to);
	LOG(L_DBG, "DEBUG: process_stun_msg: decoded request from (%s:%d)\n", ip_addr2a(&ip), 
		su_getport(&dst.to));
#endif
	
	/* send STUN response */
	if (msg_send(&dst, msg_res.msg.buf.s, msg_res.msg.buf.len) != 0) {
		goto error;
	}
	
#ifdef EXTRA_DEBUG
	LOG(L_DBG, "DEBUG: process_stun_msg: send response\n");
#endif
	clean_memory(&msg_req, &msg_res, unknown);
	return 0;
	
error:
#ifdef EXTRA_DEBUG
	LOG(L_DBG, "DEBUG: process_stun_msg: failed to decode request\n");
#endif
	clean_memory(&msg_req, &msg_res, unknown);
	return FATAL_ERROR;
}
Example #4
0
struct tcp_connection* tcpconn_connect(union sockaddr_union* server, int type)
{
	int s;
	struct socket_info* si;
	union sockaddr_union my_name;
	socklen_t my_name_len;
	struct tcp_connection* con;
	struct ip_addr ip;

	s=socket(AF2PF(server->s.sa_family), SOCK_STREAM, 0);
	if (s==-1){
		LOG(L_ERR, "ERROR: tcpconn_connect: socket: (%d) %s\n",
				errno, strerror(errno));
		goto error;
	}
	if (init_sock_opt(s)<0){
		LOG(L_ERR, "ERROR: tcpconn_connect: init_sock_opt failed\n");
		goto error;
	}
	if (tcp_blocking_connect(s, &server->s, sockaddru_len(*server))<0){
		LOG(L_ERR, "ERROR: tcpconn_connect: tcp_blocking_connect failed\n");
		goto error;
	}
	my_name_len=sizeof(my_name);
	if (getsockname(s, &my_name.s, &my_name_len)!=0){
		LOG(L_ERR, "ERROR: tcp_connect: getsockname failed: %s(%d)\n",
				strerror(errno), errno);
		si=0; /* try to go on */
	}
	su2ip_addr(&ip, &my_name);
#ifdef USE_TLS
	if (type==PROTO_TLS)
		si=find_si(&ip, 0, PROTO_TLS);
	else
#endif
		si=find_si(&ip, 0, PROTO_TCP);

	if (si==0){
		LOG(L_ERR, "ERROR: tcp_connect: could not find corresponding"
				" listening socket, using default...\n");
		if (server->s.sa_family==AF_INET) si=sendipv4_tcp;
#ifdef USE_IPV6
		else si=sendipv6_tcp;
#endif
	}
	con=tcpconn_new(s, server, si, type, S_CONN_CONNECT);
	if (con==0){
		LOG(L_ERR, "ERROR: tcp_connect: tcpconn_new failed, closing the "
				 " socket\n");
		goto error;
	}
	return con;
	/*FIXME: set sock idx! */
error:
	if (s!=-1) close(s); /* close the opened socket */
	return 0;
}
Example #5
0
int proto_sctp_read(struct socket_info *si, int* bytes_read)
{
    struct receive_info ri;
    int len;
#ifdef DYN_BUF
    char* buf;
#else
    static char buf [BUF_SIZE+1];
#endif
    char *tmp;
    unsigned int fromlen;
    struct sctp_sndrcvinfo sinfo;

#ifdef DYN_BUF
    buf=pkg_malloc(BUF_SIZE+1);
    if (buf==0) {
        LM_ERR(" could not allocate receive buffer in pkg memory\n");
        goto error;
    }
#endif
    fromlen=sockaddru_len(si->su);
    len = sctp_recvmsg(si->socket, buf, BUF_SIZE, &ri.src_su.s, &fromlen,
                       &sinfo, 0);
    if (len==-1) {
        if (errno==EAGAIN) {
            LM_DBG("packet with bad checksum received\n");
            return 0;
        }
        if ((errno==EINTR)||(errno==EWOULDBLOCK)|| (errno==ECONNREFUSED))
            return -1;
        LM_ERR("sctp_recvmsg:[%d] %s\n", errno, strerror(errno));
        return -2;
    }

    /* we must 0-term the messages, receive_msg expects it */
    buf[len]=0; /* no need to save the previous char */

    ri.bind_address = si;
    ri.dst_port = si->port_no;
    ri.dst_ip = si->address;
    ri.proto = si->proto;
    ri.proto_reserved1 = ri.proto_reserved2 = 0;

    su2ip_addr(&ri.src_ip, &ri.src_su);
    ri.src_port=su_getport(&ri.src_su);

    if (ri.src_port==0) {
        tmp=ip_addr2a(&ri.src_ip);
        LM_INFO("dropping 0 port packet from %s\n", tmp);
        return 0;
    }

    /* receive_msg must free buf too!*/
    receive_msg(buf, len, &ri);

    return 0;
}
Example #6
0
struct tcp_connection* tcpconn_new(int sock, union sockaddr_union* su,
									struct socket_info* ba, int type, 
									int state)
{
	struct tcp_connection *c;
	
	c=(struct tcp_connection*)shm_malloc(sizeof(struct tcp_connection));
	if (c==0){
		LM_ERR("shared memory allocation failure\n");
		goto error;
	}
	memset(c, 0, sizeof(struct tcp_connection)); /* zero init */
	c->s=sock;
	c->fd=-1; /* not initialized */
	if (lock_init(&c->write_lock)==0){
		LM_ERR("init lock failed\n");
		goto error;
	}
	
	c->rcv.src_su=*su;
	
	c->refcnt=0;
	su2ip_addr(&c->rcv.src_ip, su);
	c->rcv.src_port=su_getport(su);
	c->rcv.bind_address=ba;
	if (ba){
		c->rcv.dst_ip=ba->address;
		c->rcv.dst_port=ba->port_no;
	}
	print_ip("tcpconn_new: new tcp connection to: ", &c->rcv.src_ip, "\n");
	LM_DBG("on port %d, type %d\n", c->rcv.src_port, type);
	init_tcp_req(&c->req);
	c->id=(*connection_id)++;
	c->rcv.proto_reserved1=0; /* this will be filled before receive_message*/
	c->rcv.proto_reserved2=0;
	c->state=state;
	c->extra_data=0;
#ifdef USE_TLS
	if (type==PROTO_TLS){
		if (tls_tcpconn_init(c, sock)==-1) goto error;
	}else
#endif /* USE_TLS*/
	{
		c->type=PROTO_TCP;
		c->rcv.proto=PROTO_TCP;
		c->timeout=get_ticks()+tcp_con_lifetime;
	}
	c->flags|=F_CONN_REMOVED;
	
	tcp_connections_no++;
	return c;
	
error:
	if (c) shm_free(c);
	return 0;
}
Example #7
0
static struct tcp_connection* tcpconn_new(int sock, union sockaddr_union* su,
							struct socket_info* si, int state, int flags)
{
	struct tcp_connection *c;

	c=(struct tcp_connection*)shm_malloc(sizeof(struct tcp_connection));
	if (c==0){
		LM_ERR("shared memory allocation failure\n");
		return 0;
	}
	memset(c, 0, sizeof(struct tcp_connection)); /* zero init */
	c->s=sock;
	c->fd=-1; /* not initialized */
	if (lock_init(&c->write_lock)==0){
		LM_ERR("init lock failed\n");
		goto error0;
	}

	c->rcv.src_su=*su;

	c->refcnt=0;
	su2ip_addr(&c->rcv.src_ip, su);
	c->rcv.src_port=su_getport(su);
	c->rcv.bind_address = si;
	c->rcv.dst_ip = si->address;
	c->rcv.dst_port = si->port_no;
	print_ip("tcpconn_new: new tcp connection to: ", &c->rcv.src_ip, "\n");
	LM_DBG("on port %d, proto %d\n", c->rcv.src_port, si->proto);
	c->id=(*connection_id)++;
	c->rcv.proto_reserved1=0; /* this will be filled before receive_message*/
	c->rcv.proto_reserved2=0;
	c->state=state;
	c->extra_data=0;
	c->type = si->proto;
	c->rcv.proto = si->proto;
	/* start with the default conn lifetime */
	c->lifetime = get_ticks()+tcp_con_lifetime;
	c->flags|=F_CONN_REMOVED|flags;

	if (protos[si->proto].net.conn_init &&
	protos[si->proto].net.conn_init(c)<0) {
		LM_ERR("failed to do proto %d specific init for conn %p\n",
			si->proto,c);
		goto error1;
	}

	tcp_connections_no++;
	return c;

error1:
	lock_destroy(&c->write_lock);
error0:
	shm_free(c);
	return 0;
}
Example #8
0
struct tcp_conn *search_tcp_conn(unsigned int id, union sockaddr_union *to)
{
	struct tcp_conn *conn;
	struct ip_addr ip;
	unsigned short port;
	unsigned int hash;

	port = su_getport(to);
	su2ip_addr( &ip, to);

	/* if an ID is available, search for it */
	if (id!=0) {
		hash = tcp_hash( id, 0);
		lock_get( &hash_id_lock );
		for( conn=hash_id_conns[hash] ; conn ; conn=conn->id_next ) {
			if (conn->id == id) {
				if (conn->state==TCP_CONN_TERM)
					break;
				/* validate the connection with ip and port! */
				if ( ip_addr_cmp(&ip,&conn->rcv.src_ip) &&
				(port==conn->rcv.src_port || port==conn->port_alias) ) {
					conn->ref++;
					lock_release( &hash_id_lock );
					return conn;
				}
				/* conn id failed to match */
				break;
			}
		}
		lock_release( &hash_id_lock );
		/* conn id not found */
	}

	/* search based on destination information (ip and port) */
	hash = tcp_hash(ip.u.addr32[0],port);
	lock_get( &hash_ip_lock );
	for( conn=hash_ip_conns[hash] ; conn ; conn=conn->ip_next ) {
		if ( conn->state!=TCP_CONN_TERM && ip_addr_cmp(&ip,&conn->rcv.src_ip)
		&& (port==conn->rcv.src_port || port==conn->port_alias) ) {
			/* WARNING - take care, this is the only place where both
			 * locks are taken in the same time - be aware of dead-locks! */
			lock_get( &hash_id_lock );
			conn->ref++;
			lock_release( &hash_id_lock );
			lock_release( &hash_ip_lock );
			return conn;
		}
	}
	lock_release( &hash_ip_lock );

	return NULL;
}
Example #9
0
struct socket_info* find_tcp_si(union sockaddr_union* s)
{
	int r;
	struct ip_addr ip;
	
	su2ip_addr(&ip, s);
	for (r=0; r<sock_no; r++)
		if (ip_addr_cmp(&ip, &tcp_info[r].address)){
			/* found it, we use first match */
			return &tcp_info[r];
		}
	return 0; /* no match */
}
Example #10
0
/** add dst to the blacklist, specifying the timeout.
 * @param err_flags - reason (bitmap)
 * @param si - destination (protocol, ip and port)
 * @param msg - sip message that triggered the blacklisting (can be 0 if 
 *               not known)
 * @param timeout - timeout in ticks
 * @return 0 on success, -1 on error
 */
int dst_blacklist_add_to(unsigned char err_flags,  struct dest_info* si,
						struct sip_msg* msg, ticks_t timeout)
{
	struct ip_addr ip;

#ifdef DST_BLACKLIST_HOOKS
	if (unlikely (blacklist_run_hooks(&blst_add_cb, si, &err_flags, msg) ==
					DST_BLACKLIST_DENY))
		return 0;
#endif
	su2ip_addr(&ip, &si->to);
	return dst_blacklist_add_ip(err_flags, si->proto, &ip,
								su_getport(&si->to), timeout);
}
Example #11
0
int pv_get_sndto(struct sip_msg *msg, pv_param_t *param,
		pv_value_t *res)
{
	struct onsend_info* snd_inf;
	struct ip_addr ip;
	str s;

	snd_inf=get_onsend_info();
	if (! likely(snd_inf && snd_inf->send_sock))
		return pv_get_null(msg, param, res);

	switch(param->pvn.u.isname.name.n)
	{
		case 1: /* af */
			return pv_get_uintval(msg, param, res,
					(int)snd_inf->send_sock->address.af);
		case 2: /* port */
			return pv_get_uintval(msg, param, res,
					(int)su_getport(snd_inf->to));
		case 3: /* proto */
			return pv_get_uintval(msg, param, res,
					(int)snd_inf->send_sock->proto);
		case 4: /* buf */
			s.s   = snd_inf->buf;
			s.len = snd_inf->len;
			return pv_get_strval(msg, param, res, &s);
		case 5: /* len */
			return pv_get_uintval(msg, param, res,
					(int)snd_inf->len);
		case 6: /* sproto */
			if(get_valid_proto_string((int)snd_inf->send_sock->proto,
						0, 0, &s)<0)
				return pv_get_null(msg, param, res);
			return pv_get_strval(msg, param, res, &s);
		default:
			/* 0 - ip */
			su2ip_addr(&ip, snd_inf->to);
			s.s = ip_addr2a(&ip);
			s.len = strlen(s.s);
			return pv_get_strval(msg, param, res, &s);
	}

	return 0;
}
Example #12
0
/** add dst to the blacklist, specifying the timeout.
 * (like @function dst_blacklist_add_to)= above, but uses 
 * (proto, sockaddr_union) instead of struct dest_info)
 */
int dst_blacklist_su_to(unsigned char err_flags, unsigned char proto,
							union sockaddr_union* dst,
							struct sip_msg* msg, ticks_t timeout)
{
	struct ip_addr ip;
#ifdef DST_BLACKLIST_HOOKS
	struct dest_info si;
	
	init_dest_info(&si);
	si.to=*dst;
	si.proto=proto;
	if (unlikely (blacklist_run_hooks(&blst_add_cb, &si, &err_flags, msg) ==
					DST_BLACKLIST_DENY))
		return 0;
#endif
	su2ip_addr(&ip, dst);
	return dst_blacklist_add_ip(err_flags, proto, &ip,
								su_getport(dst), timeout);
}
Example #13
0
/* returns 1 if the entry was deleted, 0 if not found */
int dst_blacklist_del(struct dest_info* si, struct sip_msg* msg)
{
	unsigned short hash;
	struct ip_addr ip;
	ticks_t now;
	int ret;
	unsigned short port;
	
	ret=0;
	su2ip_addr(&ip, &si->to);
	port=su_getport(&si->to);
	now=get_ticks_raw();
	hash=dst_blst_hash_no(si->proto, &ip, port);
	if (unlikely(dst_blst_hash[hash].first)){
		LOCK_BLST(hash);
			ret=_dst_blacklist_del(hash, &ip, si->proto, port, now);
		UNLOCK_BLST(hash);
	}
	return ret;
}
Example #14
0
/*! \brief return a socket_info_pointer to the sending socket
 * \note As opposed to
 * get_send_socket(), which returns process's default socket, get_out_socket
 * attempts to determine the outbound interface which will be used;
 * it creates a temporary connected socket to determine it; it will
 * be very likely noticeably slower, but it can deal better with
 * multihomed hosts
 */
struct socket_info* get_out_socket(union sockaddr_union* to, int proto)
{
	int temp_sock;
	socklen_t len;
	union sockaddr_union from; 
	struct socket_info* si;
	struct ip_addr ip;

	if (proto!=PROTO_UDP) {
		LM_CRIT("can only be called for UDP\n");
		return 0;
	}
	
	temp_sock=socket(to->s.sa_family, SOCK_DGRAM, 0 );
	if (temp_sock==-1) {
		LM_ERR("socket() failed: %s\n", strerror(errno));
		return 0;
	}
	if (connect(temp_sock, &to->s, sockaddru_len(*to))==-1) {
		LM_ERR("connect failed: %s\n", strerror(errno));
		goto error;
	}
	len=sizeof(from);
	if (getsockname(temp_sock, &from.s, &len)==-1) {
		LM_ERR("getsockname failed: %s\n", strerror(errno));
		goto error;
	}
	su2ip_addr(&ip, &from);
	si=find_si(&ip, 0, proto);
	if (si==0) goto error;
	close(temp_sock);
	LM_DBG("socket determined: %p\n", si );
	return si;
error:
	LM_ERR("no socket found\n");
	close(temp_sock);
	return 0;
}
Example #15
0
static int add_node(clusterer_node_t **nodes, table_entry_value_t *head, int proto)
{
	clusterer_node_t *new_node = NULL;
	struct ip_addr ip;

	new_node = pkg_malloc(sizeof *new_node);
	if (!new_node) {
		LM_ERR("no more pkg memory\n");
		goto error;
	}

	new_node->next = NULL;
	new_node->description.s = NULL;
	new_node->machine_id = head->machine_id;
	new_node->state = head->state;
	new_node->proto = proto;

	memcpy(&new_node->addr, &head->addr, sizeof(head->addr));
	new_node->description.s = pkg_malloc(head->description.len * sizeof(char));
	if (!new_node->description.s) {
		LM_ERR("no more pkg memory\n");
		goto error;
	}

	memcpy(new_node->description.s, head->description.s, head->description.len);

	su2ip_addr(&ip, &new_node->addr);
	new_node->description.len = head->description.len;
	if (*nodes)
		new_node->next = *nodes;

	*nodes = new_node;
	return 0;
error:
	free_node(new_node);
	return -1;
}
Example #16
0
int parsing_hepv3_message(char *buf, unsigned int len) {

	union sockaddr_union from;
	union sockaddr_union to;
        struct receive_info ri;
	char *tmp;
	struct ip_addr dst_ip, src_ip;
	struct socket_info* si = 0;
	int tmp_len, i;
	char *payload = NULL;
	unsigned int payload_len = 0;
        struct hep_chunk *chunk;	
        struct hep_generic_recv *hg;
        int totelem = 0;
        int chunk_vendor=0, chunk_type=0, chunk_length=0;
        int total_length = 0;


	hg = (struct hep_generic_recv*)pkg_malloc(sizeof(struct hep_generic_recv));
	if(hg==NULL) {
	        LM_ERR("no more pkg memory left for hg\n");
	        return -1;
        }
	                                                 		
	memset(hg, 0, sizeof(struct hep_generic_recv));

	
        memset(heptime, 0, sizeof(struct hep_timehdr));	
	        

	/* HEADER */
	hg->header  = (hep_ctrl_t *) (buf);

	/*Packet size */
	total_length = ntohs(hg->header->length);

	ri.src_port = 0;
	ri.dst_port = 0;
	dst_ip.af = 0;
        src_ip.af = 0;
                	        
	payload = NULL;
	correlation_id = NULL;
	authkey = NULL;

	i = sizeof(hep_ctrl_t);	        
	        
	while(i < total_length) {
                
	        /*OUR TMP DATA */                                  
                tmp = buf+i;

                chunk = (struct hep_chunk*) tmp;
                             
                chunk_vendor = ntohs(chunk->vendor_id);                             
                chunk_type = ntohs(chunk->type_id);
                chunk_length = ntohs(chunk->length);
                       


                /* if chunk_length */
                if(chunk_length == 0) {
                        /* BAD LEN we drop this packet */
                        goto error;
                }

                /* SKIP not general Chunks */
                if(chunk_vendor != 0) {
                        i+=chunk_length;
                }
                else {                                                                                                                               
                        switch(chunk_type) {
                                     
                                case 0:
                                        goto error;
                                        break;
                                     
                                case 1:                                                                          
                                        hg->ip_family  = (hep_chunk_uint8_t *) (tmp);
                                        i+=chunk_length;
                                        totelem++;
                                        break;
                                case 2:
                                        hg->ip_proto  = (hep_chunk_uint8_t *) (tmp);
                                        i+=chunk_length;
                                        totelem++;
                                        break;                                                     
                                case 3:
                                        hg->hep_src_ip4  = (hep_chunk_ip4_t *) (tmp);
                                        i+=chunk_length;
                                        src_ip.af=AF_INET;
				        src_ip.len=4;
				        src_ip.u.addr32[0] = hg->hep_src_ip4->data.s_addr;
				        totelem++;
				        break;
                                case 4:
                                        hg->hep_dst_ip4  = (hep_chunk_ip4_t *) (tmp);
                                        i+=chunk_length;                                                     
					dst_ip.af=AF_INET;
				        dst_ip.len=4;
				        dst_ip.u.addr32[0] = hg->hep_dst_ip4->data.s_addr;
                                        totelem++;

                                        break;
                                case 5:
                                        hg->hep_src_ip6  = (hep_chunk_ip6_t *) (tmp);
                                        i+=chunk_length;
                                        src_ip.af=AF_INET6;
				        src_ip.len=16;
				        memcpy(src_ip.u.addr, &hg->hep_src_ip6->data, 16);
				        totelem++;
                                        break;
                                case 6:
                                        hg->hep_dst_ip6  = (hep_chunk_ip6_t *) (tmp);
                                        i+=chunk_length;                                                     
                                        dst_ip.af=AF_INET6;
				        dst_ip.len=16;
				        memcpy(dst_ip.u.addr, &hg->hep_dst_ip6->data, 16);
				        totelem++;
                                        break;
        
                                case 7:
                                        hg->src_port  = (hep_chunk_uint16_t *) (tmp);
                                        ri.src_port = ntohs(hg->src_port->data);
                                        i+=chunk_length;                      
                                        totelem++;
                                        break;

                                case 8:
                                        hg->dst_port  = (hep_chunk_uint16_t *) (tmp);
                                        ri.dst_port = ntohs(hg->dst_port->data);
                                        i+=chunk_length;
                                        totelem++;
                                        break;
                                case 9:
                                        hg->time_sec  = (hep_chunk_uint32_t *) (tmp);
                                        hg->time_sec->data = ntohl(hg->time_sec->data);
                                        heptime->tv_sec = hg->time_sec->data;
                                        i+=chunk_length;
                                        totelem++;
                                        break;                                                     
                                                     
                                case 10:
                                        hg->time_usec  = (hep_chunk_uint32_t *) (tmp);
                                        hg->time_usec->data = ntohl(hg->time_usec->data);
                                        heptime->tv_usec = hg->time_usec->data;
                                        i+=chunk_length;
                                        totelem++;
                                        break;      

                                case 11:
                                        hg->proto_t  = (hep_chunk_uint8_t *) (tmp);
                                        i+=chunk_length;
                                        totelem++;
                                        break;                                                                                                                                                         

                                case 12:
                                        hg->capt_id  = (hep_chunk_uint32_t *) (tmp);
                                        i+=chunk_length;
                                        heptime->captid = ntohs(hg->capt_id->data);
                                        totelem++;
                                        break;

                                case 13:
                                        hg->keep_tm  = (hep_chunk_uint16_t *) (tmp);
                                        i+=chunk_length;
                                        break;                                                     

                                case 14:
                                        authkey = (char *) tmp + sizeof(hep_chunk_t);
                                        i+=chunk_length;                                                                             
                                        break;
                                                     
                                case 15:
                                        hg->payload_chunk  = (hep_chunk_t *) (tmp);
                                        payload = (char *) tmp+sizeof(hep_chunk_t);
                                        payload_len = chunk_length - sizeof(hep_chunk_t);
                                        i+=chunk_length;
                                        totelem++;
                                        break;
                                case 17:
                                
                                        correlation_id = (char *) tmp + sizeof(hep_chunk_t);
                                        i+=chunk_length;                                                                            
					break;

                                                     
                                default:
                                        i+=chunk_length;
                                        break;
                        }                                        
                }
        }	                                                                                                          
                        
        /* CHECK how much elements */
        if(totelem < 9) {                        
                LM_ERR("Not all elements [%d]\n", totelem);                        
                goto done;
        }                 

        if ( dst_ip.af == 0 || src_ip.af == 0)  {
                LM_ERR("NO IP's set\n");
                goto done;
        }

                        
        ip_addr2su(&to, &dst_ip, ri.dst_port);
        ip_addr2su(&from, &src_ip, ri.src_port);
                        
        ri.src_su=from;
        su2ip_addr(&ri.src_ip, &from);
        su2ip_addr(&ri.dst_ip, &to);

	if(hg->ip_proto->data == IPPROTO_TCP) ri.proto=PROTO_TCP;
	else if(hg->ip_proto->data == IPPROTO_UDP) ri.proto=PROTO_UDP;

	/* a little bit memory */
        si=(struct socket_info*) pkg_malloc(sizeof(struct socket_info));
        if (si==0) {
                LOG(L_ERR, "ERROR: new_sock_info: memory allocation error\n");
                goto error;
        }

	memset(si, 0, sizeof(struct socket_info));
        si->address = ri.dst_ip;
        si->socket=-1;

        /* set port & proto */
        si->port_no = ri.dst_port;

        if(hg->ip_proto->data == IPPROTO_TCP) si->proto=PROTO_TCP;
        else if(hg->ip_proto->data == IPPROTO_UDP) si->proto=PROTO_UDP;

        si->flags=0;
        si->addr_info_lst=0;

        si->address_str.s = ip_addr2a(&si->address);;
        si->address_str.len = strlen(si->address_str.s);                                                

        si->port_no_str.s = int2str(si->port_no, &tmp_len);
        si->port_no_str.len = tmp_len;
	si->address_str.len = strlen(si->address_str.s);

        si->name.len = si->address_str.len;
        si->name.s = si->address_str.s;
        ri.bind_address=si;


	/*TIME*/ 
        heptime->tv_sec = hg->time_sec->data;
        heptime->tv_usec = hg->time_usec->data;
        heptime->captid = ntohs(hg->capt_id->data);
          

        if(payload != NULL ) {
                /* and now recieve message */
                if (hg->proto_t->data == 5) receive_logging_json_msg(payload, payload_len, hg, "rtcp_capture");
                else if (hg->proto_t->data == 32) receive_logging_json_msg(payload, payload_len, hg, "report_capture");
                else if (hg->proto_t->data == 99) receive_logging_json_msg(payload, payload_len, hg, "report_capture");
                else if (hg->proto_t->data == 100) receive_logging_json_msg(payload, payload_len, hg, "logs_capture");
                else receive_msg(payload, payload_len, &ri);
        }

done:
        if(si) pkg_free(si);
        if(hg) pkg_free(hg);                     

        return 1;
        
error:

        if(si) pkg_free(si);
        if(hg) pkg_free(hg);
                
        return -1;           
        
}
Example #17
0
int
add_dst(
	rt_data_t *r,
	/* id */
	char *id,
	/* ip address */
	char* ip,
	/* strip len */
	int strip,
	/* pri prefix */
	char* pri,
	/* dst type*/
	int type,
	/* dst attrs*/
	char* attrs,
	/* probe_mode */
	int probing,
	/* socket */
	struct socket_info *sock,
	/* state */
	int state
	)
{
	static unsigned id_counter = 0;
	pgw_t *pgw=NULL, *tmp=NULL;
	struct sip_uri uri;
	int l_ip,l_pri,l_attrs,l_id;
#define GWABUF_MAX_SIZE	512
	char gwabuf[GWABUF_MAX_SIZE];
	union sockaddr_union sau;
	struct proxy_l *proxy;
	unsigned int sip_prefix;
	str gwas;

	if (NULL==r || NULL==ip) {
		LM_ERR("invalid parametres\n");
		goto err_exit;
	}

	l_id = strlen(id);
	l_ip = strlen(ip);
	l_pri = pri?strlen(pri):0;
	l_attrs = attrs?strlen(attrs):0;

	/* check if GW address starts with 'sip' or 'sips' */
	if (l_ip>5) {
		if ( strncasecmp("sip:", ip, 4)==0)
			sip_prefix = 4;
		else if ( strncasecmp("sips:", ip, 5)==0)
			sip_prefix = 5;
		else sip_prefix = 0;
	} else
		sip_prefix = 0;

	if( sip_prefix==0 ) {
		if(l_ip+4>=GWABUF_MAX_SIZE) {
			LM_ERR("GW address (%d) longer "
				"than %d\n",l_ip+4,GWABUF_MAX_SIZE);
			goto err_exit;
		}
		memcpy(gwabuf, "sip:", 4);
		memcpy(gwabuf+4, ip, l_ip);
		gwas.s = gwabuf;
		gwas.len = 4+l_ip;
	} else {
		gwas.s = ip;
		gwas.len = l_ip;
	}
	/* parse the normalized address as a SIP URI */
	memset(&uri, 0, sizeof(struct sip_uri));
	if(parse_uri(gwas.s, gwas.len, &uri)!=0) {
		LM_ERR("invalid uri <%.*s>\n",
			gwas.len, gwas.s);
		goto err_exit;
	}
	/* update the sip_prefix to skip to domain part */
	if (uri.user.len)
		sip_prefix += uri.host.s - uri.user.s;

	/* allocate new structure */
	pgw = (pgw_t*)shm_malloc(sizeof(pgw_t) + l_id + (l_ip-sip_prefix) +
		l_pri + l_attrs);
	if (NULL==pgw) {
		LM_ERR("no more shm mem (%u)\n",
			(unsigned int)(sizeof(pgw_t)+l_id+l_ip-sip_prefix+l_pri +l_attrs));
		goto err_exit;
	}
	memset(pgw,0,sizeof(pgw_t));

	/* set probing related flags  */
	switch(probing) {
		case 0:
			break;
		case 1:
			pgw->flags |=  DR_DST_PING_DSBL_FLAG;
			break;
		case 2:
			pgw->flags |=  DR_DST_PING_PERM_FLAG;
			break;
		default:
			goto err_exit;
	}

	/* set state related flags  */
	switch(state) {
		case 0:
			break;
		case 1:
			pgw->flags |=  DR_DST_STAT_DSBL_FLAG|DR_DST_STAT_NOEN_FLAG;
			break;
		case 2:
			pgw->flags |=  DR_DST_STAT_DSBL_FLAG;
			break;
		default:
			goto err_exit;
	}

	/* set outbound socket */
	pgw->sock = sock;

	pgw->_id = ++id_counter;

	pgw->id.len= l_id;
	pgw->id.s = (char*)(pgw+1);
	memcpy(pgw->id.s, id, l_id);

	pgw->ip_str.len= l_ip-sip_prefix;
	pgw->ip_str.s = (char*)(pgw+1)+l_id;
	memcpy(pgw->ip_str.s, ip+sip_prefix, l_ip-sip_prefix);

	if (pri) {
		pgw->pri.len = l_pri;
		pgw->pri.s = ((char*)(pgw+1))+l_id+l_ip-sip_prefix;
		memcpy(pgw->pri.s, pri, l_pri);
	}
	if (attrs) {
		pgw->attrs.len = l_attrs;
		pgw->attrs.s = ((char*)(pgw+1))+l_id+l_ip-sip_prefix+l_pri;
		memcpy(pgw->attrs.s, attrs, l_attrs);
	}
	pgw->strip = strip;
	pgw->type = type;

	/* add address in the global list of destinations/GWs */
	proxy = mk_proxy(&uri.host,uri.port_no,uri.proto,(uri.type==SIPS_URI_T));
	if (proxy==NULL) {
		if(dr_force_dns) {
			LM_ERR("cannot resolve <%.*s>\n",
				uri.host.len, uri.host.s);
			goto err_exit;
		} else {
			LM_DBG("cannot resolve <%.*s> - won't be used"
					" by is_from_gw()\n", uri.host.len, uri.host.s);
			goto done;
		}
	}
	hostent2ip_addr( &pgw->ips[0], &proxy->host, proxy->addr_idx);
	pgw->ports[0] = proxy->port;
	LM_DBG("first gw ip addr [%s]\n", ip_addr2a(&pgw->ips[0]));

	pgw->ips_no = 1;

	while (pgw->ips_no<DR_MAX_IPS && (get_next_su( proxy, &sau, 0)==0) ) {
		su2ip_addr( &pgw->ips[pgw->ips_no], &sau);
		pgw->ports[pgw->ips_no] = proxy->port;
		LM_DBG("additional gw ip addr [%s]\n",
			ip_addr2a( &pgw->ips[pgw->ips_no] ) );
		pgw->ips_no++;
	}

	free_proxy(proxy);
	pkg_free(proxy);

done:
	if(NULL==r->pgw_l)
		r->pgw_l = pgw;
	else {
		tmp = r->pgw_l;
		while(NULL != tmp->next)
			tmp = tmp->next;
		tmp->next = pgw;
	}
	return 0;

err_exit:
	if(NULL!=pgw)
		shm_free(pgw);
	return -1;
}
Example #18
0
/**
 * Evaluate if next hop is a strict or loose router, by looking at the
 * retr. buffer of the original INVITE.
 * Assumes:
 * 	orig_inv is a parsed SIP message;
 * 	rtset is not NULL.
 * @return:
 * 	F_RB_NH_LOOSE : next hop was loose router;
 * 	F_RB_NH_STRICT: nh is strict;
 * 	0 on error.
 */
static unsigned long nhop_type(sip_msg_t *orig_inv, rte_t *rtset,
		const struct dest_info *dst_inv, str *contact)
{
	struct sip_uri puri, topr_uri, lastr_uri, inv_ruri, cont_uri;
	struct ip_addr *uri_ia;
	union sockaddr_union uri_sau;
	unsigned int uri_port, dst_port, inv_port, cont_port, lastr_port;
	rte_t *last_r;
#ifdef TM_LOC_ACK_DO_REV_DNS
	struct ip_addr ia;
	struct hostent *he;
	char **alias;
#endif

#define PARSE_URI(_str_, _uri_) \
	do { \
		/* parse_uri() 0z the puri */ \
		if (parse_uri((_str_)->s, \
				(_str_)->len, _uri_) < 0) { \
			LM_ERR("failed to parse route body '%.*s'.\n", STR_FMT(_str_)); \
			return 0; \
		} \
	} while (0)

#define HAS_LR(_rte_) \
	({ \
		PARSE_URI(&(_rte_)->ptr->nameaddr.uri, &puri); \
		puri.lr.s; \
	})

#define URI_PORT(_puri_, _port) \
	do { \
		if (! (_port = uri2port(_puri_))) \
			return 0; \
	} while (0)

	/* examine the easy/fast & positive cases foremost */

	/* [1] check if 1st route lacks ;lr */
	LM_DBG("checking lack of ';lr' in 1st route.\n");
	if (! HAS_LR(rtset))
		return F_RB_NH_STRICT;
	topr_uri = puri; /* save 1st route's URI */

	/* [2] check if last route shows ;lr */
	LM_DBG("checking presence of ';lr' in last route.\n");
	for (last_r = rtset; last_r->next; last_r = last_r->next)
		/* scroll down to last route */
		;
	if (HAS_LR(last_r))
		return F_RB_NH_LOOSE;

	/* [3] 1st route has ;lr -> check if the destination of original INV
	 * equals the address provided by this route; if does -> loose */
	LM_DBG("checking INVITE's destination against its first route.\n");
	URI_PORT(&topr_uri, uri_port);
	if (! (dst_port = su_getport(&dst_inv->to)))
		return 0; /* not really expected */
	if (dst_port != uri_port)
		return F_RB_NH_STRICT;
	/* if 1st route contains an IP address, comparing it against .dst */
	if ((uri_ia = str2ip(&topr_uri.host))
			|| (uri_ia = str2ip6(&topr_uri.host))
			) {
		/* we have an IP address in route -> comparison can go swiftly */
		if (init_su(&uri_sau, uri_ia, uri_port) < 0)
			return 0; /* not really expected */
		if (su_cmp(&uri_sau, &dst_inv->to))
			/* ;lr and sent there */
			return F_RB_NH_LOOSE;
		else
			/* ;lr and NOT sent there (probably sent to RURI address) */
			return F_RB_NH_STRICT;
	} else {
		/*if 1st route contains a name, rev resolve the .dst and compare*/
		LM_INFO("Failed to decode string '%.*s' in route set element as IP"
				" address. Trying name resolution.\n",STR_FMT(&topr_uri.host));

	/* TODO: alternatively, rev name and compare against dest. IP.  */
#ifdef TM_LOC_ACK_DO_REV_DNS
		ia.af = 0;
		su2ip_addr(&ia, (void *)&dst_inv->to);
		if (! ia.af)
			return 0; /* not really expected */
		if ((he = rev_resolvehost(&ia))) {
			if ((strlen(he->h_name) == topr_uri.host.len) &&
					(memcmp(he->h_name, topr_uri.host.s,
							topr_uri.host.len) == 0))
				return F_RB_NH_LOOSE;
			for (alias = he->h_aliases; *alias; alias ++)
				if ((strlen(*alias) == topr_uri.host.len) &&
						(memcmp(*alias, topr_uri.host.s,
								topr_uri.host.len) == 0))
					return F_RB_NH_LOOSE;
			return F_RB_NH_STRICT;
		} else {
			LM_INFO("failed to resolve address '%s' to a name.\n",
					ip_addr2a(&ia));
		}
#endif
	}

	LM_WARN("failed to establish with certainty the type of next hop;"
			" trying an educated guess.\n");

	/* [4] compare (possibly updated) remote target to original RURI; if
	 * equal, a strict router's address wasn't filled in as RURI -> loose */
	LM_DBG("checking remote target against INVITE's RURI.\n");
	PARSE_URI(contact, &cont_uri);
	PARSE_URI(GET_RURI(orig_inv), &inv_ruri);
	URI_PORT(&cont_uri, cont_port);
	URI_PORT(&inv_ruri, inv_port);
	if ((cont_port == inv_port) && (cont_uri.host.len == inv_ruri.host.len) &&
			(memcmp(cont_uri.host.s, inv_ruri.host.s, cont_uri.host.len) == 0))
		return F_RB_NH_LOOSE;

	/* [5] compare (possibly updated) remote target to last route; if equal,
	 * strict router's address might have been filled as RURI and remote
	 * target appended to route set -> strict */
	LM_DBG("checking remote target against INVITE's last route.\n");
	PARSE_URI(&last_r->ptr->nameaddr.uri, &lastr_uri);
	URI_PORT(&lastr_uri, lastr_port);
	if ((cont_port == lastr_port) &&
			(cont_uri.host.len == lastr_uri.host.len) &&
			(memcmp(cont_uri.host.s, lastr_uri.host.s,
					lastr_uri.host.len) == 0))
		return F_RB_NH_STRICT;

	LM_WARN("failed to establish the type of next hop;"
			" assuming loose router.\n");
	return F_RB_NH_LOOSE;

#undef PARSE_URI
#undef HAS_LR
#undef URI_PORT
}
Example #19
0
/* forwards a request to dst
 * parameters:
 *   msg       - sip msg
 *   dst       - destination name, if non-null it will be resolved and
 *               send_info updated with the ip/port. Even if dst is non
 *               null send_info must contain the protocol and if a non
 *               default port or non srv. lookup is desired, the port must
 *               be !=0 
 *   port      - used only if dst!=0 (else the port in send_info->to is used)
 *   send_info - value/result partially filled dest_info structure:
 *                 - send_info->proto and comp are used
 *                 - send_info->to will be filled (dns)
 *                 - send_info->send_flags is filled from the message
 *                 - if the send_socket member is null, a send_socket will be 
 *                   chosen automatically
 * WARNING: don't forget to zero-fill all the  unused members (a non-zero 
 * random id along with proto==PROTO_TCP can have bad consequences, same for
 *   a bogus send_socket value)
 */
int forward_request(struct sip_msg* msg, str* dst, unsigned short port,
							struct dest_info* send_info)
{
	unsigned int len;
	char* buf;
	char md5[MD5_LEN];
	struct socket_info* orig_send_sock; /* initial send_sock */
	int ret;
	struct ip_addr ip; /* debugging only */
	char proto;
#ifdef USE_DNS_FAILOVER
	struct socket_info* prev_send_sock;
	int err;
	struct dns_srv_handle dns_srv_h;
	
	prev_send_sock=0;
	err=0;
#endif
	
	
	buf=0;
	orig_send_sock=send_info->send_sock;
	proto=send_info->proto;
	ret=0;

	if(dst){
#ifdef USE_DNS_FAILOVER
		if (cfg_get(core, core_cfg, use_dns_failover)){
			dns_srv_handle_init(&dns_srv_h);
			err=dns_sip_resolve2su(&dns_srv_h, &send_info->to, dst, port,
									&proto, dns_flags);
			if (err!=0){
				LOG(L_ERR, "ERROR: forward_request: resolving \"%.*s\""
						" failed: %s [%d]\n", dst->len, ZSW(dst->s),
						dns_strerror(err), err);
				ret=E_BAD_ADDRESS;
				goto error;
			}
		}else
#endif
		if (sip_hostport2su(&send_info->to, dst, port, &proto)<0){
			LOG(L_ERR, "ERROR: forward_request: bad host name %.*s,"
						" dropping packet\n", dst->len, ZSW(dst->s));
			ret=E_BAD_ADDRESS;
			goto error;
		}
	}/* dst */
	send_info->send_flags=msg->fwd_send_flags;
	/* calculate branch for outbound request;  if syn_branch is turned off,
	   calculate is from transaction key, i.e., as an md5 of From/To/CallID/
	   CSeq exactly the same way as TM does; good for reboot -- than messages
	   belonging to transaction lost due to reboot will still be forwarded
	   with the same branch parameter and will be match-able downstream
	
	   if it is turned on, we don't care about reboot; we simply put a simple
	   value in there; better for performance
	*/
	if (syn_branch ) {
	        memcpy(msg->add_to_branch_s, "z9hG4bKcydzigwkX", 16);
		msg->add_to_branch_len=16;
	} else {
		if (!char_msg_val( msg, md5 )) 	{ /* parses transaction key */
			LOG(L_ERR, "ERROR: forward_request: char_msg_val failed\n");
			ret=E_UNSPEC;
			goto error;
		}
		msg->hash_index=hash( msg->callid->body, get_cseq(msg)->number);
		if (!branch_builder( msg->hash_index, 0, md5, 0 /* 0-th branch */,
					msg->add_to_branch_s, &msg->add_to_branch_len )) {
			LOG(L_ERR, "ERROR: forward_request: branch_builder failed\n");
			ret=E_UNSPEC;
			goto error;
		}
	}
	/* try to send the message until success or all the ips are exhausted
	 *  (if dns lookup is performed && the dns cache used ) */
#ifdef USE_DNS_FAILOVER
	do{
#endif
		if (orig_send_sock==0) /* no forced send_sock => find it **/
			send_info->send_sock=get_send_socket(msg, &send_info->to, proto);
		if (send_info->send_sock==0){
			LOG(L_ERR, "forward_req: ERROR: cannot forward to af %d, proto %d "
						"no corresponding listening socket\n",
						send_info->to.s.sa_family, proto);
			ret=ser_error=E_NO_SOCKET;
#ifdef USE_DNS_FAILOVER
			/* continue, maybe we find a socket for some other ip */
			continue;
#else
			goto error;
#endif
		}
	
#ifdef USE_DNS_FAILOVER
		if (prev_send_sock!=send_info->send_sock){
			/* rebuild the message only if the send_sock changed */
			prev_send_sock=send_info->send_sock;
#endif
			if (buf) pkg_free(buf);
			send_info->proto=proto;
			buf = build_req_buf_from_sip_req(msg, &len, send_info, 0);
			if (!buf){
				LOG(L_ERR, "ERROR: forward_request: building failed\n");
				ret=E_OUT_OF_MEM; /* most probable */
				goto error;
			}
#ifdef USE_DNS_FAILOVER
		}
#endif
		 /* send it! */
		DBG("Sending:\n%.*s.\n", (int)len, buf);
		DBG("orig. len=%d, new_len=%d, proto=%d\n",
				msg->len, len, send_info->proto );
	
		if (run_onsend(msg, send_info, buf, len)==0){
			su2ip_addr(&ip, &send_info->to);
			LOG(L_INFO, "forward_request: request to %s:%d(%d) dropped"
					" (onsend_route)\n", ip_addr2a(&ip),
						su_getport(&send_info->to), send_info->proto);
			ser_error=E_OK; /* no error */
			ret=E_ADM_PROHIBITED;
#ifdef USE_DNS_FAILOVER
			continue; /* try another ip */
#else
			goto error; /* error ? */
#endif
		}
#ifdef USE_DST_BLACKLIST
		if (cfg_get(core, core_cfg, use_dst_blacklist)){
			if (dst_is_blacklisted(send_info, msg)){
				su2ip_addr(&ip, &send_info->to);
				LOG(L_DBG, "DEBUG: blacklisted destination:%s:%d (%d)\n",
							ip_addr2a(&ip), su_getport(&send_info->to),
							send_info->proto);
				ret=ser_error=E_SEND;
#ifdef USE_DNS_FAILOVER
				continue; /* try another ip */
#else
				goto error;
#endif
			}
		}
#endif
		if (msg_send(send_info, buf, len)<0){
			ret=ser_error=E_SEND;
#ifdef USE_DST_BLACKLIST
			(void)dst_blacklist_add(BLST_ERR_SEND, send_info, msg);
#endif
#ifdef USE_DNS_FAILOVER
			continue; /* try another ip */
#else
			goto error;
#endif
		}else{
			ret=ser_error=E_OK;
			/* sent requests stats */
			STATS_TX_REQUEST(  msg->first_line.u.request.method_value );
			/* exit succcesfully */
			goto end;
		}
#ifdef USE_DNS_FAILOVER
	}while(dst && cfg_get(core, core_cfg, use_dns_failover) &&
			dns_srv_handle_next(&dns_srv_h, err) && 
			((err=dns_sip_resolve2su(&dns_srv_h, &send_info->to, dst, port,
										&proto, dns_flags))==0));
	if ((err!=0) && (err!=-E_DNS_EOR)){
		LOG(L_ERR, "ERROR:  resolving %.*s host name in uri"
							" failed: %s [%d] (dropping packet)\n",
									dst->len, ZSW(dst->s),
									dns_strerror(err), err);
		ret=ser_error=E_BAD_ADDRESS;
		goto error;
	}
#endif
	
error:
	STATS_TX_DROPS;
end:
#ifdef USE_DNS_FAILOVER
	if (dst && cfg_get(core, core_cfg, use_dns_failover)){
				dns_srv_handle_put(&dns_srv_h);
	}
#endif
	if (buf) pkg_free(buf);
	/* received_buf & line_buf will be freed in receive_msg by free_lump_list*/
#if defined STATS_REQ_FWD_OK || defined STATS_REQ_FWD_DROP
	if(ret==0)
		STATS_REQ_FWD_OK();
	else
		STATS_REQ_FWD_DROP();
#endif /* STATS_REQ_FWD_* */
	return ret;
}
Example #20
0
static void trace_sl_onreply_out( unsigned int types, struct sip_msg* req,
									struct sl_cb_param *sl_param)
{
	static char fromip_buff[IP_ADDR_MAX_STR_SIZE+12];
	static char toip_buff[IP_ADDR_MAX_STR_SIZE+12];
	struct sip_msg* msg;
	int_str        avp_value;
	struct usr_avp *avp;
	struct ip_addr to_ip;
	int len;
	char statusbuf[5];

	if(req==NULL || sl_param==NULL)
	{
		LM_ERR("bad parameters\n");
		goto error;
	}

	if( trace_is_off() )
	{
		LM_DBG("trace off...\n");
		return;
	}

	LM_DBG("trace slonreply out \n");

	avp = NULL;
	if(traced_user_avp >= 0)
		avp=search_first_avp(traced_user_avp_type, traced_user_avp,
				&avp_value, 0);

	if((avp==NULL) && !flag_trace_is_set(req))
	{
		LM_DBG("nothing to trace...\n");
		return;
	}

	msg = req;

	if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL)
	{
		LM_ERR("cannot parse FROM header\n");
		goto error;
	}

	if(parse_headers(msg, HDR_CALLID_F, 0)!=0)
	{
		LM_ERR("cannot parse call-id\n");
		return;
	}

	db_vals[0].val.blob_val.s   = (sl_param->buffer)?sl_param->buffer->s:"";
	db_vals[0].val.blob_val.len = (sl_param->buffer)?sl_param->buffer->len:0;

	/* check Call-ID header */
	if(msg->callid==NULL || msg->callid->body.s==NULL)
	{
		LM_ERR("cannot find Call-ID header!\n");
		goto error;
	}

	db_vals[1].val.str_val.s = msg->callid->body.s;
	db_vals[1].val.str_val.len = msg->callid->body.len;

	db_vals[2].val.str_val.s = msg->first_line.u.request.method.s;
	db_vals[2].val.str_val.len = msg->first_line.u.request.method.len;

	if(trace_local_ip.s && trace_local_ip.len > 0){
		set_columns_to_trace_local_ip( db_vals[4], db_vals[5], db_vals[6]);
	}
	else {
		set_sock_columns( db_vals[4], db_vals[5], db_vals[6], fromip_buff,
			&msg->rcv.dst_ip, msg->rcv.dst_port, msg->rcv.proto);
	}

	strcpy(statusbuf, int2str(sl_param->code, &len));
	db_vals[3].val.str_val.s = statusbuf;
	db_vals[3].val.str_val.len = len;

	memset(&to_ip, 0, sizeof(struct ip_addr));
	if(sl_param->dst==0)
	{
		set_columns_to_any(db_vals[7], db_vals[8], db_vals[9]);
	} else {
		su2ip_addr(&to_ip, sl_param->dst);
		set_sock_columns( db_vals[7], db_vals[8],db_vals[9], toip_buff, &to_ip,
			(unsigned short)su_getport(sl_param->dst), req->rcv.proto);
	}

	db_vals[10].val.time_val = time(NULL);

	db_vals[11].val.string_val = "out";

	db_vals[12].val.str_val.s = get_from(msg)->tag_value.s;
	db_vals[12].val.str_val.len = get_from(msg)->tag_value.len;

	if (save_siptrace(msg,avp,&avp_value,db_keys,db_vals) < 0) {
		LM_ERR("failed to save siptrace\n");
		goto error;
	}

#ifdef STATISTICS
	update_stat(siptrace_rpl, 1);
#endif
	return;
error:
	return;
}
Example #21
0
/* finds a tcpconn & sends on it */
int tcp_send(int type, char* buf, unsigned len, union sockaddr_union* to,
				int id)
{
	struct tcp_connection *c;
	struct tcp_connection *tmp;
	struct ip_addr ip;
	int port;
	int fd;
	long response[2];
	int n;
	
	port=0;
	if (to){
		su2ip_addr(&ip, to);
		port=su_getport(to);
		c=tcpconn_get(id, &ip, port, TCP_CON_SEND_TIMEOUT); 
	}else if (id){
		c=tcpconn_get(id, 0, 0, TCP_CON_SEND_TIMEOUT);
	}else{
		LOG(L_CRIT, "BUG: tcp_send called with null id & to\n");
		return -1;
	}
	
	if (id){
		if (c==0) {
			if (to){
				/* try again w/o id */
				c=tcpconn_get(0, &ip, port, TCP_CON_SEND_TIMEOUT);
				goto no_id;
			}else{
				LOG(L_ERR, "ERROR: tcp_send: id %d not found, dropping\n",
						id);
				return -1;
			}
		}else goto get_fd;
	}
no_id:
		if (c==0){
			DBG("tcp_send: no open tcp connection found, opening new one\n");
			/* create tcp connection */
			if ((c=tcpconn_connect(to, type))==0){
				LOG(L_ERR, "ERROR: tcp_send: connect failed\n");
				return -1;
			}
			c->refcnt++; /* safe to do it w/o locking, it's not yet
							available to the rest of the world */
			fd=c->s;
			
			/* send the new tcpconn to "tcp main" */
			response[0]=(long)c;
			response[1]=CONN_NEW;
			n=send_all(unix_tcp_sock, response, sizeof(response));
			if (n<=0){
				LOG(L_ERR, "BUG: tcp_send: failed write: %s (%d)\n",
						strerror(errno), errno);
				n=-1;
				goto end;
			}	
			n=send_fd(unix_tcp_sock, &c, sizeof(c), c->s);
			if (n<=0){
				LOG(L_ERR, "BUG: tcp_send: failed send_fd: %s (%d)\n",
						strerror(errno), errno);
				n=-1;
				goto end;
			}
			goto send_it;
		}
get_fd:
			/* todo: see if this is not the same process holding
			 *  c  and if so send directly on c->fd */
			DBG("tcp_send: tcp connection found (%p), acquiring fd\n", c);
			/* get the fd */
			response[0]=(long)c;
			response[1]=CONN_GET_FD;
			n=send_all(unix_tcp_sock, response, sizeof(response));
			if (n<=0){
				LOG(L_ERR, "BUG: tcp_send: failed to get fd(write):%s (%d)\n",
						strerror(errno), errno);
				n=-1;
				goto release_c;
			}
			DBG("tcp_send, c= %p, n=%d\n", c, n);
			tmp=c;
			n=receive_fd(unix_tcp_sock, &c, sizeof(c), &fd);
			if (n<=0){
				LOG(L_ERR, "BUG: tcp_send: failed to get fd(receive_fd):"
							" %s (%d)\n", strerror(errno), errno);
				n=-1;
				goto release_c;
			}
			if (c!=tmp){
				LOG(L_CRIT, "BUG: tcp_send: get_fd: got different connection:"
						"  %p (id= %d, refcnt=%d state=%d != "
						"  %p (id= %d, refcnt=%d state=%d (n=%d)\n",
						  c,   c->id,   c->refcnt,   c->state,
						  tmp, tmp->id, tmp->refcnt, tmp->state, n
				   );
				n=-1; /* fail */
				goto end;
			}
			DBG("tcp_send: after receive_fd: c= %p n=%d fd=%d\n",c, n, fd);
		
	
	
send_it:
	DBG("tcp_send: sending...\n");
	lock_get(&c->write_lock);
#ifdef USE_TLS
	if (c->type==PROTO_TLS)
		n=tls_blocking_write(c, fd, buf, len);
	else
#endif
		n=tcp_blocking_write(c, fd, buf, len);
	lock_release(&c->write_lock);
	DBG("tcp_send: after write: c= %p n=%d fd=%d\n",c, n, fd);
	DBG("tcp_send: buf=\n%.*s\n", (int)len, buf);
	if (n<0){
		LOG(L_ERR, "ERROR: tcp_send: failed to send\n");
		/* error on the connection , mark it as bad and set 0 timeout */
		c->state=S_CONN_BAD;
		c->timeout=0;
		/* tell "main" it should drop this (optional it will t/o anyway?)*/
		response[0]=(long)c;
		response[1]=CONN_ERROR;
		n=send_all(unix_tcp_sock, response, sizeof(response));
		/* CONN_ERROR will auto-dec refcnt => we must not call tcpconn_put !!*/
		if (n<=0){
			LOG(L_ERR, "BUG: tcp_send: error return failed (write):%s (%d)\n",
					strerror(errno), errno);
			n=-1;
		}
		close(fd);
		return n; /* error return, no tcpconn_put */
	}
end:
	close(fd);
release_c:
	tcpconn_put(c); /* release c (lock; dec refcnt; unlock) */
	return n;
}
Example #22
0
/*! \brief Finds a tcpconn & sends on it */
static int proto_ws_send(struct socket_info* send_sock,
											char* buf, unsigned int len,
											union sockaddr_union* to, int id)
{
	struct tcp_connection *c;
	struct timeval get;
	struct ip_addr ip;
	int port = 0;
	int fd, n;

	reset_tcp_vars(tcpthreshold);
	start_expire_timer(get,tcpthreshold);

	if (to){
		su2ip_addr(&ip, to);
		port=su_getport(to);
		n = tcp_conn_get(id, &ip, port, &c, &fd);
	}else if (id){
		n = tcp_conn_get(id, 0, 0, &c, &fd);
	}else{
		LM_CRIT("prot_tls_send called with null id & to\n");
		get_time_difference(get,tcpthreshold,tcp_timeout_con_get);
		return -1;
	}

	if (n<0) {
		/* error during conn get, return with error too */
		LM_ERR("failed to aquire connection\n");
		get_time_difference(get,tcpthreshold,tcp_timeout_con_get);
		return -1;
	}

	/* was connection found ?? */
	if (c==0) {
		if (tcp_no_new_conn) {
			return -1;
		}
		LM_DBG("no open tcp connection found, opening new one\n");
		/* create tcp connection */
		if ((c=ws_connect(send_sock, to, &fd))==0) {
			LM_ERR("connect failed\n");
			return -1;
		}
		goto send_it;
	}
	get_time_difference(get, tcpthreshold, tcp_timeout_con_get);

	/* now we have a connection, let's what we can do with it */
	/* BE CAREFUL now as we need to release the conn before exiting !!! */
	if (fd==-1) {
		/* connection is not writable because of its state */
		/* return error, nothing to do about it */
		tcp_conn_release(c, 0);
		return -1;
	}

send_it:
	LM_DBG("sending via fd %d...\n",fd);

	n = ws_req_write(c, fd, buf, len);
	stop_expire_timer(get, tcpthreshold, "WS ops",buf,(int)len,1);
	tcp_conn_set_lifetime( c, tcp_con_lifetime);

	LM_DBG("after write: c= %p n=%d fd=%d\n",c, n, fd);
	if (n<0){
		LM_ERR("failed to send\n");
		c->state=S_CONN_BAD;
		if (c->proc_id != process_no)
			close(fd);
		tcp_conn_release(c, 0);
		return -1;
	}

	/* only close the FD if not already in the context of our process
	either we just connected, or main sent us the FD */
	if (c->proc_id != process_no)
		close(fd);

	tcp_conn_release(c, 0);
	return n;
}
Example #23
0
int hepv3_message_parse(char *buf, unsigned int len, sip_msg_t* msg) {

	union sockaddr_union from;
	union sockaddr_union to;
	char *tmp;
	struct ip_addr dst_ip, src_ip;
	struct socket_info* si = 0;
	int i;
	char *payload = NULL;
	unsigned int payload_len = 0;
        struct hep_chunk *chunk;	
        struct hep_generic_recv *hg;
        int totelem = 0;
        int chunk_vendor=0, chunk_type=0, chunk_length=0;
        int total_length = 0;
        int ret = 0;
        
	hg = (struct hep_generic_recv*)pkg_malloc(sizeof(struct hep_generic_recv));
	if(hg==NULL) {
	        LM_ERR("no more pkg memory left for hg\n");
	        return -1;
        }
	                                                 		
	memset(hg, 0, sizeof(struct hep_generic_recv));

	
        memset(heptime, 0, sizeof(struct hep_timehdr));	
	        

	/* HEADER */
	hg->header  = (hep_ctrl_t *) (buf);

	/*Packet size */
	total_length = ntohs(hg->header->length);

	dst_ip.af = 0;
        src_ip.af = 0;
                	        
	payload = NULL;
	correlation_id = NULL;
	authkey = NULL;

	i = sizeof(hep_ctrl_t);	        
	        
	while(i < total_length) {
                
	        /*OUR TMP DATA */                                  
                tmp = buf+i;

                chunk = (struct hep_chunk*) tmp;
                             
                chunk_vendor = ntohs(chunk->vendor_id);                             
                chunk_type = ntohs(chunk->type_id);
                chunk_length = ntohs(chunk->length);
                       
                /* if chunk_length */
                if(chunk_length == 0) {
                        /* BAD LEN we drop this packet */
                        goto error;
                }

                /* SKIP not general Chunks */
                if(chunk_vendor != 0) {
                        i+=chunk_length;
                }
                else {                                                                                                                               
                        switch(chunk_type) {
                                     
                                case 0:
                                        goto error;
                                        break;
                                     
                                case 1:                                                                          
                                        hg->ip_family  = (hep_chunk_uint8_t *) (tmp);
                                        i+=chunk_length;
                                        totelem++;
                                        break;
                                case 2:
                                        hg->ip_proto  = (hep_chunk_uint8_t *) (tmp);
                                        i+=chunk_length;
                                        totelem++;
                                        break;                                                     
                                case 3:
                                        hg->hep_src_ip4  = (hep_chunk_ip4_t *) (tmp);
                                        i+=chunk_length;
                                        src_ip.af=AF_INET;
				        src_ip.len=4;
				        src_ip.u.addr32[0] = hg->hep_src_ip4->data.s_addr;
				        totelem++;
				        break;
                                case 4:
                                        hg->hep_dst_ip4  = (hep_chunk_ip4_t *) (tmp);
                                        i+=chunk_length;                                                     
					dst_ip.af=AF_INET;
				        dst_ip.len=4;
				        dst_ip.u.addr32[0] = hg->hep_dst_ip4->data.s_addr;
                                        totelem++;

                                        break;
                                case 5:
                                        hg->hep_src_ip6  = (hep_chunk_ip6_t *) (tmp);
                                        i+=chunk_length;
                                        src_ip.af=AF_INET6;
				        src_ip.len=16;
				        memcpy(src_ip.u.addr, &hg->hep_src_ip6->data, 16);
				        totelem++;
                                        break;
                                case 6:
                                        hg->hep_dst_ip6  = (hep_chunk_ip6_t *) (tmp);
                                        i+=chunk_length;                                                     
                                        dst_ip.af=AF_INET6;
				        dst_ip.len=16;
				        memcpy(dst_ip.u.addr, &hg->hep_dst_ip6->data, 16);
				        totelem++;
                                        break;
        
                                case 7:
                                        hg->src_port  = (hep_chunk_uint16_t *) (tmp);
                                        msg->rcv.src_port = ntohs(hg->src_port->data);
                                        i+=chunk_length;                      
                                        totelem++;
                                        break;

                                case 8:
                                        hg->dst_port  = (hep_chunk_uint16_t *) (tmp);
                                        msg->rcv.dst_port = ntohs(hg->dst_port->data);
                                        i+=chunk_length;
                                        totelem++;
                                        break;
                                case 9:
                                        hg->time_sec  = (hep_chunk_uint32_t *) (tmp);
                                        hg->time_sec->data = ntohl(hg->time_sec->data);
                                        heptime->tv_sec = hg->time_sec->data;
                                        i+=chunk_length;
                                        totelem++;
                                        break;                                                     
                                                     
                                case 10:
                                        hg->time_usec  = (hep_chunk_uint32_t *) (tmp);
                                        hg->time_usec->data = ntohl(hg->time_usec->data);
                                        heptime->tv_usec = hg->time_usec->data;
                                        i+=chunk_length;
                                        totelem++;
                                        break;      

                                case 11:
                                        hg->proto_t  = (hep_chunk_uint8_t *) (tmp);
                                        i+=chunk_length;
                                        totelem++;
                                        break;                                                                                                                                                         

                                case 12:
                                        hg->capt_id  = (hep_chunk_uint32_t *) (tmp);
                                        i+=chunk_length;
                                        heptime->captid = ntohs(hg->capt_id->data);
                                        totelem++;
                                        break;

                                case 13:
                                        hg->keep_tm  = (hep_chunk_uint16_t *) (tmp);
                                        i+=chunk_length;
                                        break;                                                     

                                case 14:
                                        authkey = (char *) tmp + sizeof(hep_chunk_t);
                                        i+=chunk_length;                                                                             
                                        break;
                                                     
                                case 15:
                                        hg->payload_chunk  = (hep_chunk_t *) (tmp);
                                        payload = (char *) tmp+sizeof(hep_chunk_t);
                                        payload_len = chunk_length - sizeof(hep_chunk_t);
                                        i+=chunk_length;
                                        totelem++;
                                        break;
                                case 17:
                                
                                        correlation_id = (char *) tmp + sizeof(hep_chunk_t);
                                        i+=chunk_length;                                                                            
					break;

                                                     
                                default:
                                        i+=chunk_length;
                                        break;
                        }                                        
                }
        }	                                                                                                          
                        
        /* CHECK how much elements */
        if(totelem < 9) {                        
                LM_ERR("Not all elements [%d]\n", totelem);                        
                goto done;
        }                 

        if ( dst_ip.af == 0 || src_ip.af == 0)  {
                LM_ERR("NO IP's set\n");
                goto done;
        }

                        
        ip_addr2su(&to, &dst_ip, msg->rcv.dst_port);
        ip_addr2su(&from, &src_ip, msg->rcv.src_port);
                        
        msg->rcv.src_su=from;
        su2ip_addr(&msg->rcv.src_ip, &from);
        su2ip_addr(&msg->rcv.dst_ip, &to);

	if(hg->ip_proto->data == IPPROTO_TCP) msg->rcv.proto=PROTO_TCP;
	else if(hg->ip_proto->data == IPPROTO_UDP) msg->rcv.proto=PROTO_UDP;

        if(payload != NULL) ret = len - payload_len;

	/*TIME*/ 
        heptime->tv_sec = hg->time_sec->data;
        heptime->tv_usec = hg->time_usec->data;
        heptime->captid = ntohs(hg->capt_id->data);

done:
          
        //if(si) pkg_free(si);
        if(hg) pkg_free(hg);                     

        return ret;
        
error:

        if(si) pkg_free(si);
        if(hg) pkg_free(hg);
                
        return -1;           
        
}
Example #24
0
static int hep_udp_read_req(struct socket_info *si, int* bytes_read)
{
	struct receive_info ri;
	int len;
#ifdef DYN_BUF
	char* buf;
#else
	static char buf [BUF_SIZE+1];
#endif
	char *tmp;
	unsigned int fromlen;
	str msg;

	struct hep_desc h;

	int ret = 0;

#ifdef DYN_BUF
	buf=pkg_malloc(BUF_SIZE+1);
	if (buf==0){
		LM_ERR("could not allocate receive buffer\n");
		goto error;
	}
#endif

	fromlen=sockaddru_len(si->su);
	len=recvfrom(bind_address->socket, buf, BUF_SIZE,0,&ri.src_su.s,&fromlen);
	if (len==-1){
		if (errno==EAGAIN)
			return 0;
		if ((errno==EINTR)||(errno==EWOULDBLOCK)|| (errno==ECONNREFUSED))
			return -1;
		LM_ERR("recvfrom:[%d] %s\n", errno, strerror(errno));
		return -2;
	}


	if (len<MIN_UDP_PACKET) {
		LM_DBG("probing packet received len = %d\n", len);
		return 0;
	}

	/* we must 0-term the messages, receive_msg expects it */
	buf[len]=0; /* no need to save the previous char */

	ri.bind_address = si;
	ri.dst_port = si->port_no;
	ri.dst_ip = si->address;
	ri.proto = si->proto;
	ri.proto_reserved1 = ri.proto_reserved2 = 0;

	su2ip_addr(&ri.src_ip, &ri.src_su);
	ri.src_port=su_getport(&ri.src_su);

	msg.s = buf;
	msg.len = len;

	/* if udp we are sure that version 1 or 2 of the
	 * protocol is used */
	if (unpack_hepv2(buf, len, &h)) {
		LM_ERR("hep unpacking failed\n");
		return -1;
	}

	/* run hep callbacks if looks like non-SIP message*/
	if( !isalpha(msg.s[0]) ) {    /* not-SIP related */
		ret=run_hep_cbs(&h, &ri);
		if (ret < 0) {
			LM_ERR("failed to run hep callbacks\n");
			return -1;
		}

		/* remove the hep header; leave only the payload */
		memmove(buf, h.u.hepv12.payload,
							/* also copy '\0' character */
							strlen(h.u.hepv12.payload)+1);
		msg.s   = buf;
		msg.len = strlen(buf);
	}

	if (ri.src_port==0){
		tmp=ip_addr2a(&ri.src_ip);
		LM_INFO("dropping 0 port packet for %s\n", tmp);
		return 0;
	}

	if (ret != HEP_SCRIPT_SKIP) {
		/* receive_msg must free buf too!*/
		receive_msg( msg.s, msg.len, &ri);
	}

	return 0;
}
Example #25
0
struct socket_info* get_out_socket(union sockaddr_union* to, int proto)
{
	int* temp_sock;
	socklen_t len;
	union sockaddr_union from; 
	struct socket_info* si;
	struct ip_addr ip;
	union sockaddr_union uncon;

	memset(&uncon, 0, sizeof(union sockaddr_union));
	uncon.sin.sin_family = AF_UNSPEC;

	if (unlikely(proto!=PROTO_UDP)) {
		LOG(L_CRIT, "BUG: get_out_socket can only be called for UDP\n");
		return 0;
	}
retry:
	switch(to->s.sa_family){
	case AF_INET : {
		if(unlikely(sock_inet < 0)){
			sock_inet = socket(AF_INET, SOCK_DGRAM, 0);
			if (sock_inet==-1) {
				LM_ERR("socket() failed: %s\n", strerror(errno));
				return 0;
			}
		}
		temp_sock = &sock_inet;
		break;
	}
#ifdef USE_IPV6
	case AF_INET6 : {
		if(unlikely(sock_inet6 < 0)){
			sock_inet6 = socket(AF_INET6, SOCK_DGRAM, 0);
			if (sock_inet6==-1) {
				LM_ERR("socket() failed: %s\n", strerror(errno));
				return 0;
			}
		}
		temp_sock = &sock_inet6;
		break;
	}
#endif /* USE_IPV6 */
	default: {
		LM_ERR("Unknown protocol family \n");
		return 0;
	}
	}

	if( !mhomed_sock_cache_disabled ){
		/* some Linux kernel versions (all?) along with other UNIXes don't re-bound the sock if already bound */
		/* to un-bound a socket set sin_family to AF_UNSPEC and zero out the rest*/
		if (unlikely(connect(*temp_sock, &uncon.s, sockaddru_len(uncon)) < 0))
				mhomed_sock_cache_disabled = 1;
	}

	if (unlikely(connect(*temp_sock, &to->s, sockaddru_len(*to))==-1)) {
		if (unlikely(errno==EISCONN && !mhomed_sock_cache_disabled)){
			/*  no multiple connects support on the same socket */
			mhomed_sock_cache_disabled=1;
			if (sock_inet>=0){
				close(sock_inet);
				sock_inet=-1;
			}
#ifdef USE_IPV6
			if (sock_inet6>=0){
				close(sock_inet6);
				sock_inet6=-1;
			}
#endif /* USE_IPV6 */
			goto retry;
		}
		LOG(L_ERR, "ERROR: get_out_socket: connect failed: %s\n",
				strerror(errno));
		goto error;
	}
	len=sizeof(from);
	if (unlikely(getsockname(*temp_sock, &from.s, &len)==-1)) {
		LOG(L_ERR, "ERROR: get_out_socket: getsockname failed: %s\n",
				strerror(errno));
		goto error;
	}
	su2ip_addr(&ip, &from);
	si=find_si(&ip, 0, proto);
	if (si==0) goto error;
	DBG("DEBUG: get_out_socket: socket determined: %p\n", si );
	if (unlikely(mhomed_sock_cache_disabled)){
		close(*temp_sock);
		*temp_sock=-1;
	}
	return si;
error:
	LOG(L_ERR, "ERROR: get_out_socket: no socket found\n");
	if (unlikely(mhomed_sock_cache_disabled && *temp_sock >=0)){
		close(*temp_sock);
		*temp_sock=-1;
	}
	return 0;
}
Example #26
0
static int hep_tcp_send (struct socket_info* send_sock,
		char *buf, unsigned int len, union sockaddr_union *to, int id)
{
	struct tcp_connection *c;
	int port=0;
	struct ip_addr ip;
	int fd, n;


	if (to) {
		su2ip_addr(&ip, to);
		port=su_getport(to);
		n = tcp_conn_get(id,&ip, port, &c, &fd);
	} else if (id) {
		n = tcp_conn_get(id, 0, 0, &c, &fd);
	} else {
		LM_CRIT("tcp_send called with null id & to\n");
		return -1;
	}

	if (n < 0) {
		/* error during conn get, return with error too */
		LM_ERR("failed to aquire connection\n");
		return -1;
	}

	/* was connection found ?? */
	if (c==0) {
		if (tcp_no_new_conn) {
			return -1;
		}
		if (!to) {
			LM_ERR("Unknown destination - cannot open new tcp connection\n");
			return -1;
		}
		LM_DBG("no open tcp connection found, opening new one, async = %d\n",hep_async);
		/* create tcp connection */
		if (hep_async) {
			n = tcpconn_async_connect(send_sock, to, buf, len, &c, &fd);
			if ( n<0 ) {
				LM_ERR("async TCP connect failed\n");
				return -1;
			}
			/* connect succeded, we have a connection */
			if (n==0) {
				/* connect is still in progress, break the sending
				 * flow now (the actual write will be done when
				 * connect will be completed */
				LM_DBG("Succesfully started async connection \n");
				tcp_conn_release(c, 0);
				return len;
			}
			/* our first connect attempt succeeded - go ahead as normal */
		} else if ((c=hep_sync_connect(send_sock, to, &fd))==0) {
			LM_ERR("connect failed\n");
			return -1;
		}

		goto send_it;
	}


	/* now we have a connection, let's see what we can do with it */
	/* BE CAREFUL now as we need to release the conn before exiting !!! */
	if (fd==-1) {
		/* connection is not writable because of its state - can we append
		 * data to it for later writting (async writting)? */
		if (c->state==S_CONN_CONNECTING) {
			/* the connection is currently in the process of getting
			 * connected - let's append our send chunk as well - just in
			 * case we ever manage to get through */
			LM_DBG("We have acquired a TCP connection which is still "
				"pending to connect - delaying write \n");
			n = add_write_chunk(c,buf,len,1);
			if (n < 0) {
				LM_ERR("Failed to add another write chunk to %p\n",c);
				/* we failed due to internal errors - put the
				 * connection back */
				tcp_conn_release(c, 0);
				return -1;
			}

			/* we succesfully added our write chunk - success */
			tcp_conn_release(c, 0);
			return len;
		} else {
			/* return error, nothing to do about it */
			tcp_conn_release(c, 0);
			return -1;
		}
	}


send_it:
	LM_DBG("sending via fd %d...\n",fd);

	n = _hep_write_on_socket(c, fd, buf, len);

	tcp_conn_set_lifetime( c, tcp_con_lifetime);

	LM_DBG("after write: c= %p n=%d fd=%d\n",c, n, fd);
	/* LM_DBG("buf=\n%.*s\n", (int)len, buf); */
	if (n<0){
		LM_ERR("failed to send\n");
		c->state=S_CONN_BAD;
		if (c->proc_id != process_no)
			close(fd);
		tcp_conn_release(c, 0);
		return -1;
	}

	/* only close the FD if not already in the context of our process
	either we just connected, or main sent us the FD */
	if (c->proc_id != process_no)
		close(fd);

	tcp_conn_release(c, (n<len)?1:0/*pending data in async mode?*/ );

	return n;
}
Example #27
0
static void trace_msg_out(struct sip_msg* msg, str  *sbuf,
			struct socket_info* send_sock, int proto, union sockaddr_union *to)
{
	static char fromip_buff[IP_ADDR_MAX_STR_SIZE+12];
	static char toip_buff[IP_ADDR_MAX_STR_SIZE+12];
	int_str        avp_value;
	struct usr_avp *avp;
	struct ip_addr to_ip;

	avp = NULL;
	if(traced_user_avp>=0)
		avp=search_first_avp(traced_user_avp_type, traced_user_avp,
				&avp_value, 0);

	if ( (avp==NULL) && !flag_trace_is_set(msg) )
	{
		LM_DBG("trace off...\n");
		return;
	}

	if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL)
	{
		LM_ERR("cannot parse FROM header\n");
		goto error;
	}

	if(parse_headers(msg, HDR_CALLID_F, 0)!=0)
	{
		LM_ERR("cannot parse call-id\n");
		return;
	}

	LM_DBG("trace msg out \n");

	if(sbuf!=NULL && sbuf->len>0)
	{
		db_vals[0].val.blob_val.s   = sbuf->s;
		db_vals[0].val.blob_val.len = sbuf->len;
	} else {
		db_vals[0].val.blob_val.s   = "No request buffer";
		db_vals[0].val.blob_val.len = sizeof("No request buffer")-1;
	}

	/* check Call-ID header */
	if(msg->callid==NULL || msg->callid->body.s==NULL)
	{
		LM_ERR("cannot find Call-ID header!\n");
		goto error;
	}

	db_vals[1].val.str_val.s = msg->callid->body.s;
	db_vals[1].val.str_val.len = msg->callid->body.len;

	if(sbuf!=NULL && sbuf->len > 7 && !strncasecmp(sbuf->s, "CANCEL ", 7))
	{
		db_vals[2].val.str_val.s = "CANCEL";
		db_vals[2].val.str_val.len = 6;
	} else {
		db_vals[2].val.str_val= REQ_LINE(msg).method;
	}

	db_vals[3].val.str_val.s = "";
	db_vals[3].val.str_val.len = 0;

	memset(&to_ip, 0, sizeof(struct ip_addr));

	if (trace_local_ip.s && trace_local_ip.len > 0){
		set_columns_to_trace_local_ip( db_vals[4], db_vals[5], db_vals[6]);
	}
	else {
		if(send_sock==0 || send_sock->sock_str.s==0)
		{
			set_sock_columns( db_vals[4], db_vals[5], db_vals[6], fromip_buff,
					&msg->rcv.dst_ip, msg->rcv.dst_port, msg->rcv.proto);
		} else {
			char *nbuff = proto2str(send_sock->proto,fromip_buff);
			db_vals[4].val.str_val.s = fromip_buff;
			db_vals[4].val.str_val.len = nbuff - fromip_buff;
			db_vals[5].val.str_val = send_sock->address_str;
			db_vals[6].val.int_val = send_sock->port_no;
		}
	}

	if(to==0)
	{
		set_columns_to_any(db_vals[7], db_vals[8], db_vals[9]);
	} else {
		su2ip_addr(&to_ip, to);
		set_sock_columns( db_vals[7], db_vals[8], db_vals[9], toip_buff,
			&to_ip, (unsigned short)su_getport(to), proto);
	}

	db_vals[10].val.time_val = time(NULL);

	db_vals[11].val.string_val = "out";

	db_vals[12].val.str_val.s = get_from(msg)->tag_value.s;
	db_vals[12].val.str_val.len = get_from(msg)->tag_value.len;

	if (save_siptrace(msg,avp,&avp_value,db_keys,db_vals) < 0) {
		LM_ERR("failed to save siptrace\n");
		goto error;
	}

#ifdef STATISTICS
	update_stat(siptrace_req, 1);
#endif
	return;
error:
	return;
}
Example #28
0
/* receive an ipv4 udp packet over a raw socket.
 * The packet is copied in *buf and *buf is advanced to point to the
 * payload.  Fills from and to.
 * @param rsock - raw socket
 * @param buf - the packet will be written to where *buf points intially and
 *              then *buf will be advanced to point to the udp payload.
 * @param len - buffer length (should be enough to hold at least the
 *               ip and udp headers + 1 byte).
 * @param from - result parameter, filled with source address and port of the
 *               packet.
 * @param from - result parameter, filled with destination (local) address and
 *               port of the packet.
 * @param rf   - filter used to decide whether or not the packet is
 *                accepted/processed. If null, all the packets are accepted.
 * @return packet len or  <0 on error (-1 and -2 on recv error @see recvpkt4,
 *         -3 if the headers are invalid and -4 if the packet doesn't
 *         match the  filter).
 */
int raw_udp4_recv(int rsock, char** buf, int len, union sockaddr_union* from,
					union sockaddr_union* to, struct raw_filter* rf)
{
	int n;
	unsigned short dst_port;
	unsigned short src_port;
	struct ip_addr dst_ip;
	char* end;
	char* udph_start;
	char* udp_payload;
	struct ip iph;
	struct udphdr udph;
	unsigned short udp_len;

	n=recvpkt4(rsock, *buf, len, from, to);
	if (unlikely(n<0)) goto error;
	
	end=*buf+n;
	if (unlikely(n<((sizeof(struct ip) * raw_ipip ? 2 : 1)+sizeof(struct udphdr)))) {
		n=-3;
		goto error;
	}
	
	if(raw_ipip) 
        	*buf = *buf + sizeof(struct ip);
	
	/* FIXME: if initial buffer is aligned, one could skip the memcpy
	   and directly cast ip and udphdr pointer to the memory */
	memcpy(&iph, *buf, sizeof(struct ip));
	udph_start=*buf+iph.ip_hl*4;
	udp_payload=udph_start+sizeof(struct udphdr);
	if (unlikely(udp_payload>end)){
		n=-3;
		goto error;
	}
	memcpy(&udph, udph_start, sizeof(struct udphdr));
	udp_len=ntohs(udph.uh_ulen);
	if (unlikely((udph_start+udp_len)!=end)){
		if ((udph_start+udp_len)>end){
			n=-3;
			goto error;
		}else{
			ERR("udp length too small: %d/%d\n",
					(int)udp_len, (int)(end-udph_start));
			n=-3;
			goto error;
		}
	}
	/* advance buf */
	*buf=udp_payload;
	n=(int)(end-*buf);
	/* fill ip from the packet (needed if no PKT_INFO is used) */
	dst_ip.af=AF_INET;
	dst_ip.len=4;
	dst_ip.u.addr32[0]=iph.ip_dst.s_addr;
	/* fill dst_port */
	dst_port=ntohs(udph.uh_dport);
	ip_addr2su(to, &dst_ip, dst_port);
	/* fill src_port */
	src_port=ntohs(udph.uh_sport);
	su_setport(from, src_port);
	if (likely(rf)) {
		su2ip_addr(&dst_ip, to);
		if ( (dst_port && rf->port1 && ((dst_port<rf->port1) ||
										(dst_port>rf->port2)) ) ||
			(matchnet(&dst_ip, &rf->dst)!=1) ){
			/* no match */
			n=-4;
			goto error;
		}
	}
	
error:
	return n;
}
Example #29
0
int add_lb_dsturi( struct lb_data *data, int id, int group, char *uri,
											char* resource, unsigned int flags)
{
	struct lb_res_str_list *lb_rl;
	struct lb_res_str *r;
	struct lb_dst *dst;
	struct lb_resource *res;
	struct sip_uri puri;
	struct proxy_l *proxy;
	union sockaddr_union sau;
	int len;
	int i;

	LM_DBG("uri=<%s>, grp=%d, res=<%s>\n",uri, group, resource);

	/* check uri */
	len = strlen(uri);
	if(parse_uri(uri, len, &puri)!=0 ) {
		LM_ERR("bad uri [%.*s] for destination\n", len, uri);
		return -1;
	}

	/* parse the resources string */
	lb_rl = parse_resources_list( resource, 1);
	if (lb_rl==NULL) {
		LM_ERR("failed to parse resourse string <%s>\n",resource);
		return -1;
	}

	/*add new destination */
	dst = (struct lb_dst*)shm_malloc( sizeof(struct lb_dst)
		+ lb_rl->n*sizeof(struct lb_resource_map) + len +
		(3+2*sizeof(struct lb_dst*)));
	if (dst==NULL) {
		LM_ERR("failed to get shmem\n");
		goto error;
	}
	memset( dst, 0, sizeof(struct lb_dst)+
		lb_rl->n*sizeof(struct lb_resource_map) + len +
		(3+2*sizeof(struct lb_dst*)) );

	dst->rmap = (struct lb_resource_map*)(dst+1);

	dst->uri.s = (char*)(dst->rmap + lb_rl->n);
	dst->uri.len = len;
	memcpy( dst->uri.s , uri, len);

	dst->profile_id.s = dst->uri.s + len;
	dst->profile_id.len = snprintf(dst->profile_id.s,
		2+2*sizeof(struct lb_dst*), "%X", id);

	dst->id = id;
	dst->group = group;
	dst->rmap_no = lb_rl->n;
	dst->flags = flags;

	/* add or update resource list */
	for( i=0 ; i<lb_rl->n ; i++) {
		r = lb_rl->resources + i;
		LM_DBG(" setting for uri=<%s> (%d) resource=<%.*s>, val=%d\n",
			uri, data->dst_no+1, r->name.len, r->name.s, r->val);
		res = get_resource_by_name( data, &r->name);
		if (res==NULL) {
			/* add new resource */
			res = add_lb_resource(data, &r->name);
			if (res==NULL) {
				LM_ERR("failed to create new resource\n");
				goto error;
			}
		}
		/* set the proper bit in the resource */
		if (lb_set_resource_bitmask( res, data->dst_no)==-1 ) {
			LM_ERR("failed to set destination bit\n");
			goto error;
		}
		/* set the pointer and the max load */
		dst->rmap[i].resource = res;
		dst->rmap[i].max_load = r->val;
	}

	/* Do a SIP wise DNS-Lookup for the domain part */
	proxy = mk_proxy( &puri.host, puri.port_no, puri.proto,
		(puri.type==SIPS_URI_T));
	if (proxy==NULL) {
		LM_ERR("could not resolve %.*s\n", puri.host.len, puri.host.s);
		goto error;
	}
	hostent2ip_addr( &dst->ips[0], &proxy->host, proxy->addr_idx);
	dst->ports[0] = proxy->port;
	dst->ips_cnt = 1;
	LM_DBG("first dst ip addr [%s]:%d\n",
		ip_addr2a(&dst->ips[0]), dst->ports[0]);
	/* get the next available IPs from DNS */
	while (dst->ips_cnt<LB_MAX_IPS && (get_next_su( proxy, &sau, 0)==0) ) {
		su2ip_addr( &dst->ips[dst->ips_cnt], &sau);
		dst->ports[dst->ips_cnt] = proxy->port;
		LM_DBG("additional dst ip addr [%s]:%d\n",
			ip_addr2a(&dst->ips[dst->ips_cnt]), dst->ports[dst->ips_cnt]);
		/* one more IP found */
		dst->ips_cnt++;
	}
	/* free al the helper structures */
	free_proxy(proxy);
	pkg_free(proxy);

	/* link at the end */
	if (data->last_dst==NULL) {
		data->dsts = data->last_dst = dst;
	} else {
		data->last_dst->next = dst;
		data->last_dst = dst;
	}
	data->dst_no++;

	pkg_free(lb_rl);
	return 0;
error:
	shm_free(dst);
	pkg_free(lb_rl);
	return -1;
}
Example #30
0
static void trace_onreply_out(struct cell* t, int type, struct tmcb_params *ps)
{
	int faked = 0;
	static char fromip_buff[IP_ADDR_MAX_STR_SIZE+12];
	static char toip_buff[IP_ADDR_MAX_STR_SIZE+12];
	struct sip_msg* msg;
	struct sip_msg* req;
	int_str        avp_value;
	struct usr_avp *avp;
	struct ip_addr to_ip;
	int len;
	char statusbuf[8];
	str *sbuf;
	struct dest_info *dst;

	if (t==NULL || t->uas.request==0 || ps==NULL)
	{
		LM_DBG("no uas request, local transaction\n");
		return;
	}

	LM_DBG("trace onreply out \n");

	avp = NULL;
	if(traced_user_avp>=0)
		avp=search_first_avp(traced_user_avp_type, traced_user_avp,
				&avp_value, 0);

	req = ps->req;
	msg = ps->rpl;
	if(msg==NULL || msg==FAKED_REPLY)
	{
		msg = t->uas.request;
		faked = 1;
	}

	if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL)
	{
		LM_ERR("cannot parse FROM header\n");
		goto error;
	}

	if(parse_headers(msg, HDR_CALLID_F, 0)!=0)
	{
		LM_ERR("cannot parse call-id\n");
		return;
	}

	sbuf = (str*)ps->extra1;
	if(faked==0)
	{
		if(sbuf!=0 && sbuf->len>0) {
			db_vals[0].val.blob_val.s   = sbuf->s;
			db_vals[0].val.blob_val.len = sbuf->len;
		} else if(t->uas.response.buffer.s!=NULL) {
			db_vals[0].val.blob_val.s   = t->uas.response.buffer.s;
			db_vals[0].val.blob_val.len = t->uas.response.buffer.len;
		} else if(msg->len>0) {
			db_vals[0].val.blob_val.s   = msg->buf;
			db_vals[0].val.blob_val.len = msg->len;
		} else {
			db_vals[0].val.blob_val.s   = "No reply buffer";
			db_vals[0].val.blob_val.len = sizeof("No reply buffer")-1;
		}
	} else {
		if(sbuf!=0 && sbuf->len>0) {
			db_vals[0].val.blob_val.s   = sbuf->s;
			db_vals[0].val.blob_val.len = sbuf->len;
		} else if(t->uas.response.buffer.s==NULL) {
			db_vals[0].val.blob_val.s = "No reply buffer";
			db_vals[0].val.blob_val.len = sizeof("No reply buffer")-1;
		} else {
			db_vals[0].val.blob_val.s = t->uas.response.buffer.s;
			db_vals[0].val.blob_val.len = t->uas.response.buffer.len;
		}
	}

	/* check Call-ID header */
	if(msg->callid==NULL || msg->callid->body.s==NULL)
	{
		LM_ERR("cannot find Call-ID header!\n");
		goto error;
	}

	db_vals[1].val.str_val.s = msg->callid->body.s;
	db_vals[1].val.str_val.len = msg->callid->body.len;

	db_vals[2].val.str_val.s = t->method.s;
	db_vals[2].val.str_val.len = t->method.len;


	if(trace_local_ip.s && trace_local_ip.len > 0){
		set_columns_to_trace_local_ip(db_vals[4], db_vals[5], db_vals[6]);
	}
	else {
		set_sock_columns( db_vals[4], db_vals[5], db_vals[6], fromip_buff,
			&msg->rcv.dst_ip, msg->rcv.dst_port, msg->rcv.proto);
	}

	strcpy(statusbuf, int2str(ps->code, &len));
	db_vals[3].val.str_val.s = statusbuf;
	db_vals[3].val.str_val.len = len;

	memset(&to_ip, 0, sizeof(struct ip_addr));
	dst = (struct dest_info*)ps->extra2;
	if(dst==0)
	{
		set_columns_to_any( db_vals[7], db_vals[8], db_vals[9]);
	} else {
		su2ip_addr(&to_ip, &dst->to);
		set_sock_columns( db_vals[7], db_vals[8], db_vals[9], toip_buff,
			&to_ip, (unsigned long)su_getport(&dst->to), dst->proto);
	}

	db_vals[10].val.time_val = time(NULL);

	db_vals[11].val.string_val = "out";

	db_vals[12].val.str_val.s = get_from(msg)->tag_value.s;
	db_vals[12].val.str_val.len = get_from(msg)->tag_value.len;

	if (save_siptrace(req,avp,&avp_value,db_keys,db_vals) < 0) {
		LM_ERR("failed to save siptrace\n");
		goto error;
	}

#ifdef STATISTICS
	update_stat(siptrace_rpl, 1);
#endif
	return;
error:
	return;
}