diff options
Diffstat (limited to 'net/ipv4/devinet.c')
-rw-r--r-- | net/ipv4/devinet.c | 62 |
1 files changed, 42 insertions, 20 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index a1b5bcbd04ae..0feebd5de295 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -99,6 +99,7 @@ static const struct nla_policy ifa_ipv4_policy[IFA_MAX+1] = { | |||
99 | [IFA_BROADCAST] = { .type = NLA_U32 }, | 99 | [IFA_BROADCAST] = { .type = NLA_U32 }, |
100 | [IFA_LABEL] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, | 100 | [IFA_LABEL] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, |
101 | [IFA_CACHEINFO] = { .len = sizeof(struct ifa_cacheinfo) }, | 101 | [IFA_CACHEINFO] = { .len = sizeof(struct ifa_cacheinfo) }, |
102 | [IFA_FLAGS] = { .type = NLA_U32 }, | ||
102 | }; | 103 | }; |
103 | 104 | ||
104 | #define IN4_ADDR_HSIZE_SHIFT 8 | 105 | #define IN4_ADDR_HSIZE_SHIFT 8 |
@@ -500,6 +501,7 @@ static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa) | |||
500 | return -ENOBUFS; | 501 | return -ENOBUFS; |
501 | } | 502 | } |
502 | ipv4_devconf_setall(in_dev); | 503 | ipv4_devconf_setall(in_dev); |
504 | neigh_parms_data_state_setall(in_dev->arp_parms); | ||
503 | if (ifa->ifa_dev != in_dev) { | 505 | if (ifa->ifa_dev != in_dev) { |
504 | WARN_ON(ifa->ifa_dev); | 506 | WARN_ON(ifa->ifa_dev); |
505 | in_dev_hold(in_dev); | 507 | in_dev_hold(in_dev); |
@@ -747,6 +749,7 @@ static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh, | |||
747 | goto errout; | 749 | goto errout; |
748 | 750 | ||
749 | ipv4_devconf_setall(in_dev); | 751 | ipv4_devconf_setall(in_dev); |
752 | neigh_parms_data_state_setall(in_dev->arp_parms); | ||
750 | in_dev_hold(in_dev); | 753 | in_dev_hold(in_dev); |
751 | 754 | ||
752 | if (tb[IFA_ADDRESS] == NULL) | 755 | if (tb[IFA_ADDRESS] == NULL) |
@@ -755,7 +758,8 @@ static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh, | |||
755 | INIT_HLIST_NODE(&ifa->hash); | 758 | INIT_HLIST_NODE(&ifa->hash); |
756 | ifa->ifa_prefixlen = ifm->ifa_prefixlen; | 759 | ifa->ifa_prefixlen = ifm->ifa_prefixlen; |
757 | ifa->ifa_mask = inet_make_mask(ifm->ifa_prefixlen); | 760 | ifa->ifa_mask = inet_make_mask(ifm->ifa_prefixlen); |
758 | ifa->ifa_flags = ifm->ifa_flags; | 761 | ifa->ifa_flags = tb[IFA_FLAGS] ? nla_get_u32(tb[IFA_FLAGS]) : |
762 | ifm->ifa_flags; | ||
759 | ifa->ifa_scope = ifm->ifa_scope; | 763 | ifa->ifa_scope = ifm->ifa_scope; |
760 | ifa->ifa_dev = in_dev; | 764 | ifa->ifa_dev = in_dev; |
761 | 765 | ||
@@ -1236,22 +1240,21 @@ static __be32 confirm_addr_indev(struct in_device *in_dev, __be32 dst, | |||
1236 | 1240 | ||
1237 | /* | 1241 | /* |
1238 | * Confirm that local IP address exists using wildcards: | 1242 | * Confirm that local IP address exists using wildcards: |
1239 | * - in_dev: only on this interface, 0=any interface | 1243 | * - net: netns to check, cannot be NULL |
1244 | * - in_dev: only on this interface, NULL=any interface | ||
1240 | * - dst: only in the same subnet as dst, 0=any dst | 1245 | * - dst: only in the same subnet as dst, 0=any dst |
1241 | * - local: address, 0=autoselect the local address | 1246 | * - local: address, 0=autoselect the local address |
1242 | * - scope: maximum allowed scope value for the local address | 1247 | * - scope: maximum allowed scope value for the local address |
1243 | */ | 1248 | */ |
1244 | __be32 inet_confirm_addr(struct in_device *in_dev, | 1249 | __be32 inet_confirm_addr(struct net *net, struct in_device *in_dev, |
1245 | __be32 dst, __be32 local, int scope) | 1250 | __be32 dst, __be32 local, int scope) |
1246 | { | 1251 | { |
1247 | __be32 addr = 0; | 1252 | __be32 addr = 0; |
1248 | struct net_device *dev; | 1253 | struct net_device *dev; |
1249 | struct net *net; | ||
1250 | 1254 | ||
1251 | if (scope != RT_SCOPE_LINK) | 1255 | if (in_dev != NULL) |
1252 | return confirm_addr_indev(in_dev, dst, local, scope); | 1256 | return confirm_addr_indev(in_dev, dst, local, scope); |
1253 | 1257 | ||
1254 | net = dev_net(in_dev->dev); | ||
1255 | rcu_read_lock(); | 1258 | rcu_read_lock(); |
1256 | for_each_netdev_rcu(net, dev) { | 1259 | for_each_netdev_rcu(net, dev) { |
1257 | in_dev = __in_dev_get_rcu(dev); | 1260 | in_dev = __in_dev_get_rcu(dev); |
@@ -1435,7 +1438,8 @@ static size_t inet_nlmsg_size(void) | |||
1435 | + nla_total_size(4) /* IFA_ADDRESS */ | 1438 | + nla_total_size(4) /* IFA_ADDRESS */ |
1436 | + nla_total_size(4) /* IFA_LOCAL */ | 1439 | + nla_total_size(4) /* IFA_LOCAL */ |
1437 | + nla_total_size(4) /* IFA_BROADCAST */ | 1440 | + nla_total_size(4) /* IFA_BROADCAST */ |
1438 | + nla_total_size(IFNAMSIZ); /* IFA_LABEL */ | 1441 | + nla_total_size(IFNAMSIZ) /* IFA_LABEL */ |
1442 | + nla_total_size(4); /* IFA_FLAGS */ | ||
1439 | } | 1443 | } |
1440 | 1444 | ||
1441 | static inline u32 cstamp_delta(unsigned long cstamp) | 1445 | static inline u32 cstamp_delta(unsigned long cstamp) |
@@ -1503,6 +1507,7 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa, | |||
1503 | nla_put_be32(skb, IFA_BROADCAST, ifa->ifa_broadcast)) || | 1507 | nla_put_be32(skb, IFA_BROADCAST, ifa->ifa_broadcast)) || |
1504 | (ifa->ifa_label[0] && | 1508 | (ifa->ifa_label[0] && |
1505 | nla_put_string(skb, IFA_LABEL, ifa->ifa_label)) || | 1509 | nla_put_string(skb, IFA_LABEL, ifa->ifa_label)) || |
1510 | nla_put_u32(skb, IFA_FLAGS, ifa->ifa_flags) || | ||
1506 | put_cacheinfo(skb, ifa->ifa_cstamp, ifa->ifa_tstamp, | 1511 | put_cacheinfo(skb, ifa->ifa_cstamp, ifa->ifa_tstamp, |
1507 | preferred, valid)) | 1512 | preferred, valid)) |
1508 | goto nla_put_failure; | 1513 | goto nla_put_failure; |
@@ -1691,6 +1696,8 @@ static int inet_netconf_msgsize_devconf(int type) | |||
1691 | size += nla_total_size(4); | 1696 | size += nla_total_size(4); |
1692 | if (type == -1 || type == NETCONFA_MC_FORWARDING) | 1697 | if (type == -1 || type == NETCONFA_MC_FORWARDING) |
1693 | size += nla_total_size(4); | 1698 | size += nla_total_size(4); |
1699 | if (type == -1 || type == NETCONFA_PROXY_NEIGH) | ||
1700 | size += nla_total_size(4); | ||
1694 | 1701 | ||
1695 | return size; | 1702 | return size; |
1696 | } | 1703 | } |
@@ -1727,6 +1734,10 @@ static int inet_netconf_fill_devconf(struct sk_buff *skb, int ifindex, | |||
1727 | nla_put_s32(skb, NETCONFA_MC_FORWARDING, | 1734 | nla_put_s32(skb, NETCONFA_MC_FORWARDING, |
1728 | IPV4_DEVCONF(*devconf, MC_FORWARDING)) < 0) | 1735 | IPV4_DEVCONF(*devconf, MC_FORWARDING)) < 0) |
1729 | goto nla_put_failure; | 1736 | goto nla_put_failure; |
1737 | if ((type == -1 || type == NETCONFA_PROXY_NEIGH) && | ||
1738 | nla_put_s32(skb, NETCONFA_PROXY_NEIGH, | ||
1739 | IPV4_DEVCONF(*devconf, PROXY_ARP)) < 0) | ||
1740 | goto nla_put_failure; | ||
1730 | 1741 | ||
1731 | return nlmsg_end(skb, nlh); | 1742 | return nlmsg_end(skb, nlh); |
1732 | 1743 | ||
@@ -1764,6 +1775,7 @@ static const struct nla_policy devconf_ipv4_policy[NETCONFA_MAX+1] = { | |||
1764 | [NETCONFA_IFINDEX] = { .len = sizeof(int) }, | 1775 | [NETCONFA_IFINDEX] = { .len = sizeof(int) }, |
1765 | [NETCONFA_FORWARDING] = { .len = sizeof(int) }, | 1776 | [NETCONFA_FORWARDING] = { .len = sizeof(int) }, |
1766 | [NETCONFA_RP_FILTER] = { .len = sizeof(int) }, | 1777 | [NETCONFA_RP_FILTER] = { .len = sizeof(int) }, |
1778 | [NETCONFA_PROXY_NEIGH] = { .len = sizeof(int) }, | ||
1767 | }; | 1779 | }; |
1768 | 1780 | ||
1769 | static int inet_netconf_get_devconf(struct sk_buff *in_skb, | 1781 | static int inet_netconf_get_devconf(struct sk_buff *in_skb, |
@@ -1945,6 +1957,19 @@ static void inet_forward_change(struct net *net) | |||
1945 | } | 1957 | } |
1946 | } | 1958 | } |
1947 | 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 | |||
1948 | static int devinet_conf_proc(struct ctl_table *ctl, int write, | 1973 | static int devinet_conf_proc(struct ctl_table *ctl, int write, |
1949 | void __user *buffer, | 1974 | void __user *buffer, |
1950 | size_t *lenp, loff_t *ppos) | 1975 | size_t *lenp, loff_t *ppos) |
@@ -1957,6 +1982,7 @@ static int devinet_conf_proc(struct ctl_table *ctl, int write, | |||
1957 | struct ipv4_devconf *cnf = ctl->extra1; | 1982 | struct ipv4_devconf *cnf = ctl->extra1; |
1958 | struct net *net = ctl->extra2; | 1983 | struct net *net = ctl->extra2; |
1959 | int i = (int *)ctl->data - cnf->data; | 1984 | int i = (int *)ctl->data - cnf->data; |
1985 | int ifindex; | ||
1960 | 1986 | ||
1961 | set_bit(i, cnf->state); | 1987 | set_bit(i, cnf->state); |
1962 | 1988 | ||
@@ -1966,23 +1992,19 @@ static int devinet_conf_proc(struct ctl_table *ctl, int write, | |||
1966 | i == IPV4_DEVCONF_ROUTE_LOCALNET - 1) | 1992 | i == IPV4_DEVCONF_ROUTE_LOCALNET - 1) |
1967 | if ((new_value == 0) && (old_value != 0)) | 1993 | if ((new_value == 0) && (old_value != 0)) |
1968 | rt_cache_flush(net); | 1994 | rt_cache_flush(net); |
1995 | |||
1969 | if (i == IPV4_DEVCONF_RP_FILTER - 1 && | 1996 | if (i == IPV4_DEVCONF_RP_FILTER - 1 && |
1970 | new_value != old_value) { | 1997 | new_value != old_value) { |
1971 | int ifindex; | 1998 | ifindex = devinet_conf_ifindex(net, cnf); |
1972 | |||
1973 | if (cnf == net->ipv4.devconf_dflt) | ||
1974 | ifindex = NETCONFA_IFINDEX_DEFAULT; | ||
1975 | else if (cnf == net->ipv4.devconf_all) | ||
1976 | ifindex = NETCONFA_IFINDEX_ALL; | ||
1977 | else { | ||
1978 | struct in_device *idev = | ||
1979 | container_of(cnf, struct in_device, | ||
1980 | cnf); | ||
1981 | ifindex = idev->dev->ifindex; | ||
1982 | } | ||
1983 | inet_netconf_notify_devconf(net, NETCONFA_RP_FILTER, | 1999 | inet_netconf_notify_devconf(net, NETCONFA_RP_FILTER, |
1984 | ifindex, cnf); | 2000 | ifindex, cnf); |
1985 | } | 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_NEIGH, | ||
2006 | ifindex, cnf); | ||
2007 | } | ||
1986 | } | 2008 | } |
1987 | 2009 | ||
1988 | return ret; | 2010 | return ret; |
@@ -2160,7 +2182,7 @@ static void __devinet_sysctl_unregister(struct ipv4_devconf *cnf) | |||
2160 | 2182 | ||
2161 | static void devinet_sysctl_register(struct in_device *idev) | 2183 | static void devinet_sysctl_register(struct in_device *idev) |
2162 | { | 2184 | { |
2163 | neigh_sysctl_register(idev->dev, idev->arp_parms, "ipv4", NULL); | 2185 | neigh_sysctl_register(idev->dev, idev->arp_parms, NULL); |
2164 | __devinet_sysctl_register(dev_net(idev->dev), idev->dev->name, | 2186 | __devinet_sysctl_register(dev_net(idev->dev), idev->dev->name, |
2165 | &idev->cnf); | 2187 | &idev->cnf); |
2166 | } | 2188 | } |