diff options
| author | stephen hemminger <stephen@networkplumber.org> | 2013-12-12 16:06:50 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2013-12-14 00:58:22 -0500 |
| commit | f085ff1c131c08fb6b34802f63c22921c4d8c506 (patch) | |
| tree | 45f3f1819353cbcd4f89a2656b4384b0b9fea151 | |
| parent | 68536053600425c24aba031c45f053d447eedd9c (diff) | |
netconf: add proxy-arp support
Add support to netconf to show changes to proxy-arp status on a per
interface basis via netlink in a manner similar to forwarding
and reverse path state.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | include/uapi/linux/netconf.h | 1 | ||||
| -rw-r--r-- | net/ipv4/devinet.c | 41 |
2 files changed, 30 insertions, 12 deletions
diff --git a/include/uapi/linux/netconf.h b/include/uapi/linux/netconf.h index 64804a798b0c..bd969d77ce52 100644 --- a/include/uapi/linux/netconf.h +++ b/include/uapi/linux/netconf.h | |||
| @@ -14,6 +14,7 @@ enum { | |||
| 14 | NETCONFA_FORWARDING, | 14 | NETCONFA_FORWARDING, |
| 15 | NETCONFA_RP_FILTER, | 15 | NETCONFA_RP_FILTER, |
| 16 | NETCONFA_MC_FORWARDING, | 16 | NETCONFA_MC_FORWARDING, |
| 17 | NETCONFA_PROXY_ARP, | ||
| 17 | __NETCONFA_MAX | 18 | __NETCONFA_MAX |
| 18 | }; | 19 | }; |
| 19 | #define NETCONFA_MAX (__NETCONFA_MAX - 1) | 20 | #define NETCONFA_MAX (__NETCONFA_MAX - 1) |
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 84956f5f0135..de03fe7002d0 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
| @@ -1696,6 +1696,8 @@ static int inet_netconf_msgsize_devconf(int type) | |||
| 1696 | size += nla_total_size(4); | 1696 | size += nla_total_size(4); |
| 1697 | if (type == -1 || type == NETCONFA_MC_FORWARDING) | 1697 | if (type == -1 || type == NETCONFA_MC_FORWARDING) |
| 1698 | size += nla_total_size(4); | 1698 | size += nla_total_size(4); |
| 1699 | if (type == -1 || type == NETCONFA_PROXY_ARP) | ||
| 1700 | size += nla_total_size(4); | ||
| 1699 | 1701 | ||
| 1700 | return size; | 1702 | return size; |
| 1701 | } | 1703 | } |
| @@ -1732,6 +1734,10 @@ static int inet_netconf_fill_devconf(struct sk_buff *skb, int ifindex, | |||
| 1732 | nla_put_s32(skb, NETCONFA_MC_FORWARDING, | 1734 | nla_put_s32(skb, NETCONFA_MC_FORWARDING, |
| 1733 | IPV4_DEVCONF(*devconf, MC_FORWARDING)) < 0) | 1735 | IPV4_DEVCONF(*devconf, MC_FORWARDING)) < 0) |
| 1734 | goto nla_put_failure; | 1736 | goto nla_put_failure; |
| 1737 | if ((type == -1 || type == NETCONFA_PROXY_ARP) && | ||
| 1738 | nla_put_s32(skb, NETCONFA_PROXY_ARP, | ||
| 1739 | IPV4_DEVCONF(*devconf, PROXY_ARP)) < 0) | ||
| 1740 | goto nla_put_failure; | ||
| 1735 | 1741 | ||
| 1736 | return nlmsg_end(skb, nlh); | 1742 | return nlmsg_end(skb, nlh); |
| 1737 | 1743 | ||
| @@ -1769,6 +1775,7 @@ static const struct nla_policy devconf_ipv4_policy[NETCONFA_MAX+1] = { | |||
| 1769 | [NETCONFA_IFINDEX] = { .len = sizeof(int) }, | 1775 | [NETCONFA_IFINDEX] = { .len = sizeof(int) }, |
| 1770 | [NETCONFA_FORWARDING] = { .len = sizeof(int) }, | 1776 | [NETCONFA_FORWARDING] = { .len = sizeof(int) }, |
| 1771 | [NETCONFA_RP_FILTER] = { .len = sizeof(int) }, | 1777 | [NETCONFA_RP_FILTER] = { .len = sizeof(int) }, |
| 1778 | [NETCONFA_PROXY_ARP] = { .len = sizeof(int) }, | ||
| 1772 | }; | 1779 | }; |
| 1773 | 1780 | ||
| 1774 | static int inet_netconf_get_devconf(struct sk_buff *in_skb, | 1781 | static int inet_netconf_get_devconf(struct sk_buff *in_skb, |
| @@ -1950,6 +1957,19 @@ static void inet_forward_change(struct net *net) | |||
| 1950 | } | 1957 | } |
| 1951 | } | 1958 | } |
| 1952 | 1959 | ||
| 1960 | static int devinet_conf_ifindex(struct net *net, struct ipv4_devconf *cnf) | ||
| 1961 | { | ||
| 1962 | if (cnf == net->ipv4.devconf_dflt) | ||
| 1963 | return NETCONFA_IFINDEX_DEFAULT; | ||
| 1964 | else if (cnf == net->ipv4.devconf_all) | ||
| 1965 | return NETCONFA_IFINDEX_ALL; | ||
| 1966 | else { | ||
| 1967 | struct in_device *idev | ||
| 1968 | = container_of(cnf, struct in_device, cnf); | ||
| 1969 | return idev->dev->ifindex; | ||
| 1970 | } | ||
| 1971 | } | ||
| 1972 | |||
| 1953 | static int devinet_conf_proc(struct ctl_table *ctl, int write, | 1973 | static int devinet_conf_proc(struct ctl_table *ctl, int write, |
| 1954 | void __user *buffer, | 1974 | void __user *buffer, |
| 1955 | size_t *lenp, loff_t *ppos) | 1975 | size_t *lenp, loff_t *ppos) |
| @@ -1962,6 +1982,7 @@ static int devinet_conf_proc(struct ctl_table *ctl, int write, | |||
| 1962 | struct ipv4_devconf *cnf = ctl->extra1; | 1982 | struct ipv4_devconf *cnf = ctl->extra1; |
| 1963 | struct net *net = ctl->extra2; | 1983 | struct net *net = ctl->extra2; |
| 1964 | int i = (int *)ctl->data - cnf->data; | 1984 | int i = (int *)ctl->data - cnf->data; |
| 1985 | int ifindex; | ||
| 1965 | 1986 | ||
| 1966 | set_bit(i, cnf->state); | 1987 | set_bit(i, cnf->state); |
| 1967 | 1988 | ||
| @@ -1971,23 +1992,19 @@ static int devinet_conf_proc(struct ctl_table *ctl, int write, | |||
| 1971 | i == IPV4_DEVCONF_ROUTE_LOCALNET - 1) | 1992 | i == IPV4_DEVCONF_ROUTE_LOCALNET - 1) |
| 1972 | if ((new_value == 0) && (old_value != 0)) | 1993 | if ((new_value == 0) && (old_value != 0)) |
| 1973 | rt_cache_flush(net); | 1994 | rt_cache_flush(net); |
| 1995 | |||
| 1974 | if (i == IPV4_DEVCONF_RP_FILTER - 1 && | 1996 | if (i == IPV4_DEVCONF_RP_FILTER - 1 && |
| 1975 | new_value != old_value) { | 1997 | new_value != old_value) { |
| 1976 | int ifindex; | 1998 | ifindex = devinet_conf_ifindex(net, cnf); |
| 1977 | |||
| 1978 | if (cnf == net->ipv4.devconf_dflt) | ||
| 1979 | ifindex = NETCONFA_IFINDEX_DEFAULT; | ||
| 1980 | else if (cnf == net->ipv4.devconf_all) | ||
| 1981 | ifindex = NETCONFA_IFINDEX_ALL; | ||
| 1982 | else { | ||
| 1983 | struct in_device *idev = | ||
| 1984 | container_of(cnf, struct in_device, | ||
| 1985 | cnf); | ||
| 1986 | ifindex = idev->dev->ifindex; | ||
| 1987 | } | ||
| 1988 | inet_netconf_notify_devconf(net, NETCONFA_RP_FILTER, | 1999 | inet_netconf_notify_devconf(net, NETCONFA_RP_FILTER, |
| 1989 | ifindex, cnf); | 2000 | ifindex, cnf); |
| 1990 | } | 2001 | } |
| 2002 | if (i == IPV4_DEVCONF_PROXY_ARP - 1 && | ||
| 2003 | new_value != old_value) { | ||
| 2004 | ifindex = devinet_conf_ifindex(net, cnf); | ||
| 2005 | inet_netconf_notify_devconf(net, NETCONFA_PROXY_ARP, | ||
| 2006 | ifindex, cnf); | ||
| 2007 | } | ||
| 1991 | } | 2008 | } |
| 1992 | 2009 | ||
| 1993 | return ret; | 2010 | return ret; |
