*                    specific netlink attributes.
  *     @get_link_af_size: Function to calculate size of address family specific
  *                        netlink attributes exlusive the container attribute.
- *     @parse_link_af: Function to parse a IFLA_AF_SPEC attribute and modify
- *                     net_device accordingly.
+ *     @validate_link_af: Validate a IFLA_AF_SPEC attribute, must check attr
+ *                        for invalid configuration settings.
+ *     @set_link_af: Function to parse a IFLA_AF_SPEC attribute and modify
+ *                   net_device accordingly.
  */
 struct rtnl_af_ops {
        struct list_head        list;
                                                const struct net_device *dev);
        size_t                  (*get_link_af_size)(const struct net_device *dev);
 
-       int                     (*parse_link_af)(struct net_device *dev,
-                                                const struct nlattr *attr);
+       int                     (*validate_link_af)(const struct net_device *dev,
+                                                   const struct nlattr *attr);
+       int                     (*set_link_af)(struct net_device *dev,
+                                              const struct nlattr *attr);
 };
 
 extern int     __rtnl_af_register(struct rtnl_af_ops *ops);
 
                        return -EINVAL;
        }
 
+       if (tb[IFLA_AF_SPEC]) {
+               struct nlattr *af;
+               int rem, err;
+
+               nla_for_each_nested(af, tb[IFLA_AF_SPEC], rem) {
+                       const struct rtnl_af_ops *af_ops;
+
+                       if (!(af_ops = rtnl_af_lookup(nla_type(af))))
+                               return -EAFNOSUPPORT;
+
+                       if (!af_ops->set_link_af)
+                               return -EOPNOTSUPP;
+
+                       if (af_ops->validate_link_af) {
+                               err = af_ops->validate_link_af(dev,
+                                                       tb[IFLA_AF_SPEC]);
+                               if (err < 0)
+                                       return err;
+                       }
+               }
+       }
+
        return 0;
 }
 
                        const struct rtnl_af_ops *af_ops;
 
                        if (!(af_ops = rtnl_af_lookup(nla_type(af))))
-                               continue;
-
-                       if (!af_ops->parse_link_af)
-                               continue;
+                               BUG();
 
-                       err = af_ops->parse_link_af(dev, af);
+                       err = af_ops->set_link_af(dev, af);
                        if (err < 0)
                                goto errout;
 
 
        [IFLA_INET_CONF]        = { .type = NLA_NESTED },
 };
 
-static int inet_parse_link_af(struct net_device *dev, const struct nlattr *nla)
+static int inet_validate_link_af(const struct net_device *dev,
+                                const struct nlattr *nla)
 {
-       struct in_device *in_dev = __in_dev_get_rcu(dev);
        struct nlattr *a, *tb[IFLA_INET_MAX+1];
        int err, rem;
 
-       if (!in_dev)
-               return -EOPNOTSUPP;
+       if (dev && !__in_dev_get_rcu(dev))
+               return -EAFNOSUPPORT;
 
        err = nla_parse_nested(tb, IFLA_INET_MAX, nla, inet_af_policy);
        if (err < 0)
                }
        }
 
+       return 0;
+}
+
+static int inet_set_link_af(struct net_device *dev, const struct nlattr *nla)
+{
+       struct in_device *in_dev = __in_dev_get_rcu(dev);
+       struct nlattr *a, *tb[IFLA_INET_MAX+1];
+       int rem;
+
+       if (!in_dev)
+               return -EAFNOSUPPORT;
+
+       if (nla_parse_nested(tb, IFLA_INET_MAX, nla, NULL) < 0)
+               BUG();
+
        if (tb[IFLA_INET_CONF]) {
                nla_for_each_nested(a, tb[IFLA_INET_CONF], rem)
                        ipv4_devconf_set(in_dev, nla_type(a), nla_get_u32(a));
        .family           = AF_INET,
        .fill_link_af     = inet_fill_link_af,
        .get_link_af_size = inet_get_link_af_size,
-       .parse_link_af    = inet_parse_link_af,
+       .validate_link_af = inet_validate_link_af,
+       .set_link_af      = inet_set_link_af,
 };
 
 void __init devinet_init(void)
 
        return 0;
 }
 
-static int inet6_parse_link_af(struct net_device *dev, const struct nlattr *nla)
-{
-       return -EOPNOTSUPP;
-}
-
 static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
                             u32 pid, u32 seq, int event, unsigned int flags)
 {
        .family           = AF_INET6,
        .fill_link_af     = inet6_fill_link_af,
        .get_link_af_size = inet6_get_link_af_size,
-       .parse_link_af    = inet6_parse_link_af,
 };
 
 /*