diff options
-rw-r--r-- | include/linux/inetdevice.h | 6 | ||||
-rw-r--r-- | net/ipv4/devinet.c | 19 | ||||
-rw-r--r-- | net/ipv4/ipmr.c | 15 |
3 files changed, 24 insertions, 16 deletions
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, | |||
59 | in_dev->cnf.data[index] = val; | 59 | in_dev->cnf.data[index] = val; |
60 | } | 60 | } |
61 | 61 | ||
62 | static inline void ipv4_devconf_setall(struct in_device *in_dev) | ||
63 | { | ||
64 | bitmap_fill(in_dev->cnf.state, __NET_IPV4_CONF_MAX - 1); | ||
65 | } | ||
66 | |||
62 | #define IN_DEV_CONF_GET(in_dev, attr) \ | 67 | #define IN_DEV_CONF_GET(in_dev, attr) \ |
63 | ipv4_devconf_get((in_dev), NET_IPV4_CONF_ ## attr) | 68 | ipv4_devconf_get((in_dev), NET_IPV4_CONF_ ## attr) |
64 | #define IN_DEV_CONF_SET(in_dev, attr, val) \ | 69 | #define IN_DEV_CONF_SET(in_dev, attr, val) \ |
@@ -125,7 +130,6 @@ extern struct net_device *ip_dev_find(__be32 addr); | |||
125 | extern int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b); | 130 | extern int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b); |
126 | extern int devinet_ioctl(unsigned int cmd, void __user *); | 131 | extern int devinet_ioctl(unsigned int cmd, void __user *); |
127 | extern void devinet_init(void); | 132 | extern void devinet_init(void); |
128 | extern struct in_device *inetdev_init(struct net_device *dev); | ||
129 | extern struct in_device *inetdev_by_index(int); | 133 | extern struct in_device *inetdev_by_index(int); |
130 | extern __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope); | 134 | extern __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope); |
131 | extern __be32 inet_confirm_addr(const struct net_device *dev, __be32 dst, __be32 local, int scope); | 135 | 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) | |||
147 | } | 147 | } |
148 | } | 148 | } |
149 | 149 | ||
150 | struct in_device *inetdev_init(struct net_device *dev) | 150 | static struct in_device *inetdev_init(struct net_device *dev) |
151 | { | 151 | { |
152 | struct in_device *in_dev; | 152 | struct in_device *in_dev; |
153 | 153 | ||
@@ -405,12 +405,10 @@ static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa) | |||
405 | ASSERT_RTNL(); | 405 | ASSERT_RTNL(); |
406 | 406 | ||
407 | if (!in_dev) { | 407 | if (!in_dev) { |
408 | in_dev = inetdev_init(dev); | 408 | inet_free_ifa(ifa); |
409 | if (!in_dev) { | 409 | return -ENOBUFS; |
410 | inet_free_ifa(ifa); | ||
411 | return -ENOBUFS; | ||
412 | } | ||
413 | } | 410 | } |
411 | ipv4_devconf_setall(in_dev); | ||
414 | if (ifa->ifa_dev != in_dev) { | 412 | if (ifa->ifa_dev != in_dev) { |
415 | BUG_TRAP(!ifa->ifa_dev); | 413 | BUG_TRAP(!ifa->ifa_dev); |
416 | in_dev_hold(in_dev); | 414 | in_dev_hold(in_dev); |
@@ -520,13 +518,12 @@ static struct in_ifaddr *rtm_to_ifaddr(struct nlmsghdr *nlh) | |||
520 | 518 | ||
521 | in_dev = __in_dev_get_rtnl(dev); | 519 | in_dev = __in_dev_get_rtnl(dev); |
522 | if (in_dev == NULL) { | 520 | if (in_dev == NULL) { |
523 | in_dev = inetdev_init(dev); | 521 | err = -ENOBUFS; |
524 | if (in_dev == NULL) { | 522 | goto errout; |
525 | err = -ENOBUFS; | ||
526 | goto errout; | ||
527 | } | ||
528 | } | 523 | } |
529 | 524 | ||
525 | ipv4_devconf_setall(in_dev); | ||
526 | |||
530 | ifa = inet_alloc_ifa(); | 527 | ifa = inet_alloc_ifa(); |
531 | if (ifa == NULL) { | 528 | if (ifa == NULL) { |
532 | /* | 529 | /* |
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) | |||
152 | dev->flags |= IFF_MULTICAST; | 152 | dev->flags |= IFF_MULTICAST; |
153 | 153 | ||
154 | in_dev = __in_dev_get_rtnl(dev); | 154 | in_dev = __in_dev_get_rtnl(dev); |
155 | if (in_dev == NULL && (in_dev = inetdev_init(dev)) == NULL) | 155 | if (in_dev == NULL) |
156 | goto failure; | 156 | goto failure; |
157 | IN_DEV_CONF_SET(in_dev, RP_FILTER, 0); | 157 | |
158 | ipv4_devconf_setall(in_dev); | ||
159 | IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0; | ||
158 | 160 | ||
159 | if (dev_open(dev)) | 161 | if (dev_open(dev)) |
160 | goto failure; | 162 | goto failure; |
@@ -218,10 +220,15 @@ static struct net_device *ipmr_reg_vif(void) | |||
218 | } | 220 | } |
219 | dev->iflink = 0; | 221 | dev->iflink = 0; |
220 | 222 | ||
221 | if ((in_dev = inetdev_init(dev)) == NULL) | 223 | rcu_read_lock(); |
224 | if ((in_dev = __in_dev_get_rcu(dev)) == NULL) { | ||
225 | rcu_read_unlock(); | ||
222 | goto failure; | 226 | goto failure; |
227 | } | ||
223 | 228 | ||
224 | IN_DEV_CONF_SET(in_dev, RP_FILTER, 0); | 229 | ipv4_devconf_setall(in_dev); |
230 | IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0; | ||
231 | rcu_read_unlock(); | ||
225 | 232 | ||
226 | if (dev_open(dev)) | 233 | if (dev_open(dev)) |
227 | goto failure; | 234 | goto failure; |