Esempio n. 1
0
/*! \brief returns a socket_info pointer to the sending socket or 0 on error
 * \param msg SIP message (can be null)
 * \param to  destination socket_union pointer
 * \param proto protocol
 *
 * \note if msg!=null and msg->force_send_socket, the force_send_socket will be used
 */
struct socket_info* get_send_socket(struct sip_msg *msg,
										union sockaddr_union* to, int proto)
{
	struct socket_info* send_sock;

	/* check if send interface is not forced */
	if (msg && msg->force_send_socket){
		if (msg->force_send_socket->proto!=proto){
			LM_DBG("force_send_socket of different proto (%d)!\n", proto);
			msg->force_send_socket=find_si(&(msg->force_send_socket->address),
											msg->force_send_socket->port_no,
											proto);
		}
		if (msg->force_send_socket && (msg->force_send_socket->socket!=-1))
			return msg->force_send_socket;
		else{
			if (msg->force_send_socket && msg->force_send_socket->socket==-1)
				LM_WARN("not listening on the requested socket, no fork mode?\n");
			else
				LM_WARN("protocol/port mismatch\n");
		}
	};

	if (mhomed && proto==PROTO_UDP){
		send_sock=get_out_socket(to, proto);
		if ((send_sock==0) || (send_sock->socket!=-1))
			return send_sock; /* found or error*/
		else if (send_sock->socket==-1){
			LM_WARN("not listening on the requested socket, no fork mode?\n");
			/* continue: try to use some socket */
		}
	}

	send_sock=0;
	/* check if we need to change the socket (different address families -
	 * eg: ipv4 -> ipv6 or ipv6 -> ipv4) */
	switch(proto){
		case PROTO_UDP:
			if ((bind_address)&&(to->s.sa_family==bind_address->address.af)&&
			(bind_address->proto==PROTO_UDP)) {
				send_sock = (msg &&
				msg->rcv.bind_address->address.af==bind_address->address.af &&
				msg->rcv.bind_address->proto==bind_address->proto) ?
					msg->rcv.bind_address : bind_address;
				break;
			}
			/* default logic for all protos */
		default:
			/* we don't really now the sending address (we can find it out,
			 * but we'll need also to see if we listen on it, and if yes on
			 * which port -> too complicated*/
			send_sock = (to->s.sa_family==AF_INET) ?
				protos[proto].sendipv4 : protos[proto].sendipv6;
	}
	return send_sock;
}
Esempio n. 2
0
/**
 * @brief Initialize module children
 */
static int child_init(int rank)
{
	if(rank!=PROC_INIT)
		return 0;

	_lc_udp_dst.proto = PROTO_UDP;
	_lc_udp_dst.send_sock=get_send_socket(NULL, &_lc_udp_dst.to, PROTO_UDP);
	if (_lc_udp_dst.send_sock==0) {
		_lc_udp_dst.send_sock = get_out_socket(&_lc_udp_dst.to, PROTO_UDP);
		if (_lc_udp_dst.send_sock==0) {
			LM_ERR("failed to get send socket\n");
			return -1;
		}
	}
	LM_DBG("setting udp-send custom logging function\n");
	km_log_func_set(&_lc_core_log_udp);
	_lc_log_udp = 1;



	return 0;
}
Esempio n. 3
0
/** get the sending socket for a corresponding destination.
 * @param force_send_socket - if !=0 and the protocol and af correspond
 *                            with the destination, it will be returned.
 *                            If the protocol or af check fail, a look-alike
 *                            socket will be searched for and mismatch will be
 *                            set. If no look-alike socket is found it will
 *                            fallback to normal resolution.
 * @param to - destination
 * @param proto - protocol
 * @param mismatch - result parameter, set if a force_send_socket was used, but
 *                   there was an error matching it exactly to the destination.
 *                   Possible values: 0 ok, SS_MISMATCH_PROTO,
 *                   SS_MISMATCH_ADDR, SS_MISMATCH_AF, SS_MISMATCH_MCAST.
 * @return a socket_info pointer to the sending socket on success (and possibly
 *         sets mismatch) or 0 on error.
 */
struct socket_info* get_send_socket2(struct socket_info* force_send_socket,
										union sockaddr_union* to, int proto,
										enum ss_mismatch* mismatch)
{
	struct socket_info* send_sock;
	struct socket_info* orig;
	
	if (likely(mismatch)) *mismatch=0;
	/* check if send interface is not forced */
	if (unlikely(force_send_socket)){
		orig=force_send_socket;
		/* Special case here as there is no ;transport=wss - so wss connections will
		   appear as ws ones and be sorted out in the WebSocket module */
		if (unlikely(orig->proto!=proto && !(orig->proto==PROTO_TLS && proto==PROTO_WS))){
			force_send_socket=find_si(&(force_send_socket->address),
											force_send_socket->port_no,
											proto);
			if (unlikely(force_send_socket == 0)){
				if (likely(mismatch)) *mismatch=SS_MISMATCH_ADDR;
				LOG(L_WARN, "WARNING: get_send_socket: "
						"protocol/port mismatch (forced %s:%s:%d,"
						" to %s:%s)\n",
						proto2a(orig->proto), ip_addr2a(&orig->address),
						orig->port_no,
						proto2a(proto), su2a(to, sizeof(*to)));
				goto not_forced;
			}
			if (likely(mismatch)) *mismatch=SS_MISMATCH_PROTO;
		}
		if (unlikely(force_send_socket->address.af!=to->s.sa_family)){
			DBG("get_send_socket: force_send_socket of different af"
					" (dst %d - %s:%s forced %d -%s:%s:%d)\n",
					to->s.sa_family, proto2a(proto), su2a(to, sizeof(*to)),
					force_send_socket->address.af,
					proto2a(force_send_socket->proto),
					ip_addr2a(&force_send_socket->address),
					force_send_socket->port_no);
			if (likely(mismatch)) *mismatch=SS_MISMATCH_AF;
			goto not_forced;
		}
		/* check if listening on the socket (the check does not work
		   for TCP and TLS, for them socket==-1 on all the processes
		   except tcp_main(), see close_extra_socks() */
		if (likely((force_send_socket->socket!=-1 ||
						force_send_socket->proto==PROTO_TCP ||
						force_send_socket->proto==PROTO_TLS ||
						force_send_socket->proto==PROTO_WS  ||
						force_send_socket->proto==PROTO_WSS) &&
					!(force_send_socket->flags & SI_IS_MCAST)))
				return force_send_socket;
		else{
			if (!(force_send_socket->flags & SI_IS_MCAST))
				LOG(L_WARN, "WARNING: get_send_socket: not listening"
							 " on the requested socket (%s:%s:%d),"
							 " no fork mode?\n",
							proto2a(force_send_socket->proto),
							ip_addr2a(&force_send_socket->address),
							force_send_socket->port_no);
			else if (likely(mismatch)) *mismatch=SS_MISMATCH_MCAST;
		}
	};
not_forced:
	if (mhomed && proto==PROTO_UDP){
		send_sock=get_out_socket(to, proto);
		if ((send_sock==0) || (send_sock->socket!=-1))
			return send_sock; /* found or error*/
		else if (send_sock->socket==-1){
			LOG(L_WARN, "WARNING: get_send_socket: not listening on the"
					" requested socket (%s:%s:%d), no fork mode?\n",
					proto2a(send_sock->proto), ip_addr2a(&send_sock->address),
					send_sock->port_no);
			/* continue: try to use some socket */
		}
	}

	send_sock=0;
	/* check if we need to change the socket (different address families -
	 * eg: ipv4 -> ipv6 or ipv6 -> ipv4) */
	switch(proto){
#ifdef USE_TCP
		case PROTO_WS:
		case PROTO_TCP:
		/* on tcp just use the "main address", we don't really now the
		 * sending address (we can find it out, but we'll need also to see
		 * if we listen on it, and if yes on which port -> too complicated*/
			switch(to->s.sa_family){
				/* FIXME */
				case AF_INET:	send_sock=sendipv4_tcp;
								break;
#ifdef USE_IPV6
				case AF_INET6:	send_sock=sendipv6_tcp;
								break;
#endif
				default:	LOG(L_ERR, "get_send_socket: BUG: don't know how"
									" to forward to af %d\n", to->s.sa_family);
			}
			break;
#endif
#ifdef USE_TLS
		case PROTO_WSS:
		case PROTO_TLS:
			switch(to->s.sa_family){
				/* FIXME */
				case AF_INET:	send_sock=sendipv4_tls;
								break;
#ifdef USE_IPV6
				case AF_INET6:	send_sock=sendipv6_tls;
								break;
#endif
				default:	LOG(L_ERR, "get_send_socket: BUG: don't know how"
									" to forward to af %d\n", to->s.sa_family);
			}
			break;
#endif /* USE_TLS */
#ifdef USE_SCTP
		case PROTO_SCTP:
			if ((bind_address==0) ||
					(to->s.sa_family!=bind_address->address.af) ||
					(bind_address->proto!=PROTO_SCTP)){
				switch(to->s.sa_family){
					case AF_INET:	send_sock=sendipv4_sctp;
									break;
#ifdef USE_IPV6
					case AF_INET6:	send_sock=sendipv6_sctp;
									break;
#endif
					default:	LOG(L_ERR, "get_send_socket: BUG: don't know"
										" how to forward to af %d\n",
										to->s.sa_family);
				}
			}else send_sock=bind_address;
			break;
#endif /* USE_SCTP */
		case PROTO_UDP:
			if ((bind_address==0) ||
					(to->s.sa_family!=bind_address->address.af) ||
					(bind_address->proto!=PROTO_UDP)){
				switch(to->s.sa_family){
					case AF_INET:	send_sock=sendipv4;
									break;
#ifdef USE_IPV6
					case AF_INET6:	send_sock=sendipv6;
									break;
#endif
					default:	LOG(L_ERR, "get_send_socket: BUG: don't know"
										" how to forward to af %d\n",
										to->s.sa_family);
				}
			}else send_sock=bind_address;
			break;
		default:
			LOG(L_CRIT, "BUG: get_send_socket: unsupported proto %d (%s)\n",
					proto, proto2a(proto));
	}
	return send_sock;
}
Esempio n. 4
0
/*! \brief returns a socket_info pointer to the sending socket or 0 on error
 * \param msg SIP message (can be null)
 * \param to  destination socket_union pointer
 * \param proto protocol 
 *
 * \note if msg!=null and msg->force_send_socket, the force_send_socket will be used
 */
struct socket_info* get_send_socket(struct sip_msg *msg, 
										union sockaddr_union* to, int proto)
{
	struct socket_info* send_sock;
	
	/* check if send interface is not forced */
	if (msg && msg->force_send_socket){
		if (msg->force_send_socket->proto!=proto){
			LM_DBG("force_send_socket of different proto (%d)!\n", proto);
			msg->force_send_socket=find_si(&(msg->force_send_socket->address),
											msg->force_send_socket->port_no,
											proto);
		}
		if (msg->force_send_socket && (msg->force_send_socket->socket!=-1)) 
			return msg->force_send_socket;
		else{
			if (msg->force_send_socket && msg->force_send_socket->socket==-1)
				LM_WARN("not listening on the requested socket, no fork mode?\n");
			else
				LM_WARN("protocol/port mismatch\n");
		}
	};

	if (mhomed && proto==PROTO_UDP){
		send_sock=get_out_socket(to, proto);
		if ((send_sock==0) || (send_sock->socket!=-1))
			return send_sock; /* found or error*/
		else if (send_sock->socket==-1){
			LM_WARN("not listening on the requested socket, no fork mode?\n");
			/* continue: try to use some socket */
		}
	}

	send_sock=0;
	/* check if we need to change the socket (different address families -
	 * eg: ipv4 -> ipv6 or ipv6 -> ipv4) */
	switch(proto){
#ifdef USE_TCP
		case PROTO_TCP:
		/* on tcp just use the "main address", we don't really now the
		 * sending address (we can find it out, but we'll need also to see
		 * if we listen on it, and if yes on which port -> too complicated*/
			switch(to->s.sa_family){
				/* FIXME */
				case AF_INET:	send_sock=sendipv4_tcp;
								break;
#ifdef USE_IPV6
				case AF_INET6:	send_sock=sendipv6_tcp;
								break;
#endif
				default:	LM_ERR("don't know how to forward to af %d\n", 
								to->s.sa_family);
			}
			break;
#endif
#ifdef USE_TLS
		case PROTO_TLS:
			switch(to->s.sa_family){
				/* FIXME */
				case AF_INET:	send_sock=sendipv4_tls;
								break;
#ifdef USE_IPV6
				case AF_INET6:	send_sock=sendipv6_tls;
								break;
#endif
				default:	LM_ERR("don't know how"
									" to forward to af %d\n", to->s.sa_family);
			}
			break;
#endif /* USE_TLS */
#ifdef USE_SCTP
		case PROTO_SCTP:
			switch(to->s.sa_family){
				case AF_INET:	send_sock=sendipv4_sctp;
								break;
#ifdef USE_IPV6
				case AF_INET6:	send_sock=sendipv6_sctp;
								break;
#endif
				default:	LM_ERR("don't know how to forward to af %d\n", 
								to->s.sa_family);
			}
			break;
#endif /* USE_SCTP */
		case PROTO_UDP:
			if ((bind_address==0)||(to->s.sa_family!=bind_address->address.af)||
				  (bind_address->proto!=PROTO_UDP)){
				switch(to->s.sa_family){
					case AF_INET:	send_sock=sendipv4;
									break;
#ifdef USE_IPV6
					case AF_INET6:	send_sock=sendipv6;
									break;
#endif
					default:	LM_ERR("don't know how to forward to af %d\n",
										to->s.sa_family);
				}
			}else send_sock=bind_address;
			break;
		default:
			LM_CRIT("unknown proto %d\n", proto);
	}
	return send_sock;
}