Improve support for IPv4 vs IPv6 virtual hosts (fixes SF bugs #1087699, #1087668).
[ircu2.10.12-pk.git] / ircd / os_generic.c
index 3f52e76cd1e9e0aa7ecd121b08ca8e240065b63d..f72bbe900bede427e86a6a9c2b2c47bc4d9c5b28 100644 (file)
@@ -107,21 +107,18 @@ int sockaddr_from_irc(struct sockaddr_in6 *v6, const struct irc_sockaddr *irc, i
     socklen_t slen;
     int family;
 
+    assert(irc != 0);
     slen = sizeof(sin6);
-    if ((0 <= compat_fd) && (0 == getsockname(compat_fd, (struct sockaddr*)&sin6, &slen)))
+    if ((0 <= compat_fd)
+        && (0 == getsockname(compat_fd, (struct sockaddr*)&sin6, &slen)))
         family = sin6.sin6_family;
-    else if (irc_in_addr_is_ipv4(&VirtualHost.addr))
+    else if ((irc == &VirtualHost_v4) || irc_in_addr_is_ipv4(&irc->addr))
         family = AF_INET;
     else
         family = AF_INET6;
 
     memset(v6, 0, sizeof(*v6));
-    if (!irc) {
-        memset(v6, 0, sizeof(v6));
-        v6->sin6_family = AF_INET6;
-        return sizeof(*v6);
-    }
-    else if ((family == AF_INET) && irc_in_addr_is_ipv4(&irc->addr)) {
+    if (family == AF_INET) {
         struct sockaddr_in *v4 = (struct sockaddr_in*)v6;
         v4->sin_family = AF_INET;
         memcpy(&v4->sin_addr, &irc->addr.in6_16[6], sizeof(v4->sin_addr));
@@ -150,6 +147,7 @@ void sockaddr_to_irc(const struct sockaddr_in *v4, struct irc_sockaddr *irc)
 
 int sockaddr_from_irc(struct sockaddr_in *v4, const struct irc_sockaddr *irc, int compat_fd)
 {
+    assert(irc != 0);
     v4->sin_family = AF_INET;
     if (irc) {
         assert(!irc->addr.in6_16[0] && !irc->addr.in6_16[1] && !irc->addr.in6_16[2] && !irc->addr.in6_16[3] && !irc->addr.in6_16[4] && (!irc->addr.in6_16[5] || irc->addr.in6_16[5] == 0xffff));
@@ -510,6 +508,7 @@ IOResult os_sendto_nonb(int fd, const char* buf, unsigned int length,
   errno = 0;
 
   size = sockaddr_from_irc(&addr, peer, fd);
+  assert((addr.sn_family == AF_INET) == irc_in_addr_is_ipv4(&peer->addr));
   if (-1 < (res = sendto(fd, buf, length, flags, (struct sockaddr*)&addr, size))) {
     if (count_out)
       *count_out = (unsigned) res;
@@ -611,6 +610,7 @@ int os_socket(const struct irc_sockaddr* local, int type, const char* port_name)
   struct sockaddr_native addr;
   int size, fd;
 
+  assert(local != 0);
   size = sockaddr_from_irc(&addr, local, -1);
   fd = socket(addr.sn_family, type, 0);
   if (fd < 0) {