/*! \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; }
/** * @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; }
/** 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; }
/*! \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; }