static bool test_socket_wrapper_default_iface(struct torture_context *tctx) { backup_env(); unsetenv("SOCKET_WRAPPER_DEFAULT_IFACE"); torture_assert_int_equal(tctx, socket_wrapper_default_iface(), 1, "unset"); setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "2", 1); torture_assert_int_equal(tctx, socket_wrapper_default_iface(), 2, "unset"); setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "bla", 1); torture_assert_int_equal(tctx, socket_wrapper_default_iface(), 1, "unset"); restore_env(); return true; }
static PyObject *py_socket_wrapper_default_interface(PyObject *self) { unsigned int id; id = socket_wrapper_default_iface(); return PyInt_FromLong(id); }
static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un, int *bcast) { char type = '\0'; unsigned int prt; unsigned int iface; struct stat st; int is_bcast = 0; if (bcast) *bcast = 0; switch (si->family) { case AF_INET: { const struct sockaddr_in *in = (const struct sockaddr_in *)inaddr; unsigned int addr = ntohl(in->sin_addr.s_addr); char u_type = '\0'; char d_type = '\0'; char b_type = '\0'; char a_type = '\0'; prt = ntohs(in->sin_port); switch (si->type) { case SOCK_STREAM: u_type = SOCKET_TYPE_CHAR_TCP; d_type = SOCKET_TYPE_CHAR_TCP; break; case SOCK_DGRAM: u_type = SOCKET_TYPE_CHAR_UDP; d_type = SOCKET_TYPE_CHAR_UDP; a_type = SOCKET_TYPE_CHAR_UDP; b_type = SOCKET_TYPE_CHAR_UDP; break; } if (addr == 0) { /* 0.0.0.0 */ is_bcast = 0; type = d_type; iface = socket_wrapper_default_iface(); } else if (a_type && addr == 0xFFFFFFFF) { /* 255.255.255.255 only udp */ is_bcast = 2; type = a_type; iface = socket_wrapper_default_iface(); } else if (b_type && addr == 0x7FFFFFFF) { /* 127.255.255.255 only udp */ is_bcast = 1; type = b_type; iface = socket_wrapper_default_iface(); } else if ((addr & 0xFFFFFF00) == 0x7F000000) { /* 127.0.0.X */ is_bcast = 0; type = u_type; iface = (addr & 0x000000FF); } else { errno = EADDRNOTAVAIL; return -1; } break; } #ifdef HAVE_IPV6 case AF_INET6: { const struct sockaddr_in6 *in = (const struct sockaddr_in6 *)inaddr; struct in6_addr cmp; switch (si->type) { case SOCK_STREAM: type = SOCKET_TYPE_CHAR_TCP_V6; break; case SOCK_DGRAM: type = SOCKET_TYPE_CHAR_UDP_V6; break; } /* XXX no multicast/broadcast */ prt = ntohs(in->sin6_port); cmp = in->sin6_addr; cmp.s6_addr[15] = 0; if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) { iface = socket_wrapper_default_iface(); } else if (IN6_ARE_ADDR_EQUAL(swrap_ipv6(), &cmp)) { iface = in->sin6_addr.s6_addr[15]; } else { errno = EADDRNOTAVAIL; return -1; } break; } #endif default: errno = EADDRNOTAVAIL; return -1; } if (bcast) *bcast = is_bcast; if (prt == 0) { /* handle auto-allocation of ephemeral ports */ for (prt = 5001; prt < 10000; prt++) { snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, socket_wrapper_dir(), type, iface, prt); if (stat(un->sun_path, &st) == 0) continue; set_port(si->family, prt, si->myname); break; } if (prt == 10000) { errno = ENFILE; return -1; } } snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, socket_wrapper_dir(), type, iface, prt); return 0; }
static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un, int *bcast) { char type = '\0'; unsigned int prt; unsigned int iface; int is_bcast = 0; if (bcast) *bcast = 0; switch (si->family) { case AF_INET: { const struct sockaddr_in *in = (const struct sockaddr_in *)inaddr; unsigned int addr = ntohl(in->sin_addr.s_addr); char u_type = '\0'; char b_type = '\0'; char a_type = '\0'; switch (si->type) { case SOCK_STREAM: u_type = SOCKET_TYPE_CHAR_TCP; break; case SOCK_DGRAM: u_type = SOCKET_TYPE_CHAR_UDP; a_type = SOCKET_TYPE_CHAR_UDP; b_type = SOCKET_TYPE_CHAR_UDP; break; } prt = ntohs(in->sin_port); if (a_type && addr == 0xFFFFFFFF) { /* 255.255.255.255 only udp */ is_bcast = 2; type = a_type; iface = socket_wrapper_default_iface(); } else if (b_type && addr == 0x7FFFFFFF) { /* 127.255.255.255 only udp */ is_bcast = 1; type = b_type; iface = socket_wrapper_default_iface(); } else if ((addr & 0xFFFFFF00) == 0x7F000000) { /* 127.0.0.X */ is_bcast = 0; type = u_type; iface = (addr & 0x000000FF); } else { errno = ENETUNREACH; return -1; } if (bcast) *bcast = is_bcast; break; } #ifdef HAVE_IPV6 case AF_INET6: { const struct sockaddr_in6 *in = (const struct sockaddr_in6 *)inaddr; struct in6_addr cmp; switch (si->type) { case SOCK_STREAM: type = SOCKET_TYPE_CHAR_TCP_V6; break; case SOCK_DGRAM: type = SOCKET_TYPE_CHAR_UDP_V6; break; } /* XXX no multicast/broadcast */ prt = ntohs(in->sin6_port); cmp = in->sin6_addr; cmp.s6_addr[15] = 0; if (IN6_ARE_ADDR_EQUAL(swrap_ipv6(), &cmp)) { iface = in->sin6_addr.s6_addr[15]; } else { errno = ENETUNREACH; return -1; } break; } #endif default: errno = ENETUNREACH; return -1; } if (prt == 0) { errno = EINVAL; return -1; } if (is_bcast) { snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL", socket_wrapper_dir()); /* the caller need to do more processing */ return 0; } snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, socket_wrapper_dir(), type, iface, prt); return 0; }
/* using sendto() or connect() on an unbound socket would give the recipient no way to reply, as unlike UDP and TCP, a unix domain socket can't auto-assign emphemeral port numbers, so we need to assign it here. Note: this might change the family from ipv6 to ipv4 */ static int swrap_auto_bind(struct socket_info *si, int family) { struct sockaddr_un un_addr; int i; char type; int ret; int port; struct stat st; if (autobind_start_init != 1) { autobind_start_init = 1; autobind_start = getpid(); autobind_start %= 50000; autobind_start += 10000; } un_addr.sun_family = AF_UNIX; switch (family) { case AF_INET: { struct sockaddr_in in; switch (si->type) { case SOCK_STREAM: type = SOCKET_TYPE_CHAR_TCP; break; case SOCK_DGRAM: type = SOCKET_TYPE_CHAR_UDP; break; default: errno = ESOCKTNOSUPPORT; return -1; } memset(&in, 0, sizeof(in)); in.sin_family = AF_INET; in.sin_addr.s_addr = htonl(127<<24 | socket_wrapper_default_iface()); si->myname_len = sizeof(in); si->myname = sockaddr_dup(&in, si->myname_len); break; } #ifdef HAVE_IPV6 case AF_INET6: { struct sockaddr_in6 in6; if (si->family != family) { errno = ENETUNREACH; return -1; } switch (si->type) { case SOCK_STREAM: type = SOCKET_TYPE_CHAR_TCP_V6; break; case SOCK_DGRAM: type = SOCKET_TYPE_CHAR_UDP_V6; break; default: errno = ESOCKTNOSUPPORT; return -1; } memset(&in6, 0, sizeof(in6)); in6.sin6_family = AF_INET6; in6.sin6_addr = *swrap_ipv6(); in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface(); si->myname_len = sizeof(in6); si->myname = sockaddr_dup(&in6, si->myname_len); break; } #endif default: errno = ESOCKTNOSUPPORT; return -1; } if (autobind_start > 60000) { autobind_start = 10000; } for (i=0;i<1000;i++) { port = autobind_start + i; snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT, socket_wrapper_dir(), type, socket_wrapper_default_iface(), port); if (stat(un_addr.sun_path, &st) == 0) continue; ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr)); if (ret == -1) return ret; si->tmp_path = strdup(un_addr.sun_path); si->bound = 1; autobind_start = port + 1; break; } if (i == 1000) { errno = ENFILE; return -1; } si->family = family; set_port(si->family, port, si->myname); return 0; }
static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un, int *bcast) { char u_type = '\0'; char d_type = '\0'; char b_type = '\0'; char a_type = '\0'; char type = '\0'; unsigned int addr= ntohl(in->sin_addr.s_addr); unsigned int prt = ntohs(in->sin_port); unsigned int iface; struct stat st; int is_bcast = 0; if (bcast) *bcast = 0; switch (si->type) { case SOCK_STREAM: u_type = SOCKET_TYPE_CHAR_TCP; d_type = SOCKET_TYPE_CHAR_TCP; break; case SOCK_DGRAM: u_type = SOCKET_TYPE_CHAR_UDP; d_type = SOCKET_TYPE_CHAR_UDP; a_type = SOCKET_TYPE_CHAR_UDP; b_type = SOCKET_TYPE_CHAR_UDP; break; } if (addr == 0) { /* 0.0.0.0 */ is_bcast = 0; type = d_type; iface = socket_wrapper_default_iface(); } else if (a_type && addr == 0xFFFFFFFF) { /* 255.255.255.255 only udp */ is_bcast = 2; type = a_type; iface = socket_wrapper_default_iface(); } else if (b_type && addr == 0x7FFFFFFF) { /* 127.255.255.255 only udp */ is_bcast = 1; type = b_type; iface = socket_wrapper_default_iface(); } else if ((addr & 0xFFFFFF00) == 0x7F000000) { /* 127.0.0.X */ is_bcast = 0; type = u_type; iface = (addr & 0x000000FF); } else { errno = EADDRNOTAVAIL; return -1; } if (bcast) *bcast = is_bcast; if (prt == 0) { /* handle auto-allocation of ephemeral ports */ for (prt = 5001; prt < 10000; prt++) { snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, socket_wrapper_dir(), type, iface, prt); if (stat(un->sun_path, &st) == 0) continue; ((struct sockaddr_in *)si->myname)->sin_port = htons(prt); return 0; } errno = ENFILE; return -1; } snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, socket_wrapper_dir(), type, iface, prt); return 0; }
static int convert_in_un_remote(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un, int *bcast) { char u_type = '\0'; char b_type = '\0'; char a_type = '\0'; char type = '\0'; unsigned int addr= ntohl(in->sin_addr.s_addr); unsigned int prt = ntohs(in->sin_port); unsigned int iface; int is_bcast = 0; if (bcast) *bcast = 0; if (prt == 0) { errno = EINVAL; return -1; } switch (si->type) { case SOCK_STREAM: u_type = SOCKET_TYPE_CHAR_TCP; break; case SOCK_DGRAM: u_type = SOCKET_TYPE_CHAR_UDP; a_type = SOCKET_TYPE_CHAR_UDP; b_type = SOCKET_TYPE_CHAR_UDP; break; } if (a_type && addr == 0xFFFFFFFF) { /* 255.255.255.255 only udp */ is_bcast = 2; type = a_type; iface = socket_wrapper_default_iface(); } else if (b_type && addr == 0x7FFFFFFF) { /* 127.255.255.255 only udp */ is_bcast = 1; type = b_type; iface = socket_wrapper_default_iface(); } else if ((addr & 0xFFFFFF00) == 0x7F000000) { /* 127.0.0.X */ is_bcast = 0; type = u_type; iface = (addr & 0x000000FF); } else { errno = ENETUNREACH; return -1; } if (bcast) *bcast = is_bcast; if (is_bcast) { snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL", socket_wrapper_dir()); /* the caller need to do more processing */ return 0; } snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, socket_wrapper_dir(), type, iface, prt); return 0; }