Add IPv6 support.
[srvx.git] / src / proto-common.c
index c740093c38edaf6b254a9c1e2f41e7a01f0bcded..b5e5118a02e246706df003fbfdc5f21fb122dd52 100644 (file)
@@ -134,7 +134,7 @@ create_socket_client(struct uplinkNode *target)
 
     log_module(MAIN_LOG, LOG_INFO, "Connecting to %s:%i...", addr, port);
 
-    socket_io_fd = ioset_connect((struct sockaddr*)cManager.uplink->bind_addr, sizeof(struct sockaddr), addr, port, 1, 0, NULL);
+    socket_io_fd = ioset_connect(cManager.uplink->bind_addr, cManager.uplink->bind_addr_len, addr, port, 1, 0, NULL);
     if (!socket_io_fd) {
         log_module(MAIN_LOG, LOG_ERROR, "Connection to uplink failed: %s (%d)", strerror(errno), errno);
         target->state = DISCONNECTED;
@@ -654,8 +654,8 @@ irc_make_chanmode(struct chanNode *chan, char *out)
 char *
 generate_hostmask(struct userNode *user, int options)
 {
-    char *nickname, *ident, *hostname;
-    char *mask;
+    irc_in_addr_t ip;
+    char *nickname, *ident, *hostname, *mask;
     int len, ii;
 
     /* figure out string parts */
@@ -680,32 +680,21 @@ generate_hostmask(struct userNode *user, int options)
     } else if (IsHiddenHost(user) && user->handle_info && hidden_host_suffix && !(options & GENMASK_NO_HIDING)) {
         hostname = alloca(strlen(user->handle_info->handle) + strlen(hidden_host_suffix) + 2);
         sprintf(hostname, "%s.%s", user->handle_info->handle, hidden_host_suffix);
-    } else if (options & GENMASK_STRICT_HOST) {
-        if (options & GENMASK_BYIP)
-            hostname = inet_ntoa(user->ip);
-    } else if ((options & GENMASK_BYIP) || !hostname[strspn(hostname, "0123456789.")]) {
-        /* Should generate an IP-based hostmask.  By popular acclaim, a /16
-         * hostmask is used by default. */
-        unsigned masked_ip, mask, masklen;
-        masklen = 16;
-        mask = ~0 << masklen;
-        masked_ip = ntohl(user->ip.s_addr) & mask;
-        hostname = alloca(32);
-        if (options & GENMASK_SRVXMASK) {
-            sprintf(hostname, "%d.%d.%d.%d/%d", (masked_ip>>24)&0xFF, (masked_ip>>16)&0xFF, (masked_ip>>8)&0xFF, masked_ip&0xFF, masklen);
+    } else if (options & GENMASK_STRICT_HOST && options & GENMASK_BYIP) {
+        hostname = (char*)irc_ntoa(&user->ip);
+    } else if ((options & GENMASK_BYIP) || irc_pton(&ip, NULL, hostname)) {
+        /* Should generate an IP-based hostmask. */
+        hostname = alloca(IRC_NTOP_MAX_SIZE);
+        hostname[IRC_NTOP_MAX_SIZE-1] = '\0';
+        if (irc_in_addr_is_ipv4(user->ip)) {
+            /* By popular acclaim, a /16 hostmask is used. */
+            sprintf(hostname, "%d.%d.*", user->ip.in6_8[12], user->ip.in6_8[13]);
+        } else if (irc_in_addr_is_ipv6(user->ip)) {
+            /* Who knows what the default mask should be?  Use a /48 to start with. */
+            sprintf(hostname, "%x:%x:%x:*", user->ip.in6[0], user->ip.in6[1], user->ip.in6[2]);
         } else {
-            int ofs = 0;
-            for (ii=0; ii<4; ii++) {
-                if (masklen) {
-                    ofs += sprintf(hostname+ofs, "%d.", (masked_ip>>24)&0xFF);
-                    masklen -= 8;
-                    masked_ip <<= 8;
-                } else {
-                    ofs += sprintf(hostname+ofs, "*.");
-                }
-            }
-            /* Truncate the last . */
-            hostname[ofs-1] = 0;
+            /* Unknown type; just copy IP directly. */
+            irc_ntop(hostname, IRC_NTOP_MAX_SIZE, &user->ip);
         }
     } else {
         int cnt;