diff options
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/dev.c | 44 | ||||
-rw-r--r-- | net/core/dev_mcast.c | 37 | ||||
-rw-r--r-- | net/core/dst.c | 15 | ||||
-rw-r--r-- | net/core/ethtool.c | 64 | ||||
-rw-r--r-- | net/core/fib_rules.c | 13 | ||||
-rw-r--r-- | net/core/filter.c | 57 | ||||
-rw-r--r-- | net/core/neighbour.c | 171 | ||||
-rw-r--r-- | net/core/net_namespace.c | 104 | ||||
-rw-r--r-- | net/core/netpoll.c | 6 | ||||
-rw-r--r-- | net/core/pktgen.c | 2 | ||||
-rw-r--r-- | net/core/rtnetlink.c | 45 | ||||
-rw-r--r-- | net/core/skbuff.c | 96 | ||||
-rw-r--r-- | net/core/sock.c | 151 | ||||
-rw-r--r-- | net/core/sysctl_net_core.c | 12 |
14 files changed, 595 insertions, 222 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 460e7f99ce3e..e1df1ab3e04a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -216,7 +216,7 @@ static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex) | |||
216 | /* Device list insertion */ | 216 | /* Device list insertion */ |
217 | static int list_netdevice(struct net_device *dev) | 217 | static int list_netdevice(struct net_device *dev) |
218 | { | 218 | { |
219 | struct net *net = dev->nd_net; | 219 | struct net *net = dev_net(dev); |
220 | 220 | ||
221 | ASSERT_RTNL(); | 221 | ASSERT_RTNL(); |
222 | 222 | ||
@@ -852,8 +852,8 @@ int dev_alloc_name(struct net_device *dev, const char *name) | |||
852 | struct net *net; | 852 | struct net *net; |
853 | int ret; | 853 | int ret; |
854 | 854 | ||
855 | BUG_ON(!dev->nd_net); | 855 | BUG_ON(!dev_net(dev)); |
856 | net = dev->nd_net; | 856 | net = dev_net(dev); |
857 | ret = __dev_alloc_name(net, name, buf); | 857 | ret = __dev_alloc_name(net, name, buf); |
858 | if (ret >= 0) | 858 | if (ret >= 0) |
859 | strlcpy(dev->name, buf, IFNAMSIZ); | 859 | strlcpy(dev->name, buf, IFNAMSIZ); |
@@ -877,9 +877,9 @@ int dev_change_name(struct net_device *dev, char *newname) | |||
877 | struct net *net; | 877 | struct net *net; |
878 | 878 | ||
879 | ASSERT_RTNL(); | 879 | ASSERT_RTNL(); |
880 | BUG_ON(!dev->nd_net); | 880 | BUG_ON(!dev_net(dev)); |
881 | 881 | ||
882 | net = dev->nd_net; | 882 | net = dev_net(dev); |
883 | if (dev->flags & IFF_UP) | 883 | if (dev->flags & IFF_UP) |
884 | return -EBUSY; | 884 | return -EBUSY; |
885 | 885 | ||
@@ -2615,7 +2615,7 @@ static int ptype_seq_show(struct seq_file *seq, void *v) | |||
2615 | 2615 | ||
2616 | if (v == SEQ_START_TOKEN) | 2616 | if (v == SEQ_START_TOKEN) |
2617 | seq_puts(seq, "Type Device Function\n"); | 2617 | seq_puts(seq, "Type Device Function\n"); |
2618 | else { | 2618 | else if (pt->dev == NULL || dev_net(pt->dev) == seq_file_net(seq)) { |
2619 | if (pt->type == htons(ETH_P_ALL)) | 2619 | if (pt->type == htons(ETH_P_ALL)) |
2620 | seq_puts(seq, "ALL "); | 2620 | seq_puts(seq, "ALL "); |
2621 | else | 2621 | else |
@@ -2639,7 +2639,8 @@ static const struct seq_operations ptype_seq_ops = { | |||
2639 | 2639 | ||
2640 | static int ptype_seq_open(struct inode *inode, struct file *file) | 2640 | static int ptype_seq_open(struct inode *inode, struct file *file) |
2641 | { | 2641 | { |
2642 | return seq_open(file, &ptype_seq_ops); | 2642 | return seq_open_net(inode, file, &ptype_seq_ops, |
2643 | sizeof(struct seq_net_private)); | ||
2643 | } | 2644 | } |
2644 | 2645 | ||
2645 | static const struct file_operations ptype_seq_fops = { | 2646 | static const struct file_operations ptype_seq_fops = { |
@@ -2647,7 +2648,7 @@ static const struct file_operations ptype_seq_fops = { | |||
2647 | .open = ptype_seq_open, | 2648 | .open = ptype_seq_open, |
2648 | .read = seq_read, | 2649 | .read = seq_read, |
2649 | .llseek = seq_lseek, | 2650 | .llseek = seq_lseek, |
2650 | .release = seq_release, | 2651 | .release = seq_release_net, |
2651 | }; | 2652 | }; |
2652 | 2653 | ||
2653 | 2654 | ||
@@ -3688,8 +3689,8 @@ int register_netdevice(struct net_device *dev) | |||
3688 | 3689 | ||
3689 | /* When net_device's are persistent, this will be fatal. */ | 3690 | /* When net_device's are persistent, this will be fatal. */ |
3690 | BUG_ON(dev->reg_state != NETREG_UNINITIALIZED); | 3691 | BUG_ON(dev->reg_state != NETREG_UNINITIALIZED); |
3691 | BUG_ON(!dev->nd_net); | 3692 | BUG_ON(!dev_net(dev)); |
3692 | net = dev->nd_net; | 3693 | net = dev_net(dev); |
3693 | 3694 | ||
3694 | spin_lock_init(&dev->queue_lock); | 3695 | spin_lock_init(&dev->queue_lock); |
3695 | spin_lock_init(&dev->_xmit_lock); | 3696 | spin_lock_init(&dev->_xmit_lock); |
@@ -3995,11 +3996,15 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, | |||
3995 | 3996 | ||
3996 | BUG_ON(strlen(name) >= sizeof(dev->name)); | 3997 | BUG_ON(strlen(name) >= sizeof(dev->name)); |
3997 | 3998 | ||
3998 | /* ensure 32-byte alignment of both the device and private area */ | 3999 | alloc_size = sizeof(struct net_device) + |
3999 | alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST + | 4000 | sizeof(struct net_device_subqueue) * (queue_count - 1); |
4000 | (sizeof(struct net_device_subqueue) * (queue_count - 1))) & | 4001 | if (sizeof_priv) { |
4001 | ~NETDEV_ALIGN_CONST; | 4002 | /* ensure 32-byte alignment of private area */ |
4002 | alloc_size += sizeof_priv + NETDEV_ALIGN_CONST; | 4003 | alloc_size = (alloc_size + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST; |
4004 | alloc_size += sizeof_priv; | ||
4005 | } | ||
4006 | /* ensure 32-byte alignment of whole construct */ | ||
4007 | alloc_size += NETDEV_ALIGN_CONST; | ||
4003 | 4008 | ||
4004 | p = kzalloc(alloc_size, GFP_KERNEL); | 4009 | p = kzalloc(alloc_size, GFP_KERNEL); |
4005 | if (!p) { | 4010 | if (!p) { |
@@ -4010,7 +4015,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, | |||
4010 | dev = (struct net_device *) | 4015 | dev = (struct net_device *) |
4011 | (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); | 4016 | (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); |
4012 | dev->padded = (char *)dev - (char *)p; | 4017 | dev->padded = (char *)dev - (char *)p; |
4013 | dev->nd_net = &init_net; | 4018 | dev_net_set(dev, &init_net); |
4014 | 4019 | ||
4015 | if (sizeof_priv) { | 4020 | if (sizeof_priv) { |
4016 | dev->priv = ((char *)dev + | 4021 | dev->priv = ((char *)dev + |
@@ -4021,6 +4026,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, | |||
4021 | } | 4026 | } |
4022 | 4027 | ||
4023 | dev->egress_subqueue_count = queue_count; | 4028 | dev->egress_subqueue_count = queue_count; |
4029 | dev->gso_max_size = GSO_MAX_SIZE; | ||
4024 | 4030 | ||
4025 | dev->get_stats = internal_stats; | 4031 | dev->get_stats = internal_stats; |
4026 | netpoll_netdev_init(dev); | 4032 | netpoll_netdev_init(dev); |
@@ -4040,6 +4046,8 @@ EXPORT_SYMBOL(alloc_netdev_mq); | |||
4040 | */ | 4046 | */ |
4041 | void free_netdev(struct net_device *dev) | 4047 | void free_netdev(struct net_device *dev) |
4042 | { | 4048 | { |
4049 | release_net(dev_net(dev)); | ||
4050 | |||
4043 | /* Compatibility with error handling in drivers */ | 4051 | /* Compatibility with error handling in drivers */ |
4044 | if (dev->reg_state == NETREG_UNINITIALIZED) { | 4052 | if (dev->reg_state == NETREG_UNINITIALIZED) { |
4045 | kfree((char *)dev - dev->padded); | 4053 | kfree((char *)dev - dev->padded); |
@@ -4134,7 +4142,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char | |||
4134 | 4142 | ||
4135 | /* Get out if there is nothing todo */ | 4143 | /* Get out if there is nothing todo */ |
4136 | err = 0; | 4144 | err = 0; |
4137 | if (dev->nd_net == net) | 4145 | if (net_eq(dev_net(dev), net)) |
4138 | goto out; | 4146 | goto out; |
4139 | 4147 | ||
4140 | /* Pick the destination device name, and ensure | 4148 | /* Pick the destination device name, and ensure |
@@ -4185,7 +4193,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char | |||
4185 | dev_addr_discard(dev); | 4193 | dev_addr_discard(dev); |
4186 | 4194 | ||
4187 | /* Actually switch the network namespace */ | 4195 | /* Actually switch the network namespace */ |
4188 | dev->nd_net = net; | 4196 | dev_net_set(dev, net); |
4189 | 4197 | ||
4190 | /* Assign the new device name */ | 4198 | /* Assign the new device name */ |
4191 | if (destname != dev->name) | 4199 | if (destname != dev->name) |
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c index cec582563e0d..f8a3455f4493 100644 --- a/net/core/dev_mcast.c +++ b/net/core/dev_mcast.c | |||
@@ -156,39 +156,14 @@ void dev_mc_unsync(struct net_device *to, struct net_device *from) | |||
156 | EXPORT_SYMBOL(dev_mc_unsync); | 156 | EXPORT_SYMBOL(dev_mc_unsync); |
157 | 157 | ||
158 | #ifdef CONFIG_PROC_FS | 158 | #ifdef CONFIG_PROC_FS |
159 | static void *dev_mc_seq_start(struct seq_file *seq, loff_t *pos) | ||
160 | __acquires(dev_base_lock) | ||
161 | { | ||
162 | struct net *net = seq_file_net(seq); | ||
163 | struct net_device *dev; | ||
164 | loff_t off = 0; | ||
165 | |||
166 | read_lock(&dev_base_lock); | ||
167 | for_each_netdev(net, dev) { | ||
168 | if (off++ == *pos) | ||
169 | return dev; | ||
170 | } | ||
171 | return NULL; | ||
172 | } | ||
173 | |||
174 | static void *dev_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
175 | { | ||
176 | ++*pos; | ||
177 | return next_net_device((struct net_device *)v); | ||
178 | } | ||
179 | |||
180 | static void dev_mc_seq_stop(struct seq_file *seq, void *v) | ||
181 | __releases(dev_base_lock) | ||
182 | { | ||
183 | read_unlock(&dev_base_lock); | ||
184 | } | ||
185 | |||
186 | |||
187 | static int dev_mc_seq_show(struct seq_file *seq, void *v) | 159 | static int dev_mc_seq_show(struct seq_file *seq, void *v) |
188 | { | 160 | { |
189 | struct dev_addr_list *m; | 161 | struct dev_addr_list *m; |
190 | struct net_device *dev = v; | 162 | struct net_device *dev = v; |
191 | 163 | ||
164 | if (v == SEQ_START_TOKEN) | ||
165 | return 0; | ||
166 | |||
192 | netif_tx_lock_bh(dev); | 167 | netif_tx_lock_bh(dev); |
193 | for (m = dev->mc_list; m; m = m->next) { | 168 | for (m = dev->mc_list; m; m = m->next) { |
194 | int i; | 169 | int i; |
@@ -206,9 +181,9 @@ static int dev_mc_seq_show(struct seq_file *seq, void *v) | |||
206 | } | 181 | } |
207 | 182 | ||
208 | static const struct seq_operations dev_mc_seq_ops = { | 183 | static const struct seq_operations dev_mc_seq_ops = { |
209 | .start = dev_mc_seq_start, | 184 | .start = dev_seq_start, |
210 | .next = dev_mc_seq_next, | 185 | .next = dev_seq_next, |
211 | .stop = dev_mc_seq_stop, | 186 | .stop = dev_seq_stop, |
212 | .show = dev_mc_seq_show, | 187 | .show = dev_mc_seq_show, |
213 | }; | 188 | }; |
214 | 189 | ||
diff --git a/net/core/dst.c b/net/core/dst.c index 7deef483c79f..fe03266130b6 100644 --- a/net/core/dst.c +++ b/net/core/dst.c | |||
@@ -259,6 +259,16 @@ again: | |||
259 | return NULL; | 259 | return NULL; |
260 | } | 260 | } |
261 | 261 | ||
262 | void dst_release(struct dst_entry *dst) | ||
263 | { | ||
264 | if (dst) { | ||
265 | WARN_ON(atomic_read(&dst->__refcnt) < 1); | ||
266 | smp_mb__before_atomic_dec(); | ||
267 | atomic_dec(&dst->__refcnt); | ||
268 | } | ||
269 | } | ||
270 | EXPORT_SYMBOL(dst_release); | ||
271 | |||
262 | /* Dirty hack. We did it in 2.2 (in __dst_free), | 272 | /* Dirty hack. We did it in 2.2 (in __dst_free), |
263 | * we have _very_ good reasons not to repeat | 273 | * we have _very_ good reasons not to repeat |
264 | * this mistake in 2.3, but we have no choice | 274 | * this mistake in 2.3, but we have no choice |
@@ -279,7 +289,7 @@ static inline void dst_ifdown(struct dst_entry *dst, struct net_device *dev, | |||
279 | if (!unregister) { | 289 | if (!unregister) { |
280 | dst->input = dst->output = dst_discard; | 290 | dst->input = dst->output = dst_discard; |
281 | } else { | 291 | } else { |
282 | dst->dev = dst->dev->nd_net->loopback_dev; | 292 | dst->dev = dev_net(dst->dev)->loopback_dev; |
283 | dev_hold(dst->dev); | 293 | dev_hold(dst->dev); |
284 | dev_put(dev); | 294 | dev_put(dev); |
285 | if (dst->neighbour && dst->neighbour->dev == dev) { | 295 | if (dst->neighbour && dst->neighbour->dev == dev) { |
@@ -295,9 +305,6 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, void | |||
295 | struct net_device *dev = ptr; | 305 | struct net_device *dev = ptr; |
296 | struct dst_entry *dst, *last = NULL; | 306 | struct dst_entry *dst, *last = NULL; |
297 | 307 | ||
298 | if (dev->nd_net != &init_net) | ||
299 | return NOTIFY_DONE; | ||
300 | |||
301 | switch (event) { | 308 | switch (event) { |
302 | case NETDEV_UNREGISTER: | 309 | case NETDEV_UNREGISTER: |
303 | case NETDEV_DOWN: | 310 | case NETDEV_DOWN: |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 1163eb2256d0..a29b43d0b450 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -284,8 +284,10 @@ static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr) | |||
284 | { | 284 | { |
285 | struct ethtool_eeprom eeprom; | 285 | struct ethtool_eeprom eeprom; |
286 | const struct ethtool_ops *ops = dev->ethtool_ops; | 286 | const struct ethtool_ops *ops = dev->ethtool_ops; |
287 | void __user *userbuf = useraddr + sizeof(eeprom); | ||
288 | u32 bytes_remaining; | ||
287 | u8 *data; | 289 | u8 *data; |
288 | int ret; | 290 | int ret = 0; |
289 | 291 | ||
290 | if (!ops->get_eeprom || !ops->get_eeprom_len) | 292 | if (!ops->get_eeprom || !ops->get_eeprom_len) |
291 | return -EOPNOTSUPP; | 293 | return -EOPNOTSUPP; |
@@ -301,26 +303,26 @@ static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr) | |||
301 | if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) | 303 | if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) |
302 | return -EINVAL; | 304 | return -EINVAL; |
303 | 305 | ||
304 | data = kmalloc(eeprom.len, GFP_USER); | 306 | data = kmalloc(PAGE_SIZE, GFP_USER); |
305 | if (!data) | 307 | if (!data) |
306 | return -ENOMEM; | 308 | return -ENOMEM; |
307 | 309 | ||
308 | ret = -EFAULT; | 310 | bytes_remaining = eeprom.len; |
309 | if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) | 311 | while (bytes_remaining > 0) { |
310 | goto out; | 312 | eeprom.len = min(bytes_remaining, (u32)PAGE_SIZE); |
311 | |||
312 | ret = ops->get_eeprom(dev, &eeprom, data); | ||
313 | if (ret) | ||
314 | goto out; | ||
315 | 313 | ||
316 | ret = -EFAULT; | 314 | ret = ops->get_eeprom(dev, &eeprom, data); |
317 | if (copy_to_user(useraddr, &eeprom, sizeof(eeprom))) | 315 | if (ret) |
318 | goto out; | 316 | break; |
319 | if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) | 317 | if (copy_to_user(userbuf, data, eeprom.len)) { |
320 | goto out; | 318 | ret = -EFAULT; |
321 | ret = 0; | 319 | break; |
320 | } | ||
321 | userbuf += eeprom.len; | ||
322 | eeprom.offset += eeprom.len; | ||
323 | bytes_remaining -= eeprom.len; | ||
324 | } | ||
322 | 325 | ||
323 | out: | ||
324 | kfree(data); | 326 | kfree(data); |
325 | return ret; | 327 | return ret; |
326 | } | 328 | } |
@@ -329,8 +331,10 @@ static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr) | |||
329 | { | 331 | { |
330 | struct ethtool_eeprom eeprom; | 332 | struct ethtool_eeprom eeprom; |
331 | const struct ethtool_ops *ops = dev->ethtool_ops; | 333 | const struct ethtool_ops *ops = dev->ethtool_ops; |
334 | void __user *userbuf = useraddr + sizeof(eeprom); | ||
335 | u32 bytes_remaining; | ||
332 | u8 *data; | 336 | u8 *data; |
333 | int ret; | 337 | int ret = 0; |
334 | 338 | ||
335 | if (!ops->set_eeprom || !ops->get_eeprom_len) | 339 | if (!ops->set_eeprom || !ops->get_eeprom_len) |
336 | return -EOPNOTSUPP; | 340 | return -EOPNOTSUPP; |
@@ -346,22 +350,26 @@ static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr) | |||
346 | if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) | 350 | if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) |
347 | return -EINVAL; | 351 | return -EINVAL; |
348 | 352 | ||
349 | data = kmalloc(eeprom.len, GFP_USER); | 353 | data = kmalloc(PAGE_SIZE, GFP_USER); |
350 | if (!data) | 354 | if (!data) |
351 | return -ENOMEM; | 355 | return -ENOMEM; |
352 | 356 | ||
353 | ret = -EFAULT; | 357 | bytes_remaining = eeprom.len; |
354 | if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) | 358 | while (bytes_remaining > 0) { |
355 | goto out; | 359 | eeprom.len = min(bytes_remaining, (u32)PAGE_SIZE); |
356 | |||
357 | ret = ops->set_eeprom(dev, &eeprom, data); | ||
358 | if (ret) | ||
359 | goto out; | ||
360 | 360 | ||
361 | if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) | 361 | if (copy_from_user(data, userbuf, eeprom.len)) { |
362 | ret = -EFAULT; | 362 | ret = -EFAULT; |
363 | break; | ||
364 | } | ||
365 | ret = ops->set_eeprom(dev, &eeprom, data); | ||
366 | if (ret) | ||
367 | break; | ||
368 | userbuf += eeprom.len; | ||
369 | eeprom.offset += eeprom.len; | ||
370 | bytes_remaining -= eeprom.len; | ||
371 | } | ||
363 | 372 | ||
364 | out: | ||
365 | kfree(data); | 373 | kfree(data); |
366 | return ret; | 374 | return ret; |
367 | } | 375 | } |
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 42ccaf5b8509..e3e9ab0f74e3 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c | |||
@@ -29,7 +29,7 @@ int fib_default_rule_add(struct fib_rules_ops *ops, | |||
29 | r->pref = pref; | 29 | r->pref = pref; |
30 | r->table = table; | 30 | r->table = table; |
31 | r->flags = flags; | 31 | r->flags = flags; |
32 | r->fr_net = ops->fro_net; | 32 | r->fr_net = hold_net(ops->fro_net); |
33 | 33 | ||
34 | /* The lock is not required here, the list in unreacheable | 34 | /* The lock is not required here, the list in unreacheable |
35 | * at the moment this function is called */ | 35 | * at the moment this function is called */ |
@@ -214,7 +214,7 @@ errout: | |||
214 | 214 | ||
215 | static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | 215 | static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) |
216 | { | 216 | { |
217 | struct net *net = skb->sk->sk_net; | 217 | struct net *net = sock_net(skb->sk); |
218 | struct fib_rule_hdr *frh = nlmsg_data(nlh); | 218 | struct fib_rule_hdr *frh = nlmsg_data(nlh); |
219 | struct fib_rules_ops *ops = NULL; | 219 | struct fib_rules_ops *ops = NULL; |
220 | struct fib_rule *rule, *r, *last = NULL; | 220 | struct fib_rule *rule, *r, *last = NULL; |
@@ -243,7 +243,7 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
243 | err = -ENOMEM; | 243 | err = -ENOMEM; |
244 | goto errout; | 244 | goto errout; |
245 | } | 245 | } |
246 | rule->fr_net = net; | 246 | rule->fr_net = hold_net(net); |
247 | 247 | ||
248 | if (tb[FRA_PRIORITY]) | 248 | if (tb[FRA_PRIORITY]) |
249 | rule->pref = nla_get_u32(tb[FRA_PRIORITY]); | 249 | rule->pref = nla_get_u32(tb[FRA_PRIORITY]); |
@@ -344,6 +344,7 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
344 | return 0; | 344 | return 0; |
345 | 345 | ||
346 | errout_free: | 346 | errout_free: |
347 | release_net(rule->fr_net); | ||
347 | kfree(rule); | 348 | kfree(rule); |
348 | errout: | 349 | errout: |
349 | rules_ops_put(ops); | 350 | rules_ops_put(ops); |
@@ -352,7 +353,7 @@ errout: | |||
352 | 353 | ||
353 | static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | 354 | static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) |
354 | { | 355 | { |
355 | struct net *net = skb->sk->sk_net; | 356 | struct net *net = sock_net(skb->sk); |
356 | struct fib_rule_hdr *frh = nlmsg_data(nlh); | 357 | struct fib_rule_hdr *frh = nlmsg_data(nlh); |
357 | struct fib_rules_ops *ops = NULL; | 358 | struct fib_rules_ops *ops = NULL; |
358 | struct fib_rule *rule, *tmp; | 359 | struct fib_rule *rule, *tmp; |
@@ -534,7 +535,7 @@ skip: | |||
534 | 535 | ||
535 | static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb) | 536 | static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb) |
536 | { | 537 | { |
537 | struct net *net = skb->sk->sk_net; | 538 | struct net *net = sock_net(skb->sk); |
538 | struct fib_rules_ops *ops; | 539 | struct fib_rules_ops *ops; |
539 | int idx = 0, family; | 540 | int idx = 0, family; |
540 | 541 | ||
@@ -618,7 +619,7 @@ static int fib_rules_event(struct notifier_block *this, unsigned long event, | |||
618 | void *ptr) | 619 | void *ptr) |
619 | { | 620 | { |
620 | struct net_device *dev = ptr; | 621 | struct net_device *dev = ptr; |
621 | struct net *net = dev->nd_net; | 622 | struct net *net = dev_net(dev); |
622 | struct fib_rules_ops *ops; | 623 | struct fib_rules_ops *ops; |
623 | 624 | ||
624 | ASSERT_RTNL(); | 625 | ASSERT_RTNL(); |
diff --git a/net/core/filter.c b/net/core/filter.c index e0a06942c025..f5f3cf603064 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/if_packet.h> | 27 | #include <linux/if_packet.h> |
28 | #include <net/ip.h> | 28 | #include <net/ip.h> |
29 | #include <net/protocol.h> | 29 | #include <net/protocol.h> |
30 | #include <net/netlink.h> | ||
30 | #include <linux/skbuff.h> | 31 | #include <linux/skbuff.h> |
31 | #include <net/sock.h> | 32 | #include <net/sock.h> |
32 | #include <linux/errno.h> | 33 | #include <linux/errno.h> |
@@ -64,6 +65,41 @@ static inline void *load_pointer(struct sk_buff *skb, int k, | |||
64 | } | 65 | } |
65 | 66 | ||
66 | /** | 67 | /** |
68 | * sk_filter - run a packet through a socket filter | ||
69 | * @sk: sock associated with &sk_buff | ||
70 | * @skb: buffer to filter | ||
71 | * @needlock: set to 1 if the sock is not locked by caller. | ||
72 | * | ||
73 | * Run the filter code and then cut skb->data to correct size returned by | ||
74 | * sk_run_filter. If pkt_len is 0 we toss packet. If skb->len is smaller | ||
75 | * than pkt_len we keep whole skb->data. This is the socket level | ||
76 | * wrapper to sk_run_filter. It returns 0 if the packet should | ||
77 | * be accepted or -EPERM if the packet should be tossed. | ||
78 | * | ||
79 | */ | ||
80 | int sk_filter(struct sock *sk, struct sk_buff *skb) | ||
81 | { | ||
82 | int err; | ||
83 | struct sk_filter *filter; | ||
84 | |||
85 | err = security_sock_rcv_skb(sk, skb); | ||
86 | if (err) | ||
87 | return err; | ||
88 | |||
89 | rcu_read_lock_bh(); | ||
90 | filter = rcu_dereference(sk->sk_filter); | ||
91 | if (filter) { | ||
92 | unsigned int pkt_len = sk_run_filter(skb, filter->insns, | ||
93 | filter->len); | ||
94 | err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM; | ||
95 | } | ||
96 | rcu_read_unlock_bh(); | ||
97 | |||
98 | return err; | ||
99 | } | ||
100 | EXPORT_SYMBOL(sk_filter); | ||
101 | |||
102 | /** | ||
67 | * sk_run_filter - run a filter on a socket | 103 | * sk_run_filter - run a filter on a socket |
68 | * @skb: buffer to run the filter on | 104 | * @skb: buffer to run the filter on |
69 | * @filter: filter to apply | 105 | * @filter: filter to apply |
@@ -268,6 +304,22 @@ load_b: | |||
268 | case SKF_AD_IFINDEX: | 304 | case SKF_AD_IFINDEX: |
269 | A = skb->dev->ifindex; | 305 | A = skb->dev->ifindex; |
270 | continue; | 306 | continue; |
307 | case SKF_AD_NLATTR: { | ||
308 | struct nlattr *nla; | ||
309 | |||
310 | if (skb_is_nonlinear(skb)) | ||
311 | return 0; | ||
312 | if (A > skb->len - sizeof(struct nlattr)) | ||
313 | return 0; | ||
314 | |||
315 | nla = nla_find((struct nlattr *)&skb->data[A], | ||
316 | skb->len - A, X); | ||
317 | if (nla) | ||
318 | A = (void *)nla - (void *)skb->data; | ||
319 | else | ||
320 | A = 0; | ||
321 | continue; | ||
322 | } | ||
271 | default: | 323 | default: |
272 | return 0; | 324 | return 0; |
273 | } | 325 | } |
@@ -275,6 +327,7 @@ load_b: | |||
275 | 327 | ||
276 | return 0; | 328 | return 0; |
277 | } | 329 | } |
330 | EXPORT_SYMBOL(sk_run_filter); | ||
278 | 331 | ||
279 | /** | 332 | /** |
280 | * sk_chk_filter - verify socket filter code | 333 | * sk_chk_filter - verify socket filter code |
@@ -385,6 +438,7 @@ int sk_chk_filter(struct sock_filter *filter, int flen) | |||
385 | 438 | ||
386 | return (BPF_CLASS(filter[flen - 1].code) == BPF_RET) ? 0 : -EINVAL; | 439 | return (BPF_CLASS(filter[flen - 1].code) == BPF_RET) ? 0 : -EINVAL; |
387 | } | 440 | } |
441 | EXPORT_SYMBOL(sk_chk_filter); | ||
388 | 442 | ||
389 | /** | 443 | /** |
390 | * sk_filter_rcu_release: Release a socket filter by rcu_head | 444 | * sk_filter_rcu_release: Release a socket filter by rcu_head |
@@ -467,6 +521,3 @@ int sk_detach_filter(struct sock *sk) | |||
467 | rcu_read_unlock_bh(); | 521 | rcu_read_unlock_bh(); |
468 | return ret; | 522 | return ret; |
469 | } | 523 | } |
470 | |||
471 | EXPORT_SYMBOL(sk_chk_filter); | ||
472 | EXPORT_SYMBOL(sk_run_filter); | ||
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 19b8e003f150..75075c303c44 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -123,6 +123,7 @@ unsigned long neigh_rand_reach_time(unsigned long base) | |||
123 | { | 123 | { |
124 | return (base ? (net_random() % base) + (base >> 1) : 0); | 124 | return (base ? (net_random() % base) + (base >> 1) : 0); |
125 | } | 125 | } |
126 | EXPORT_SYMBOL(neigh_rand_reach_time); | ||
126 | 127 | ||
127 | 128 | ||
128 | static int neigh_forced_gc(struct neigh_table *tbl) | 129 | static int neigh_forced_gc(struct neigh_table *tbl) |
@@ -241,6 +242,7 @@ void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev) | |||
241 | neigh_flush_dev(tbl, dev); | 242 | neigh_flush_dev(tbl, dev); |
242 | write_unlock_bh(&tbl->lock); | 243 | write_unlock_bh(&tbl->lock); |
243 | } | 244 | } |
245 | EXPORT_SYMBOL(neigh_changeaddr); | ||
244 | 246 | ||
245 | int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev) | 247 | int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev) |
246 | { | 248 | { |
@@ -253,6 +255,7 @@ int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev) | |||
253 | pneigh_queue_purge(&tbl->proxy_queue); | 255 | pneigh_queue_purge(&tbl->proxy_queue); |
254 | return 0; | 256 | return 0; |
255 | } | 257 | } |
258 | EXPORT_SYMBOL(neigh_ifdown); | ||
256 | 259 | ||
257 | static struct neighbour *neigh_alloc(struct neigh_table *tbl) | 260 | static struct neighbour *neigh_alloc(struct neigh_table *tbl) |
258 | { | 261 | { |
@@ -374,6 +377,7 @@ struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey, | |||
374 | read_unlock_bh(&tbl->lock); | 377 | read_unlock_bh(&tbl->lock); |
375 | return n; | 378 | return n; |
376 | } | 379 | } |
380 | EXPORT_SYMBOL(neigh_lookup); | ||
377 | 381 | ||
378 | struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net, | 382 | struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net, |
379 | const void *pkey) | 383 | const void *pkey) |
@@ -388,7 +392,7 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net, | |||
388 | hash_val = tbl->hash(pkey, NULL); | 392 | hash_val = tbl->hash(pkey, NULL); |
389 | for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) { | 393 | for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) { |
390 | if (!memcmp(n->primary_key, pkey, key_len) && | 394 | if (!memcmp(n->primary_key, pkey, key_len) && |
391 | (net == n->dev->nd_net)) { | 395 | net_eq(dev_net(n->dev), net)) { |
392 | neigh_hold(n); | 396 | neigh_hold(n); |
393 | NEIGH_CACHE_STAT_INC(tbl, hits); | 397 | NEIGH_CACHE_STAT_INC(tbl, hits); |
394 | break; | 398 | break; |
@@ -397,6 +401,7 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net, | |||
397 | read_unlock_bh(&tbl->lock); | 401 | read_unlock_bh(&tbl->lock); |
398 | return n; | 402 | return n; |
399 | } | 403 | } |
404 | EXPORT_SYMBOL(neigh_lookup_nodev); | ||
400 | 405 | ||
401 | struct neighbour *neigh_create(struct neigh_table *tbl, const void *pkey, | 406 | struct neighbour *neigh_create(struct neigh_table *tbl, const void *pkey, |
402 | struct net_device *dev) | 407 | struct net_device *dev) |
@@ -465,28 +470,44 @@ out_neigh_release: | |||
465 | neigh_release(n); | 470 | neigh_release(n); |
466 | goto out; | 471 | goto out; |
467 | } | 472 | } |
473 | EXPORT_SYMBOL(neigh_create); | ||
468 | 474 | ||
469 | struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl, | 475 | static u32 pneigh_hash(const void *pkey, int key_len) |
470 | struct net *net, const void *pkey, struct net_device *dev) | ||
471 | { | 476 | { |
472 | struct pneigh_entry *n; | ||
473 | int key_len = tbl->key_len; | ||
474 | u32 hash_val = *(u32 *)(pkey + key_len - 4); | 477 | u32 hash_val = *(u32 *)(pkey + key_len - 4); |
475 | |||
476 | hash_val ^= (hash_val >> 16); | 478 | hash_val ^= (hash_val >> 16); |
477 | hash_val ^= hash_val >> 8; | 479 | hash_val ^= hash_val >> 8; |
478 | hash_val ^= hash_val >> 4; | 480 | hash_val ^= hash_val >> 4; |
479 | hash_val &= PNEIGH_HASHMASK; | 481 | hash_val &= PNEIGH_HASHMASK; |
482 | return hash_val; | ||
483 | } | ||
480 | 484 | ||
481 | for (n = tbl->phash_buckets[hash_val]; n; n = n->next) { | 485 | static struct pneigh_entry *__pneigh_lookup_1(struct pneigh_entry *n, |
486 | struct net *net, | ||
487 | const void *pkey, | ||
488 | int key_len, | ||
489 | struct net_device *dev) | ||
490 | { | ||
491 | while (n) { | ||
482 | if (!memcmp(n->key, pkey, key_len) && | 492 | if (!memcmp(n->key, pkey, key_len) && |
483 | (n->net == net) && | 493 | net_eq(pneigh_net(n), net) && |
484 | (n->dev == dev || !n->dev)) | 494 | (n->dev == dev || !n->dev)) |
485 | break; | 495 | return n; |
496 | n = n->next; | ||
486 | } | 497 | } |
498 | return NULL; | ||
499 | } | ||
487 | 500 | ||
488 | return n; | 501 | struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl, |
502 | struct net *net, const void *pkey, struct net_device *dev) | ||
503 | { | ||
504 | int key_len = tbl->key_len; | ||
505 | u32 hash_val = pneigh_hash(pkey, key_len); | ||
506 | |||
507 | return __pneigh_lookup_1(tbl->phash_buckets[hash_val], | ||
508 | net, pkey, key_len, dev); | ||
489 | } | 509 | } |
510 | EXPORT_SYMBOL_GPL(__pneigh_lookup); | ||
490 | 511 | ||
491 | struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, | 512 | struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, |
492 | struct net *net, const void *pkey, | 513 | struct net *net, const void *pkey, |
@@ -494,26 +515,14 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, | |||
494 | { | 515 | { |
495 | struct pneigh_entry *n; | 516 | struct pneigh_entry *n; |
496 | int key_len = tbl->key_len; | 517 | int key_len = tbl->key_len; |
497 | u32 hash_val = *(u32 *)(pkey + key_len - 4); | 518 | u32 hash_val = pneigh_hash(pkey, key_len); |
498 | |||
499 | hash_val ^= (hash_val >> 16); | ||
500 | hash_val ^= hash_val >> 8; | ||
501 | hash_val ^= hash_val >> 4; | ||
502 | hash_val &= PNEIGH_HASHMASK; | ||
503 | 519 | ||
504 | read_lock_bh(&tbl->lock); | 520 | read_lock_bh(&tbl->lock); |
505 | 521 | n = __pneigh_lookup_1(tbl->phash_buckets[hash_val], | |
506 | for (n = tbl->phash_buckets[hash_val]; n; n = n->next) { | 522 | net, pkey, key_len, dev); |
507 | if (!memcmp(n->key, pkey, key_len) && | ||
508 | (n->net == net) && | ||
509 | (n->dev == dev || !n->dev)) { | ||
510 | read_unlock_bh(&tbl->lock); | ||
511 | goto out; | ||
512 | } | ||
513 | } | ||
514 | read_unlock_bh(&tbl->lock); | 523 | read_unlock_bh(&tbl->lock); |
515 | n = NULL; | 524 | |
516 | if (!creat) | 525 | if (n || !creat) |
517 | goto out; | 526 | goto out; |
518 | 527 | ||
519 | ASSERT_RTNL(); | 528 | ASSERT_RTNL(); |
@@ -522,7 +531,9 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, | |||
522 | if (!n) | 531 | if (!n) |
523 | goto out; | 532 | goto out; |
524 | 533 | ||
534 | #ifdef CONFIG_NET_NS | ||
525 | n->net = hold_net(net); | 535 | n->net = hold_net(net); |
536 | #endif | ||
526 | memcpy(n->key, pkey, key_len); | 537 | memcpy(n->key, pkey, key_len); |
527 | n->dev = dev; | 538 | n->dev = dev; |
528 | if (dev) | 539 | if (dev) |
@@ -544,6 +555,7 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, | |||
544 | out: | 555 | out: |
545 | return n; | 556 | return n; |
546 | } | 557 | } |
558 | EXPORT_SYMBOL(pneigh_lookup); | ||
547 | 559 | ||
548 | 560 | ||
549 | int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey, | 561 | int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey, |
@@ -551,25 +563,20 @@ int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey, | |||
551 | { | 563 | { |
552 | struct pneigh_entry *n, **np; | 564 | struct pneigh_entry *n, **np; |
553 | int key_len = tbl->key_len; | 565 | int key_len = tbl->key_len; |
554 | u32 hash_val = *(u32 *)(pkey + key_len - 4); | 566 | u32 hash_val = pneigh_hash(pkey, key_len); |
555 | |||
556 | hash_val ^= (hash_val >> 16); | ||
557 | hash_val ^= hash_val >> 8; | ||
558 | hash_val ^= hash_val >> 4; | ||
559 | hash_val &= PNEIGH_HASHMASK; | ||
560 | 567 | ||
561 | write_lock_bh(&tbl->lock); | 568 | write_lock_bh(&tbl->lock); |
562 | for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL; | 569 | for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL; |
563 | np = &n->next) { | 570 | np = &n->next) { |
564 | if (!memcmp(n->key, pkey, key_len) && n->dev == dev && | 571 | if (!memcmp(n->key, pkey, key_len) && n->dev == dev && |
565 | (n->net == net)) { | 572 | net_eq(pneigh_net(n), net)) { |
566 | *np = n->next; | 573 | *np = n->next; |
567 | write_unlock_bh(&tbl->lock); | 574 | write_unlock_bh(&tbl->lock); |
568 | if (tbl->pdestructor) | 575 | if (tbl->pdestructor) |
569 | tbl->pdestructor(n); | 576 | tbl->pdestructor(n); |
570 | if (n->dev) | 577 | if (n->dev) |
571 | dev_put(n->dev); | 578 | dev_put(n->dev); |
572 | release_net(n->net); | 579 | release_net(pneigh_net(n)); |
573 | kfree(n); | 580 | kfree(n); |
574 | return 0; | 581 | return 0; |
575 | } | 582 | } |
@@ -592,7 +599,7 @@ static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev) | |||
592 | tbl->pdestructor(n); | 599 | tbl->pdestructor(n); |
593 | if (n->dev) | 600 | if (n->dev) |
594 | dev_put(n->dev); | 601 | dev_put(n->dev); |
595 | release_net(n->net); | 602 | release_net(pneigh_net(n)); |
596 | kfree(n); | 603 | kfree(n); |
597 | continue; | 604 | continue; |
598 | } | 605 | } |
@@ -651,6 +658,7 @@ void neigh_destroy(struct neighbour *neigh) | |||
651 | atomic_dec(&neigh->tbl->entries); | 658 | atomic_dec(&neigh->tbl->entries); |
652 | kmem_cache_free(neigh->tbl->kmem_cachep, neigh); | 659 | kmem_cache_free(neigh->tbl->kmem_cachep, neigh); |
653 | } | 660 | } |
661 | EXPORT_SYMBOL(neigh_destroy); | ||
654 | 662 | ||
655 | /* Neighbour state is suspicious; | 663 | /* Neighbour state is suspicious; |
656 | disable fast path. | 664 | disable fast path. |
@@ -931,6 +939,7 @@ out_unlock_bh: | |||
931 | write_unlock_bh(&neigh->lock); | 939 | write_unlock_bh(&neigh->lock); |
932 | return rc; | 940 | return rc; |
933 | } | 941 | } |
942 | EXPORT_SYMBOL(__neigh_event_send); | ||
934 | 943 | ||
935 | static void neigh_update_hhs(struct neighbour *neigh) | 944 | static void neigh_update_hhs(struct neighbour *neigh) |
936 | { | 945 | { |
@@ -1103,6 +1112,7 @@ out: | |||
1103 | 1112 | ||
1104 | return err; | 1113 | return err; |
1105 | } | 1114 | } |
1115 | EXPORT_SYMBOL(neigh_update); | ||
1106 | 1116 | ||
1107 | struct neighbour *neigh_event_ns(struct neigh_table *tbl, | 1117 | struct neighbour *neigh_event_ns(struct neigh_table *tbl, |
1108 | u8 *lladdr, void *saddr, | 1118 | u8 *lladdr, void *saddr, |
@@ -1115,6 +1125,7 @@ struct neighbour *neigh_event_ns(struct neigh_table *tbl, | |||
1115 | NEIGH_UPDATE_F_OVERRIDE); | 1125 | NEIGH_UPDATE_F_OVERRIDE); |
1116 | return neigh; | 1126 | return neigh; |
1117 | } | 1127 | } |
1128 | EXPORT_SYMBOL(neigh_event_ns); | ||
1118 | 1129 | ||
1119 | static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst, | 1130 | static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst, |
1120 | __be16 protocol) | 1131 | __be16 protocol) |
@@ -1169,6 +1180,7 @@ int neigh_compat_output(struct sk_buff *skb) | |||
1169 | 1180 | ||
1170 | return dev_queue_xmit(skb); | 1181 | return dev_queue_xmit(skb); |
1171 | } | 1182 | } |
1183 | EXPORT_SYMBOL(neigh_compat_output); | ||
1172 | 1184 | ||
1173 | /* Slow and careful. */ | 1185 | /* Slow and careful. */ |
1174 | 1186 | ||
@@ -1214,6 +1226,7 @@ out_kfree_skb: | |||
1214 | kfree_skb(skb); | 1226 | kfree_skb(skb); |
1215 | goto out; | 1227 | goto out; |
1216 | } | 1228 | } |
1229 | EXPORT_SYMBOL(neigh_resolve_output); | ||
1217 | 1230 | ||
1218 | /* As fast as possible without hh cache */ | 1231 | /* As fast as possible without hh cache */ |
1219 | 1232 | ||
@@ -1238,6 +1251,7 @@ int neigh_connected_output(struct sk_buff *skb) | |||
1238 | } | 1251 | } |
1239 | return err; | 1252 | return err; |
1240 | } | 1253 | } |
1254 | EXPORT_SYMBOL(neigh_connected_output); | ||
1241 | 1255 | ||
1242 | static void neigh_proxy_process(unsigned long arg) | 1256 | static void neigh_proxy_process(unsigned long arg) |
1243 | { | 1257 | { |
@@ -1299,6 +1313,7 @@ void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p, | |||
1299 | mod_timer(&tbl->proxy_timer, sched_next); | 1313 | mod_timer(&tbl->proxy_timer, sched_next); |
1300 | spin_unlock(&tbl->proxy_queue.lock); | 1314 | spin_unlock(&tbl->proxy_queue.lock); |
1301 | } | 1315 | } |
1316 | EXPORT_SYMBOL(pneigh_enqueue); | ||
1302 | 1317 | ||
1303 | static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl, | 1318 | static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl, |
1304 | struct net *net, int ifindex) | 1319 | struct net *net, int ifindex) |
@@ -1306,9 +1321,7 @@ static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl, | |||
1306 | struct neigh_parms *p; | 1321 | struct neigh_parms *p; |
1307 | 1322 | ||
1308 | for (p = &tbl->parms; p; p = p->next) { | 1323 | for (p = &tbl->parms; p; p = p->next) { |
1309 | if (p->net != net) | 1324 | if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) || |
1310 | continue; | ||
1311 | if ((p->dev && p->dev->ifindex == ifindex) || | ||
1312 | (!p->dev && !ifindex)) | 1325 | (!p->dev && !ifindex)) |
1313 | return p; | 1326 | return p; |
1314 | } | 1327 | } |
@@ -1322,7 +1335,7 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev, | |||
1322 | struct neigh_parms *p, *ref; | 1335 | struct neigh_parms *p, *ref; |
1323 | struct net *net; | 1336 | struct net *net; |
1324 | 1337 | ||
1325 | net = dev->nd_net; | 1338 | net = dev_net(dev); |
1326 | ref = lookup_neigh_params(tbl, net, 0); | 1339 | ref = lookup_neigh_params(tbl, net, 0); |
1327 | if (!ref) | 1340 | if (!ref) |
1328 | return NULL; | 1341 | return NULL; |
@@ -1342,7 +1355,9 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev, | |||
1342 | 1355 | ||
1343 | dev_hold(dev); | 1356 | dev_hold(dev); |
1344 | p->dev = dev; | 1357 | p->dev = dev; |
1358 | #ifdef CONFIG_NET_NS | ||
1345 | p->net = hold_net(net); | 1359 | p->net = hold_net(net); |
1360 | #endif | ||
1346 | p->sysctl_table = NULL; | 1361 | p->sysctl_table = NULL; |
1347 | write_lock_bh(&tbl->lock); | 1362 | write_lock_bh(&tbl->lock); |
1348 | p->next = tbl->parms.next; | 1363 | p->next = tbl->parms.next; |
@@ -1351,6 +1366,7 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev, | |||
1351 | } | 1366 | } |
1352 | return p; | 1367 | return p; |
1353 | } | 1368 | } |
1369 | EXPORT_SYMBOL(neigh_parms_alloc); | ||
1354 | 1370 | ||
1355 | static void neigh_rcu_free_parms(struct rcu_head *head) | 1371 | static void neigh_rcu_free_parms(struct rcu_head *head) |
1356 | { | 1372 | { |
@@ -1381,10 +1397,11 @@ void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms) | |||
1381 | write_unlock_bh(&tbl->lock); | 1397 | write_unlock_bh(&tbl->lock); |
1382 | NEIGH_PRINTK1("neigh_parms_release: not found\n"); | 1398 | NEIGH_PRINTK1("neigh_parms_release: not found\n"); |
1383 | } | 1399 | } |
1400 | EXPORT_SYMBOL(neigh_parms_release); | ||
1384 | 1401 | ||
1385 | static void neigh_parms_destroy(struct neigh_parms *parms) | 1402 | static void neigh_parms_destroy(struct neigh_parms *parms) |
1386 | { | 1403 | { |
1387 | release_net(parms->net); | 1404 | release_net(neigh_parms_net(parms)); |
1388 | kfree(parms); | 1405 | kfree(parms); |
1389 | } | 1406 | } |
1390 | 1407 | ||
@@ -1395,7 +1412,9 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl) | |||
1395 | unsigned long now = jiffies; | 1412 | unsigned long now = jiffies; |
1396 | unsigned long phsize; | 1413 | unsigned long phsize; |
1397 | 1414 | ||
1415 | #ifdef CONFIG_NET_NS | ||
1398 | tbl->parms.net = &init_net; | 1416 | tbl->parms.net = &init_net; |
1417 | #endif | ||
1399 | atomic_set(&tbl->parms.refcnt, 1); | 1418 | atomic_set(&tbl->parms.refcnt, 1); |
1400 | INIT_RCU_HEAD(&tbl->parms.rcu_head); | 1419 | INIT_RCU_HEAD(&tbl->parms.rcu_head); |
1401 | tbl->parms.reachable_time = | 1420 | tbl->parms.reachable_time = |
@@ -1441,6 +1460,7 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl) | |||
1441 | tbl->last_flush = now; | 1460 | tbl->last_flush = now; |
1442 | tbl->last_rand = now + tbl->parms.reachable_time * 20; | 1461 | tbl->last_rand = now + tbl->parms.reachable_time * 20; |
1443 | } | 1462 | } |
1463 | EXPORT_SYMBOL(neigh_table_init_no_netlink); | ||
1444 | 1464 | ||
1445 | void neigh_table_init(struct neigh_table *tbl) | 1465 | void neigh_table_init(struct neigh_table *tbl) |
1446 | { | 1466 | { |
@@ -1462,6 +1482,7 @@ void neigh_table_init(struct neigh_table *tbl) | |||
1462 | dump_stack(); | 1482 | dump_stack(); |
1463 | } | 1483 | } |
1464 | } | 1484 | } |
1485 | EXPORT_SYMBOL(neigh_table_init); | ||
1465 | 1486 | ||
1466 | int neigh_table_clear(struct neigh_table *tbl) | 1487 | int neigh_table_clear(struct neigh_table *tbl) |
1467 | { | 1488 | { |
@@ -1499,10 +1520,11 @@ int neigh_table_clear(struct neigh_table *tbl) | |||
1499 | 1520 | ||
1500 | return 0; | 1521 | return 0; |
1501 | } | 1522 | } |
1523 | EXPORT_SYMBOL(neigh_table_clear); | ||
1502 | 1524 | ||
1503 | static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 1525 | static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
1504 | { | 1526 | { |
1505 | struct net *net = skb->sk->sk_net; | 1527 | struct net *net = sock_net(skb->sk); |
1506 | struct ndmsg *ndm; | 1528 | struct ndmsg *ndm; |
1507 | struct nlattr *dst_attr; | 1529 | struct nlattr *dst_attr; |
1508 | struct neigh_table *tbl; | 1530 | struct neigh_table *tbl; |
@@ -1568,7 +1590,7 @@ out: | |||
1568 | 1590 | ||
1569 | static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 1591 | static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
1570 | { | 1592 | { |
1571 | struct net *net = skb->sk->sk_net; | 1593 | struct net *net = sock_net(skb->sk); |
1572 | struct ndmsg *ndm; | 1594 | struct ndmsg *ndm; |
1573 | struct nlattr *tb[NDA_MAX+1]; | 1595 | struct nlattr *tb[NDA_MAX+1]; |
1574 | struct neigh_table *tbl; | 1596 | struct neigh_table *tbl; |
@@ -1836,7 +1858,7 @@ static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = { | |||
1836 | 1858 | ||
1837 | static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 1859 | static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
1838 | { | 1860 | { |
1839 | struct net *net = skb->sk->sk_net; | 1861 | struct net *net = sock_net(skb->sk); |
1840 | struct neigh_table *tbl; | 1862 | struct neigh_table *tbl; |
1841 | struct ndtmsg *ndtmsg; | 1863 | struct ndtmsg *ndtmsg; |
1842 | struct nlattr *tb[NDTA_MAX+1]; | 1864 | struct nlattr *tb[NDTA_MAX+1]; |
@@ -1961,7 +1983,7 @@ errout: | |||
1961 | 1983 | ||
1962 | static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb) | 1984 | static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb) |
1963 | { | 1985 | { |
1964 | struct net *net = skb->sk->sk_net; | 1986 | struct net *net = sock_net(skb->sk); |
1965 | int family, tidx, nidx = 0; | 1987 | int family, tidx, nidx = 0; |
1966 | int tbl_skip = cb->args[0]; | 1988 | int tbl_skip = cb->args[0]; |
1967 | int neigh_skip = cb->args[1]; | 1989 | int neigh_skip = cb->args[1]; |
@@ -1982,7 +2004,7 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb) | |||
1982 | break; | 2004 | break; |
1983 | 2005 | ||
1984 | for (nidx = 0, p = tbl->parms.next; p; p = p->next) { | 2006 | for (nidx = 0, p = tbl->parms.next; p; p = p->next) { |
1985 | if (net != p->net) | 2007 | if (!net_eq(neigh_parms_net(p), net)) |
1986 | continue; | 2008 | continue; |
1987 | 2009 | ||
1988 | if (nidx++ < neigh_skip) | 2010 | if (nidx++ < neigh_skip) |
@@ -2061,7 +2083,7 @@ static void neigh_update_notify(struct neighbour *neigh) | |||
2061 | static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, | 2083 | static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, |
2062 | struct netlink_callback *cb) | 2084 | struct netlink_callback *cb) |
2063 | { | 2085 | { |
2064 | struct net * net = skb->sk->sk_net; | 2086 | struct net * net = sock_net(skb->sk); |
2065 | struct neighbour *n; | 2087 | struct neighbour *n; |
2066 | int rc, h, s_h = cb->args[1]; | 2088 | int rc, h, s_h = cb->args[1]; |
2067 | int idx, s_idx = idx = cb->args[2]; | 2089 | int idx, s_idx = idx = cb->args[2]; |
@@ -2074,7 +2096,7 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, | |||
2074 | s_idx = 0; | 2096 | s_idx = 0; |
2075 | for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next) { | 2097 | for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next) { |
2076 | int lidx; | 2098 | int lidx; |
2077 | if (n->dev->nd_net != net) | 2099 | if (dev_net(n->dev) != net) |
2078 | continue; | 2100 | continue; |
2079 | lidx = idx++; | 2101 | lidx = idx++; |
2080 | if (lidx < s_idx) | 2102 | if (lidx < s_idx) |
@@ -2169,7 +2191,7 @@ EXPORT_SYMBOL(__neigh_for_each_release); | |||
2169 | static struct neighbour *neigh_get_first(struct seq_file *seq) | 2191 | static struct neighbour *neigh_get_first(struct seq_file *seq) |
2170 | { | 2192 | { |
2171 | struct neigh_seq_state *state = seq->private; | 2193 | struct neigh_seq_state *state = seq->private; |
2172 | struct net *net = state->p.net; | 2194 | struct net *net = seq_file_net(seq); |
2173 | struct neigh_table *tbl = state->tbl; | 2195 | struct neigh_table *tbl = state->tbl; |
2174 | struct neighbour *n = NULL; | 2196 | struct neighbour *n = NULL; |
2175 | int bucket = state->bucket; | 2197 | int bucket = state->bucket; |
@@ -2179,7 +2201,7 @@ static struct neighbour *neigh_get_first(struct seq_file *seq) | |||
2179 | n = tbl->hash_buckets[bucket]; | 2201 | n = tbl->hash_buckets[bucket]; |
2180 | 2202 | ||
2181 | while (n) { | 2203 | while (n) { |
2182 | if (n->dev->nd_net != net) | 2204 | if (!net_eq(dev_net(n->dev), net)) |
2183 | goto next; | 2205 | goto next; |
2184 | if (state->neigh_sub_iter) { | 2206 | if (state->neigh_sub_iter) { |
2185 | loff_t fakep = 0; | 2207 | loff_t fakep = 0; |
@@ -2210,7 +2232,7 @@ static struct neighbour *neigh_get_next(struct seq_file *seq, | |||
2210 | loff_t *pos) | 2232 | loff_t *pos) |
2211 | { | 2233 | { |
2212 | struct neigh_seq_state *state = seq->private; | 2234 | struct neigh_seq_state *state = seq->private; |
2213 | struct net *net = state->p.net; | 2235 | struct net *net = seq_file_net(seq); |
2214 | struct neigh_table *tbl = state->tbl; | 2236 | struct neigh_table *tbl = state->tbl; |
2215 | 2237 | ||
2216 | if (state->neigh_sub_iter) { | 2238 | if (state->neigh_sub_iter) { |
@@ -2222,7 +2244,7 @@ static struct neighbour *neigh_get_next(struct seq_file *seq, | |||
2222 | 2244 | ||
2223 | while (1) { | 2245 | while (1) { |
2224 | while (n) { | 2246 | while (n) { |
2225 | if (n->dev->nd_net != net) | 2247 | if (!net_eq(dev_net(n->dev), net)) |
2226 | goto next; | 2248 | goto next; |
2227 | if (state->neigh_sub_iter) { | 2249 | if (state->neigh_sub_iter) { |
2228 | void *v = state->neigh_sub_iter(state, n, pos); | 2250 | void *v = state->neigh_sub_iter(state, n, pos); |
@@ -2270,7 +2292,7 @@ static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos) | |||
2270 | static struct pneigh_entry *pneigh_get_first(struct seq_file *seq) | 2292 | static struct pneigh_entry *pneigh_get_first(struct seq_file *seq) |
2271 | { | 2293 | { |
2272 | struct neigh_seq_state *state = seq->private; | 2294 | struct neigh_seq_state *state = seq->private; |
2273 | struct net * net = state->p.net; | 2295 | struct net *net = seq_file_net(seq); |
2274 | struct neigh_table *tbl = state->tbl; | 2296 | struct neigh_table *tbl = state->tbl; |
2275 | struct pneigh_entry *pn = NULL; | 2297 | struct pneigh_entry *pn = NULL; |
2276 | int bucket = state->bucket; | 2298 | int bucket = state->bucket; |
@@ -2278,7 +2300,7 @@ static struct pneigh_entry *pneigh_get_first(struct seq_file *seq) | |||
2278 | state->flags |= NEIGH_SEQ_IS_PNEIGH; | 2300 | state->flags |= NEIGH_SEQ_IS_PNEIGH; |
2279 | for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) { | 2301 | for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) { |
2280 | pn = tbl->phash_buckets[bucket]; | 2302 | pn = tbl->phash_buckets[bucket]; |
2281 | while (pn && (pn->net != net)) | 2303 | while (pn && !net_eq(pneigh_net(pn), net)) |
2282 | pn = pn->next; | 2304 | pn = pn->next; |
2283 | if (pn) | 2305 | if (pn) |
2284 | break; | 2306 | break; |
@@ -2293,7 +2315,7 @@ static struct pneigh_entry *pneigh_get_next(struct seq_file *seq, | |||
2293 | loff_t *pos) | 2315 | loff_t *pos) |
2294 | { | 2316 | { |
2295 | struct neigh_seq_state *state = seq->private; | 2317 | struct neigh_seq_state *state = seq->private; |
2296 | struct net * net = state->p.net; | 2318 | struct net *net = seq_file_net(seq); |
2297 | struct neigh_table *tbl = state->tbl; | 2319 | struct neigh_table *tbl = state->tbl; |
2298 | 2320 | ||
2299 | pn = pn->next; | 2321 | pn = pn->next; |
@@ -2301,7 +2323,7 @@ static struct pneigh_entry *pneigh_get_next(struct seq_file *seq, | |||
2301 | if (++state->bucket > PNEIGH_HASHMASK) | 2323 | if (++state->bucket > PNEIGH_HASHMASK) |
2302 | break; | 2324 | break; |
2303 | pn = tbl->phash_buckets[state->bucket]; | 2325 | pn = tbl->phash_buckets[state->bucket]; |
2304 | while (pn && (pn->net != net)) | 2326 | while (pn && !net_eq(pneigh_net(pn), net)) |
2305 | pn = pn->next; | 2327 | pn = pn->next; |
2306 | if (pn) | 2328 | if (pn) |
2307 | break; | 2329 | break; |
@@ -2506,7 +2528,7 @@ static inline size_t neigh_nlmsg_size(void) | |||
2506 | 2528 | ||
2507 | static void __neigh_notify(struct neighbour *n, int type, int flags) | 2529 | static void __neigh_notify(struct neighbour *n, int type, int flags) |
2508 | { | 2530 | { |
2509 | struct net *net = n->dev->nd_net; | 2531 | struct net *net = dev_net(n->dev); |
2510 | struct sk_buff *skb; | 2532 | struct sk_buff *skb; |
2511 | int err = -ENOBUFS; | 2533 | int err = -ENOBUFS; |
2512 | 2534 | ||
@@ -2532,6 +2554,7 @@ void neigh_app_ns(struct neighbour *n) | |||
2532 | { | 2554 | { |
2533 | __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST); | 2555 | __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST); |
2534 | } | 2556 | } |
2557 | EXPORT_SYMBOL(neigh_app_ns); | ||
2535 | #endif /* CONFIG_ARPD */ | 2558 | #endif /* CONFIG_ARPD */ |
2536 | 2559 | ||
2537 | #ifdef CONFIG_SYSCTL | 2560 | #ifdef CONFIG_SYSCTL |
@@ -2763,7 +2786,8 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, | |||
2763 | neigh_path[NEIGH_CTL_PATH_PROTO].procname = p_name; | 2786 | neigh_path[NEIGH_CTL_PATH_PROTO].procname = p_name; |
2764 | neigh_path[NEIGH_CTL_PATH_PROTO].ctl_name = p_id; | 2787 | neigh_path[NEIGH_CTL_PATH_PROTO].ctl_name = p_id; |
2765 | 2788 | ||
2766 | t->sysctl_header = register_sysctl_paths(neigh_path, t->neigh_vars); | 2789 | t->sysctl_header = |
2790 | register_net_sysctl_table(neigh_parms_net(p), neigh_path, t->neigh_vars); | ||
2767 | if (!t->sysctl_header) | 2791 | if (!t->sysctl_header) |
2768 | goto free_procname; | 2792 | goto free_procname; |
2769 | 2793 | ||
@@ -2777,6 +2801,7 @@ free: | |||
2777 | err: | 2801 | err: |
2778 | return -ENOBUFS; | 2802 | return -ENOBUFS; |
2779 | } | 2803 | } |
2804 | EXPORT_SYMBOL(neigh_sysctl_register); | ||
2780 | 2805 | ||
2781 | void neigh_sysctl_unregister(struct neigh_parms *p) | 2806 | void neigh_sysctl_unregister(struct neigh_parms *p) |
2782 | { | 2807 | { |
@@ -2788,6 +2813,7 @@ void neigh_sysctl_unregister(struct neigh_parms *p) | |||
2788 | kfree(t); | 2813 | kfree(t); |
2789 | } | 2814 | } |
2790 | } | 2815 | } |
2816 | EXPORT_SYMBOL(neigh_sysctl_unregister); | ||
2791 | 2817 | ||
2792 | #endif /* CONFIG_SYSCTL */ | 2818 | #endif /* CONFIG_SYSCTL */ |
2793 | 2819 | ||
@@ -2805,32 +2831,3 @@ static int __init neigh_init(void) | |||
2805 | 2831 | ||
2806 | subsys_initcall(neigh_init); | 2832 | subsys_initcall(neigh_init); |
2807 | 2833 | ||
2808 | EXPORT_SYMBOL(__neigh_event_send); | ||
2809 | EXPORT_SYMBOL(neigh_changeaddr); | ||
2810 | EXPORT_SYMBOL(neigh_compat_output); | ||
2811 | EXPORT_SYMBOL(neigh_connected_output); | ||
2812 | EXPORT_SYMBOL(neigh_create); | ||
2813 | EXPORT_SYMBOL(neigh_destroy); | ||
2814 | EXPORT_SYMBOL(neigh_event_ns); | ||
2815 | EXPORT_SYMBOL(neigh_ifdown); | ||
2816 | EXPORT_SYMBOL(neigh_lookup); | ||
2817 | EXPORT_SYMBOL(neigh_lookup_nodev); | ||
2818 | EXPORT_SYMBOL(neigh_parms_alloc); | ||
2819 | EXPORT_SYMBOL(neigh_parms_release); | ||
2820 | EXPORT_SYMBOL(neigh_rand_reach_time); | ||
2821 | EXPORT_SYMBOL(neigh_resolve_output); | ||
2822 | EXPORT_SYMBOL(neigh_table_clear); | ||
2823 | EXPORT_SYMBOL(neigh_table_init); | ||
2824 | EXPORT_SYMBOL(neigh_table_init_no_netlink); | ||
2825 | EXPORT_SYMBOL(neigh_update); | ||
2826 | EXPORT_SYMBOL(pneigh_enqueue); | ||
2827 | EXPORT_SYMBOL(pneigh_lookup); | ||
2828 | EXPORT_SYMBOL_GPL(__pneigh_lookup); | ||
2829 | |||
2830 | #ifdef CONFIG_ARPD | ||
2831 | EXPORT_SYMBOL(neigh_app_ns); | ||
2832 | #endif | ||
2833 | #ifdef CONFIG_SYSCTL | ||
2834 | EXPORT_SYMBOL(neigh_sysctl_register); | ||
2835 | EXPORT_SYMBOL(neigh_sysctl_unregister); | ||
2836 | #endif | ||
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 7b660834a4c2..72b4c184dd84 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c | |||
@@ -5,7 +5,9 @@ | |||
5 | #include <linux/list.h> | 5 | #include <linux/list.h> |
6 | #include <linux/delay.h> | 6 | #include <linux/delay.h> |
7 | #include <linux/sched.h> | 7 | #include <linux/sched.h> |
8 | #include <linux/idr.h> | ||
8 | #include <net/net_namespace.h> | 9 | #include <net/net_namespace.h> |
10 | #include <net/netns/generic.h> | ||
9 | 11 | ||
10 | /* | 12 | /* |
11 | * Our network namespace constructor/destructor lists | 13 | * Our network namespace constructor/destructor lists |
@@ -20,6 +22,8 @@ LIST_HEAD(net_namespace_list); | |||
20 | struct net init_net; | 22 | struct net init_net; |
21 | EXPORT_SYMBOL(init_net); | 23 | EXPORT_SYMBOL(init_net); |
22 | 24 | ||
25 | #define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */ | ||
26 | |||
23 | /* | 27 | /* |
24 | * setup_net runs the initializers for the network namespace object. | 28 | * setup_net runs the initializers for the network namespace object. |
25 | */ | 29 | */ |
@@ -28,9 +32,22 @@ static __net_init int setup_net(struct net *net) | |||
28 | /* Must be called with net_mutex held */ | 32 | /* Must be called with net_mutex held */ |
29 | struct pernet_operations *ops; | 33 | struct pernet_operations *ops; |
30 | int error; | 34 | int error; |
35 | struct net_generic *ng; | ||
31 | 36 | ||
32 | atomic_set(&net->count, 1); | 37 | atomic_set(&net->count, 1); |
38 | #ifdef NETNS_REFCNT_DEBUG | ||
33 | atomic_set(&net->use_count, 0); | 39 | atomic_set(&net->use_count, 0); |
40 | #endif | ||
41 | |||
42 | error = -ENOMEM; | ||
43 | ng = kzalloc(sizeof(struct net_generic) + | ||
44 | INITIAL_NET_GEN_PTRS * sizeof(void *), GFP_KERNEL); | ||
45 | if (ng == NULL) | ||
46 | goto out; | ||
47 | |||
48 | ng->len = INITIAL_NET_GEN_PTRS; | ||
49 | INIT_RCU_HEAD(&ng->rcu); | ||
50 | rcu_assign_pointer(net->gen, ng); | ||
34 | 51 | ||
35 | error = 0; | 52 | error = 0; |
36 | list_for_each_entry(ops, &pernet_list, list) { | 53 | list_for_each_entry(ops, &pernet_list, list) { |
@@ -53,6 +70,7 @@ out_undo: | |||
53 | } | 70 | } |
54 | 71 | ||
55 | rcu_barrier(); | 72 | rcu_barrier(); |
73 | kfree(ng); | ||
56 | goto out; | 74 | goto out; |
57 | } | 75 | } |
58 | 76 | ||
@@ -70,11 +88,13 @@ static void net_free(struct net *net) | |||
70 | if (!net) | 88 | if (!net) |
71 | return; | 89 | return; |
72 | 90 | ||
91 | #ifdef NETNS_REFCNT_DEBUG | ||
73 | if (unlikely(atomic_read(&net->use_count) != 0)) { | 92 | if (unlikely(atomic_read(&net->use_count) != 0)) { |
74 | printk(KERN_EMERG "network namespace not free! Usage: %d\n", | 93 | printk(KERN_EMERG "network namespace not free! Usage: %d\n", |
75 | atomic_read(&net->use_count)); | 94 | atomic_read(&net->use_count)); |
76 | return; | 95 | return; |
77 | } | 96 | } |
97 | #endif | ||
78 | 98 | ||
79 | kmem_cache_free(net_cachep, net); | 99 | kmem_cache_free(net_cachep, net); |
80 | } | 100 | } |
@@ -253,6 +273,8 @@ static void unregister_pernet_operations(struct pernet_operations *ops) | |||
253 | } | 273 | } |
254 | #endif | 274 | #endif |
255 | 275 | ||
276 | static DEFINE_IDA(net_generic_ids); | ||
277 | |||
256 | /** | 278 | /** |
257 | * register_pernet_subsys - register a network namespace subsystem | 279 | * register_pernet_subsys - register a network namespace subsystem |
258 | * @ops: pernet operations structure for the subsystem | 280 | * @ops: pernet operations structure for the subsystem |
@@ -330,6 +352,30 @@ int register_pernet_device(struct pernet_operations *ops) | |||
330 | } | 352 | } |
331 | EXPORT_SYMBOL_GPL(register_pernet_device); | 353 | EXPORT_SYMBOL_GPL(register_pernet_device); |
332 | 354 | ||
355 | int register_pernet_gen_device(int *id, struct pernet_operations *ops) | ||
356 | { | ||
357 | int error; | ||
358 | mutex_lock(&net_mutex); | ||
359 | again: | ||
360 | error = ida_get_new_above(&net_generic_ids, 1, id); | ||
361 | if (error) { | ||
362 | if (error == -EAGAIN) { | ||
363 | ida_pre_get(&net_generic_ids, GFP_KERNEL); | ||
364 | goto again; | ||
365 | } | ||
366 | goto out; | ||
367 | } | ||
368 | error = register_pernet_operations(&pernet_list, ops); | ||
369 | if (error) | ||
370 | ida_remove(&net_generic_ids, *id); | ||
371 | else if (first_device == &pernet_list) | ||
372 | first_device = &ops->list; | ||
373 | out: | ||
374 | mutex_unlock(&net_mutex); | ||
375 | return error; | ||
376 | } | ||
377 | EXPORT_SYMBOL_GPL(register_pernet_gen_device); | ||
378 | |||
333 | /** | 379 | /** |
334 | * unregister_pernet_device - unregister a network namespace netdevice | 380 | * unregister_pernet_device - unregister a network namespace netdevice |
335 | * @ops: pernet operations structure to manipulate | 381 | * @ops: pernet operations structure to manipulate |
@@ -348,3 +394,61 @@ void unregister_pernet_device(struct pernet_operations *ops) | |||
348 | mutex_unlock(&net_mutex); | 394 | mutex_unlock(&net_mutex); |
349 | } | 395 | } |
350 | EXPORT_SYMBOL_GPL(unregister_pernet_device); | 396 | EXPORT_SYMBOL_GPL(unregister_pernet_device); |
397 | |||
398 | void unregister_pernet_gen_device(int id, struct pernet_operations *ops) | ||
399 | { | ||
400 | mutex_lock(&net_mutex); | ||
401 | if (&ops->list == first_device) | ||
402 | first_device = first_device->next; | ||
403 | unregister_pernet_operations(ops); | ||
404 | ida_remove(&net_generic_ids, id); | ||
405 | mutex_unlock(&net_mutex); | ||
406 | } | ||
407 | EXPORT_SYMBOL_GPL(unregister_pernet_gen_device); | ||
408 | |||
409 | static void net_generic_release(struct rcu_head *rcu) | ||
410 | { | ||
411 | struct net_generic *ng; | ||
412 | |||
413 | ng = container_of(rcu, struct net_generic, rcu); | ||
414 | kfree(ng); | ||
415 | } | ||
416 | |||
417 | int net_assign_generic(struct net *net, int id, void *data) | ||
418 | { | ||
419 | struct net_generic *ng, *old_ng; | ||
420 | |||
421 | BUG_ON(!mutex_is_locked(&net_mutex)); | ||
422 | BUG_ON(id == 0); | ||
423 | |||
424 | ng = old_ng = net->gen; | ||
425 | if (old_ng->len >= id) | ||
426 | goto assign; | ||
427 | |||
428 | ng = kzalloc(sizeof(struct net_generic) + | ||
429 | id * sizeof(void *), GFP_KERNEL); | ||
430 | if (ng == NULL) | ||
431 | return -ENOMEM; | ||
432 | |||
433 | /* | ||
434 | * Some synchronisation notes: | ||
435 | * | ||
436 | * The net_generic explores the net->gen array inside rcu | ||
437 | * read section. Besides once set the net->gen->ptr[x] | ||
438 | * pointer never changes (see rules in netns/generic.h). | ||
439 | * | ||
440 | * That said, we simply duplicate this array and schedule | ||
441 | * the old copy for kfree after a grace period. | ||
442 | */ | ||
443 | |||
444 | ng->len = id; | ||
445 | INIT_RCU_HEAD(&ng->rcu); | ||
446 | memcpy(&ng->ptr, &old_ng->ptr, old_ng->len); | ||
447 | |||
448 | rcu_assign_pointer(net->gen, ng); | ||
449 | call_rcu(&old_ng->rcu, net_generic_release); | ||
450 | assign: | ||
451 | ng->ptr[id - 1] = data; | ||
452 | return 0; | ||
453 | } | ||
454 | EXPORT_SYMBOL_GPL(net_assign_generic); | ||
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index c635de52526c..b04d643fc3c7 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
@@ -390,9 +390,7 @@ static void arp_reply(struct sk_buff *skb) | |||
390 | if (skb->dev->flags & IFF_NOARP) | 390 | if (skb->dev->flags & IFF_NOARP) |
391 | return; | 391 | return; |
392 | 392 | ||
393 | if (!pskb_may_pull(skb, (sizeof(struct arphdr) + | 393 | if (!pskb_may_pull(skb, arp_hdr_len(skb->dev))) |
394 | (2 * skb->dev->addr_len) + | ||
395 | (2 * sizeof(u32))))) | ||
396 | return; | 394 | return; |
397 | 395 | ||
398 | skb_reset_network_header(skb); | 396 | skb_reset_network_header(skb); |
@@ -420,7 +418,7 @@ static void arp_reply(struct sk_buff *skb) | |||
420 | ipv4_is_loopback(tip) || ipv4_is_multicast(tip)) | 418 | ipv4_is_loopback(tip) || ipv4_is_multicast(tip)) |
421 | return; | 419 | return; |
422 | 420 | ||
423 | size = sizeof(struct arphdr) + 2 * (skb->dev->addr_len + 4); | 421 | size = arp_hdr_len(skb->dev); |
424 | send_skb = find_skb(np, size + LL_RESERVED_SPACE(np->dev), | 422 | send_skb = find_skb(np, size + LL_RESERVED_SPACE(np->dev), |
425 | LL_RESERVED_SPACE(np->dev)); | 423 | LL_RESERVED_SPACE(np->dev)); |
426 | 424 | ||
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 20e63b302ba6..a803b442234c 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
@@ -1874,7 +1874,7 @@ static int pktgen_device_event(struct notifier_block *unused, | |||
1874 | { | 1874 | { |
1875 | struct net_device *dev = ptr; | 1875 | struct net_device *dev = ptr; |
1876 | 1876 | ||
1877 | if (dev->nd_net != &init_net) | 1877 | if (dev_net(dev) != &init_net) |
1878 | return NOTIFY_DONE; | 1878 | return NOTIFY_DONE; |
1879 | 1879 | ||
1880 | /* It is OK that we do not hold the group lock right now, | 1880 | /* It is OK that we do not hold the group lock right now, |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 2bd9c5f7627d..bc39e417694a 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -269,6 +269,26 @@ int rtnl_link_register(struct rtnl_link_ops *ops) | |||
269 | 269 | ||
270 | EXPORT_SYMBOL_GPL(rtnl_link_register); | 270 | EXPORT_SYMBOL_GPL(rtnl_link_register); |
271 | 271 | ||
272 | static void __rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops) | ||
273 | { | ||
274 | struct net_device *dev; | ||
275 | restart: | ||
276 | for_each_netdev(net, dev) { | ||
277 | if (dev->rtnl_link_ops == ops) { | ||
278 | ops->dellink(dev); | ||
279 | goto restart; | ||
280 | } | ||
281 | } | ||
282 | } | ||
283 | |||
284 | void rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops) | ||
285 | { | ||
286 | rtnl_lock(); | ||
287 | __rtnl_kill_links(net, ops); | ||
288 | rtnl_unlock(); | ||
289 | } | ||
290 | EXPORT_SYMBOL_GPL(rtnl_kill_links); | ||
291 | |||
272 | /** | 292 | /** |
273 | * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink. | 293 | * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink. |
274 | * @ops: struct rtnl_link_ops * to unregister | 294 | * @ops: struct rtnl_link_ops * to unregister |
@@ -277,17 +297,10 @@ EXPORT_SYMBOL_GPL(rtnl_link_register); | |||
277 | */ | 297 | */ |
278 | void __rtnl_link_unregister(struct rtnl_link_ops *ops) | 298 | void __rtnl_link_unregister(struct rtnl_link_ops *ops) |
279 | { | 299 | { |
280 | struct net_device *dev, *n; | ||
281 | struct net *net; | 300 | struct net *net; |
282 | 301 | ||
283 | for_each_net(net) { | 302 | for_each_net(net) { |
284 | restart: | 303 | __rtnl_kill_links(net, ops); |
285 | for_each_netdev_safe(net, dev, n) { | ||
286 | if (dev->rtnl_link_ops == ops) { | ||
287 | ops->dellink(dev); | ||
288 | goto restart; | ||
289 | } | ||
290 | } | ||
291 | } | 304 | } |
292 | list_del(&ops->list); | 305 | list_del(&ops->list); |
293 | } | 306 | } |
@@ -662,7 +675,7 @@ nla_put_failure: | |||
662 | 675 | ||
663 | static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | 676 | static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) |
664 | { | 677 | { |
665 | struct net *net = skb->sk->sk_net; | 678 | struct net *net = sock_net(skb->sk); |
666 | int idx; | 679 | int idx; |
667 | int s_idx = cb->args[0]; | 680 | int s_idx = cb->args[0]; |
668 | struct net_device *dev; | 681 | struct net_device *dev; |
@@ -879,7 +892,7 @@ errout: | |||
879 | 892 | ||
880 | static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 893 | static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
881 | { | 894 | { |
882 | struct net *net = skb->sk->sk_net; | 895 | struct net *net = sock_net(skb->sk); |
883 | struct ifinfomsg *ifm; | 896 | struct ifinfomsg *ifm; |
884 | struct net_device *dev; | 897 | struct net_device *dev; |
885 | int err; | 898 | int err; |
@@ -921,7 +934,7 @@ errout: | |||
921 | 934 | ||
922 | static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 935 | static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
923 | { | 936 | { |
924 | struct net *net = skb->sk->sk_net; | 937 | struct net *net = sock_net(skb->sk); |
925 | const struct rtnl_link_ops *ops; | 938 | const struct rtnl_link_ops *ops; |
926 | struct net_device *dev; | 939 | struct net_device *dev; |
927 | struct ifinfomsg *ifm; | 940 | struct ifinfomsg *ifm; |
@@ -972,7 +985,7 @@ struct net_device *rtnl_create_link(struct net *net, char *ifname, | |||
972 | goto err_free; | 985 | goto err_free; |
973 | } | 986 | } |
974 | 987 | ||
975 | dev->nd_net = net; | 988 | dev_net_set(dev, net); |
976 | dev->rtnl_link_ops = ops; | 989 | dev->rtnl_link_ops = ops; |
977 | 990 | ||
978 | if (tb[IFLA_MTU]) | 991 | if (tb[IFLA_MTU]) |
@@ -1000,7 +1013,7 @@ err: | |||
1000 | 1013 | ||
1001 | static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 1014 | static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
1002 | { | 1015 | { |
1003 | struct net *net = skb->sk->sk_net; | 1016 | struct net *net = sock_net(skb->sk); |
1004 | const struct rtnl_link_ops *ops; | 1017 | const struct rtnl_link_ops *ops; |
1005 | struct net_device *dev; | 1018 | struct net_device *dev; |
1006 | struct ifinfomsg *ifm; | 1019 | struct ifinfomsg *ifm; |
@@ -1132,7 +1145,7 @@ replay: | |||
1132 | 1145 | ||
1133 | static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | 1146 | static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) |
1134 | { | 1147 | { |
1135 | struct net *net = skb->sk->sk_net; | 1148 | struct net *net = sock_net(skb->sk); |
1136 | struct ifinfomsg *ifm; | 1149 | struct ifinfomsg *ifm; |
1137 | struct nlattr *tb[IFLA_MAX+1]; | 1150 | struct nlattr *tb[IFLA_MAX+1]; |
1138 | struct net_device *dev = NULL; | 1151 | struct net_device *dev = NULL; |
@@ -1198,7 +1211,7 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb) | |||
1198 | 1211 | ||
1199 | void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change) | 1212 | void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change) |
1200 | { | 1213 | { |
1201 | struct net *net = dev->nd_net; | 1214 | struct net *net = dev_net(dev); |
1202 | struct sk_buff *skb; | 1215 | struct sk_buff *skb; |
1203 | int err = -ENOBUFS; | 1216 | int err = -ENOBUFS; |
1204 | 1217 | ||
@@ -1227,7 +1240,7 @@ static int rtattr_max; | |||
1227 | 1240 | ||
1228 | static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | 1241 | static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) |
1229 | { | 1242 | { |
1230 | struct net *net = skb->sk->sk_net; | 1243 | struct net *net = sock_net(skb->sk); |
1231 | rtnl_doit_func doit; | 1244 | rtnl_doit_func doit; |
1232 | int sz_idx, kind; | 1245 | int sz_idx, kind; |
1233 | int min_len; | 1246 | int min_len; |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 608701339620..4fe605fa6f8a 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -263,6 +263,28 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev, | |||
263 | return skb; | 263 | return skb; |
264 | } | 264 | } |
265 | 265 | ||
266 | /** | ||
267 | * dev_alloc_skb - allocate an skbuff for receiving | ||
268 | * @length: length to allocate | ||
269 | * | ||
270 | * Allocate a new &sk_buff and assign it a usage count of one. The | ||
271 | * buffer has unspecified headroom built in. Users should allocate | ||
272 | * the headroom they think they need without accounting for the | ||
273 | * built in space. The built in space is used for optimisations. | ||
274 | * | ||
275 | * %NULL is returned if there is no free memory. Although this function | ||
276 | * allocates memory it can be called from an interrupt. | ||
277 | */ | ||
278 | struct sk_buff *dev_alloc_skb(unsigned int length) | ||
279 | { | ||
280 | /* | ||
281 | * There is more code here than it seems: | ||
282 | * __dev_alloc_skb is an inline | ||
283 | */ | ||
284 | return __dev_alloc_skb(length, GFP_ATOMIC); | ||
285 | } | ||
286 | EXPORT_SYMBOL(dev_alloc_skb); | ||
287 | |||
266 | static void skb_drop_list(struct sk_buff **listp) | 288 | static void skb_drop_list(struct sk_buff **listp) |
267 | { | 289 | { |
268 | struct sk_buff *list = *listp; | 290 | struct sk_buff *list = *listp; |
@@ -857,6 +879,78 @@ free_skb: | |||
857 | return err; | 879 | return err; |
858 | } | 880 | } |
859 | 881 | ||
882 | /** | ||
883 | * skb_put - add data to a buffer | ||
884 | * @skb: buffer to use | ||
885 | * @len: amount of data to add | ||
886 | * | ||
887 | * This function extends the used data area of the buffer. If this would | ||
888 | * exceed the total buffer size the kernel will panic. A pointer to the | ||
889 | * first byte of the extra data is returned. | ||
890 | */ | ||
891 | unsigned char *skb_put(struct sk_buff *skb, unsigned int len) | ||
892 | { | ||
893 | unsigned char *tmp = skb_tail_pointer(skb); | ||
894 | SKB_LINEAR_ASSERT(skb); | ||
895 | skb->tail += len; | ||
896 | skb->len += len; | ||
897 | if (unlikely(skb->tail > skb->end)) | ||
898 | skb_over_panic(skb, len, __builtin_return_address(0)); | ||
899 | return tmp; | ||
900 | } | ||
901 | EXPORT_SYMBOL(skb_put); | ||
902 | |||
903 | /** | ||
904 | * skb_push - add data to the start of a buffer | ||
905 | * @skb: buffer to use | ||
906 | * @len: amount of data to add | ||
907 | * | ||
908 | * This function extends the used data area of the buffer at the buffer | ||
909 | * start. If this would exceed the total buffer headroom the kernel will | ||
910 | * panic. A pointer to the first byte of the extra data is returned. | ||
911 | */ | ||
912 | unsigned char *skb_push(struct sk_buff *skb, unsigned int len) | ||
913 | { | ||
914 | skb->data -= len; | ||
915 | skb->len += len; | ||
916 | if (unlikely(skb->data<skb->head)) | ||
917 | skb_under_panic(skb, len, __builtin_return_address(0)); | ||
918 | return skb->data; | ||
919 | } | ||
920 | EXPORT_SYMBOL(skb_push); | ||
921 | |||
922 | /** | ||
923 | * skb_pull - remove data from the start of a buffer | ||
924 | * @skb: buffer to use | ||
925 | * @len: amount of data to remove | ||
926 | * | ||
927 | * This function removes data from the start of a buffer, returning | ||
928 | * the memory to the headroom. A pointer to the next data in the buffer | ||
929 | * is returned. Once the data has been pulled future pushes will overwrite | ||
930 | * the old data. | ||
931 | */ | ||
932 | unsigned char *skb_pull(struct sk_buff *skb, unsigned int len) | ||
933 | { | ||
934 | return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len); | ||
935 | } | ||
936 | EXPORT_SYMBOL(skb_pull); | ||
937 | |||
938 | /** | ||
939 | * skb_trim - remove end from a buffer | ||
940 | * @skb: buffer to alter | ||
941 | * @len: new length | ||
942 | * | ||
943 | * Cut the length of a buffer down by removing data from the tail. If | ||
944 | * the buffer is already under the length specified it is not modified. | ||
945 | * The skb must be linear. | ||
946 | */ | ||
947 | void skb_trim(struct sk_buff *skb, unsigned int len) | ||
948 | { | ||
949 | if (skb->len > len) | ||
950 | __skb_trim(skb, len); | ||
951 | } | ||
952 | EXPORT_SYMBOL(skb_trim); | ||
953 | |||
860 | /* Trims skb to length len. It can change skb pointers. | 954 | /* Trims skb to length len. It can change skb pointers. |
861 | */ | 955 | */ |
862 | 956 | ||
@@ -1766,7 +1860,7 @@ void skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head | |||
1766 | unsigned long flags; | 1860 | unsigned long flags; |
1767 | 1861 | ||
1768 | spin_lock_irqsave(&list->lock, flags); | 1862 | spin_lock_irqsave(&list->lock, flags); |
1769 | __skb_append(old, newsk, list); | 1863 | __skb_queue_after(list, old, newsk); |
1770 | spin_unlock_irqrestore(&list->lock, flags); | 1864 | spin_unlock_irqrestore(&list->lock, flags); |
1771 | } | 1865 | } |
1772 | 1866 | ||
diff --git a/net/core/sock.c b/net/core/sock.c index 7a0567b4b2c9..54c836a2216b 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -372,7 +372,7 @@ static int sock_bindtodevice(struct sock *sk, char __user *optval, int optlen) | |||
372 | { | 372 | { |
373 | int ret = -ENOPROTOOPT; | 373 | int ret = -ENOPROTOOPT; |
374 | #ifdef CONFIG_NETDEVICES | 374 | #ifdef CONFIG_NETDEVICES |
375 | struct net *net = sk->sk_net; | 375 | struct net *net = sock_net(sk); |
376 | char devname[IFNAMSIZ]; | 376 | char devname[IFNAMSIZ]; |
377 | int index; | 377 | int index; |
378 | 378 | ||
@@ -958,7 +958,7 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority, | |||
958 | */ | 958 | */ |
959 | sk->sk_prot = sk->sk_prot_creator = prot; | 959 | sk->sk_prot = sk->sk_prot_creator = prot; |
960 | sock_lock_init(sk); | 960 | sock_lock_init(sk); |
961 | sk->sk_net = get_net(net); | 961 | sock_net_set(sk, get_net(net)); |
962 | } | 962 | } |
963 | 963 | ||
964 | return sk; | 964 | return sk; |
@@ -981,12 +981,32 @@ void sk_free(struct sock *sk) | |||
981 | 981 | ||
982 | if (atomic_read(&sk->sk_omem_alloc)) | 982 | if (atomic_read(&sk->sk_omem_alloc)) |
983 | printk(KERN_DEBUG "%s: optmem leakage (%d bytes) detected.\n", | 983 | printk(KERN_DEBUG "%s: optmem leakage (%d bytes) detected.\n", |
984 | __FUNCTION__, atomic_read(&sk->sk_omem_alloc)); | 984 | __func__, atomic_read(&sk->sk_omem_alloc)); |
985 | 985 | ||
986 | put_net(sk->sk_net); | 986 | put_net(sock_net(sk)); |
987 | sk_prot_free(sk->sk_prot_creator, sk); | 987 | sk_prot_free(sk->sk_prot_creator, sk); |
988 | } | 988 | } |
989 | 989 | ||
990 | /* | ||
991 | * Last sock_put should drop referrence to sk->sk_net. It has already | ||
992 | * been dropped in sk_change_net. Taking referrence to stopping namespace | ||
993 | * is not an option. | ||
994 | * Take referrence to a socket to remove it from hash _alive_ and after that | ||
995 | * destroy it in the context of init_net. | ||
996 | */ | ||
997 | void sk_release_kernel(struct sock *sk) | ||
998 | { | ||
999 | if (sk == NULL || sk->sk_socket == NULL) | ||
1000 | return; | ||
1001 | |||
1002 | sock_hold(sk); | ||
1003 | sock_release(sk->sk_socket); | ||
1004 | release_net(sock_net(sk)); | ||
1005 | sock_net_set(sk, get_net(&init_net)); | ||
1006 | sock_put(sk); | ||
1007 | } | ||
1008 | EXPORT_SYMBOL(sk_release_kernel); | ||
1009 | |||
990 | struct sock *sk_clone(const struct sock *sk, const gfp_t priority) | 1010 | struct sock *sk_clone(const struct sock *sk, const gfp_t priority) |
991 | { | 1011 | { |
992 | struct sock *newsk; | 1012 | struct sock *newsk; |
@@ -998,7 +1018,7 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority) | |||
998 | sock_copy(newsk, sk); | 1018 | sock_copy(newsk, sk); |
999 | 1019 | ||
1000 | /* SANITY */ | 1020 | /* SANITY */ |
1001 | get_net(newsk->sk_net); | 1021 | get_net(sock_net(newsk)); |
1002 | sk_node_init(&newsk->sk_node); | 1022 | sk_node_init(&newsk->sk_node); |
1003 | sock_lock_init(newsk); | 1023 | sock_lock_init(newsk); |
1004 | bh_lock_sock(newsk); | 1024 | bh_lock_sock(newsk); |
@@ -1076,10 +1096,12 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst) | |||
1076 | if (sk->sk_route_caps & NETIF_F_GSO) | 1096 | if (sk->sk_route_caps & NETIF_F_GSO) |
1077 | sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE; | 1097 | sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE; |
1078 | if (sk_can_gso(sk)) { | 1098 | if (sk_can_gso(sk)) { |
1079 | if (dst->header_len) | 1099 | if (dst->header_len) { |
1080 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; | 1100 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; |
1081 | else | 1101 | } else { |
1082 | sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM; | 1102 | sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM; |
1103 | sk->sk_gso_max_size = dst->dev->gso_max_size; | ||
1104 | } | ||
1083 | } | 1105 | } |
1084 | } | 1106 | } |
1085 | EXPORT_SYMBOL_GPL(sk_setup_caps); | 1107 | EXPORT_SYMBOL_GPL(sk_setup_caps); |
@@ -1919,16 +1941,113 @@ EXPORT_SYMBOL(sk_common_release); | |||
1919 | static DEFINE_RWLOCK(proto_list_lock); | 1941 | static DEFINE_RWLOCK(proto_list_lock); |
1920 | static LIST_HEAD(proto_list); | 1942 | static LIST_HEAD(proto_list); |
1921 | 1943 | ||
1944 | #ifdef CONFIG_PROC_FS | ||
1945 | #define PROTO_INUSE_NR 64 /* should be enough for the first time */ | ||
1946 | struct prot_inuse { | ||
1947 | int val[PROTO_INUSE_NR]; | ||
1948 | }; | ||
1949 | |||
1950 | static DECLARE_BITMAP(proto_inuse_idx, PROTO_INUSE_NR); | ||
1951 | |||
1952 | #ifdef CONFIG_NET_NS | ||
1953 | void sock_prot_inuse_add(struct net *net, struct proto *prot, int val) | ||
1954 | { | ||
1955 | int cpu = smp_processor_id(); | ||
1956 | per_cpu_ptr(net->core.inuse, cpu)->val[prot->inuse_idx] += val; | ||
1957 | } | ||
1958 | EXPORT_SYMBOL_GPL(sock_prot_inuse_add); | ||
1959 | |||
1960 | int sock_prot_inuse_get(struct net *net, struct proto *prot) | ||
1961 | { | ||
1962 | int cpu, idx = prot->inuse_idx; | ||
1963 | int res = 0; | ||
1964 | |||
1965 | for_each_possible_cpu(cpu) | ||
1966 | res += per_cpu_ptr(net->core.inuse, cpu)->val[idx]; | ||
1967 | |||
1968 | return res >= 0 ? res : 0; | ||
1969 | } | ||
1970 | EXPORT_SYMBOL_GPL(sock_prot_inuse_get); | ||
1971 | |||
1972 | static int sock_inuse_init_net(struct net *net) | ||
1973 | { | ||
1974 | net->core.inuse = alloc_percpu(struct prot_inuse); | ||
1975 | return net->core.inuse ? 0 : -ENOMEM; | ||
1976 | } | ||
1977 | |||
1978 | static void sock_inuse_exit_net(struct net *net) | ||
1979 | { | ||
1980 | free_percpu(net->core.inuse); | ||
1981 | } | ||
1982 | |||
1983 | static struct pernet_operations net_inuse_ops = { | ||
1984 | .init = sock_inuse_init_net, | ||
1985 | .exit = sock_inuse_exit_net, | ||
1986 | }; | ||
1987 | |||
1988 | static __init int net_inuse_init(void) | ||
1989 | { | ||
1990 | if (register_pernet_subsys(&net_inuse_ops)) | ||
1991 | panic("Cannot initialize net inuse counters"); | ||
1992 | |||
1993 | return 0; | ||
1994 | } | ||
1995 | |||
1996 | core_initcall(net_inuse_init); | ||
1997 | #else | ||
1998 | static DEFINE_PER_CPU(struct prot_inuse, prot_inuse); | ||
1999 | |||
2000 | void sock_prot_inuse_add(struct net *net, struct proto *prot, int val) | ||
2001 | { | ||
2002 | __get_cpu_var(prot_inuse).val[prot->inuse_idx] += val; | ||
2003 | } | ||
2004 | EXPORT_SYMBOL_GPL(sock_prot_inuse_add); | ||
2005 | |||
2006 | int sock_prot_inuse_get(struct net *net, struct proto *prot) | ||
2007 | { | ||
2008 | int cpu, idx = prot->inuse_idx; | ||
2009 | int res = 0; | ||
2010 | |||
2011 | for_each_possible_cpu(cpu) | ||
2012 | res += per_cpu(prot_inuse, cpu).val[idx]; | ||
2013 | |||
2014 | return res >= 0 ? res : 0; | ||
2015 | } | ||
2016 | EXPORT_SYMBOL_GPL(sock_prot_inuse_get); | ||
2017 | #endif | ||
2018 | |||
2019 | static void assign_proto_idx(struct proto *prot) | ||
2020 | { | ||
2021 | prot->inuse_idx = find_first_zero_bit(proto_inuse_idx, PROTO_INUSE_NR); | ||
2022 | |||
2023 | if (unlikely(prot->inuse_idx == PROTO_INUSE_NR - 1)) { | ||
2024 | printk(KERN_ERR "PROTO_INUSE_NR exhausted\n"); | ||
2025 | return; | ||
2026 | } | ||
2027 | |||
2028 | set_bit(prot->inuse_idx, proto_inuse_idx); | ||
2029 | } | ||
2030 | |||
2031 | static void release_proto_idx(struct proto *prot) | ||
2032 | { | ||
2033 | if (prot->inuse_idx != PROTO_INUSE_NR - 1) | ||
2034 | clear_bit(prot->inuse_idx, proto_inuse_idx); | ||
2035 | } | ||
2036 | #else | ||
2037 | static inline void assign_proto_idx(struct proto *prot) | ||
2038 | { | ||
2039 | } | ||
2040 | |||
2041 | static inline void release_proto_idx(struct proto *prot) | ||
2042 | { | ||
2043 | } | ||
2044 | #endif | ||
2045 | |||
1922 | int proto_register(struct proto *prot, int alloc_slab) | 2046 | int proto_register(struct proto *prot, int alloc_slab) |
1923 | { | 2047 | { |
1924 | char *request_sock_slab_name = NULL; | 2048 | char *request_sock_slab_name = NULL; |
1925 | char *timewait_sock_slab_name; | 2049 | char *timewait_sock_slab_name; |
1926 | 2050 | ||
1927 | if (sock_prot_inuse_init(prot) != 0) { | ||
1928 | printk(KERN_CRIT "%s: Can't alloc inuse counters!\n", prot->name); | ||
1929 | goto out; | ||
1930 | } | ||
1931 | |||
1932 | if (alloc_slab) { | 2051 | if (alloc_slab) { |
1933 | prot->slab = kmem_cache_create(prot->name, prot->obj_size, 0, | 2052 | prot->slab = kmem_cache_create(prot->name, prot->obj_size, 0, |
1934 | SLAB_HWCACHE_ALIGN, NULL); | 2053 | SLAB_HWCACHE_ALIGN, NULL); |
@@ -1936,7 +2055,7 @@ int proto_register(struct proto *prot, int alloc_slab) | |||
1936 | if (prot->slab == NULL) { | 2055 | if (prot->slab == NULL) { |
1937 | printk(KERN_CRIT "%s: Can't create sock SLAB cache!\n", | 2056 | printk(KERN_CRIT "%s: Can't create sock SLAB cache!\n", |
1938 | prot->name); | 2057 | prot->name); |
1939 | goto out_free_inuse; | 2058 | goto out; |
1940 | } | 2059 | } |
1941 | 2060 | ||
1942 | if (prot->rsk_prot != NULL) { | 2061 | if (prot->rsk_prot != NULL) { |
@@ -1979,6 +2098,7 @@ int proto_register(struct proto *prot, int alloc_slab) | |||
1979 | 2098 | ||
1980 | write_lock(&proto_list_lock); | 2099 | write_lock(&proto_list_lock); |
1981 | list_add(&prot->node, &proto_list); | 2100 | list_add(&prot->node, &proto_list); |
2101 | assign_proto_idx(prot); | ||
1982 | write_unlock(&proto_list_lock); | 2102 | write_unlock(&proto_list_lock); |
1983 | return 0; | 2103 | return 0; |
1984 | 2104 | ||
@@ -1994,8 +2114,6 @@ out_free_request_sock_slab_name: | |||
1994 | out_free_sock_slab: | 2114 | out_free_sock_slab: |
1995 | kmem_cache_destroy(prot->slab); | 2115 | kmem_cache_destroy(prot->slab); |
1996 | prot->slab = NULL; | 2116 | prot->slab = NULL; |
1997 | out_free_inuse: | ||
1998 | sock_prot_inuse_free(prot); | ||
1999 | out: | 2117 | out: |
2000 | return -ENOBUFS; | 2118 | return -ENOBUFS; |
2001 | } | 2119 | } |
@@ -2005,11 +2123,10 @@ EXPORT_SYMBOL(proto_register); | |||
2005 | void proto_unregister(struct proto *prot) | 2123 | void proto_unregister(struct proto *prot) |
2006 | { | 2124 | { |
2007 | write_lock(&proto_list_lock); | 2125 | write_lock(&proto_list_lock); |
2126 | release_proto_idx(prot); | ||
2008 | list_del(&prot->node); | 2127 | list_del(&prot->node); |
2009 | write_unlock(&proto_list_lock); | 2128 | write_unlock(&proto_list_lock); |
2010 | 2129 | ||
2011 | sock_prot_inuse_free(prot); | ||
2012 | |||
2013 | if (prot->slab != NULL) { | 2130 | if (prot->slab != NULL) { |
2014 | kmem_cache_destroy(prot->slab); | 2131 | kmem_cache_destroy(prot->slab); |
2015 | prot->slab = NULL; | 2132 | prot->slab = NULL; |
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 130338f83ae5..5fc801057244 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c | |||
@@ -127,7 +127,7 @@ static struct ctl_table net_core_table[] = { | |||
127 | { | 127 | { |
128 | .ctl_name = NET_CORE_SOMAXCONN, | 128 | .ctl_name = NET_CORE_SOMAXCONN, |
129 | .procname = "somaxconn", | 129 | .procname = "somaxconn", |
130 | .data = &init_net.sysctl_somaxconn, | 130 | .data = &init_net.core.sysctl_somaxconn, |
131 | .maxlen = sizeof(int), | 131 | .maxlen = sizeof(int), |
132 | .mode = 0644, | 132 | .mode = 0644, |
133 | .proc_handler = &proc_dointvec | 133 | .proc_handler = &proc_dointvec |
@@ -161,7 +161,7 @@ static __net_init int sysctl_core_net_init(struct net *net) | |||
161 | { | 161 | { |
162 | struct ctl_table *tbl, *tmp; | 162 | struct ctl_table *tbl, *tmp; |
163 | 163 | ||
164 | net->sysctl_somaxconn = SOMAXCONN; | 164 | net->core.sysctl_somaxconn = SOMAXCONN; |
165 | 165 | ||
166 | tbl = net_core_table; | 166 | tbl = net_core_table; |
167 | if (net != &init_net) { | 167 | if (net != &init_net) { |
@@ -178,9 +178,9 @@ static __net_init int sysctl_core_net_init(struct net *net) | |||
178 | } | 178 | } |
179 | } | 179 | } |
180 | 180 | ||
181 | net->sysctl_core_hdr = register_net_sysctl_table(net, | 181 | net->core.sysctl_hdr = register_net_sysctl_table(net, |
182 | net_core_path, tbl); | 182 | net_core_path, tbl); |
183 | if (net->sysctl_core_hdr == NULL) | 183 | if (net->core.sysctl_hdr == NULL) |
184 | goto err_reg; | 184 | goto err_reg; |
185 | 185 | ||
186 | return 0; | 186 | return 0; |
@@ -196,8 +196,8 @@ static __net_exit void sysctl_core_net_exit(struct net *net) | |||
196 | { | 196 | { |
197 | struct ctl_table *tbl; | 197 | struct ctl_table *tbl; |
198 | 198 | ||
199 | tbl = net->sysctl_core_hdr->ctl_table_arg; | 199 | tbl = net->core.sysctl_hdr->ctl_table_arg; |
200 | unregister_net_sysctl_table(net->sysctl_core_hdr); | 200 | unregister_net_sysctl_table(net->core.sysctl_hdr); |
201 | BUG_ON(tbl == net_core_table); | 201 | BUG_ON(tbl == net_core_table); |
202 | kfree(tbl); | 202 | kfree(tbl); |
203 | } | 203 | } |