diff options
Diffstat (limited to 'net/ipv4/devinet.c')
-rw-r--r-- | net/ipv4/devinet.c | 76 |
1 files changed, 51 insertions, 25 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index a1b5bcbd04ae..ac2dff3c2c1c 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 |
@@ -463,7 +464,7 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh, | |||
463 | } | 464 | } |
464 | 465 | ||
465 | if (!(ifa->ifa_flags & IFA_F_SECONDARY)) { | 466 | if (!(ifa->ifa_flags & IFA_F_SECONDARY)) { |
466 | net_srandom(ifa->ifa_local); | 467 | prandom_seed((__force u32) ifa->ifa_local); |
467 | ifap = last_primary; | 468 | ifap = last_primary; |
468 | } | 469 | } |
469 | 470 | ||
@@ -473,7 +474,7 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh, | |||
473 | inet_hash_insert(dev_net(in_dev->dev), ifa); | 474 | inet_hash_insert(dev_net(in_dev->dev), ifa); |
474 | 475 | ||
475 | cancel_delayed_work(&check_lifetime_work); | 476 | cancel_delayed_work(&check_lifetime_work); |
476 | schedule_delayed_work(&check_lifetime_work, 0); | 477 | queue_delayed_work(system_power_efficient_wq, &check_lifetime_work, 0); |
477 | 478 | ||
478 | /* Send message first, then call notifier. | 479 | /* Send message first, then call notifier. |
479 | Notifier will trigger FIB update, so that | 480 | Notifier will trigger FIB update, so that |
@@ -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); |
@@ -682,7 +684,8 @@ static void check_lifetime(struct work_struct *work) | |||
682 | if (time_before(next_sched, now + ADDRCONF_TIMER_FUZZ_MAX)) | 684 | if (time_before(next_sched, now + ADDRCONF_TIMER_FUZZ_MAX)) |
683 | next_sched = now + ADDRCONF_TIMER_FUZZ_MAX; | 685 | next_sched = now + ADDRCONF_TIMER_FUZZ_MAX; |
684 | 686 | ||
685 | schedule_delayed_work(&check_lifetime_work, next_sched - now); | 687 | queue_delayed_work(system_power_efficient_wq, &check_lifetime_work, |
688 | next_sched - now); | ||
686 | } | 689 | } |
687 | 690 | ||
688 | static void set_ifa_lifetime(struct in_ifaddr *ifa, __u32 valid_lft, | 691 | static void set_ifa_lifetime(struct in_ifaddr *ifa, __u32 valid_lft, |
@@ -747,6 +750,7 @@ static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh, | |||
747 | goto errout; | 750 | goto errout; |
748 | 751 | ||
749 | ipv4_devconf_setall(in_dev); | 752 | ipv4_devconf_setall(in_dev); |
753 | neigh_parms_data_state_setall(in_dev->arp_parms); | ||
750 | in_dev_hold(in_dev); | 754 | in_dev_hold(in_dev); |
751 | 755 | ||
752 | if (tb[IFA_ADDRESS] == NULL) | 756 | if (tb[IFA_ADDRESS] == NULL) |
@@ -755,7 +759,8 @@ static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh, | |||
755 | INIT_HLIST_NODE(&ifa->hash); | 759 | INIT_HLIST_NODE(&ifa->hash); |
756 | ifa->ifa_prefixlen = ifm->ifa_prefixlen; | 760 | ifa->ifa_prefixlen = ifm->ifa_prefixlen; |
757 | ifa->ifa_mask = inet_make_mask(ifm->ifa_prefixlen); | 761 | ifa->ifa_mask = inet_make_mask(ifm->ifa_prefixlen); |
758 | ifa->ifa_flags = ifm->ifa_flags; | 762 | ifa->ifa_flags = tb[IFA_FLAGS] ? nla_get_u32(tb[IFA_FLAGS]) : |
763 | ifm->ifa_flags; | ||
759 | ifa->ifa_scope = ifm->ifa_scope; | 764 | ifa->ifa_scope = ifm->ifa_scope; |
760 | ifa->ifa_dev = in_dev; | 765 | ifa->ifa_dev = in_dev; |
761 | 766 | ||
@@ -838,7 +843,8 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
838 | ifa = ifa_existing; | 843 | ifa = ifa_existing; |
839 | set_ifa_lifetime(ifa, valid_lft, prefered_lft); | 844 | set_ifa_lifetime(ifa, valid_lft, prefered_lft); |
840 | cancel_delayed_work(&check_lifetime_work); | 845 | cancel_delayed_work(&check_lifetime_work); |
841 | schedule_delayed_work(&check_lifetime_work, 0); | 846 | queue_delayed_work(system_power_efficient_wq, |
847 | &check_lifetime_work, 0); | ||
842 | rtmsg_ifa(RTM_NEWADDR, ifa, nlh, NETLINK_CB(skb).portid); | 848 | rtmsg_ifa(RTM_NEWADDR, ifa, nlh, NETLINK_CB(skb).portid); |
843 | blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa); | 849 | blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa); |
844 | } | 850 | } |
@@ -1236,22 +1242,21 @@ static __be32 confirm_addr_indev(struct in_device *in_dev, __be32 dst, | |||
1236 | 1242 | ||
1237 | /* | 1243 | /* |
1238 | * Confirm that local IP address exists using wildcards: | 1244 | * Confirm that local IP address exists using wildcards: |
1239 | * - in_dev: only on this interface, 0=any interface | 1245 | * - net: netns to check, cannot be NULL |
1246 | * - in_dev: only on this interface, NULL=any interface | ||
1240 | * - dst: only in the same subnet as dst, 0=any dst | 1247 | * - dst: only in the same subnet as dst, 0=any dst |
1241 | * - local: address, 0=autoselect the local address | 1248 | * - local: address, 0=autoselect the local address |
1242 | * - scope: maximum allowed scope value for the local address | 1249 | * - scope: maximum allowed scope value for the local address |
1243 | */ | 1250 | */ |
1244 | __be32 inet_confirm_addr(struct in_device *in_dev, | 1251 | __be32 inet_confirm_addr(struct net *net, struct in_device *in_dev, |
1245 | __be32 dst, __be32 local, int scope) | 1252 | __be32 dst, __be32 local, int scope) |
1246 | { | 1253 | { |
1247 | __be32 addr = 0; | 1254 | __be32 addr = 0; |
1248 | struct net_device *dev; | 1255 | struct net_device *dev; |
1249 | struct net *net; | ||
1250 | 1256 | ||
1251 | if (scope != RT_SCOPE_LINK) | 1257 | if (in_dev != NULL) |
1252 | return confirm_addr_indev(in_dev, dst, local, scope); | 1258 | return confirm_addr_indev(in_dev, dst, local, scope); |
1253 | 1259 | ||
1254 | net = dev_net(in_dev->dev); | ||
1255 | rcu_read_lock(); | 1260 | rcu_read_lock(); |
1256 | for_each_netdev_rcu(net, dev) { | 1261 | for_each_netdev_rcu(net, dev) { |
1257 | in_dev = __in_dev_get_rcu(dev); | 1262 | in_dev = __in_dev_get_rcu(dev); |
@@ -1382,6 +1387,8 @@ static int inetdev_event(struct notifier_block *this, unsigned long event, | |||
1382 | memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); | 1387 | memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); |
1383 | set_ifa_lifetime(ifa, INFINITY_LIFE_TIME, | 1388 | set_ifa_lifetime(ifa, INFINITY_LIFE_TIME, |
1384 | INFINITY_LIFE_TIME); | 1389 | INFINITY_LIFE_TIME); |
1390 | ipv4_devconf_setall(in_dev); | ||
1391 | neigh_parms_data_state_setall(in_dev->arp_parms); | ||
1385 | inet_insert_ifa(ifa); | 1392 | inet_insert_ifa(ifa); |
1386 | } | 1393 | } |
1387 | } | 1394 | } |
@@ -1435,7 +1442,8 @@ static size_t inet_nlmsg_size(void) | |||
1435 | + nla_total_size(4) /* IFA_ADDRESS */ | 1442 | + nla_total_size(4) /* IFA_ADDRESS */ |
1436 | + nla_total_size(4) /* IFA_LOCAL */ | 1443 | + nla_total_size(4) /* IFA_LOCAL */ |
1437 | + nla_total_size(4) /* IFA_BROADCAST */ | 1444 | + nla_total_size(4) /* IFA_BROADCAST */ |
1438 | + nla_total_size(IFNAMSIZ); /* IFA_LABEL */ | 1445 | + nla_total_size(IFNAMSIZ) /* IFA_LABEL */ |
1446 | + nla_total_size(4); /* IFA_FLAGS */ | ||
1439 | } | 1447 | } |
1440 | 1448 | ||
1441 | static inline u32 cstamp_delta(unsigned long cstamp) | 1449 | static inline u32 cstamp_delta(unsigned long cstamp) |
@@ -1503,6 +1511,7 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa, | |||
1503 | nla_put_be32(skb, IFA_BROADCAST, ifa->ifa_broadcast)) || | 1511 | nla_put_be32(skb, IFA_BROADCAST, ifa->ifa_broadcast)) || |
1504 | (ifa->ifa_label[0] && | 1512 | (ifa->ifa_label[0] && |
1505 | nla_put_string(skb, IFA_LABEL, ifa->ifa_label)) || | 1513 | nla_put_string(skb, IFA_LABEL, ifa->ifa_label)) || |
1514 | nla_put_u32(skb, IFA_FLAGS, ifa->ifa_flags) || | ||
1506 | put_cacheinfo(skb, ifa->ifa_cstamp, ifa->ifa_tstamp, | 1515 | put_cacheinfo(skb, ifa->ifa_cstamp, ifa->ifa_tstamp, |
1507 | preferred, valid)) | 1516 | preferred, valid)) |
1508 | goto nla_put_failure; | 1517 | goto nla_put_failure; |
@@ -1691,6 +1700,8 @@ static int inet_netconf_msgsize_devconf(int type) | |||
1691 | size += nla_total_size(4); | 1700 | size += nla_total_size(4); |
1692 | if (type == -1 || type == NETCONFA_MC_FORWARDING) | 1701 | if (type == -1 || type == NETCONFA_MC_FORWARDING) |
1693 | size += nla_total_size(4); | 1702 | size += nla_total_size(4); |
1703 | if (type == -1 || type == NETCONFA_PROXY_NEIGH) | ||
1704 | size += nla_total_size(4); | ||
1694 | 1705 | ||
1695 | return size; | 1706 | return size; |
1696 | } | 1707 | } |
@@ -1727,6 +1738,10 @@ static int inet_netconf_fill_devconf(struct sk_buff *skb, int ifindex, | |||
1727 | nla_put_s32(skb, NETCONFA_MC_FORWARDING, | 1738 | nla_put_s32(skb, NETCONFA_MC_FORWARDING, |
1728 | IPV4_DEVCONF(*devconf, MC_FORWARDING)) < 0) | 1739 | IPV4_DEVCONF(*devconf, MC_FORWARDING)) < 0) |
1729 | goto nla_put_failure; | 1740 | goto nla_put_failure; |
1741 | if ((type == -1 || type == NETCONFA_PROXY_NEIGH) && | ||
1742 | nla_put_s32(skb, NETCONFA_PROXY_NEIGH, | ||
1743 | IPV4_DEVCONF(*devconf, PROXY_ARP)) < 0) | ||
1744 | goto nla_put_failure; | ||
1730 | 1745 | ||
1731 | return nlmsg_end(skb, nlh); | 1746 | return nlmsg_end(skb, nlh); |
1732 | 1747 | ||
@@ -1764,6 +1779,7 @@ static const struct nla_policy devconf_ipv4_policy[NETCONFA_MAX+1] = { | |||
1764 | [NETCONFA_IFINDEX] = { .len = sizeof(int) }, | 1779 | [NETCONFA_IFINDEX] = { .len = sizeof(int) }, |
1765 | [NETCONFA_FORWARDING] = { .len = sizeof(int) }, | 1780 | [NETCONFA_FORWARDING] = { .len = sizeof(int) }, |
1766 | [NETCONFA_RP_FILTER] = { .len = sizeof(int) }, | 1781 | [NETCONFA_RP_FILTER] = { .len = sizeof(int) }, |
1782 | [NETCONFA_PROXY_NEIGH] = { .len = sizeof(int) }, | ||
1767 | }; | 1783 | }; |
1768 | 1784 | ||
1769 | static int inet_netconf_get_devconf(struct sk_buff *in_skb, | 1785 | static int inet_netconf_get_devconf(struct sk_buff *in_skb, |
@@ -1945,6 +1961,19 @@ static void inet_forward_change(struct net *net) | |||
1945 | } | 1961 | } |
1946 | } | 1962 | } |
1947 | 1963 | ||
1964 | static int devinet_conf_ifindex(struct net *net, struct ipv4_devconf *cnf) | ||
1965 | { | ||
1966 | if (cnf == net->ipv4.devconf_dflt) | ||
1967 | return NETCONFA_IFINDEX_DEFAULT; | ||
1968 | else if (cnf == net->ipv4.devconf_all) | ||
1969 | return NETCONFA_IFINDEX_ALL; | ||
1970 | else { | ||
1971 | struct in_device *idev | ||
1972 | = container_of(cnf, struct in_device, cnf); | ||
1973 | return idev->dev->ifindex; | ||
1974 | } | ||
1975 | } | ||
1976 | |||
1948 | static int devinet_conf_proc(struct ctl_table *ctl, int write, | 1977 | static int devinet_conf_proc(struct ctl_table *ctl, int write, |
1949 | void __user *buffer, | 1978 | void __user *buffer, |
1950 | size_t *lenp, loff_t *ppos) | 1979 | size_t *lenp, loff_t *ppos) |
@@ -1957,6 +1986,7 @@ static int devinet_conf_proc(struct ctl_table *ctl, int write, | |||
1957 | struct ipv4_devconf *cnf = ctl->extra1; | 1986 | struct ipv4_devconf *cnf = ctl->extra1; |
1958 | struct net *net = ctl->extra2; | 1987 | struct net *net = ctl->extra2; |
1959 | int i = (int *)ctl->data - cnf->data; | 1988 | int i = (int *)ctl->data - cnf->data; |
1989 | int ifindex; | ||
1960 | 1990 | ||
1961 | set_bit(i, cnf->state); | 1991 | set_bit(i, cnf->state); |
1962 | 1992 | ||
@@ -1966,23 +1996,19 @@ static int devinet_conf_proc(struct ctl_table *ctl, int write, | |||
1966 | i == IPV4_DEVCONF_ROUTE_LOCALNET - 1) | 1996 | i == IPV4_DEVCONF_ROUTE_LOCALNET - 1) |
1967 | if ((new_value == 0) && (old_value != 0)) | 1997 | if ((new_value == 0) && (old_value != 0)) |
1968 | rt_cache_flush(net); | 1998 | rt_cache_flush(net); |
1999 | |||
1969 | if (i == IPV4_DEVCONF_RP_FILTER - 1 && | 2000 | if (i == IPV4_DEVCONF_RP_FILTER - 1 && |
1970 | new_value != old_value) { | 2001 | new_value != old_value) { |
1971 | int ifindex; | 2002 | 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, | 2003 | inet_netconf_notify_devconf(net, NETCONFA_RP_FILTER, |
1984 | ifindex, cnf); | 2004 | ifindex, cnf); |
1985 | } | 2005 | } |
2006 | if (i == IPV4_DEVCONF_PROXY_ARP - 1 && | ||
2007 | new_value != old_value) { | ||
2008 | ifindex = devinet_conf_ifindex(net, cnf); | ||
2009 | inet_netconf_notify_devconf(net, NETCONFA_PROXY_NEIGH, | ||
2010 | ifindex, cnf); | ||
2011 | } | ||
1986 | } | 2012 | } |
1987 | 2013 | ||
1988 | return ret; | 2014 | return ret; |
@@ -2160,7 +2186,7 @@ static void __devinet_sysctl_unregister(struct ipv4_devconf *cnf) | |||
2160 | 2186 | ||
2161 | static void devinet_sysctl_register(struct in_device *idev) | 2187 | static void devinet_sysctl_register(struct in_device *idev) |
2162 | { | 2188 | { |
2163 | neigh_sysctl_register(idev->dev, idev->arp_parms, "ipv4", NULL); | 2189 | neigh_sysctl_register(idev->dev, idev->arp_parms, NULL); |
2164 | __devinet_sysctl_register(dev_net(idev->dev), idev->dev->name, | 2190 | __devinet_sysctl_register(dev_net(idev->dev), idev->dev->name, |
2165 | &idev->cnf); | 2191 | &idev->cnf); |
2166 | } | 2192 | } |
@@ -2298,7 +2324,7 @@ void __init devinet_init(void) | |||
2298 | register_gifconf(PF_INET, inet_gifconf); | 2324 | register_gifconf(PF_INET, inet_gifconf); |
2299 | register_netdevice_notifier(&ip_netdev_notifier); | 2325 | register_netdevice_notifier(&ip_netdev_notifier); |
2300 | 2326 | ||
2301 | schedule_delayed_work(&check_lifetime_work, 0); | 2327 | queue_delayed_work(system_power_efficient_wq, &check_lifetime_work, 0); |
2302 | 2328 | ||
2303 | rtnl_af_register(&inet_af_ops); | 2329 | rtnl_af_register(&inet_af_ops); |
2304 | 2330 | ||