]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
xtables-compat: fix wildcard detection
authorFlorian Westphal <fw@strlen.de>
Tue, 8 May 2018 10:45:25 +0000 (12:45 +0200)
committerFlorian Westphal <fw@strlen.de>
Thu, 10 May 2018 00:31:05 +0000 (02:31 +0200)
if (outiface[len] == '\0')

is always true. 'eth+' is stored as 'eth' with length 3, so
   "eth"[3] == 0.

'eth' is stored as 'eth\0' with length 4, so "eth\0"[4] is also true.
Add a helper for this, then use it.

Signed-off-by: Florian Westphal <fw@strlen.de>
iptables/nft-shared.c

index fcc33d28104fb2b94356c1b5037c16d1bc800089..ecc54024b00b11fae54058655e371573c61805b1 100644 (file)
@@ -217,6 +217,30 @@ bool is_same_interfaces(const char *a_iniface, const char *a_outiface,
        return true;
 }
 
+static void parse_ifname(const char *name, unsigned int len, char *dst, unsigned char *mask)
+{
+       if (len == 0)
+               return;
+
+       memcpy(dst, name, len);
+       if (name[len - 1] == '\0') {
+               if (mask)
+                       memset(mask, 0xff, len);
+               return;
+       }
+
+       if (len >= IFNAMSIZ)
+               return;
+
+       /* wildcard */
+       dst[len++] = '+';
+       if (len >= IFNAMSIZ)
+               return;
+       dst[len++] = 0;
+       if (mask)
+               memset(mask, 0xff, len + 1);
+}
+
 int parse_meta(struct nftnl_expr *e, uint8_t key, char *iniface,
                unsigned char *iniface_mask, char *outiface,
                unsigned char *outiface_mask, uint8_t *invflags)
@@ -249,30 +273,14 @@ int parse_meta(struct nftnl_expr *e, uint8_t key, char *iniface,
                if (nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP) == NFT_CMP_NEQ)
                        *invflags |= IPT_INV_VIA_IN;
 
-               memcpy(iniface, ifname, len);
-
-               if (iniface[len] == '\0')
-                       memset(iniface_mask, 0xff, len);
-               else {
-                       iniface[len] = '+';
-                       iniface[len+1] = '\0';
-                       memset(iniface_mask, 0xff, len + 1);
-               }
+               parse_ifname(ifname, len, iniface, iniface_mask);
                break;
        case NFT_META_OIFNAME:
                ifname = nftnl_expr_get(e, NFTNL_EXPR_CMP_DATA, &len);
                if (nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP) == NFT_CMP_NEQ)
                        *invflags |= IPT_INV_VIA_OUT;
 
-               memcpy(outiface, ifname, len);
-
-               if (outiface[len] == '\0')
-                       memset(outiface_mask, 0xff, len);
-               else {
-                       outiface[len] = '+';
-                       outiface[len+1] = '\0';
-                       memset(outiface_mask, 0xff, len + 1);
-               }
+               parse_ifname(ifname, len, outiface, outiface_mask);
                break;
        default:
                return -1;