firewall3: fix left shift on 64 bit systems in fw3_bitlen2netmask
[project/firewall3.git] / utils.c
diff --git a/utils.c b/utils.c
index d8a881c7552369150aa8da2c80bd68175301d765..b2fbe0223c6d7338600654c09750a7d2a5b9622a 100644 (file)
--- a/utils.c
+++ b/utils.c
@@ -529,7 +529,7 @@ write_zone_uci(struct uci_context *ctx, struct fw3_zone *z,
 
                for (ifa = ifaddr; ifa; ifa = ifa->ifa_next)
                {
-                       if (strcmp(dev->name, ifa->ifa_name))
+                       if (!ifa->ifa_addr || strcmp(dev->name, ifa->ifa_name))
                                continue;
 
                        if (ifa->ifa_addr->sa_family == AF_INET)
@@ -774,6 +774,7 @@ bool
 fw3_bitlen2netmask(int family, int bits, void *mask)
 {
        int i;
+       uint8_t rem, b;
        struct in_addr *v4;
        struct in6_addr *v6;
 
@@ -783,14 +784,17 @@ fw3_bitlen2netmask(int family, int bits, void *mask)
                        return false;
 
                v6 = mask;
-               i = abs(bits);
+               rem = abs(bits);
 
-               memset(v6->s6_addr, 0xff, i / 8);
-               memset(v6->s6_addr + (i / 8) + 1, 0, (128 - i) / 8);
-               v6->s6_addr[i / 8] = 0xff << (8 - (i & 7));
+               for (i = 0; i < sizeof(v6->s6_addr); i++)
+               {
+                       b = (rem > 8) ? 8 : rem;
+                       v6->s6_addr[i] = (uint8_t)(0xFF << (8 - b));
+                       rem -= b;
+               }
 
                if (bits < 0)
-                       for (i = 0; i < 16; i++)
+                       for (i = 0; i < sizeof(v6->s6_addr); i++)
                                v6->s6_addr[i] = ~v6->s6_addr[i];
        }
        else
@@ -799,7 +803,7 @@ fw3_bitlen2netmask(int family, int bits, void *mask)
                        return false;
 
                v4 = mask;
-               v4->s_addr = htonl(~((1 << (32 - abs(bits))) - 1));
+               v4->s_addr = bits ? htonl(~((1 << (32 - abs(bits))) - 1)) : 0;
 
                if (bits < 0)
                        v4->s_addr = ~v4->s_addr;
@@ -852,7 +856,7 @@ fw3_flush_conntrack(void *state)
                        {
                                for (ifa = ifaddr; ifa && !found; ifa = ifa->ifa_next)
                                {
-                                       if (strcmp(dev->name, ifa->ifa_name))
+                                       if (!ifa->ifa_addr || strcmp(dev->name, ifa->ifa_name))
                                                continue;
 
                                        sin = (struct sockaddr_in *)ifa->ifa_addr;