diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h index 40adefdfe5d1..ae04901aa09a 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h @@ -59,6 +59,11 @@ static inline void ipv4_devconf_set(struct in_device *in_dev, int index, in_dev->cnf.data[index] = val; } +static inline void ipv4_devconf_setall(struct in_device *in_dev) +{ + bitmap_fill(in_dev->cnf.state, __NET_IPV4_CONF_MAX - 1); +} + #define IN_DEV_CONF_GET(in_dev, attr) \ ipv4_devconf_get((in_dev), NET_IPV4_CONF_ ## attr) #define IN_DEV_CONF_SET(in_dev, attr, val) \ @@ -125,7 +130,6 @@ extern struct net_device *ip_dev_find(__be32 addr); extern int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b); extern int devinet_ioctl(unsigned int cmd, void __user *); extern void devinet_init(void); -extern struct in_device *inetdev_init(struct net_device *dev); extern struct in_device *inetdev_by_index(int); extern __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope); extern __be32 inet_confirm_addr(const struct net_device *dev, __be32 dst, __be32 local, int scope); diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index e19734795a7b..354e800be18d 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -147,7 +147,7 @@ void in_dev_finish_destroy(struct in_device *idev) } } -struct in_device *inetdev_init(struct net_device *dev) +static struct in_device *inetdev_init(struct net_device *dev) { struct in_device *in_dev; @@ -405,12 +405,10 @@ static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa) ASSERT_RTNL(); if (!in_dev) { - in_dev = inetdev_init(dev); - if (!in_dev) { - inet_free_ifa(ifa); - return -ENOBUFS; - } + inet_free_ifa(ifa); + return -ENOBUFS; } + ipv4_devconf_setall(in_dev); if (ifa->ifa_dev != in_dev) { BUG_TRAP(!ifa->ifa_dev); in_dev_hold(in_dev); @@ -520,13 +518,12 @@ static struct in_ifaddr *rtm_to_ifaddr(struct nlmsghdr *nlh) in_dev = __in_dev_get_rtnl(dev); if (in_dev == NULL) { - in_dev = inetdev_init(dev); - if (in_dev == NULL) { - err = -ENOBUFS; - goto errout; - } + err = -ENOBUFS; + goto errout; } + ipv4_devconf_setall(in_dev); + ifa = inet_alloc_ifa(); if (ifa == NULL) { /* diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index d570d3ad40a9..d96582acdf69 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -152,9 +152,11 @@ struct net_device *ipmr_new_tunnel(struct vifctl *v) dev->flags |= IFF_MULTICAST; in_dev = __in_dev_get_rtnl(dev); - if (in_dev == NULL && (in_dev = inetdev_init(dev)) == NULL) + if (in_dev == NULL) goto failure; - IN_DEV_CONF_SET(in_dev, RP_FILTER, 0); + + ipv4_devconf_setall(in_dev); + IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0; if (dev_open(dev)) goto failure; @@ -218,10 +220,15 @@ static struct net_device *ipmr_reg_vif(void) } dev->iflink = 0; - if ((in_dev = inetdev_init(dev)) == NULL) + rcu_read_lock(); + if ((in_dev = __in_dev_get_rcu(dev)) == NULL) { + rcu_read_unlock(); goto failure; + } - IN_DEV_CONF_SET(in_dev, RP_FILTER, 0); + ipv4_devconf_setall(in_dev); + IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0; + rcu_read_unlock(); if (dev_open(dev)) goto failure;