Merge tag 'mips_5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux
[linux-2.6-microblaze.git] / net / ipv6 / addrconf.c
index 3bf685f..17756f3 100644 (file)
@@ -89,6 +89,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/export.h>
+#include <linux/ioam6.h>
 
 #define        INFINITY_LIFE_TIME      0xFFFFFFFF
 
@@ -237,6 +238,9 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
        .addr_gen_mode          = IN6_ADDR_GEN_MODE_EUI64,
        .disable_policy         = 0,
        .rpl_seg_enabled        = 0,
+       .ioam6_enabled          = 0,
+       .ioam6_id               = IOAM6_DEFAULT_IF_ID,
+       .ioam6_id_wide          = IOAM6_DEFAULT_IF_ID_WIDE,
 };
 
 static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
@@ -293,6 +297,9 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
        .addr_gen_mode          = IN6_ADDR_GEN_MODE_EUI64,
        .disable_policy         = 0,
        .rpl_seg_enabled        = 0,
+       .ioam6_enabled          = 0,
+       .ioam6_id               = IOAM6_DEFAULT_IF_ID,
+       .ioam6_id_wide          = IOAM6_DEFAULT_IF_ID_WIDE,
 };
 
 /* Check if link is ready: is it up and is a valid qdisc available */
@@ -387,6 +394,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
                ndev->cnf.addr_gen_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
 
        ndev->cnf.mtu6 = dev->mtu;
+       ndev->ra_mtu = 0;
        ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl);
        if (!ndev->nd_parms) {
                kfree(ndev);
@@ -694,8 +702,7 @@ static int inet6_netconf_get_devconf(struct sk_buff *in_skb,
 errout:
        if (in6_dev)
                in6_dev_put(in6_dev);
-       if (dev)
-               dev_put(dev);
+       dev_put(dev);
        return err;
 }
 
@@ -1080,7 +1087,7 @@ ipv6_add_addr(struct inet6_dev *idev, struct ifa6_config *cfg,
                        goto out;
        }
 
-       ifa = kzalloc(sizeof(*ifa), gfp_flags);
+       ifa = kzalloc(sizeof(*ifa), gfp_flags | __GFP_ACCOUNT);
        if (!ifa) {
                err = -ENOBUFS;
                goto out;
@@ -3843,6 +3850,7 @@ restart:
        }
 
        idev->tstamp = jiffies;
+       idev->ra_mtu = 0;
 
        /* Last: Shot the device (if unregistered) */
        if (unregister) {
@@ -5211,8 +5219,7 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
                .netnsid = -1,
                .type = type,
        };
-       struct net *net = sock_net(skb->sk);
-       struct net *tgt_net = net;
+       struct net *tgt_net = sock_net(skb->sk);
        int idx, s_idx, s_ip_idx;
        int h, s_h;
        struct net_device *dev;
@@ -5351,7 +5358,7 @@ static int inet6_rtm_valid_getaddr_req(struct sk_buff *skb,
 static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh,
                             struct netlink_ext_ack *extack)
 {
-       struct net *net = sock_net(in_skb->sk);
+       struct net *tgt_net = sock_net(in_skb->sk);
        struct inet6_fill_args fillargs = {
                .portid = NETLINK_CB(in_skb).portid,
                .seq = nlh->nlmsg_seq,
@@ -5359,7 +5366,6 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh,
                .flags = 0,
                .netnsid = -1,
        };
-       struct net *tgt_net = net;
        struct ifaddrmsg *ifm;
        struct nlattr *tb[IFA_MAX+1];
        struct in6_addr *addr = NULL, *peer;
@@ -5412,8 +5418,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh,
 errout_ifa:
        in6_ifa_put(ifa);
 errout:
-       if (dev)
-               dev_put(dev);
+       dev_put(dev);
        if (fillargs.netnsid >= 0)
                put_net(tgt_net);
 
@@ -5526,6 +5531,9 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
        array[DEVCONF_DISABLE_POLICY] = cnf->disable_policy;
        array[DEVCONF_NDISC_TCLASS] = cnf->ndisc_tclass;
        array[DEVCONF_RPL_SEG_ENABLED] = cnf->rpl_seg_enabled;
+       array[DEVCONF_IOAM6_ENABLED] = cnf->ioam6_enabled;
+       array[DEVCONF_IOAM6_ID] = cnf->ioam6_id;
+       array[DEVCONF_IOAM6_ID_WIDE] = cnf->ioam6_id_wide;
 }
 
 static inline size_t inet6_ifla6_size(void)
@@ -5537,6 +5545,7 @@ static inline size_t inet6_ifla6_size(void)
             + nla_total_size(ICMP6_MIB_MAX * 8) /* IFLA_INET6_ICMP6STATS */
             + nla_total_size(sizeof(struct in6_addr)) /* IFLA_INET6_TOKEN */
             + nla_total_size(1) /* IFLA_INET6_ADDR_GEN_MODE */
+            + nla_total_size(4) /* IFLA_INET6_RA_MTU */
             + 0;
 }
 
@@ -5645,6 +5654,10 @@ static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev,
        if (nla_put_u8(skb, IFLA_INET6_ADDR_GEN_MODE, idev->cnf.addr_gen_mode))
                goto nla_put_failure;
 
+       if (idev->ra_mtu &&
+           nla_put_u32(skb, IFLA_INET6_RA_MTU, idev->ra_mtu))
+               goto nla_put_failure;
+
        return 0;
 
 nla_put_failure:
@@ -5761,6 +5774,9 @@ update_lft:
 static const struct nla_policy inet6_af_policy[IFLA_INET6_MAX + 1] = {
        [IFLA_INET6_ADDR_GEN_MODE]      = { .type = NLA_U8 },
        [IFLA_INET6_TOKEN]              = { .len = sizeof(struct in6_addr) },
+       [IFLA_INET6_RA_MTU]             = { .type = NLA_REJECT,
+                                           .reject_message =
+                                               "IFLA_INET6_RA_MTU can not be set" },
 };
 
 static int check_addr_gen_mode(int mode)
@@ -5784,7 +5800,8 @@ static int check_stable_privacy(struct inet6_dev *idev, struct net *net,
 }
 
 static int inet6_validate_link_af(const struct net_device *dev,
-                                 const struct nlattr *nla)
+                                 const struct nlattr *nla,
+                                 struct netlink_ext_ack *extack)
 {
        struct nlattr *tb[IFLA_INET6_MAX + 1];
        struct inet6_dev *idev = NULL;
@@ -5797,7 +5814,7 @@ static int inet6_validate_link_af(const struct net_device *dev,
        }
 
        err = nla_parse_nested_deprecated(tb, IFLA_INET6_MAX, nla,
-                                         inet6_af_policy, NULL);
+                                         inet6_af_policy, extack);
        if (err)
                return err;
 
@@ -6540,6 +6557,7 @@ static int addrconf_sysctl_disable_policy(struct ctl_table *ctl, int write,
 
 static int minus_one = -1;
 static const int two_five_five = 255;
+static u32 ioam6_if_id_max = U16_MAX;
 
 static const struct ctl_table addrconf_sysctl[] = {
        {
@@ -6932,6 +6950,31 @@ static const struct ctl_table addrconf_sysctl[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
        },
+       {
+               .procname       = "ioam6_enabled",
+               .data           = &ipv6_devconf.ioam6_enabled,
+               .maxlen         = sizeof(u8),
+               .mode           = 0644,
+               .proc_handler   = proc_dou8vec_minmax,
+               .extra1         = (void *)SYSCTL_ZERO,
+               .extra2         = (void *)SYSCTL_ONE,
+       },
+       {
+               .procname       = "ioam6_id",
+               .data           = &ipv6_devconf.ioam6_id,
+               .maxlen         = sizeof(u32),
+               .mode           = 0644,
+               .proc_handler   = proc_douintvec_minmax,
+               .extra1         = (void *)SYSCTL_ZERO,
+               .extra2         = (void *)&ioam6_if_id_max,
+       },
+       {
+               .procname       = "ioam6_id_wide",
+               .data           = &ipv6_devconf.ioam6_id_wide,
+               .maxlen         = sizeof(u32),
+               .mode           = 0644,
+               .proc_handler   = proc_douintvec,
+       },
        {
                /* sentinel */
        }