diff options
author | Nicolas Dichtel <nicolas.dichtel@6wind.com> | 2012-10-25 18:28:52 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-10-28 19:05:00 -0400 |
commit | edc9e748934cf406cab708ca5dda7bd3c0f0a1db (patch) | |
tree | 0c7e4b1aa6f747ca24f09bd4a8752032a4d22834 /net/ipv4 | |
parent | 76f8f6cb76b110aaace90b6208b1ceb46bd78b7f (diff) |
rtnl/ipv4: use netconf msg to advertise forwarding status
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/devinet.c | 93 |
1 files changed, 89 insertions, 4 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 2a6abc163ed2..020fdd2e6e19 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -55,6 +55,7 @@ | |||
55 | #include <linux/sysctl.h> | 55 | #include <linux/sysctl.h> |
56 | #endif | 56 | #endif |
57 | #include <linux/kmod.h> | 57 | #include <linux/kmod.h> |
58 | #include <linux/netconf.h> | ||
58 | 59 | ||
59 | #include <net/arp.h> | 60 | #include <net/arp.h> |
60 | #include <net/ip.h> | 61 | #include <net/ip.h> |
@@ -1442,6 +1443,73 @@ static int inet_set_link_af(struct net_device *dev, const struct nlattr *nla) | |||
1442 | return 0; | 1443 | return 0; |
1443 | } | 1444 | } |
1444 | 1445 | ||
1446 | static int inet_netconf_msgsize_devconf(int type) | ||
1447 | { | ||
1448 | int size = NLMSG_ALIGN(sizeof(struct netconfmsg)) | ||
1449 | + nla_total_size(4); /* NETCONFA_IFINDEX */ | ||
1450 | |||
1451 | if (type == NETCONFA_FORWARDING) | ||
1452 | size += nla_total_size(4); | ||
1453 | |||
1454 | return size; | ||
1455 | } | ||
1456 | |||
1457 | static int inet_netconf_fill_devconf(struct sk_buff *skb, int ifindex, | ||
1458 | struct ipv4_devconf *devconf, u32 portid, | ||
1459 | u32 seq, int event, unsigned int flags, | ||
1460 | int type) | ||
1461 | { | ||
1462 | struct nlmsghdr *nlh; | ||
1463 | struct netconfmsg *ncm; | ||
1464 | |||
1465 | nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct netconfmsg), | ||
1466 | flags); | ||
1467 | if (nlh == NULL) | ||
1468 | return -EMSGSIZE; | ||
1469 | |||
1470 | ncm = nlmsg_data(nlh); | ||
1471 | ncm->ncm_family = AF_INET; | ||
1472 | |||
1473 | if (nla_put_s32(skb, NETCONFA_IFINDEX, ifindex) < 0) | ||
1474 | goto nla_put_failure; | ||
1475 | |||
1476 | if (type == NETCONFA_FORWARDING && | ||
1477 | nla_put_s32(skb, NETCONFA_FORWARDING, | ||
1478 | IPV4_DEVCONF(*devconf, FORWARDING)) < 0) | ||
1479 | goto nla_put_failure; | ||
1480 | |||
1481 | return nlmsg_end(skb, nlh); | ||
1482 | |||
1483 | nla_put_failure: | ||
1484 | nlmsg_cancel(skb, nlh); | ||
1485 | return -EMSGSIZE; | ||
1486 | } | ||
1487 | |||
1488 | static void inet_netconf_notify_devconf(struct net *net, int type, int ifindex, | ||
1489 | struct ipv4_devconf *devconf) | ||
1490 | { | ||
1491 | struct sk_buff *skb; | ||
1492 | int err = -ENOBUFS; | ||
1493 | |||
1494 | skb = nlmsg_new(inet_netconf_msgsize_devconf(type), GFP_ATOMIC); | ||
1495 | if (skb == NULL) | ||
1496 | goto errout; | ||
1497 | |||
1498 | err = inet_netconf_fill_devconf(skb, ifindex, devconf, 0, 0, | ||
1499 | RTM_NEWNETCONF, 0, type); | ||
1500 | if (err < 0) { | ||
1501 | /* -EMSGSIZE implies BUG in inet_netconf_msgsize_devconf() */ | ||
1502 | WARN_ON(err == -EMSGSIZE); | ||
1503 | kfree_skb(skb); | ||
1504 | goto errout; | ||
1505 | } | ||
1506 | rtnl_notify(skb, net, 0, RTNLGRP_IPV4_NETCONF, NULL, GFP_ATOMIC); | ||
1507 | return; | ||
1508 | errout: | ||
1509 | if (err < 0) | ||
1510 | rtnl_set_sk_err(net, RTNLGRP_IPV4_NETCONF, err); | ||
1511 | } | ||
1512 | |||
1445 | #ifdef CONFIG_SYSCTL | 1513 | #ifdef CONFIG_SYSCTL |
1446 | 1514 | ||
1447 | static void devinet_copy_dflt_conf(struct net *net, int i) | 1515 | static void devinet_copy_dflt_conf(struct net *net, int i) |
@@ -1467,6 +1535,12 @@ static void inet_forward_change(struct net *net) | |||
1467 | 1535 | ||
1468 | IPV4_DEVCONF_ALL(net, ACCEPT_REDIRECTS) = !on; | 1536 | IPV4_DEVCONF_ALL(net, ACCEPT_REDIRECTS) = !on; |
1469 | IPV4_DEVCONF_DFLT(net, FORWARDING) = on; | 1537 | IPV4_DEVCONF_DFLT(net, FORWARDING) = on; |
1538 | inet_netconf_notify_devconf(net, NETCONFA_FORWARDING, | ||
1539 | NETCONFA_IFINDEX_ALL, | ||
1540 | net->ipv4.devconf_all); | ||
1541 | inet_netconf_notify_devconf(net, NETCONFA_FORWARDING, | ||
1542 | NETCONFA_IFINDEX_DEFAULT, | ||
1543 | net->ipv4.devconf_dflt); | ||
1470 | 1544 | ||
1471 | for_each_netdev(net, dev) { | 1545 | for_each_netdev(net, dev) { |
1472 | struct in_device *in_dev; | 1546 | struct in_device *in_dev; |
@@ -1474,8 +1548,11 @@ static void inet_forward_change(struct net *net) | |||
1474 | dev_disable_lro(dev); | 1548 | dev_disable_lro(dev); |
1475 | rcu_read_lock(); | 1549 | rcu_read_lock(); |
1476 | in_dev = __in_dev_get_rcu(dev); | 1550 | in_dev = __in_dev_get_rcu(dev); |
1477 | if (in_dev) | 1551 | if (in_dev) { |
1478 | IN_DEV_CONF_SET(in_dev, FORWARDING, on); | 1552 | IN_DEV_CONF_SET(in_dev, FORWARDING, on); |
1553 | inet_netconf_notify_devconf(net, NETCONFA_FORWARDING, | ||
1554 | dev->ifindex, &in_dev->cnf); | ||
1555 | } | ||
1479 | rcu_read_unlock(); | 1556 | rcu_read_unlock(); |
1480 | } | 1557 | } |
1481 | } | 1558 | } |
@@ -1527,15 +1604,23 @@ static int devinet_sysctl_forward(ctl_table *ctl, int write, | |||
1527 | } | 1604 | } |
1528 | if (valp == &IPV4_DEVCONF_ALL(net, FORWARDING)) { | 1605 | if (valp == &IPV4_DEVCONF_ALL(net, FORWARDING)) { |
1529 | inet_forward_change(net); | 1606 | inet_forward_change(net); |
1530 | } else if (*valp) { | 1607 | } else { |
1531 | struct ipv4_devconf *cnf = ctl->extra1; | 1608 | struct ipv4_devconf *cnf = ctl->extra1; |
1532 | struct in_device *idev = | 1609 | struct in_device *idev = |
1533 | container_of(cnf, struct in_device, cnf); | 1610 | container_of(cnf, struct in_device, cnf); |
1534 | dev_disable_lro(idev->dev); | 1611 | if (*valp) |
1612 | dev_disable_lro(idev->dev); | ||
1613 | inet_netconf_notify_devconf(net, | ||
1614 | NETCONFA_FORWARDING, | ||
1615 | idev->dev->ifindex, | ||
1616 | cnf); | ||
1535 | } | 1617 | } |
1536 | rtnl_unlock(); | 1618 | rtnl_unlock(); |
1537 | rt_cache_flush(net); | 1619 | rt_cache_flush(net); |
1538 | } | 1620 | } else |
1621 | inet_netconf_notify_devconf(net, NETCONFA_FORWARDING, | ||
1622 | NETCONFA_IFINDEX_DEFAULT, | ||
1623 | net->ipv4.devconf_dflt); | ||
1539 | } | 1624 | } |
1540 | 1625 | ||
1541 | return ret; | 1626 | return ret; |