int *notify)
 {
        bool rc = false;
-       u8 ndm_flags;
+       u32 ndm_flags;
 
        if (!(flags & NEIGH_UPDATE_F_ADMIN))
                return rc;
 
 static struct neighbour *neigh_alloc(struct neigh_table *tbl,
                                     struct net_device *dev,
-                                    u8 flags, bool exempt_from_gc)
+                                    u32 flags, bool exempt_from_gc)
 {
        struct neighbour *n = NULL;
        unsigned long now = jiffies;
 
 static struct neighbour *
 ___neigh_create(struct neigh_table *tbl, const void *pkey,
-               struct net_device *dev, u8 flags,
+               struct net_device *dev, u32 flags,
                bool exempt_from_gc, bool want_ref)
 {
        u32 hash_val, key_len = tbl->key_len;
        [NDA_MASTER]            = { .type = NLA_U32 },
        [NDA_PROTOCOL]          = { .type = NLA_U8 },
        [NDA_NH_ID]             = { .type = NLA_U32 },
+       [NDA_FLAGS_EXT]         = { .type = NLA_U32 },
        [NDA_FDB_EXT_ATTRS]     = { .type = NLA_NESTED },
 };
 
                     struct netlink_ext_ack *extack)
 {
        int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE |
-               NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
+                   NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
        struct net *net = sock_net(skb->sk);
        struct ndmsg *ndm;
        struct nlattr *tb[NDA_MAX+1];
        struct neighbour *neigh;
        void *dst, *lladdr;
        u8 protocol = 0;
+       u32 ndm_flags;
        int err;
 
        ASSERT_RTNL();
        }
 
        ndm = nlmsg_data(nlh);
+       ndm_flags = ndm->ndm_flags;
+       if (tb[NDA_FLAGS_EXT]) {
+               u32 ext = nla_get_u32(tb[NDA_FLAGS_EXT]);
+
+               if (ext & ~0) {
+                       NL_SET_ERR_MSG(extack, "Invalid extended flags");
+                       goto out;
+               }
+               ndm_flags |= (ext << NTF_EXT_SHIFT);
+       }
        if (ndm->ndm_ifindex) {
                dev = __dev_get_by_index(net, ndm->ndm_ifindex);
                if (dev == NULL) {
 
        if (tb[NDA_PROTOCOL])
                protocol = nla_get_u8(tb[NDA_PROTOCOL]);
-
-       if (ndm->ndm_flags & NTF_PROXY) {
+       if (ndm_flags & NTF_PROXY) {
                struct pneigh_entry *pn;
 
                err = -ENOBUFS;
                pn = pneigh_lookup(tbl, net, dst, dev, 1);
                if (pn) {
-                       pn->flags = ndm->ndm_flags;
+                       pn->flags = ndm_flags;
                        if (protocol)
                                pn->protocol = protocol;
                        err = 0;
                }
 
                exempt_from_gc = ndm->ndm_state & NUD_PERMANENT ||
-                                ndm->ndm_flags & NTF_EXT_LEARNED;
+                                ndm_flags & NTF_EXT_LEARNED;
                neigh = ___neigh_create(tbl, dst, dev,
-                                       ndm->ndm_flags & NTF_EXT_LEARNED,
+                                       ndm_flags & NTF_EXT_LEARNED,
                                        exempt_from_gc, true);
                if (IS_ERR(neigh)) {
                        err = PTR_ERR(neigh);
 
        if (protocol)
                neigh->protocol = protocol;
-       if (ndm->ndm_flags & NTF_EXT_LEARNED)
+       if (ndm_flags & NTF_EXT_LEARNED)
                flags |= NEIGH_UPDATE_F_EXT_LEARNED;
-       if (ndm->ndm_flags & NTF_ROUTER)
+       if (ndm_flags & NTF_ROUTER)
                flags |= NEIGH_UPDATE_F_ISROUTER;
-       if (ndm->ndm_flags & NTF_USE)
+       if (ndm_flags & NTF_USE)
                flags |= NEIGH_UPDATE_F_USE;
 
        err = __neigh_update(neigh, lladdr, ndm->ndm_state, flags,
                             NETLINK_CB(skb).portid, extack);
-       if (!err && ndm->ndm_flags & NTF_USE) {
+       if (!err && ndm_flags & NTF_USE) {
                neigh_event_send(neigh, NULL);
                err = 0;
        }
 static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
                           u32 pid, u32 seq, int type, unsigned int flags)
 {
+       u32 neigh_flags, neigh_flags_ext;
        unsigned long now = jiffies;
        struct nda_cacheinfo ci;
        struct nlmsghdr *nlh;
        if (nlh == NULL)
                return -EMSGSIZE;
 
+       neigh_flags_ext = neigh->flags >> NTF_EXT_SHIFT;
+       neigh_flags     = neigh->flags & NTF_OLD_MASK;
+
        ndm = nlmsg_data(nlh);
        ndm->ndm_family  = neigh->ops->family;
        ndm->ndm_pad1    = 0;
        ndm->ndm_pad2    = 0;
-       ndm->ndm_flags   = neigh->flags;
+       ndm->ndm_flags   = neigh_flags;
        ndm->ndm_type    = neigh->type;
        ndm->ndm_ifindex = neigh->dev->ifindex;
 
 
        if (neigh->protocol && nla_put_u8(skb, NDA_PROTOCOL, neigh->protocol))
                goto nla_put_failure;
+       if (neigh_flags_ext && nla_put_u32(skb, NDA_FLAGS_EXT, neigh_flags_ext))
+               goto nla_put_failure;
 
        nlmsg_end(skb, nlh);
        return 0;
                            u32 pid, u32 seq, int type, unsigned int flags,
                            struct neigh_table *tbl)
 {
+       u32 neigh_flags, neigh_flags_ext;
        struct nlmsghdr *nlh;
        struct ndmsg *ndm;
 
        if (nlh == NULL)
                return -EMSGSIZE;
 
+       neigh_flags_ext = pn->flags >> NTF_EXT_SHIFT;
+       neigh_flags     = pn->flags & NTF_OLD_MASK;
+
        ndm = nlmsg_data(nlh);
        ndm->ndm_family  = tbl->family;
        ndm->ndm_pad1    = 0;
        ndm->ndm_pad2    = 0;
-       ndm->ndm_flags   = pn->flags | NTF_PROXY;
+       ndm->ndm_flags   = neigh_flags | NTF_PROXY;
        ndm->ndm_type    = RTN_UNICAST;
        ndm->ndm_ifindex = pn->dev ? pn->dev->ifindex : 0;
        ndm->ndm_state   = NUD_NONE;
 
        if (pn->protocol && nla_put_u8(skb, NDA_PROTOCOL, pn->protocol))
                goto nla_put_failure;
+       if (neigh_flags_ext && nla_put_u32(skb, NDA_FLAGS_EXT, neigh_flags_ext))
+               goto nla_put_failure;
 
        nlmsg_end(skb, nlh);
        return 0;
               + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
               + nla_total_size(sizeof(struct nda_cacheinfo))
               + nla_total_size(4)  /* NDA_PROBES */
+              + nla_total_size(4)  /* NDA_FLAGS_EXT */
               + nla_total_size(1); /* NDA_PROTOCOL */
 }
 
 {
        return NLMSG_ALIGN(sizeof(struct ndmsg))
               + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
+              + nla_total_size(4)  /* NDA_FLAGS_EXT */
               + nla_total_size(1); /* NDA_PROTOCOL */
 }