aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/devinet.c
diff options
context:
space:
mode:
authorThomas Graf <tgraf@infradead.org>2010-11-15 23:32:48 -0500
committerDavid S. Miller <davem@davemloft.net>2010-11-17 14:28:25 -0500
commit9f0f7272ac9506f4c8c05cc597b7e376b0b9f3e4 (patch)
treed26f7c7e8f06313ffc8c0869935650f2b104ab58 /net/ipv4/devinet.c
parentca7479ebbd9f7621646bf2792cb7143647f035bb (diff)
ipv4: AF_INET link address family
Implements the AF_INET link address family exposing the per device configuration settings via netlink using the attribute IFLA_INET_CONF. The format of IFLA_INET_CONF differs depending on the direction the attribute is sent. The attribute sent by the kernel consists of a u32 array, basically a 1:1 copy of in_device->cnf.data[]. The attribute expected by the kernel must consist of a sequence of nested u32 attributes, each representing a change request, e.g. [IFLA_INET_CONF] = { [IPV4_DEVCONF_FORWARDING] = 1, [IPV4_DEVCONF_NOXFRM] = 0, } libnl userspace API documentation and example available from: http://www.infradead.org/~tgr/libnl/doc-git/group__link__inet.html Signed-off-by: Thomas Graf <tgraf@infradead.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/devinet.c')
-rw-r--r--net/ipv4/devinet.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index dc94b0316b78..71afc26c2df8 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1256,6 +1256,72 @@ errout:
1256 rtnl_set_sk_err(net, RTNLGRP_IPV4_IFADDR, err); 1256 rtnl_set_sk_err(net, RTNLGRP_IPV4_IFADDR, err);
1257} 1257}
1258 1258
1259static size_t inet_get_link_af_size(const struct net_device *dev)
1260{
1261 struct in_device *in_dev = __in_dev_get_rcu(dev);
1262
1263 if (!in_dev)
1264 return 0;
1265
1266 return nla_total_size(IPV4_DEVCONF_MAX * 4); /* IFLA_INET_CONF */
1267}
1268
1269static int inet_fill_link_af(struct sk_buff *skb, const struct net_device *dev)
1270{
1271 struct in_device *in_dev = __in_dev_get_rcu(dev);
1272 struct nlattr *nla;
1273 int i;
1274
1275 if (!in_dev)
1276 return -ENODATA;
1277
1278 nla = nla_reserve(skb, IFLA_INET_CONF, IPV4_DEVCONF_MAX * 4);
1279 if (nla == NULL)
1280 return -EMSGSIZE;
1281
1282 for (i = 0; i < IPV4_DEVCONF_MAX; i++)
1283 ((u32 *) nla_data(nla))[i] = in_dev->cnf.data[i];
1284
1285 return 0;
1286}
1287
1288static const struct nla_policy inet_af_policy[IFLA_INET_MAX+1] = {
1289 [IFLA_INET_CONF] = { .type = NLA_NESTED },
1290};
1291
1292static int inet_parse_link_af(struct net_device *dev, const struct nlattr *nla)
1293{
1294 struct in_device *in_dev = __in_dev_get_rcu(dev);
1295 struct nlattr *a, *tb[IFLA_INET_MAX+1];
1296 int err, rem;
1297
1298 if (!in_dev)
1299 return -EOPNOTSUPP;
1300
1301 err = nla_parse_nested(tb, IFLA_INET_MAX, nla, inet_af_policy);
1302 if (err < 0)
1303 return err;
1304
1305 if (tb[IFLA_INET_CONF]) {
1306 nla_for_each_nested(a, tb[IFLA_INET_CONF], rem) {
1307 int cfgid = nla_type(a);
1308
1309 if (nla_len(a) < 4)
1310 return -EINVAL;
1311
1312 if (cfgid <= 0 || cfgid > IPV4_DEVCONF_MAX)
1313 return -EINVAL;
1314 }
1315 }
1316
1317 if (tb[IFLA_INET_CONF]) {
1318 nla_for_each_nested(a, tb[IFLA_INET_CONF], rem)
1319 ipv4_devconf_set(in_dev, nla_type(a), nla_get_u32(a));
1320 }
1321
1322 return 0;
1323}
1324
1259#ifdef CONFIG_SYSCTL 1325#ifdef CONFIG_SYSCTL
1260 1326
1261static void devinet_copy_dflt_conf(struct net *net, int i) 1327static void devinet_copy_dflt_conf(struct net *net, int i)
@@ -1619,6 +1685,13 @@ static __net_initdata struct pernet_operations devinet_ops = {
1619 .exit = devinet_exit_net, 1685 .exit = devinet_exit_net,
1620}; 1686};
1621 1687
1688static struct rtnl_af_ops inet_af_ops = {
1689 .family = AF_INET,
1690 .fill_link_af = inet_fill_link_af,
1691 .get_link_af_size = inet_get_link_af_size,
1692 .parse_link_af = inet_parse_link_af,
1693};
1694
1622void __init devinet_init(void) 1695void __init devinet_init(void)
1623{ 1696{
1624 register_pernet_subsys(&devinet_ops); 1697 register_pernet_subsys(&devinet_ops);
@@ -1626,6 +1699,8 @@ void __init devinet_init(void)
1626 register_gifconf(PF_INET, inet_gifconf); 1699 register_gifconf(PF_INET, inet_gifconf);
1627 register_netdevice_notifier(&ip_netdev_notifier); 1700 register_netdevice_notifier(&ip_netdev_notifier);
1628 1701
1702 rtnl_af_register(&inet_af_ops);
1703
1629 rtnl_register(PF_INET, RTM_NEWADDR, inet_rtm_newaddr, NULL); 1704 rtnl_register(PF_INET, RTM_NEWADDR, inet_rtm_newaddr, NULL);
1630 rtnl_register(PF_INET, RTM_DELADDR, inet_rtm_deladdr, NULL); 1705 rtnl_register(PF_INET, RTM_DELADDR, inet_rtm_deladdr, NULL);
1631 rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr); 1706 rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr);