! \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 */
| 91 | * multihomed hosts |
| 92 | */ |
| 93 | const struct socket_info* get_out_socket(const union sockaddr_union* to, int proto) |
| 94 | { |
| 95 | int temp_sock; |
| 96 | socklen_t len; |
| 97 | union sockaddr_union from; |
| 98 | const struct socket_info* si; |
| 99 | struct ip_addr ip, ip_dst; |
| 100 | |
| 101 | if (proto!=PROTO_UDP) { |
| 102 | LM_CRIT("can only be called for UDP\n"); |
| 103 | return 0; |
| 104 | } |
| 105 | |
| 106 | temp_sock=socket(to->s.sa_family, SOCK_DGRAM, 0 ); |
| 107 | if (temp_sock==-1) { |
| 108 | LM_ERR("socket() failed: %s\n", strerror(errno)); |
| 109 | return 0; |
| 110 | } |
| 111 | if (connect(temp_sock, &to->s, sockaddru_len(*to))==-1) { |
| 112 | LM_ERR("connect failed: %s\n", strerror(errno)); |
| 113 | goto error; |
| 114 | } |
| 115 | len=sizeof(from); |
| 116 | if (getsockname(temp_sock, &from.s, &len)==-1) { |
| 117 | LM_ERR("getsockname failed: %s\n", strerror(errno)); |
| 118 | goto error; |
| 119 | } |
| 120 | su2ip_addr(&ip, &from); |
| 121 | si=find_si(&ip, 0, proto); |
| 122 | if (si==0) { |
| 123 | LM_ERR("outbound IP %s not found as listener\n", ip_addr2a(&ip)); |
| 124 | goto error; |
| 125 | } |
| 126 | close(temp_sock); |
| 127 | LM_DBG("socket determined: %p\n", si ); |
| 128 | return si; |
| 129 | error: |
| 130 | su2ip_addr( &ip_dst, to); |
| 131 | LM_ERR("failed to find route to %s\n", ip_addr2a(&ip_dst)); |
| 132 | close(temp_sock); |
| 133 | return 0; |
| 134 | } |
| 135 | |
| 136 | |
| 137 |
no test coverage detected