]> source.dussan.org Git - rspamd.git/commitdiff
[Fix] Try to deal with v4 mapped to v6 addresses on accept
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 17 May 2017 17:57:06 +0000 (18:57 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 17 May 2017 17:57:36 +0000 (18:57 +0100)
src/libutil/addr.c

index 5a1e9cf6ed733647a58a8bf50b512537dee37f8d..1687c80bd32ec656f1c8e21867ba9e1fdf62f228 100644 (file)
@@ -257,25 +257,52 @@ rspamd_accept_from_socket (gint sock, rspamd_inet_addr_t **target,
                return -1;
        }
 
-       addr = rspamd_inet_addr_create (su.sa.sa_family);
-       addr->slen = len;
+       if (su.sa.sa_family == AF_INET6) {
+               /* Deal with bloody v4 mapped to v6 addresses */
 
-       if (addr->af == AF_UNIX) {
-               addr->u.un = g_slice_alloc0 (sizeof (*addr->u.un));
-               /* Get name from the listening socket */
-               len = sizeof (su);
+               static const guint8 mask[] = {
+                               0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+               };
+               const guint8 *p;
 
-               if (getsockname (sock, &su.sa, &len) != -1) {
-                       memcpy (&addr->u.un->addr, &su.su, MIN (len,
-                                       sizeof (struct sockaddr_un)));
-               }
-               else {
-                       /* Just copy socket address */
-                       memcpy (&addr->u.un->addr, &su.sa, sizeof (struct sockaddr));
+               if (memcmp ((const guint8 *)&su.s6.sin6_addr, mask, sizeof (mask)) == 0) {
+                       p = (const guint8 *)&su.s6.sin6_addr;
+
+                       if ((p[10] == 0xff && p[11] == 0xff)) {
+                               addr = rspamd_inet_addr_create (AF_INET);
+                               memcpy (&addr->u.in.addr.s4.sin_addr, &p[12],
+                                               sizeof (struct in_addr));
+                       }
+                       else {
+                               /* Something strange but not mapped v4 address */
+                               addr = rspamd_inet_addr_create (AF_INET6);
+                               memcpy (&addr->u.in.addr.s6.sin6_addr, &su.s6.sin6_addr,
+                                               sizeof (struct in6_addr));
+                       }
                }
+
        }
        else {
-               memcpy (&addr->u.in.addr, &su, MIN (len, sizeof (addr->u.in.addr)));
+               addr = rspamd_inet_addr_create (su.sa.sa_family);
+               addr->slen = len;
+
+               if (addr->af == AF_UNIX) {
+                       addr->u.un = g_slice_alloc0 (sizeof (*addr->u.un));
+                       /* Get name from the listening socket */
+                       len = sizeof (su);
+
+                       if (getsockname (sock, &su.sa, &len) != -1) {
+                               memcpy (&addr->u.un->addr, &su.su, MIN (len,
+                                               sizeof (struct sockaddr_un)));
+                       }
+                       else {
+                               /* Just copy socket address */
+                               memcpy (&addr->u.un->addr, &su.sa, sizeof (struct sockaddr));
+                       }
+               }
+               else {
+                       memcpy (&addr->u.in.addr, &su, MIN (len, sizeof (addr->u.in.addr)));
+               }
        }
 
        if (rspamd_socket_nonblocking (nfd) < 0) {