[IFA_FLAGS]             = { .type = NLA_U32 },
        [IFA_RT_PRIORITY]       = { .type = NLA_U32 },
        [IFA_TARGET_NETNSID]    = { .type = NLA_S32 },
+       [IFA_PROTO]             = { .type = NLA_U8 },
 };
 
 struct inet_fill_args {
        if (tb[IFA_RT_PRIORITY])
                ifa->ifa_rt_priority = nla_get_u32(tb[IFA_RT_PRIORITY]);
 
+       if (tb[IFA_PROTO])
+               ifa->ifa_proto = nla_get_u8(tb[IFA_PROTO]);
+
        if (tb[IFA_CACHEINFO]) {
                struct ifa_cacheinfo *ci;
 
               + nla_total_size(4) /* IFA_BROADCAST */
               + nla_total_size(IFNAMSIZ) /* IFA_LABEL */
               + nla_total_size(4)  /* IFA_FLAGS */
+              + nla_total_size(1)  /* IFA_PROTO */
               + nla_total_size(4)  /* IFA_RT_PRIORITY */
               + nla_total_size(sizeof(struct ifa_cacheinfo)); /* IFA_CACHEINFO */
 }
             nla_put_in_addr(skb, IFA_BROADCAST, ifa->ifa_broadcast)) ||
            (ifa->ifa_label[0] &&
             nla_put_string(skb, IFA_LABEL, ifa->ifa_label)) ||
+           (ifa->ifa_proto &&
+            nla_put_u8(skb, IFA_PROTO, ifa->ifa_proto)) ||
            nla_put_u32(skb, IFA_FLAGS, ifa->ifa_flags) ||
            (ifa->ifa_rt_priority &&
             nla_put_u32(skb, IFA_RT_PRIORITY, ifa->ifa_rt_priority)) ||
 
        ifa->prefix_len = cfg->plen;
        ifa->rt_priority = cfg->rt_priority;
        ifa->flags = cfg->ifa_flags;
+       ifa->ifa_proto = cfg->ifa_proto;
        /* No need to add the TENTATIVE flag for addresses with NODAD */
        if (!(cfg->ifa_flags & IFA_F_NODAD))
                ifa->flags |= IFA_F_TENTATIVE;
                        .valid_lft = valid_lft,
                        .preferred_lft = prefered_lft,
                        .scope = addr_type & IPV6_ADDR_SCOPE_MASK,
+                       .ifa_proto = IFAPROT_KERNEL_RA
                };
 
 #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
 }
 
 static void add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
-                    int plen, int scope)
+                    int plen, int scope, u8 proto)
 {
        struct inet6_ifaddr *ifp;
        struct ifa6_config cfg = {
                .ifa_flags = IFA_F_PERMANENT,
                .valid_lft = INFINITY_LIFE_TIME,
                .preferred_lft = INFINITY_LIFE_TIME,
-               .scope = scope
+               .scope = scope,
+               .ifa_proto = proto
        };
 
        ifp = ipv6_add_addr(idev, &cfg, true, NULL);
        }
 
        if (addr.s6_addr32[3]) {
-               add_addr(idev, &addr, plen, scope);
+               add_addr(idev, &addr, plen, scope, IFAPROT_UNSPEC);
                addrconf_prefix_route(&addr, plen, 0, idev->dev, 0, pflags,
                                      GFP_KERNEL);
                return;
                                        flag |= IFA_HOST;
                                }
 
-                               add_addr(idev, &addr, plen, flag);
+                               add_addr(idev, &addr, plen, flag,
+                                        IFAPROT_UNSPEC);
                                addrconf_prefix_route(&addr, plen, 0, idev->dev,
                                                      0, pflags, GFP_KERNEL);
                        }
                return;
        }
 
-       add_addr(idev, &in6addr_loopback, 128, IFA_HOST);
+       add_addr(idev, &in6addr_loopback, 128, IFA_HOST, IFAPROT_KERNEL_LO);
 }
 
 void addrconf_add_linklocal(struct inet6_dev *idev,
                .ifa_flags = flags | IFA_F_PERMANENT,
                .valid_lft = INFINITY_LIFE_TIME,
                .preferred_lft = INFINITY_LIFE_TIME,
-               .scope = IFA_LINK
+               .scope = IFA_LINK,
+               .ifa_proto = IFAPROT_KERNEL_LL
        };
        struct inet6_ifaddr *ifp;
 
        [IFA_FLAGS]             = { .len = sizeof(u32) },
        [IFA_RT_PRIORITY]       = { .len = sizeof(u32) },
        [IFA_TARGET_NETNSID]    = { .type = NLA_S32 },
+       [IFA_PROTO]             = { .type = NLA_U8 },
 };
 
 static int
        ifp->tstamp = jiffies;
        ifp->valid_lft = cfg->valid_lft;
        ifp->prefered_lft = cfg->preferred_lft;
+       ifp->ifa_proto = cfg->ifa_proto;
 
        if (cfg->rt_priority && cfg->rt_priority != ifp->rt_priority)
                ifp->rt_priority = cfg->rt_priority;
        if (tb[IFA_RT_PRIORITY])
                cfg.rt_priority = nla_get_u32(tb[IFA_RT_PRIORITY]);
 
+       if (tb[IFA_PROTO])
+               cfg.ifa_proto = nla_get_u8(tb[IFA_PROTO]);
+
        cfg.valid_lft = INFINITY_LIFE_TIME;
        cfg.preferred_lft = INFINITY_LIFE_TIME;
 
               + nla_total_size(16) /* IFA_ADDRESS */
               + nla_total_size(sizeof(struct ifa_cacheinfo))
               + nla_total_size(4)  /* IFA_FLAGS */
+              + nla_total_size(1)  /* IFA_PROTO */
               + nla_total_size(4)  /* IFA_RT_PRIORITY */;
 }
 
        if (nla_put_u32(skb, IFA_FLAGS, ifa->flags) < 0)
                goto error;
 
+       if (ifa->ifa_proto &&
+           nla_put_u8(skb, IFA_PROTO, ifa->ifa_proto))
+               goto error;
+
        nlmsg_end(skb, nlh);
        return 0;