Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 224499
b: refs/heads/master
c: cf7afbf
h: refs/heads/master
i:
  224497: f553d04
  224495: a6695cf
v: v3
  • Loading branch information
Thomas Graf authored and David S. Miller committed Nov 28, 2010
1 parent 542562d commit ce428c6
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 21 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 89bf67f1f080c947c92f8773482d9e57767ca292
refs/heads/master: cf7afbfeb8ceb0187348d0a1a0db61305e25f05f
12 changes: 8 additions & 4 deletions trunk/include/net/rtnetlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,10 @@ extern void rtnl_link_unregister(struct rtnl_link_ops *ops);
* 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;
Expand All @@ -103,8 +105,10 @@ struct rtnl_af_ops {
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);
Expand Down
29 changes: 24 additions & 5 deletions trunk/net/core/rtnetlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -1107,6 +1107,28 @@ static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[])
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;
}

Expand Down Expand Up @@ -1356,12 +1378,9 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
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;

Expand Down
26 changes: 21 additions & 5 deletions trunk/net/ipv4/devinet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1289,14 +1289,14 @@ static const struct nla_policy inet_af_policy[IFLA_INET_MAX+1] = {
[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)
Expand All @@ -1314,6 +1314,21 @@ static int inet_parse_link_af(struct net_device *dev, const struct nlattr *nla)
}
}

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));
Expand Down Expand Up @@ -1689,7 +1704,8 @@ static struct rtnl_af_ops inet_af_ops = {
.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)
Expand Down
6 changes: 0 additions & 6 deletions trunk/net/ipv6/addrconf.c
Original file line number Diff line number Diff line change
Expand Up @@ -3956,11 +3956,6 @@ static int inet6_fill_link_af(struct sk_buff *skb, const struct net_device *dev)
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)
{
Expand Down Expand Up @@ -4670,7 +4665,6 @@ static struct rtnl_af_ops inet6_ops = {
.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,
};

/*
Expand Down

0 comments on commit ce428c6

Please sign in to comment.