]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: ipv6: support reporting otherwise unknown prefix flags in RTM_NEWPREFIX
authorMaciej Żenczykowski <maze@google.com>
Wed, 6 Dec 2023 17:36:12 +0000 (09:36 -0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 8 Dec 2023 10:40:51 +0000 (10:40 +0000)
Lorenzo points out that we effectively clear all unknown
flags from PIO when copying them to userspace in the netlink
RTM_NEWPREFIX notification.

We could fix this one at a time as new flags are defined,
or in one fell swoop - I choose the latter.

We could either define 6 new reserved flags (reserved1..6) and handle
them individually (and rename them as new flags are defined), or we
could simply copy the entire unmodified byte over - I choose the latter.

This unfortunately requires some anonymous union/struct magic,
so we add a static assert on the struct size for a little extra safety.

Cc: David Ahern <dsahern@kernel.org>
Cc: Lorenzo Colitti <lorenzo@google.com>
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/addrconf.h
include/net/if_inet6.h
net/ipv6/addrconf.c

index 82da55101b5a30b2a5512d964429d2c5f73d03fd..61ebe723ee4d5078afdeec1ec70d392d0ef54ec4 100644 (file)
@@ -31,17 +31,22 @@ struct prefix_info {
        __u8                    length;
        __u8                    prefix_len;
 
+       union __packed {
+               __u8            flags;
+               struct __packed {
 #if defined(__BIG_ENDIAN_BITFIELD)
-       __u8                    onlink : 1,
+                       __u8    onlink : 1,
                                autoconf : 1,
                                reserved : 6;
 #elif defined(__LITTLE_ENDIAN_BITFIELD)
-       __u8                    reserved : 6,
+                       __u8    reserved : 6,
                                autoconf : 1,
                                onlink : 1;
 #else
 #error "Please fix <asm/byteorder.h>"
 #endif
+               };
+       };
        __be32                  valid;
        __be32                  prefered;
        __be32                  reserved2;
@@ -49,6 +54,9 @@ struct prefix_info {
        struct in6_addr         prefix;
 };
 
+/* rfc4861 4.6.2: IPv6 PIO is 32 bytes in size */
+static_assert(sizeof(struct prefix_info) == 32);
+
 #include <linux/ipv6.h>
 #include <linux/netdevice.h>
 #include <net/if_inet6.h>
index 3e454c4d7ba623d6abcfcfb396c0f4390de84c5a..f07642264c1eb622e57b9ce0715e296360a4db6e 100644 (file)
 #define IF_RS_SENT     0x10
 #define IF_READY       0x80000000
 
-/* prefix flags */
-#define IF_PREFIX_ONLINK       0x01
-#define IF_PREFIX_AUTOCONF     0x02
-
 enum {
        INET6_IFADDR_STATE_PREDAD,
        INET6_IFADDR_STATE_DAD,
index 3aaea56b516601070a11ec2c00150b8268bd481d..2692a7b24c40977a44c33358f558090036338f2c 100644 (file)
@@ -6149,11 +6149,7 @@ static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
        pmsg->prefix_len = pinfo->prefix_len;
        pmsg->prefix_type = pinfo->type;
        pmsg->prefix_pad3 = 0;
-       pmsg->prefix_flags = 0;
-       if (pinfo->onlink)
-               pmsg->prefix_flags |= IF_PREFIX_ONLINK;
-       if (pinfo->autoconf)
-               pmsg->prefix_flags |= IF_PREFIX_AUTOCONF;
+       pmsg->prefix_flags = pinfo->flags;
 
        if (nla_put(skb, PREFIX_ADDRESS, sizeof(pinfo->prefix), &pinfo->prefix))
                goto nla_put_failure;