diff options
Diffstat (limited to 'net')
344 files changed, 13920 insertions, 8411 deletions
diff --git a/net/802/tr.c b/net/802/tr.c index 0ba1946211c9..e56e61a7f545 100644 --- a/net/802/tr.c +++ b/net/802/tr.c | |||
@@ -567,7 +567,7 @@ static int rif_seq_show(struct seq_file *seq, void *v) | |||
567 | } | 567 | } |
568 | 568 | ||
569 | 569 | ||
570 | static struct seq_operations rif_seq_ops = { | 570 | static const struct seq_operations rif_seq_ops = { |
571 | .start = rif_seq_start, | 571 | .start = rif_seq_start, |
572 | .next = rif_seq_next, | 572 | .next = rif_seq_next, |
573 | .stop = rif_seq_stop, | 573 | .stop = rif_seq_stop, |
diff --git a/net/8021q/Makefile b/net/8021q/Makefile index 97feb44dbdce..10ca7f486c3a 100644 --- a/net/8021q/Makefile +++ b/net/8021q/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_VLAN_8021Q) += 8021q.o | 5 | obj-$(CONFIG_VLAN_8021Q) += 8021q.o |
6 | 6 | ||
7 | 8021q-objs := vlan.o vlan_dev.o | 7 | 8021q-objs := vlan.o vlan_dev.o vlan_netlink.o |
8 | 8 | ||
9 | ifeq ($(CONFIG_PROC_FS),y) | 9 | ifeq ($(CONFIG_PROC_FS),y) |
10 | 8021q-objs += vlanproc.o | 10 | 8021q-objs += vlanproc.o |
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index de78c9dd713b..cda936b77d22 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
@@ -97,35 +97,22 @@ static int __init vlan_proto_init(void) | |||
97 | 97 | ||
98 | /* Register us to receive netdevice events */ | 98 | /* Register us to receive netdevice events */ |
99 | err = register_netdevice_notifier(&vlan_notifier_block); | 99 | err = register_netdevice_notifier(&vlan_notifier_block); |
100 | if (err < 0) { | 100 | if (err < 0) |
101 | dev_remove_pack(&vlan_packet_type); | 101 | goto err1; |
102 | vlan_proc_cleanup(); | ||
103 | return err; | ||
104 | } | ||
105 | 102 | ||
106 | vlan_ioctl_set(vlan_ioctl_handler); | 103 | err = vlan_netlink_init(); |
104 | if (err < 0) | ||
105 | goto err2; | ||
107 | 106 | ||
107 | vlan_ioctl_set(vlan_ioctl_handler); | ||
108 | return 0; | 108 | return 0; |
109 | } | ||
110 | |||
111 | /* Cleanup all vlan devices | ||
112 | * Note: devices that have been registered that but not | ||
113 | * brought up will exist but have no module ref count. | ||
114 | */ | ||
115 | static void __exit vlan_cleanup_devices(void) | ||
116 | { | ||
117 | struct net_device *dev, *nxt; | ||
118 | |||
119 | rtnl_lock(); | ||
120 | for_each_netdev_safe(dev, nxt) { | ||
121 | if (dev->priv_flags & IFF_802_1Q_VLAN) { | ||
122 | unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev, | ||
123 | VLAN_DEV_INFO(dev)->vlan_id); | ||
124 | 109 | ||
125 | unregister_netdevice(dev); | 110 | err2: |
126 | } | 111 | unregister_netdevice_notifier(&vlan_notifier_block); |
127 | } | 112 | err1: |
128 | rtnl_unlock(); | 113 | vlan_proc_cleanup(); |
114 | dev_remove_pack(&vlan_packet_type); | ||
115 | return err; | ||
129 | } | 116 | } |
130 | 117 | ||
131 | /* | 118 | /* |
@@ -136,13 +123,13 @@ static void __exit vlan_cleanup_module(void) | |||
136 | { | 123 | { |
137 | int i; | 124 | int i; |
138 | 125 | ||
126 | vlan_netlink_fini(); | ||
139 | vlan_ioctl_set(NULL); | 127 | vlan_ioctl_set(NULL); |
140 | 128 | ||
141 | /* Un-register us from receiving netdevice events */ | 129 | /* Un-register us from receiving netdevice events */ |
142 | unregister_netdevice_notifier(&vlan_notifier_block); | 130 | unregister_netdevice_notifier(&vlan_notifier_block); |
143 | 131 | ||
144 | dev_remove_pack(&vlan_packet_type); | 132 | dev_remove_pack(&vlan_packet_type); |
145 | vlan_cleanup_devices(); | ||
146 | 133 | ||
147 | /* This table must be empty if there are no module | 134 | /* This table must be empty if there are no module |
148 | * references left. | 135 | * references left. |
@@ -197,6 +184,34 @@ static void vlan_group_free(struct vlan_group *grp) | |||
197 | kfree(grp); | 184 | kfree(grp); |
198 | } | 185 | } |
199 | 186 | ||
187 | static struct vlan_group *vlan_group_alloc(int ifindex) | ||
188 | { | ||
189 | struct vlan_group *grp; | ||
190 | unsigned int size; | ||
191 | unsigned int i; | ||
192 | |||
193 | grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL); | ||
194 | if (!grp) | ||
195 | return NULL; | ||
196 | |||
197 | size = sizeof(struct net_device *) * VLAN_GROUP_ARRAY_PART_LEN; | ||
198 | |||
199 | for (i = 0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) { | ||
200 | grp->vlan_devices_arrays[i] = kzalloc(size, GFP_KERNEL); | ||
201 | if (!grp->vlan_devices_arrays[i]) | ||
202 | goto err; | ||
203 | } | ||
204 | |||
205 | grp->real_dev_ifindex = ifindex; | ||
206 | hlist_add_head_rcu(&grp->hlist, | ||
207 | &vlan_group_hash[vlan_grp_hashfn(ifindex)]); | ||
208 | return grp; | ||
209 | |||
210 | err: | ||
211 | vlan_group_free(grp); | ||
212 | return NULL; | ||
213 | } | ||
214 | |||
200 | static void vlan_rcu_free(struct rcu_head *rcu) | 215 | static void vlan_rcu_free(struct rcu_head *rcu) |
201 | { | 216 | { |
202 | vlan_group_free(container_of(rcu, struct vlan_group, rcu)); | 217 | vlan_group_free(container_of(rcu, struct vlan_group, rcu)); |
@@ -278,50 +293,66 @@ static int unregister_vlan_dev(struct net_device *real_dev, | |||
278 | return ret; | 293 | return ret; |
279 | } | 294 | } |
280 | 295 | ||
281 | static int unregister_vlan_device(const char *vlan_IF_name) | 296 | int unregister_vlan_device(struct net_device *dev) |
282 | { | 297 | { |
283 | struct net_device *dev = NULL; | ||
284 | int ret; | 298 | int ret; |
285 | 299 | ||
300 | ret = unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev, | ||
301 | VLAN_DEV_INFO(dev)->vlan_id); | ||
302 | unregister_netdevice(dev); | ||
286 | 303 | ||
287 | dev = dev_get_by_name(vlan_IF_name); | 304 | if (ret == 1) |
288 | ret = -EINVAL; | 305 | ret = 0; |
289 | if (dev) { | 306 | return ret; |
290 | if (dev->priv_flags & IFF_802_1Q_VLAN) { | 307 | } |
291 | rtnl_lock(); | ||
292 | 308 | ||
293 | ret = unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev, | 309 | /* |
294 | VLAN_DEV_INFO(dev)->vlan_id); | 310 | * vlan network devices have devices nesting below it, and are a special |
311 | * "super class" of normal network devices; split their locks off into a | ||
312 | * separate class since they always nest. | ||
313 | */ | ||
314 | static struct lock_class_key vlan_netdev_xmit_lock_key; | ||
295 | 315 | ||
296 | dev_put(dev); | 316 | static int vlan_dev_init(struct net_device *dev) |
297 | unregister_netdevice(dev); | 317 | { |
318 | struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev; | ||
298 | 319 | ||
299 | rtnl_unlock(); | 320 | /* IFF_BROADCAST|IFF_MULTICAST; ??? */ |
321 | dev->flags = real_dev->flags & ~IFF_UP; | ||
322 | dev->iflink = real_dev->ifindex; | ||
323 | dev->state = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) | | ||
324 | (1<<__LINK_STATE_DORMANT))) | | ||
325 | (1<<__LINK_STATE_PRESENT); | ||
300 | 326 | ||
301 | if (ret == 1) | 327 | if (is_zero_ether_addr(dev->dev_addr)) |
302 | ret = 0; | 328 | memcpy(dev->dev_addr, real_dev->dev_addr, dev->addr_len); |
303 | } else { | 329 | if (is_zero_ether_addr(dev->broadcast)) |
304 | printk(VLAN_ERR | 330 | memcpy(dev->broadcast, real_dev->broadcast, dev->addr_len); |
305 | "%s: ERROR: Tried to remove a non-vlan device " | 331 | |
306 | "with VLAN code, name: %s priv_flags: %hX\n", | 332 | if (real_dev->features & NETIF_F_HW_VLAN_TX) { |
307 | __FUNCTION__, dev->name, dev->priv_flags); | 333 | dev->hard_header = real_dev->hard_header; |
308 | dev_put(dev); | 334 | dev->hard_header_len = real_dev->hard_header_len; |
309 | ret = -EPERM; | 335 | dev->hard_start_xmit = vlan_dev_hwaccel_hard_start_xmit; |
310 | } | 336 | dev->rebuild_header = real_dev->rebuild_header; |
311 | } else { | 337 | } else { |
312 | #ifdef VLAN_DEBUG | 338 | dev->hard_header = vlan_dev_hard_header; |
313 | printk(VLAN_DBG "%s: WARNING: Could not find dev.\n", __FUNCTION__); | 339 | dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN; |
314 | #endif | 340 | dev->hard_start_xmit = vlan_dev_hard_start_xmit; |
315 | ret = -EINVAL; | 341 | dev->rebuild_header = vlan_dev_rebuild_header; |
316 | } | 342 | } |
343 | dev->hard_header_parse = real_dev->hard_header_parse; | ||
344 | dev->hard_header_cache = NULL; | ||
317 | 345 | ||
318 | return ret; | 346 | lockdep_set_class(&dev->_xmit_lock, &vlan_netdev_xmit_lock_key); |
347 | return 0; | ||
319 | } | 348 | } |
320 | 349 | ||
321 | static void vlan_setup(struct net_device *new_dev) | 350 | void vlan_setup(struct net_device *new_dev) |
322 | { | 351 | { |
323 | SET_MODULE_OWNER(new_dev); | 352 | SET_MODULE_OWNER(new_dev); |
324 | 353 | ||
354 | ether_setup(new_dev); | ||
355 | |||
325 | /* new_dev->ifindex = 0; it will be set when added to | 356 | /* new_dev->ifindex = 0; it will be set when added to |
326 | * the global list. | 357 | * the global list. |
327 | * iflink is set as well. | 358 | * iflink is set as well. |
@@ -338,12 +369,15 @@ static void vlan_setup(struct net_device *new_dev) | |||
338 | 369 | ||
339 | /* set up method calls */ | 370 | /* set up method calls */ |
340 | new_dev->change_mtu = vlan_dev_change_mtu; | 371 | new_dev->change_mtu = vlan_dev_change_mtu; |
372 | new_dev->init = vlan_dev_init; | ||
341 | new_dev->open = vlan_dev_open; | 373 | new_dev->open = vlan_dev_open; |
342 | new_dev->stop = vlan_dev_stop; | 374 | new_dev->stop = vlan_dev_stop; |
343 | new_dev->set_mac_address = vlan_dev_set_mac_address; | ||
344 | new_dev->set_multicast_list = vlan_dev_set_multicast_list; | 375 | new_dev->set_multicast_list = vlan_dev_set_multicast_list; |
376 | new_dev->change_rx_flags = vlan_change_rx_flags; | ||
345 | new_dev->destructor = free_netdev; | 377 | new_dev->destructor = free_netdev; |
346 | new_dev->do_ioctl = vlan_dev_ioctl; | 378 | new_dev->do_ioctl = vlan_dev_ioctl; |
379 | |||
380 | memset(new_dev->broadcast, 0, ETH_ALEN); | ||
347 | } | 381 | } |
348 | 382 | ||
349 | static void vlan_transfer_operstate(const struct net_device *dev, struct net_device *vlandev) | 383 | static void vlan_transfer_operstate(const struct net_device *dev, struct net_device *vlandev) |
@@ -366,77 +400,110 @@ static void vlan_transfer_operstate(const struct net_device *dev, struct net_dev | |||
366 | } | 400 | } |
367 | } | 401 | } |
368 | 402 | ||
369 | /* | 403 | int vlan_check_real_dev(struct net_device *real_dev, unsigned short vlan_id) |
370 | * vlan network devices have devices nesting below it, and are a special | ||
371 | * "super class" of normal network devices; split their locks off into a | ||
372 | * separate class since they always nest. | ||
373 | */ | ||
374 | static struct lock_class_key vlan_netdev_xmit_lock_key; | ||
375 | |||
376 | |||
377 | /* Attach a VLAN device to a mac address (ie Ethernet Card). | ||
378 | * Returns the device that was created, or NULL if there was | ||
379 | * an error of some kind. | ||
380 | */ | ||
381 | static struct net_device *register_vlan_device(const char *eth_IF_name, | ||
382 | unsigned short VLAN_ID) | ||
383 | { | 404 | { |
384 | struct vlan_group *grp; | ||
385 | struct net_device *new_dev; | ||
386 | struct net_device *real_dev; /* the ethernet device */ | ||
387 | char name[IFNAMSIZ]; | ||
388 | int i; | ||
389 | |||
390 | #ifdef VLAN_DEBUG | ||
391 | printk(VLAN_DBG "%s: if_name -:%s:- vid: %i\n", | ||
392 | __FUNCTION__, eth_IF_name, VLAN_ID); | ||
393 | #endif | ||
394 | |||
395 | if (VLAN_ID >= VLAN_VID_MASK) | ||
396 | goto out_ret_null; | ||
397 | |||
398 | /* find the device relating to eth_IF_name. */ | ||
399 | real_dev = dev_get_by_name(eth_IF_name); | ||
400 | if (!real_dev) | ||
401 | goto out_ret_null; | ||
402 | |||
403 | if (real_dev->features & NETIF_F_VLAN_CHALLENGED) { | 405 | if (real_dev->features & NETIF_F_VLAN_CHALLENGED) { |
404 | printk(VLAN_DBG "%s: VLANs not supported on %s.\n", | 406 | printk(VLAN_DBG "%s: VLANs not supported on %s.\n", |
405 | __FUNCTION__, real_dev->name); | 407 | __FUNCTION__, real_dev->name); |
406 | goto out_put_dev; | 408 | return -EOPNOTSUPP; |
407 | } | 409 | } |
408 | 410 | ||
409 | if ((real_dev->features & NETIF_F_HW_VLAN_RX) && | 411 | if ((real_dev->features & NETIF_F_HW_VLAN_RX) && |
410 | !real_dev->vlan_rx_register) { | 412 | !real_dev->vlan_rx_register) { |
411 | printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n", | 413 | printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n", |
412 | __FUNCTION__, real_dev->name); | 414 | __FUNCTION__, real_dev->name); |
413 | goto out_put_dev; | 415 | return -EOPNOTSUPP; |
414 | } | 416 | } |
415 | 417 | ||
416 | if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) && | 418 | if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) && |
417 | (!real_dev->vlan_rx_add_vid || !real_dev->vlan_rx_kill_vid)) { | 419 | (!real_dev->vlan_rx_add_vid || !real_dev->vlan_rx_kill_vid)) { |
418 | printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n", | 420 | printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n", |
419 | __FUNCTION__, real_dev->name); | 421 | __FUNCTION__, real_dev->name); |
420 | goto out_put_dev; | 422 | return -EOPNOTSUPP; |
421 | } | 423 | } |
422 | 424 | ||
423 | /* From this point on, all the data structures must remain | ||
424 | * consistent. | ||
425 | */ | ||
426 | rtnl_lock(); | ||
427 | |||
428 | /* The real device must be up and operating in order to | 425 | /* The real device must be up and operating in order to |
429 | * assosciate a VLAN device with it. | 426 | * assosciate a VLAN device with it. |
430 | */ | 427 | */ |
431 | if (!(real_dev->flags & IFF_UP)) | 428 | if (!(real_dev->flags & IFF_UP)) |
432 | goto out_unlock; | 429 | return -ENETDOWN; |
433 | 430 | ||
434 | if (__find_vlan_dev(real_dev, VLAN_ID) != NULL) { | 431 | if (__find_vlan_dev(real_dev, vlan_id) != NULL) { |
435 | /* was already registered. */ | 432 | /* was already registered. */ |
436 | printk(VLAN_DBG "%s: ALREADY had VLAN registered\n", __FUNCTION__); | 433 | printk(VLAN_DBG "%s: ALREADY had VLAN registered\n", __FUNCTION__); |
437 | goto out_unlock; | 434 | return -EEXIST; |
435 | } | ||
436 | |||
437 | return 0; | ||
438 | } | ||
439 | |||
440 | int register_vlan_dev(struct net_device *dev) | ||
441 | { | ||
442 | struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev); | ||
443 | struct net_device *real_dev = vlan->real_dev; | ||
444 | unsigned short vlan_id = vlan->vlan_id; | ||
445 | struct vlan_group *grp, *ngrp = NULL; | ||
446 | int err; | ||
447 | |||
448 | grp = __vlan_find_group(real_dev->ifindex); | ||
449 | if (!grp) { | ||
450 | ngrp = grp = vlan_group_alloc(real_dev->ifindex); | ||
451 | if (!grp) | ||
452 | return -ENOBUFS; | ||
438 | } | 453 | } |
439 | 454 | ||
455 | err = register_netdevice(dev); | ||
456 | if (err < 0) | ||
457 | goto out_free_group; | ||
458 | |||
459 | /* Account for reference in struct vlan_dev_info */ | ||
460 | dev_hold(real_dev); | ||
461 | |||
462 | vlan_transfer_operstate(real_dev, dev); | ||
463 | linkwatch_fire_event(dev); /* _MUST_ call rfc2863_policy() */ | ||
464 | |||
465 | /* So, got the sucker initialized, now lets place | ||
466 | * it into our local structure. | ||
467 | */ | ||
468 | vlan_group_set_device(grp, vlan_id, dev); | ||
469 | if (ngrp && real_dev->features & NETIF_F_HW_VLAN_RX) | ||
470 | real_dev->vlan_rx_register(real_dev, ngrp); | ||
471 | if (real_dev->features & NETIF_F_HW_VLAN_FILTER) | ||
472 | real_dev->vlan_rx_add_vid(real_dev, vlan_id); | ||
473 | |||
474 | if (vlan_proc_add_dev(dev) < 0) | ||
475 | printk(KERN_WARNING "VLAN: failed to add proc entry for %s\n", | ||
476 | dev->name); | ||
477 | return 0; | ||
478 | |||
479 | out_free_group: | ||
480 | if (ngrp) | ||
481 | vlan_group_free(ngrp); | ||
482 | return err; | ||
483 | } | ||
484 | |||
485 | /* Attach a VLAN device to a mac address (ie Ethernet Card). | ||
486 | * Returns 0 if the device was created or a negative error code otherwise. | ||
487 | */ | ||
488 | static int register_vlan_device(struct net_device *real_dev, | ||
489 | unsigned short VLAN_ID) | ||
490 | { | ||
491 | struct net_device *new_dev; | ||
492 | char name[IFNAMSIZ]; | ||
493 | int err; | ||
494 | |||
495 | #ifdef VLAN_DEBUG | ||
496 | printk(VLAN_DBG "%s: if_name -:%s:- vid: %i\n", | ||
497 | __FUNCTION__, eth_IF_name, VLAN_ID); | ||
498 | #endif | ||
499 | |||
500 | if (VLAN_ID >= VLAN_VID_MASK) | ||
501 | return -ERANGE; | ||
502 | |||
503 | err = vlan_check_real_dev(real_dev, VLAN_ID); | ||
504 | if (err < 0) | ||
505 | return err; | ||
506 | |||
440 | /* Gotta set up the fields for the device. */ | 507 | /* Gotta set up the fields for the device. */ |
441 | #ifdef VLAN_DEBUG | 508 | #ifdef VLAN_DEBUG |
442 | printk(VLAN_DBG "About to allocate name, vlan_name_type: %i\n", | 509 | printk(VLAN_DBG "About to allocate name, vlan_name_type: %i\n", |
@@ -471,138 +538,64 @@ static struct net_device *register_vlan_device(const char *eth_IF_name, | |||
471 | vlan_setup); | 538 | vlan_setup); |
472 | 539 | ||
473 | if (new_dev == NULL) | 540 | if (new_dev == NULL) |
474 | goto out_unlock; | 541 | return -ENOBUFS; |
475 | |||
476 | #ifdef VLAN_DEBUG | ||
477 | printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name); | ||
478 | #endif | ||
479 | /* IFF_BROADCAST|IFF_MULTICAST; ??? */ | ||
480 | new_dev->flags = real_dev->flags; | ||
481 | new_dev->flags &= ~IFF_UP; | ||
482 | |||
483 | new_dev->state = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) | | ||
484 | (1<<__LINK_STATE_DORMANT))) | | ||
485 | (1<<__LINK_STATE_PRESENT); | ||
486 | 542 | ||
487 | /* need 4 bytes for extra VLAN header info, | 543 | /* need 4 bytes for extra VLAN header info, |
488 | * hope the underlying device can handle it. | 544 | * hope the underlying device can handle it. |
489 | */ | 545 | */ |
490 | new_dev->mtu = real_dev->mtu; | 546 | new_dev->mtu = real_dev->mtu; |
491 | 547 | ||
492 | /* TODO: maybe just assign it to be ETHERNET? */ | 548 | #ifdef VLAN_DEBUG |
493 | new_dev->type = real_dev->type; | 549 | printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name); |
494 | |||
495 | new_dev->hard_header_len = real_dev->hard_header_len; | ||
496 | if (!(real_dev->features & NETIF_F_HW_VLAN_TX)) { | ||
497 | /* Regular ethernet + 4 bytes (18 total). */ | ||
498 | new_dev->hard_header_len += VLAN_HLEN; | ||
499 | } | ||
500 | |||
501 | VLAN_MEM_DBG("new_dev->priv malloc, addr: %p size: %i\n", | 550 | VLAN_MEM_DBG("new_dev->priv malloc, addr: %p size: %i\n", |
502 | new_dev->priv, | 551 | new_dev->priv, |
503 | sizeof(struct vlan_dev_info)); | 552 | sizeof(struct vlan_dev_info)); |
504 | 553 | #endif | |
505 | memcpy(new_dev->broadcast, real_dev->broadcast, real_dev->addr_len); | ||
506 | memcpy(new_dev->dev_addr, real_dev->dev_addr, real_dev->addr_len); | ||
507 | new_dev->addr_len = real_dev->addr_len; | ||
508 | |||
509 | if (real_dev->features & NETIF_F_HW_VLAN_TX) { | ||
510 | new_dev->hard_header = real_dev->hard_header; | ||
511 | new_dev->hard_start_xmit = vlan_dev_hwaccel_hard_start_xmit; | ||
512 | new_dev->rebuild_header = real_dev->rebuild_header; | ||
513 | } else { | ||
514 | new_dev->hard_header = vlan_dev_hard_header; | ||
515 | new_dev->hard_start_xmit = vlan_dev_hard_start_xmit; | ||
516 | new_dev->rebuild_header = vlan_dev_rebuild_header; | ||
517 | } | ||
518 | new_dev->hard_header_parse = real_dev->hard_header_parse; | ||
519 | 554 | ||
520 | VLAN_DEV_INFO(new_dev)->vlan_id = VLAN_ID; /* 1 through VLAN_VID_MASK */ | 555 | VLAN_DEV_INFO(new_dev)->vlan_id = VLAN_ID; /* 1 through VLAN_VID_MASK */ |
521 | VLAN_DEV_INFO(new_dev)->real_dev = real_dev; | 556 | VLAN_DEV_INFO(new_dev)->real_dev = real_dev; |
522 | VLAN_DEV_INFO(new_dev)->dent = NULL; | 557 | VLAN_DEV_INFO(new_dev)->dent = NULL; |
523 | VLAN_DEV_INFO(new_dev)->flags = 1; | 558 | VLAN_DEV_INFO(new_dev)->flags = VLAN_FLAG_REORDER_HDR; |
524 | 559 | ||
525 | #ifdef VLAN_DEBUG | 560 | new_dev->rtnl_link_ops = &vlan_link_ops; |
526 | printk(VLAN_DBG "About to go find the group for idx: %i\n", | 561 | err = register_vlan_dev(new_dev); |
527 | real_dev->ifindex); | 562 | if (err < 0) |
528 | #endif | ||
529 | |||
530 | if (register_netdevice(new_dev)) | ||
531 | goto out_free_newdev; | 563 | goto out_free_newdev; |
532 | 564 | ||
533 | lockdep_set_class(&new_dev->_xmit_lock, &vlan_netdev_xmit_lock_key); | 565 | /* Account for reference in struct vlan_dev_info */ |
534 | 566 | dev_hold(real_dev); | |
535 | new_dev->iflink = real_dev->ifindex; | ||
536 | vlan_transfer_operstate(real_dev, new_dev); | ||
537 | linkwatch_fire_event(new_dev); /* _MUST_ call rfc2863_policy() */ | ||
538 | |||
539 | /* So, got the sucker initialized, now lets place | ||
540 | * it into our local structure. | ||
541 | */ | ||
542 | grp = __vlan_find_group(real_dev->ifindex); | ||
543 | |||
544 | /* Note, we are running under the RTNL semaphore | ||
545 | * so it cannot "appear" on us. | ||
546 | */ | ||
547 | if (!grp) { /* need to add a new group */ | ||
548 | grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL); | ||
549 | if (!grp) | ||
550 | goto out_free_unregister; | ||
551 | |||
552 | for (i=0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) { | ||
553 | grp->vlan_devices_arrays[i] = kzalloc( | ||
554 | sizeof(struct net_device *)*VLAN_GROUP_ARRAY_PART_LEN, | ||
555 | GFP_KERNEL); | ||
556 | |||
557 | if (!grp->vlan_devices_arrays[i]) | ||
558 | goto out_free_arrays; | ||
559 | } | ||
560 | |||
561 | /* printk(KERN_ALERT "VLAN REGISTER: Allocated new group.\n"); */ | ||
562 | grp->real_dev_ifindex = real_dev->ifindex; | ||
563 | |||
564 | hlist_add_head_rcu(&grp->hlist, | ||
565 | &vlan_group_hash[vlan_grp_hashfn(real_dev->ifindex)]); | ||
566 | |||
567 | if (real_dev->features & NETIF_F_HW_VLAN_RX) | ||
568 | real_dev->vlan_rx_register(real_dev, grp); | ||
569 | } | ||
570 | |||
571 | vlan_group_set_device(grp, VLAN_ID, new_dev); | ||
572 | |||
573 | if (vlan_proc_add_dev(new_dev)<0)/* create it's proc entry */ | ||
574 | printk(KERN_WARNING "VLAN: failed to add proc entry for %s\n", | ||
575 | new_dev->name); | ||
576 | |||
577 | if (real_dev->features & NETIF_F_HW_VLAN_FILTER) | ||
578 | real_dev->vlan_rx_add_vid(real_dev, VLAN_ID); | ||
579 | |||
580 | rtnl_unlock(); | ||
581 | |||
582 | |||
583 | #ifdef VLAN_DEBUG | 567 | #ifdef VLAN_DEBUG |
584 | printk(VLAN_DBG "Allocated new device successfully, returning.\n"); | 568 | printk(VLAN_DBG "Allocated new device successfully, returning.\n"); |
585 | #endif | 569 | #endif |
586 | return new_dev; | 570 | return 0; |
587 | |||
588 | out_free_arrays: | ||
589 | vlan_group_free(grp); | ||
590 | |||
591 | out_free_unregister: | ||
592 | unregister_netdev(new_dev); | ||
593 | goto out_unlock; | ||
594 | 571 | ||
595 | out_free_newdev: | 572 | out_free_newdev: |
596 | free_netdev(new_dev); | 573 | free_netdev(new_dev); |
574 | return err; | ||
575 | } | ||
597 | 576 | ||
598 | out_unlock: | 577 | static void vlan_sync_address(struct net_device *dev, |
599 | rtnl_unlock(); | 578 | struct net_device *vlandev) |
579 | { | ||
580 | struct vlan_dev_info *vlan = VLAN_DEV_INFO(vlandev); | ||
600 | 581 | ||
601 | out_put_dev: | 582 | /* May be called without an actual change */ |
602 | dev_put(real_dev); | 583 | if (!compare_ether_addr(vlan->real_dev_addr, dev->dev_addr)) |
584 | return; | ||
603 | 585 | ||
604 | out_ret_null: | 586 | /* vlan address was different from the old address and is equal to |
605 | return NULL; | 587 | * the new address */ |
588 | if (compare_ether_addr(vlandev->dev_addr, vlan->real_dev_addr) && | ||
589 | !compare_ether_addr(vlandev->dev_addr, dev->dev_addr)) | ||
590 | dev_unicast_delete(dev, vlandev->dev_addr, ETH_ALEN); | ||
591 | |||
592 | /* vlan address was equal to the old address and is different from | ||
593 | * the new address */ | ||
594 | if (!compare_ether_addr(vlandev->dev_addr, vlan->real_dev_addr) && | ||
595 | compare_ether_addr(vlandev->dev_addr, dev->dev_addr)) | ||
596 | dev_unicast_add(dev, vlandev->dev_addr, ETH_ALEN); | ||
597 | |||
598 | memcpy(vlan->real_dev_addr, dev->dev_addr, ETH_ALEN); | ||
606 | } | 599 | } |
607 | 600 | ||
608 | static int vlan_device_event(struct notifier_block *unused, unsigned long event, void *ptr) | 601 | static int vlan_device_event(struct notifier_block *unused, unsigned long event, void *ptr) |
@@ -631,6 +624,17 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
631 | } | 624 | } |
632 | break; | 625 | break; |
633 | 626 | ||
627 | case NETDEV_CHANGEADDR: | ||
628 | /* Adjust unicast filters on underlying device */ | ||
629 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | ||
630 | vlandev = vlan_group_get_device(grp, i); | ||
631 | if (!vlandev) | ||
632 | continue; | ||
633 | |||
634 | vlan_sync_address(dev, vlandev); | ||
635 | } | ||
636 | break; | ||
637 | |||
634 | case NETDEV_DOWN: | 638 | case NETDEV_DOWN: |
635 | /* Put all VLANs for this dev in the down state too. */ | 639 | /* Put all VLANs for this dev in the down state too. */ |
636 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | 640 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { |
@@ -693,9 +697,10 @@ out: | |||
693 | */ | 697 | */ |
694 | static int vlan_ioctl_handler(void __user *arg) | 698 | static int vlan_ioctl_handler(void __user *arg) |
695 | { | 699 | { |
696 | int err = 0; | 700 | int err; |
697 | unsigned short vid = 0; | 701 | unsigned short vid = 0; |
698 | struct vlan_ioctl_args args; | 702 | struct vlan_ioctl_args args; |
703 | struct net_device *dev = NULL; | ||
699 | 704 | ||
700 | if (copy_from_user(&args, arg, sizeof(struct vlan_ioctl_args))) | 705 | if (copy_from_user(&args, arg, sizeof(struct vlan_ioctl_args))) |
701 | return -EFAULT; | 706 | return -EFAULT; |
@@ -708,35 +713,61 @@ static int vlan_ioctl_handler(void __user *arg) | |||
708 | printk(VLAN_DBG "%s: args.cmd: %x\n", __FUNCTION__, args.cmd); | 713 | printk(VLAN_DBG "%s: args.cmd: %x\n", __FUNCTION__, args.cmd); |
709 | #endif | 714 | #endif |
710 | 715 | ||
716 | rtnl_lock(); | ||
717 | |||
718 | switch (args.cmd) { | ||
719 | case SET_VLAN_INGRESS_PRIORITY_CMD: | ||
720 | case SET_VLAN_EGRESS_PRIORITY_CMD: | ||
721 | case SET_VLAN_FLAG_CMD: | ||
722 | case ADD_VLAN_CMD: | ||
723 | case DEL_VLAN_CMD: | ||
724 | case GET_VLAN_REALDEV_NAME_CMD: | ||
725 | case GET_VLAN_VID_CMD: | ||
726 | err = -ENODEV; | ||
727 | dev = __dev_get_by_name(args.device1); | ||
728 | if (!dev) | ||
729 | goto out; | ||
730 | |||
731 | err = -EINVAL; | ||
732 | if (args.cmd != ADD_VLAN_CMD && | ||
733 | !(dev->priv_flags & IFF_802_1Q_VLAN)) | ||
734 | goto out; | ||
735 | } | ||
736 | |||
711 | switch (args.cmd) { | 737 | switch (args.cmd) { |
712 | case SET_VLAN_INGRESS_PRIORITY_CMD: | 738 | case SET_VLAN_INGRESS_PRIORITY_CMD: |
739 | err = -EPERM; | ||
713 | if (!capable(CAP_NET_ADMIN)) | 740 | if (!capable(CAP_NET_ADMIN)) |
714 | return -EPERM; | 741 | break; |
715 | err = vlan_dev_set_ingress_priority(args.device1, | 742 | vlan_dev_set_ingress_priority(dev, |
716 | args.u.skb_priority, | 743 | args.u.skb_priority, |
717 | args.vlan_qos); | 744 | args.vlan_qos); |
718 | break; | 745 | break; |
719 | 746 | ||
720 | case SET_VLAN_EGRESS_PRIORITY_CMD: | 747 | case SET_VLAN_EGRESS_PRIORITY_CMD: |
748 | err = -EPERM; | ||
721 | if (!capable(CAP_NET_ADMIN)) | 749 | if (!capable(CAP_NET_ADMIN)) |
722 | return -EPERM; | 750 | break; |
723 | err = vlan_dev_set_egress_priority(args.device1, | 751 | err = vlan_dev_set_egress_priority(dev, |
724 | args.u.skb_priority, | 752 | args.u.skb_priority, |
725 | args.vlan_qos); | 753 | args.vlan_qos); |
726 | break; | 754 | break; |
727 | 755 | ||
728 | case SET_VLAN_FLAG_CMD: | 756 | case SET_VLAN_FLAG_CMD: |
757 | err = -EPERM; | ||
729 | if (!capable(CAP_NET_ADMIN)) | 758 | if (!capable(CAP_NET_ADMIN)) |
730 | return -EPERM; | 759 | break; |
731 | err = vlan_dev_set_vlan_flag(args.device1, | 760 | err = vlan_dev_set_vlan_flag(dev, |
732 | args.u.flag, | 761 | args.u.flag, |
733 | args.vlan_qos); | 762 | args.vlan_qos); |
734 | break; | 763 | break; |
735 | 764 | ||
736 | case SET_VLAN_NAME_TYPE_CMD: | 765 | case SET_VLAN_NAME_TYPE_CMD: |
766 | err = -EPERM; | ||
737 | if (!capable(CAP_NET_ADMIN)) | 767 | if (!capable(CAP_NET_ADMIN)) |
738 | return -EPERM; | 768 | return -EPERM; |
739 | if (args.u.name_type < VLAN_NAME_TYPE_HIGHEST) { | 769 | if ((args.u.name_type >= 0) && |
770 | (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) { | ||
740 | vlan_name_type = args.u.name_type; | 771 | vlan_name_type = args.u.name_type; |
741 | err = 0; | 772 | err = 0; |
742 | } else { | 773 | } else { |
@@ -745,26 +776,17 @@ static int vlan_ioctl_handler(void __user *arg) | |||
745 | break; | 776 | break; |
746 | 777 | ||
747 | case ADD_VLAN_CMD: | 778 | case ADD_VLAN_CMD: |
779 | err = -EPERM; | ||
748 | if (!capable(CAP_NET_ADMIN)) | 780 | if (!capable(CAP_NET_ADMIN)) |
749 | return -EPERM; | 781 | break; |
750 | /* we have been given the name of the Ethernet Device we want to | 782 | err = register_vlan_device(dev, args.u.VID); |
751 | * talk to: args.dev1 We also have the | ||
752 | * VLAN ID: args.u.VID | ||
753 | */ | ||
754 | if (register_vlan_device(args.device1, args.u.VID)) { | ||
755 | err = 0; | ||
756 | } else { | ||
757 | err = -EINVAL; | ||
758 | } | ||
759 | break; | 783 | break; |
760 | 784 | ||
761 | case DEL_VLAN_CMD: | 785 | case DEL_VLAN_CMD: |
786 | err = -EPERM; | ||
762 | if (!capable(CAP_NET_ADMIN)) | 787 | if (!capable(CAP_NET_ADMIN)) |
763 | return -EPERM; | 788 | break; |
764 | /* Here, the args.dev1 is the actual VLAN we want | 789 | err = unregister_vlan_device(dev); |
765 | * to get rid of. | ||
766 | */ | ||
767 | err = unregister_vlan_device(args.device1); | ||
768 | break; | 790 | break; |
769 | 791 | ||
770 | case GET_VLAN_INGRESS_PRIORITY_CMD: | 792 | case GET_VLAN_INGRESS_PRIORITY_CMD: |
@@ -788,9 +810,7 @@ static int vlan_ioctl_handler(void __user *arg) | |||
788 | err = -EINVAL; | 810 | err = -EINVAL; |
789 | break; | 811 | break; |
790 | case GET_VLAN_REALDEV_NAME_CMD: | 812 | case GET_VLAN_REALDEV_NAME_CMD: |
791 | err = vlan_dev_get_realdev_name(args.device1, args.u.device2); | 813 | vlan_dev_get_realdev_name(dev, args.u.device2); |
792 | if (err) | ||
793 | goto out; | ||
794 | if (copy_to_user(arg, &args, | 814 | if (copy_to_user(arg, &args, |
795 | sizeof(struct vlan_ioctl_args))) { | 815 | sizeof(struct vlan_ioctl_args))) { |
796 | err = -EFAULT; | 816 | err = -EFAULT; |
@@ -798,9 +818,7 @@ static int vlan_ioctl_handler(void __user *arg) | |||
798 | break; | 818 | break; |
799 | 819 | ||
800 | case GET_VLAN_VID_CMD: | 820 | case GET_VLAN_VID_CMD: |
801 | err = vlan_dev_get_vid(args.device1, &vid); | 821 | vlan_dev_get_vid(dev, &vid); |
802 | if (err) | ||
803 | goto out; | ||
804 | args.u.VID = vid; | 822 | args.u.VID = vid; |
805 | if (copy_to_user(arg, &args, | 823 | if (copy_to_user(arg, &args, |
806 | sizeof(struct vlan_ioctl_args))) { | 824 | sizeof(struct vlan_ioctl_args))) { |
@@ -812,9 +830,11 @@ static int vlan_ioctl_handler(void __user *arg) | |||
812 | /* pass on to underlying device instead?? */ | 830 | /* pass on to underlying device instead?? */ |
813 | printk(VLAN_DBG "%s: Unknown VLAN CMD: %x \n", | 831 | printk(VLAN_DBG "%s: Unknown VLAN CMD: %x \n", |
814 | __FUNCTION__, args.cmd); | 832 | __FUNCTION__, args.cmd); |
815 | return -EINVAL; | 833 | err = -EINVAL; |
834 | break; | ||
816 | } | 835 | } |
817 | out: | 836 | out: |
837 | rtnl_unlock(); | ||
818 | return err; | 838 | return err; |
819 | } | 839 | } |
820 | 840 | ||
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h index 1976cdba8f72..7df5b2935579 100644 --- a/net/8021q/vlan.h +++ b/net/8021q/vlan.h | |||
@@ -58,15 +58,28 @@ int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev, | |||
58 | int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev); | 58 | int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev); |
59 | int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev); | 59 | int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev); |
60 | int vlan_dev_change_mtu(struct net_device *dev, int new_mtu); | 60 | int vlan_dev_change_mtu(struct net_device *dev, int new_mtu); |
61 | int vlan_dev_set_mac_address(struct net_device *dev, void* addr); | ||
62 | int vlan_dev_open(struct net_device* dev); | 61 | int vlan_dev_open(struct net_device* dev); |
63 | int vlan_dev_stop(struct net_device* dev); | 62 | int vlan_dev_stop(struct net_device* dev); |
64 | int vlan_dev_ioctl(struct net_device* dev, struct ifreq *ifr, int cmd); | 63 | int vlan_dev_ioctl(struct net_device* dev, struct ifreq *ifr, int cmd); |
65 | int vlan_dev_set_ingress_priority(char* dev_name, __u32 skb_prio, short vlan_prio); | 64 | void vlan_dev_set_ingress_priority(const struct net_device *dev, |
66 | int vlan_dev_set_egress_priority(char* dev_name, __u32 skb_prio, short vlan_prio); | 65 | u32 skb_prio, short vlan_prio); |
67 | int vlan_dev_set_vlan_flag(char* dev_name, __u32 flag, short flag_val); | 66 | int vlan_dev_set_egress_priority(const struct net_device *dev, |
68 | int vlan_dev_get_realdev_name(const char* dev_name, char* result); | 67 | u32 skb_prio, short vlan_prio); |
69 | int vlan_dev_get_vid(const char* dev_name, unsigned short* result); | 68 | int vlan_dev_set_vlan_flag(const struct net_device *dev, |
69 | u32 flag, short flag_val); | ||
70 | void vlan_dev_get_realdev_name(const struct net_device *dev, char *result); | ||
71 | void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result); | ||
72 | void vlan_change_rx_flags(struct net_device *dev, int change); | ||
70 | void vlan_dev_set_multicast_list(struct net_device *vlan_dev); | 73 | void vlan_dev_set_multicast_list(struct net_device *vlan_dev); |
71 | 74 | ||
75 | int vlan_check_real_dev(struct net_device *real_dev, unsigned short vlan_id); | ||
76 | void vlan_setup(struct net_device *dev); | ||
77 | int register_vlan_dev(struct net_device *dev); | ||
78 | int unregister_vlan_device(struct net_device *dev); | ||
79 | |||
80 | int vlan_netlink_init(void); | ||
81 | void vlan_netlink_fini(void); | ||
82 | |||
83 | extern struct rtnl_link_ops vlan_link_ops; | ||
84 | |||
72 | #endif /* !(__BEN_VLAN_802_1Q_INC__) */ | 85 | #endif /* !(__BEN_VLAN_802_1Q_INC__) */ |
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index ec46084f44b4..4d2aa4dd42ac 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -73,7 +73,7 @@ int vlan_dev_rebuild_header(struct sk_buff *skb) | |||
73 | 73 | ||
74 | static inline struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb) | 74 | static inline struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb) |
75 | { | 75 | { |
76 | if (VLAN_DEV_INFO(skb->dev)->flags & 1) { | 76 | if (VLAN_DEV_INFO(skb->dev)->flags & VLAN_FLAG_REORDER_HDR) { |
77 | if (skb_shared(skb) || skb_cloned(skb)) { | 77 | if (skb_shared(skb) || skb_cloned(skb)) { |
78 | struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC); | 78 | struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC); |
79 | kfree_skb(skb); | 79 | kfree_skb(skb); |
@@ -350,7 +350,8 @@ int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev, | |||
350 | * header shuffling in the hard_start_xmit. Users can turn off this | 350 | * header shuffling in the hard_start_xmit. Users can turn off this |
351 | * REORDER behaviour with the vconfig tool. | 351 | * REORDER behaviour with the vconfig tool. |
352 | */ | 352 | */ |
353 | build_vlan_header = ((VLAN_DEV_INFO(dev)->flags & 1) == 0); | 353 | if (!(VLAN_DEV_INFO(dev)->flags & VLAN_FLAG_REORDER_HDR)) |
354 | build_vlan_header = 1; | ||
354 | 355 | ||
355 | if (build_vlan_header) { | 356 | if (build_vlan_header) { |
356 | vhdr = (struct vlan_hdr *) skb_push(skb, VLAN_HLEN); | 357 | vhdr = (struct vlan_hdr *) skb_push(skb, VLAN_HLEN); |
@@ -534,272 +535,123 @@ int vlan_dev_change_mtu(struct net_device *dev, int new_mtu) | |||
534 | return 0; | 535 | return 0; |
535 | } | 536 | } |
536 | 537 | ||
537 | int vlan_dev_set_ingress_priority(char *dev_name, __u32 skb_prio, short vlan_prio) | 538 | void vlan_dev_set_ingress_priority(const struct net_device *dev, |
539 | u32 skb_prio, short vlan_prio) | ||
538 | { | 540 | { |
539 | struct net_device *dev = dev_get_by_name(dev_name); | 541 | struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev); |
540 | 542 | ||
541 | if (dev) { | 543 | if (vlan->ingress_priority_map[vlan_prio & 0x7] && !skb_prio) |
542 | if (dev->priv_flags & IFF_802_1Q_VLAN) { | 544 | vlan->nr_ingress_mappings--; |
543 | /* see if a priority mapping exists.. */ | 545 | else if (!vlan->ingress_priority_map[vlan_prio & 0x7] && skb_prio) |
544 | VLAN_DEV_INFO(dev)->ingress_priority_map[vlan_prio & 0x7] = skb_prio; | 546 | vlan->nr_ingress_mappings++; |
545 | dev_put(dev); | ||
546 | return 0; | ||
547 | } | ||
548 | 547 | ||
549 | dev_put(dev); | 548 | vlan->ingress_priority_map[vlan_prio & 0x7] = skb_prio; |
550 | } | ||
551 | return -EINVAL; | ||
552 | } | 549 | } |
553 | 550 | ||
554 | int vlan_dev_set_egress_priority(char *dev_name, __u32 skb_prio, short vlan_prio) | 551 | int vlan_dev_set_egress_priority(const struct net_device *dev, |
552 | u32 skb_prio, short vlan_prio) | ||
555 | { | 553 | { |
556 | struct net_device *dev = dev_get_by_name(dev_name); | 554 | struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev); |
557 | struct vlan_priority_tci_mapping *mp = NULL; | 555 | struct vlan_priority_tci_mapping *mp = NULL; |
558 | struct vlan_priority_tci_mapping *np; | 556 | struct vlan_priority_tci_mapping *np; |
557 | u32 vlan_qos = (vlan_prio << 13) & 0xE000; | ||
559 | 558 | ||
560 | if (dev) { | 559 | /* See if a priority mapping exists.. */ |
561 | if (dev->priv_flags & IFF_802_1Q_VLAN) { | 560 | mp = vlan->egress_priority_map[skb_prio & 0xF]; |
562 | /* See if a priority mapping exists.. */ | 561 | while (mp) { |
563 | mp = VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF]; | 562 | if (mp->priority == skb_prio) { |
564 | while (mp) { | 563 | if (mp->vlan_qos && !vlan_qos) |
565 | if (mp->priority == skb_prio) { | 564 | vlan->nr_egress_mappings--; |
566 | mp->vlan_qos = ((vlan_prio << 13) & 0xE000); | 565 | else if (!mp->vlan_qos && vlan_qos) |
567 | dev_put(dev); | 566 | vlan->nr_egress_mappings++; |
568 | return 0; | 567 | mp->vlan_qos = vlan_qos; |
569 | } | 568 | return 0; |
570 | mp = mp->next; | ||
571 | } | ||
572 | |||
573 | /* Create a new mapping then. */ | ||
574 | mp = VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF]; | ||
575 | np = kmalloc(sizeof(struct vlan_priority_tci_mapping), GFP_KERNEL); | ||
576 | if (np) { | ||
577 | np->next = mp; | ||
578 | np->priority = skb_prio; | ||
579 | np->vlan_qos = ((vlan_prio << 13) & 0xE000); | ||
580 | VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF] = np; | ||
581 | dev_put(dev); | ||
582 | return 0; | ||
583 | } else { | ||
584 | dev_put(dev); | ||
585 | return -ENOBUFS; | ||
586 | } | ||
587 | } | ||
588 | dev_put(dev); | ||
589 | } | ||
590 | return -EINVAL; | ||
591 | } | ||
592 | |||
593 | /* Flags are defined in the vlan_dev_info class in include/linux/if_vlan.h file. */ | ||
594 | int vlan_dev_set_vlan_flag(char *dev_name, __u32 flag, short flag_val) | ||
595 | { | ||
596 | struct net_device *dev = dev_get_by_name(dev_name); | ||
597 | |||
598 | if (dev) { | ||
599 | if (dev->priv_flags & IFF_802_1Q_VLAN) { | ||
600 | /* verify flag is supported */ | ||
601 | if (flag == 1) { | ||
602 | if (flag_val) { | ||
603 | VLAN_DEV_INFO(dev)->flags |= 1; | ||
604 | } else { | ||
605 | VLAN_DEV_INFO(dev)->flags &= ~1; | ||
606 | } | ||
607 | dev_put(dev); | ||
608 | return 0; | ||
609 | } else { | ||
610 | printk(KERN_ERR "%s: flag %i is not valid.\n", | ||
611 | __FUNCTION__, (int)(flag)); | ||
612 | dev_put(dev); | ||
613 | return -EINVAL; | ||
614 | } | ||
615 | } else { | ||
616 | printk(KERN_ERR | ||
617 | "%s: %s is not a vlan device, priv_flags: %hX.\n", | ||
618 | __FUNCTION__, dev->name, dev->priv_flags); | ||
619 | dev_put(dev); | ||
620 | } | 569 | } |
621 | } else { | 570 | mp = mp->next; |
622 | printk(KERN_ERR "%s: Could not find device: %s\n", | ||
623 | __FUNCTION__, dev_name); | ||
624 | } | 571 | } |
625 | 572 | ||
626 | return -EINVAL; | 573 | /* Create a new mapping then. */ |
627 | } | 574 | mp = vlan->egress_priority_map[skb_prio & 0xF]; |
628 | 575 | np = kmalloc(sizeof(struct vlan_priority_tci_mapping), GFP_KERNEL); | |
629 | 576 | if (!np) | |
630 | int vlan_dev_get_realdev_name(const char *dev_name, char* result) | 577 | return -ENOBUFS; |
631 | { | 578 | |
632 | struct net_device *dev = dev_get_by_name(dev_name); | 579 | np->next = mp; |
633 | int rv = 0; | 580 | np->priority = skb_prio; |
634 | if (dev) { | 581 | np->vlan_qos = vlan_qos; |
635 | if (dev->priv_flags & IFF_802_1Q_VLAN) { | 582 | vlan->egress_priority_map[skb_prio & 0xF] = np; |
636 | strncpy(result, VLAN_DEV_INFO(dev)->real_dev->name, 23); | 583 | if (vlan_qos) |
637 | rv = 0; | 584 | vlan->nr_egress_mappings++; |
638 | } else { | 585 | return 0; |
639 | rv = -EINVAL; | ||
640 | } | ||
641 | dev_put(dev); | ||
642 | } else { | ||
643 | rv = -ENODEV; | ||
644 | } | ||
645 | return rv; | ||
646 | } | 586 | } |
647 | 587 | ||
648 | int vlan_dev_get_vid(const char *dev_name, unsigned short* result) | 588 | /* Flags are defined in the vlan_flags enum in include/linux/if_vlan.h file. */ |
589 | int vlan_dev_set_vlan_flag(const struct net_device *dev, | ||
590 | u32 flag, short flag_val) | ||
649 | { | 591 | { |
650 | struct net_device *dev = dev_get_by_name(dev_name); | 592 | /* verify flag is supported */ |
651 | int rv = 0; | 593 | if (flag == VLAN_FLAG_REORDER_HDR) { |
652 | if (dev) { | 594 | if (flag_val) { |
653 | if (dev->priv_flags & IFF_802_1Q_VLAN) { | 595 | VLAN_DEV_INFO(dev)->flags |= VLAN_FLAG_REORDER_HDR; |
654 | *result = VLAN_DEV_INFO(dev)->vlan_id; | ||
655 | rv = 0; | ||
656 | } else { | 596 | } else { |
657 | rv = -EINVAL; | 597 | VLAN_DEV_INFO(dev)->flags &= ~VLAN_FLAG_REORDER_HDR; |
658 | } | 598 | } |
659 | dev_put(dev); | 599 | return 0; |
660 | } else { | ||
661 | rv = -ENODEV; | ||
662 | } | 600 | } |
663 | return rv; | 601 | printk(KERN_ERR "%s: flag %i is not valid.\n", __FUNCTION__, flag); |
602 | return -EINVAL; | ||
664 | } | 603 | } |
665 | 604 | ||
666 | 605 | void vlan_dev_get_realdev_name(const struct net_device *dev, char *result) | |
667 | int vlan_dev_set_mac_address(struct net_device *dev, void *addr_struct_p) | ||
668 | { | 606 | { |
669 | struct sockaddr *addr = (struct sockaddr *)(addr_struct_p); | 607 | strncpy(result, VLAN_DEV_INFO(dev)->real_dev->name, 23); |
670 | int i; | ||
671 | |||
672 | if (netif_running(dev)) | ||
673 | return -EBUSY; | ||
674 | |||
675 | memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); | ||
676 | |||
677 | printk("%s: Setting MAC address to ", dev->name); | ||
678 | for (i = 0; i < 6; i++) | ||
679 | printk(" %2.2x", dev->dev_addr[i]); | ||
680 | printk(".\n"); | ||
681 | |||
682 | if (memcmp(VLAN_DEV_INFO(dev)->real_dev->dev_addr, | ||
683 | dev->dev_addr, | ||
684 | dev->addr_len) != 0) { | ||
685 | if (!(VLAN_DEV_INFO(dev)->real_dev->flags & IFF_PROMISC)) { | ||
686 | int flgs = VLAN_DEV_INFO(dev)->real_dev->flags; | ||
687 | |||
688 | /* Increment our in-use promiscuity counter */ | ||
689 | dev_set_promiscuity(VLAN_DEV_INFO(dev)->real_dev, 1); | ||
690 | |||
691 | /* Make PROMISC visible to the user. */ | ||
692 | flgs |= IFF_PROMISC; | ||
693 | printk("VLAN (%s): Setting underlying device (%s) to promiscious mode.\n", | ||
694 | dev->name, VLAN_DEV_INFO(dev)->real_dev->name); | ||
695 | dev_change_flags(VLAN_DEV_INFO(dev)->real_dev, flgs); | ||
696 | } | ||
697 | } else { | ||
698 | printk("VLAN (%s): Underlying device (%s) has same MAC, not checking promiscious mode.\n", | ||
699 | dev->name, VLAN_DEV_INFO(dev)->real_dev->name); | ||
700 | } | ||
701 | |||
702 | return 0; | ||
703 | } | 608 | } |
704 | 609 | ||
705 | static inline int vlan_dmi_equals(struct dev_mc_list *dmi1, | 610 | void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result) |
706 | struct dev_mc_list *dmi2) | ||
707 | { | 611 | { |
708 | return ((dmi1->dmi_addrlen == dmi2->dmi_addrlen) && | 612 | *result = VLAN_DEV_INFO(dev)->vlan_id; |
709 | (memcmp(dmi1->dmi_addr, dmi2->dmi_addr, dmi1->dmi_addrlen) == 0)); | ||
710 | } | 613 | } |
711 | 614 | ||
712 | /** dmi is a single entry into a dev_mc_list, a single node. mc_list is | 615 | int vlan_dev_open(struct net_device *dev) |
713 | * an entire list, and we'll iterate through it. | ||
714 | */ | ||
715 | static int vlan_should_add_mc(struct dev_mc_list *dmi, struct dev_mc_list *mc_list) | ||
716 | { | 616 | { |
717 | struct dev_mc_list *idmi; | 617 | struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev); |
718 | 618 | struct net_device *real_dev = vlan->real_dev; | |
719 | for (idmi = mc_list; idmi != NULL; ) { | 619 | int err; |
720 | if (vlan_dmi_equals(dmi, idmi)) { | ||
721 | if (dmi->dmi_users > idmi->dmi_users) | ||
722 | return 1; | ||
723 | else | ||
724 | return 0; | ||
725 | } else { | ||
726 | idmi = idmi->next; | ||
727 | } | ||
728 | } | ||
729 | |||
730 | return 1; | ||
731 | } | ||
732 | 620 | ||
733 | static inline void vlan_destroy_mc_list(struct dev_mc_list *mc_list) | 621 | if (!(real_dev->flags & IFF_UP)) |
734 | { | 622 | return -ENETDOWN; |
735 | struct dev_mc_list *dmi = mc_list; | ||
736 | struct dev_mc_list *next; | ||
737 | 623 | ||
738 | while(dmi) { | 624 | if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) { |
739 | next = dmi->next; | 625 | err = dev_unicast_add(real_dev, dev->dev_addr, ETH_ALEN); |
740 | kfree(dmi); | 626 | if (err < 0) |
741 | dmi = next; | 627 | return err; |
742 | } | 628 | } |
743 | } | 629 | memcpy(vlan->real_dev_addr, real_dev->dev_addr, ETH_ALEN); |
744 | |||
745 | static void vlan_copy_mc_list(struct dev_mc_list *mc_list, struct vlan_dev_info *vlan_info) | ||
746 | { | ||
747 | struct dev_mc_list *dmi, *new_dmi; | ||
748 | 630 | ||
749 | vlan_destroy_mc_list(vlan_info->old_mc_list); | 631 | if (dev->flags & IFF_ALLMULTI) |
750 | vlan_info->old_mc_list = NULL; | 632 | dev_set_allmulti(real_dev, 1); |
633 | if (dev->flags & IFF_PROMISC) | ||
634 | dev_set_promiscuity(real_dev, 1); | ||
751 | 635 | ||
752 | for (dmi = mc_list; dmi != NULL; dmi = dmi->next) { | 636 | return 0; |
753 | new_dmi = kmalloc(sizeof(*new_dmi), GFP_ATOMIC); | ||
754 | if (new_dmi == NULL) { | ||
755 | printk(KERN_ERR "vlan: cannot allocate memory. " | ||
756 | "Multicast may not work properly from now.\n"); | ||
757 | return; | ||
758 | } | ||
759 | |||
760 | /* Copy whole structure, then make new 'next' pointer */ | ||
761 | *new_dmi = *dmi; | ||
762 | new_dmi->next = vlan_info->old_mc_list; | ||
763 | vlan_info->old_mc_list = new_dmi; | ||
764 | } | ||
765 | } | 637 | } |
766 | 638 | ||
767 | static void vlan_flush_mc_list(struct net_device *dev) | 639 | int vlan_dev_stop(struct net_device *dev) |
768 | { | 640 | { |
769 | struct dev_mc_list *dmi = dev->mc_list; | 641 | struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev; |
770 | |||
771 | while (dmi) { | ||
772 | printk(KERN_DEBUG "%s: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from vlan interface\n", | ||
773 | dev->name, | ||
774 | dmi->dmi_addr[0], | ||
775 | dmi->dmi_addr[1], | ||
776 | dmi->dmi_addr[2], | ||
777 | dmi->dmi_addr[3], | ||
778 | dmi->dmi_addr[4], | ||
779 | dmi->dmi_addr[5]); | ||
780 | dev_mc_delete(dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); | ||
781 | dmi = dev->mc_list; | ||
782 | } | ||
783 | 642 | ||
784 | /* dev->mc_list is NULL by the time we get here. */ | 643 | dev_mc_unsync(real_dev, dev); |
785 | vlan_destroy_mc_list(VLAN_DEV_INFO(dev)->old_mc_list); | 644 | if (dev->flags & IFF_ALLMULTI) |
786 | VLAN_DEV_INFO(dev)->old_mc_list = NULL; | 645 | dev_set_allmulti(real_dev, -1); |
787 | } | 646 | if (dev->flags & IFF_PROMISC) |
647 | dev_set_promiscuity(real_dev, -1); | ||
788 | 648 | ||
789 | int vlan_dev_open(struct net_device *dev) | 649 | if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) |
790 | { | 650 | dev_unicast_delete(real_dev, dev->dev_addr, dev->addr_len); |
791 | if (!(VLAN_DEV_INFO(dev)->real_dev->flags & IFF_UP)) | ||
792 | return -ENETDOWN; | ||
793 | 651 | ||
794 | return 0; | 652 | return 0; |
795 | } | 653 | } |
796 | 654 | ||
797 | int vlan_dev_stop(struct net_device *dev) | ||
798 | { | ||
799 | vlan_flush_mc_list(dev); | ||
800 | return 0; | ||
801 | } | ||
802 | |||
803 | int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | 655 | int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) |
804 | { | 656 | { |
805 | struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev; | 657 | struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev; |
@@ -827,68 +679,18 @@ int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
827 | return err; | 679 | return err; |
828 | } | 680 | } |
829 | 681 | ||
830 | /** Taken from Gleb + Lennert's VLAN code, and modified... */ | 682 | void vlan_change_rx_flags(struct net_device *dev, int change) |
831 | void vlan_dev_set_multicast_list(struct net_device *vlan_dev) | ||
832 | { | 683 | { |
833 | struct dev_mc_list *dmi; | 684 | struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev; |
834 | struct net_device *real_dev; | ||
835 | int inc; | ||
836 | |||
837 | if (vlan_dev && (vlan_dev->priv_flags & IFF_802_1Q_VLAN)) { | ||
838 | /* Then it's a real vlan device, as far as we can tell.. */ | ||
839 | real_dev = VLAN_DEV_INFO(vlan_dev)->real_dev; | ||
840 | |||
841 | /* compare the current promiscuity to the last promisc we had.. */ | ||
842 | inc = vlan_dev->promiscuity - VLAN_DEV_INFO(vlan_dev)->old_promiscuity; | ||
843 | if (inc) { | ||
844 | printk(KERN_INFO "%s: dev_set_promiscuity(master, %d)\n", | ||
845 | vlan_dev->name, inc); | ||
846 | dev_set_promiscuity(real_dev, inc); /* found in dev.c */ | ||
847 | VLAN_DEV_INFO(vlan_dev)->old_promiscuity = vlan_dev->promiscuity; | ||
848 | } | ||
849 | |||
850 | inc = vlan_dev->allmulti - VLAN_DEV_INFO(vlan_dev)->old_allmulti; | ||
851 | if (inc) { | ||
852 | printk(KERN_INFO "%s: dev_set_allmulti(master, %d)\n", | ||
853 | vlan_dev->name, inc); | ||
854 | dev_set_allmulti(real_dev, inc); /* dev.c */ | ||
855 | VLAN_DEV_INFO(vlan_dev)->old_allmulti = vlan_dev->allmulti; | ||
856 | } | ||
857 | |||
858 | /* looking for addresses to add to master's list */ | ||
859 | for (dmi = vlan_dev->mc_list; dmi != NULL; dmi = dmi->next) { | ||
860 | if (vlan_should_add_mc(dmi, VLAN_DEV_INFO(vlan_dev)->old_mc_list)) { | ||
861 | dev_mc_add(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); | ||
862 | printk(KERN_DEBUG "%s: add %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address to master interface\n", | ||
863 | vlan_dev->name, | ||
864 | dmi->dmi_addr[0], | ||
865 | dmi->dmi_addr[1], | ||
866 | dmi->dmi_addr[2], | ||
867 | dmi->dmi_addr[3], | ||
868 | dmi->dmi_addr[4], | ||
869 | dmi->dmi_addr[5]); | ||
870 | } | ||
871 | } | ||
872 | 685 | ||
873 | /* looking for addresses to delete from master's list */ | 686 | if (change & IFF_ALLMULTI) |
874 | for (dmi = VLAN_DEV_INFO(vlan_dev)->old_mc_list; dmi != NULL; dmi = dmi->next) { | 687 | dev_set_allmulti(real_dev, dev->flags & IFF_ALLMULTI ? 1 : -1); |
875 | if (vlan_should_add_mc(dmi, vlan_dev->mc_list)) { | 688 | if (change & IFF_PROMISC) |
876 | /* if we think we should add it to the new list, then we should really | 689 | dev_set_promiscuity(real_dev, dev->flags & IFF_PROMISC ? 1 : -1); |
877 | * delete it from the real list on the underlying device. | 690 | } |
878 | */ | ||
879 | dev_mc_delete(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); | ||
880 | printk(KERN_DEBUG "%s: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from master interface\n", | ||
881 | vlan_dev->name, | ||
882 | dmi->dmi_addr[0], | ||
883 | dmi->dmi_addr[1], | ||
884 | dmi->dmi_addr[2], | ||
885 | dmi->dmi_addr[3], | ||
886 | dmi->dmi_addr[4], | ||
887 | dmi->dmi_addr[5]); | ||
888 | } | ||
889 | } | ||
890 | 691 | ||
891 | /* save multicast list */ | 692 | /** Taken from Gleb + Lennert's VLAN code, and modified... */ |
892 | vlan_copy_mc_list(vlan_dev->mc_list, VLAN_DEV_INFO(vlan_dev)); | 693 | void vlan_dev_set_multicast_list(struct net_device *vlan_dev) |
893 | } | 694 | { |
695 | dev_mc_sync(VLAN_DEV_INFO(vlan_dev)->real_dev, vlan_dev); | ||
894 | } | 696 | } |
diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c new file mode 100644 index 000000000000..6cdd1e015e2d --- /dev/null +++ b/net/8021q/vlan_netlink.c | |||
@@ -0,0 +1,243 @@ | |||
1 | /* | ||
2 | * VLAN netlink control interface | ||
3 | * | ||
4 | * Copyright (c) 2007 Patrick McHardy <kaber@trash.net> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/netdevice.h> | ||
13 | #include <linux/if_vlan.h> | ||
14 | #include <net/netlink.h> | ||
15 | #include <net/rtnetlink.h> | ||
16 | #include "vlan.h" | ||
17 | |||
18 | |||
19 | static const struct nla_policy vlan_policy[IFLA_VLAN_MAX + 1] = { | ||
20 | [IFLA_VLAN_ID] = { .type = NLA_U16 }, | ||
21 | [IFLA_VLAN_FLAGS] = { .len = sizeof(struct ifla_vlan_flags) }, | ||
22 | [IFLA_VLAN_EGRESS_QOS] = { .type = NLA_NESTED }, | ||
23 | [IFLA_VLAN_INGRESS_QOS] = { .type = NLA_NESTED }, | ||
24 | }; | ||
25 | |||
26 | static const struct nla_policy vlan_map_policy[IFLA_VLAN_QOS_MAX + 1] = { | ||
27 | [IFLA_VLAN_QOS_MAPPING] = { .len = sizeof(struct ifla_vlan_qos_mapping) }, | ||
28 | }; | ||
29 | |||
30 | |||
31 | static inline int vlan_validate_qos_map(struct nlattr *attr) | ||
32 | { | ||
33 | if (!attr) | ||
34 | return 0; | ||
35 | return nla_validate_nested(attr, IFLA_VLAN_QOS_MAX, vlan_map_policy); | ||
36 | } | ||
37 | |||
38 | static int vlan_validate(struct nlattr *tb[], struct nlattr *data[]) | ||
39 | { | ||
40 | struct ifla_vlan_flags *flags; | ||
41 | u16 id; | ||
42 | int err; | ||
43 | |||
44 | if (tb[IFLA_ADDRESS]) { | ||
45 | if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) | ||
46 | return -EINVAL; | ||
47 | if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) | ||
48 | return -EADDRNOTAVAIL; | ||
49 | } | ||
50 | |||
51 | if (!data) | ||
52 | return -EINVAL; | ||
53 | |||
54 | if (data[IFLA_VLAN_ID]) { | ||
55 | id = nla_get_u16(data[IFLA_VLAN_ID]); | ||
56 | if (id >= VLAN_VID_MASK) | ||
57 | return -ERANGE; | ||
58 | } | ||
59 | if (data[IFLA_VLAN_FLAGS]) { | ||
60 | flags = nla_data(data[IFLA_VLAN_FLAGS]); | ||
61 | if ((flags->flags & flags->mask) & ~VLAN_FLAG_REORDER_HDR) | ||
62 | return -EINVAL; | ||
63 | } | ||
64 | |||
65 | err = vlan_validate_qos_map(data[IFLA_VLAN_INGRESS_QOS]); | ||
66 | if (err < 0) | ||
67 | return err; | ||
68 | err = vlan_validate_qos_map(data[IFLA_VLAN_EGRESS_QOS]); | ||
69 | if (err < 0) | ||
70 | return err; | ||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static int vlan_changelink(struct net_device *dev, | ||
75 | struct nlattr *tb[], struct nlattr *data[]) | ||
76 | { | ||
77 | struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev); | ||
78 | struct ifla_vlan_flags *flags; | ||
79 | struct ifla_vlan_qos_mapping *m; | ||
80 | struct nlattr *attr; | ||
81 | int rem; | ||
82 | |||
83 | if (data[IFLA_VLAN_FLAGS]) { | ||
84 | flags = nla_data(data[IFLA_VLAN_FLAGS]); | ||
85 | vlan->flags = (vlan->flags & ~flags->mask) | | ||
86 | (flags->flags & flags->mask); | ||
87 | } | ||
88 | if (data[IFLA_VLAN_INGRESS_QOS]) { | ||
89 | nla_for_each_nested(attr, data[IFLA_VLAN_INGRESS_QOS], rem) { | ||
90 | m = nla_data(attr); | ||
91 | vlan_dev_set_ingress_priority(dev, m->to, m->from); | ||
92 | } | ||
93 | } | ||
94 | if (data[IFLA_VLAN_EGRESS_QOS]) { | ||
95 | nla_for_each_nested(attr, data[IFLA_VLAN_EGRESS_QOS], rem) { | ||
96 | m = nla_data(attr); | ||
97 | vlan_dev_set_egress_priority(dev, m->from, m->to); | ||
98 | } | ||
99 | } | ||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static int vlan_newlink(struct net_device *dev, | ||
104 | struct nlattr *tb[], struct nlattr *data[]) | ||
105 | { | ||
106 | struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev); | ||
107 | struct net_device *real_dev; | ||
108 | int err; | ||
109 | |||
110 | if (!data[IFLA_VLAN_ID]) | ||
111 | return -EINVAL; | ||
112 | |||
113 | if (!tb[IFLA_LINK]) | ||
114 | return -EINVAL; | ||
115 | real_dev = __dev_get_by_index(nla_get_u32(tb[IFLA_LINK])); | ||
116 | if (!real_dev) | ||
117 | return -ENODEV; | ||
118 | |||
119 | vlan->vlan_id = nla_get_u16(data[IFLA_VLAN_ID]); | ||
120 | vlan->real_dev = real_dev; | ||
121 | vlan->flags = VLAN_FLAG_REORDER_HDR; | ||
122 | |||
123 | err = vlan_check_real_dev(real_dev, vlan->vlan_id); | ||
124 | if (err < 0) | ||
125 | return err; | ||
126 | |||
127 | if (!tb[IFLA_MTU]) | ||
128 | dev->mtu = real_dev->mtu; | ||
129 | else if (dev->mtu > real_dev->mtu) | ||
130 | return -EINVAL; | ||
131 | |||
132 | err = vlan_changelink(dev, tb, data); | ||
133 | if (err < 0) | ||
134 | return err; | ||
135 | |||
136 | return register_vlan_dev(dev); | ||
137 | } | ||
138 | |||
139 | static void vlan_dellink(struct net_device *dev) | ||
140 | { | ||
141 | unregister_vlan_device(dev); | ||
142 | } | ||
143 | |||
144 | static inline size_t vlan_qos_map_size(unsigned int n) | ||
145 | { | ||
146 | if (n == 0) | ||
147 | return 0; | ||
148 | /* IFLA_VLAN_{EGRESS,INGRESS}_QOS + n * IFLA_VLAN_QOS_MAPPING */ | ||
149 | return nla_total_size(sizeof(struct nlattr)) + | ||
150 | nla_total_size(sizeof(struct ifla_vlan_qos_mapping)) * n; | ||
151 | } | ||
152 | |||
153 | static size_t vlan_get_size(const struct net_device *dev) | ||
154 | { | ||
155 | struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev); | ||
156 | |||
157 | return nla_total_size(2) + /* IFLA_VLAN_ID */ | ||
158 | vlan_qos_map_size(vlan->nr_ingress_mappings) + | ||
159 | vlan_qos_map_size(vlan->nr_egress_mappings); | ||
160 | } | ||
161 | |||
162 | static int vlan_fill_info(struct sk_buff *skb, const struct net_device *dev) | ||
163 | { | ||
164 | struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev); | ||
165 | struct vlan_priority_tci_mapping *pm; | ||
166 | struct ifla_vlan_flags f; | ||
167 | struct ifla_vlan_qos_mapping m; | ||
168 | struct nlattr *nest; | ||
169 | unsigned int i; | ||
170 | |||
171 | NLA_PUT_U16(skb, IFLA_VLAN_ID, VLAN_DEV_INFO(dev)->vlan_id); | ||
172 | if (vlan->flags) { | ||
173 | f.flags = vlan->flags; | ||
174 | f.mask = ~0; | ||
175 | NLA_PUT(skb, IFLA_VLAN_FLAGS, sizeof(f), &f); | ||
176 | } | ||
177 | if (vlan->nr_ingress_mappings) { | ||
178 | nest = nla_nest_start(skb, IFLA_VLAN_INGRESS_QOS); | ||
179 | if (nest == NULL) | ||
180 | goto nla_put_failure; | ||
181 | |||
182 | for (i = 0; i < ARRAY_SIZE(vlan->ingress_priority_map); i++) { | ||
183 | if (!vlan->ingress_priority_map[i]) | ||
184 | continue; | ||
185 | |||
186 | m.from = i; | ||
187 | m.to = vlan->ingress_priority_map[i]; | ||
188 | NLA_PUT(skb, IFLA_VLAN_QOS_MAPPING, | ||
189 | sizeof(m), &m); | ||
190 | } | ||
191 | nla_nest_end(skb, nest); | ||
192 | } | ||
193 | |||
194 | if (vlan->nr_egress_mappings) { | ||
195 | nest = nla_nest_start(skb, IFLA_VLAN_EGRESS_QOS); | ||
196 | if (nest == NULL) | ||
197 | goto nla_put_failure; | ||
198 | |||
199 | for (i = 0; i < ARRAY_SIZE(vlan->egress_priority_map); i++) { | ||
200 | for (pm = vlan->egress_priority_map[i]; pm; | ||
201 | pm = pm->next) { | ||
202 | if (!pm->vlan_qos) | ||
203 | continue; | ||
204 | |||
205 | m.from = pm->priority; | ||
206 | m.to = (pm->vlan_qos >> 13) & 0x7; | ||
207 | NLA_PUT(skb, IFLA_VLAN_QOS_MAPPING, | ||
208 | sizeof(m), &m); | ||
209 | } | ||
210 | } | ||
211 | nla_nest_end(skb, nest); | ||
212 | } | ||
213 | return 0; | ||
214 | |||
215 | nla_put_failure: | ||
216 | return -EMSGSIZE; | ||
217 | } | ||
218 | |||
219 | struct rtnl_link_ops vlan_link_ops __read_mostly = { | ||
220 | .kind = "vlan", | ||
221 | .maxtype = IFLA_VLAN_MAX, | ||
222 | .policy = vlan_policy, | ||
223 | .priv_size = sizeof(struct vlan_dev_info), | ||
224 | .setup = vlan_setup, | ||
225 | .validate = vlan_validate, | ||
226 | .newlink = vlan_newlink, | ||
227 | .changelink = vlan_changelink, | ||
228 | .dellink = vlan_dellink, | ||
229 | .get_size = vlan_get_size, | ||
230 | .fill_info = vlan_fill_info, | ||
231 | }; | ||
232 | |||
233 | int __init vlan_netlink_init(void) | ||
234 | { | ||
235 | return rtnl_link_register(&vlan_link_ops); | ||
236 | } | ||
237 | |||
238 | void __exit vlan_netlink_fini(void) | ||
239 | { | ||
240 | rtnl_link_unregister(&vlan_link_ops); | ||
241 | } | ||
242 | |||
243 | MODULE_ALIAS_RTNL_LINK("vlan"); | ||
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c index d216a64421cd..c0040c9064a1 100644 --- a/net/8021q/vlanproc.c +++ b/net/8021q/vlanproc.c | |||
@@ -69,7 +69,7 @@ static const char name_conf[] = "config"; | |||
69 | * Generic /proc/net/vlan/<file> file and inode operations | 69 | * Generic /proc/net/vlan/<file> file and inode operations |
70 | */ | 70 | */ |
71 | 71 | ||
72 | static struct seq_operations vlan_seq_ops = { | 72 | static const struct seq_operations vlan_seq_ops = { |
73 | .start = vlan_seq_start, | 73 | .start = vlan_seq_start, |
74 | .next = vlan_seq_next, | 74 | .next = vlan_seq_next, |
75 | .stop = vlan_seq_stop, | 75 | .stop = vlan_seq_stop, |
@@ -342,7 +342,7 @@ static int vlandev_seq_show(struct seq_file *seq, void *offset) | |||
342 | seq_printf(seq, "Device: %s", dev_info->real_dev->name); | 342 | seq_printf(seq, "Device: %s", dev_info->real_dev->name); |
343 | /* now show all PRIORITY mappings relating to this VLAN */ | 343 | /* now show all PRIORITY mappings relating to this VLAN */ |
344 | seq_printf(seq, | 344 | seq_printf(seq, |
345 | "\nINGRESS priority mappings: 0:%lu 1:%lu 2:%lu 3:%lu 4:%lu 5:%lu 6:%lu 7:%lu\n", | 345 | "\nINGRESS priority mappings: 0:%u 1:%u 2:%u 3:%u 4:%u 5:%u 6:%u 7:%u\n", |
346 | dev_info->ingress_priority_map[0], | 346 | dev_info->ingress_priority_map[0], |
347 | dev_info->ingress_priority_map[1], | 347 | dev_info->ingress_priority_map[1], |
348 | dev_info->ingress_priority_map[2], | 348 | dev_info->ingress_priority_map[2], |
@@ -357,7 +357,7 @@ static int vlandev_seq_show(struct seq_file *seq, void *offset) | |||
357 | const struct vlan_priority_tci_mapping *mp | 357 | const struct vlan_priority_tci_mapping *mp |
358 | = dev_info->egress_priority_map[i]; | 358 | = dev_info->egress_priority_map[i]; |
359 | while (mp) { | 359 | while (mp) { |
360 | seq_printf(seq, "%lu:%hu ", | 360 | seq_printf(seq, "%u:%hu ", |
361 | mp->priority, ((mp->vlan_qos >> 13) & 0x7)); | 361 | mp->priority, ((mp->vlan_qos >> 13) & 0x7)); |
362 | mp = mp->next; | 362 | mp = mp->next; |
363 | } | 363 | } |
diff --git a/net/9p/Kconfig b/net/9p/Kconfig new file mode 100644 index 000000000000..66821cd64a76 --- /dev/null +++ b/net/9p/Kconfig | |||
@@ -0,0 +1,21 @@ | |||
1 | # | ||
2 | # 9P protocol configuration | ||
3 | # | ||
4 | |||
5 | menuconfig NET_9P | ||
6 | depends on NET && EXPERIMENTAL | ||
7 | tristate "Plan 9 Resource Sharing Support (9P2000) (Experimental)" | ||
8 | help | ||
9 | If you say Y here, you will get experimental support for | ||
10 | Plan 9 resource sharing via the 9P2000 protocol. | ||
11 | |||
12 | See <http://v9fs.sf.net> for more information. | ||
13 | |||
14 | If unsure, say N. | ||
15 | |||
16 | config NET_9P_DEBUG | ||
17 | bool "Debug information" | ||
18 | depends on NET_9P | ||
19 | help | ||
20 | Say Y if you want the 9P subsistem to log debug information. | ||
21 | |||
diff --git a/net/9p/Makefile b/net/9p/Makefile new file mode 100644 index 000000000000..85b3a7838acf --- /dev/null +++ b/net/9p/Makefile | |||
@@ -0,0 +1,13 @@ | |||
1 | obj-$(CONFIG_NET_9P) := 9pnet.o | ||
2 | |||
3 | 9pnet-objs := \ | ||
4 | mod.o \ | ||
5 | trans_fd.o \ | ||
6 | mux.o \ | ||
7 | client.o \ | ||
8 | conv.o \ | ||
9 | error.o \ | ||
10 | fcprint.o \ | ||
11 | util.o \ | ||
12 | |||
13 | 9pnet-$(CONFIG_SYSCTL) += sysctl.o | ||
diff --git a/net/9p/client.c b/net/9p/client.c new file mode 100644 index 000000000000..cb170750337c --- /dev/null +++ b/net/9p/client.c | |||
@@ -0,0 +1,965 @@ | |||
1 | /* | ||
2 | * net/9p/clnt.c | ||
3 | * | ||
4 | * 9P Client | ||
5 | * | ||
6 | * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 | ||
10 | * as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to: | ||
19 | * Free Software Foundation | ||
20 | * 51 Franklin Street, Fifth Floor | ||
21 | * Boston, MA 02111-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/module.h> | ||
26 | #include <linux/errno.h> | ||
27 | #include <linux/fs.h> | ||
28 | #include <linux/idr.h> | ||
29 | #include <linux/mutex.h> | ||
30 | #include <linux/sched.h> | ||
31 | #include <linux/uaccess.h> | ||
32 | #include <net/9p/9p.h> | ||
33 | #include <net/9p/transport.h> | ||
34 | #include <net/9p/conn.h> | ||
35 | #include <net/9p/client.h> | ||
36 | |||
37 | static struct p9_fid *p9_fid_create(struct p9_client *clnt); | ||
38 | static void p9_fid_destroy(struct p9_fid *fid); | ||
39 | static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu); | ||
40 | |||
41 | struct p9_client *p9_client_create(struct p9_transport *trans, int msize, | ||
42 | int dotu) | ||
43 | { | ||
44 | int err, n; | ||
45 | struct p9_client *clnt; | ||
46 | struct p9_fcall *tc, *rc; | ||
47 | struct p9_str *version; | ||
48 | |||
49 | err = 0; | ||
50 | tc = NULL; | ||
51 | rc = NULL; | ||
52 | clnt = kmalloc(sizeof(struct p9_client), GFP_KERNEL); | ||
53 | if (!clnt) | ||
54 | return ERR_PTR(-ENOMEM); | ||
55 | |||
56 | P9_DPRINTK(P9_DEBUG_9P, "clnt %p trans %p msize %d dotu %d\n", | ||
57 | clnt, trans, msize, dotu); | ||
58 | spin_lock_init(&clnt->lock); | ||
59 | clnt->trans = trans; | ||
60 | clnt->msize = msize; | ||
61 | clnt->dotu = dotu; | ||
62 | INIT_LIST_HEAD(&clnt->fidlist); | ||
63 | clnt->fidpool = p9_idpool_create(); | ||
64 | if (!clnt->fidpool) { | ||
65 | err = PTR_ERR(clnt->fidpool); | ||
66 | clnt->fidpool = NULL; | ||
67 | goto error; | ||
68 | } | ||
69 | |||
70 | clnt->conn = p9_conn_create(clnt->trans, clnt->msize, &clnt->dotu); | ||
71 | if (IS_ERR(clnt->conn)) { | ||
72 | err = PTR_ERR(clnt->conn); | ||
73 | clnt->conn = NULL; | ||
74 | goto error; | ||
75 | } | ||
76 | |||
77 | tc = p9_create_tversion(clnt->msize, clnt->dotu?"9P2000.u":"9P2000"); | ||
78 | if (IS_ERR(tc)) { | ||
79 | err = PTR_ERR(tc); | ||
80 | tc = NULL; | ||
81 | goto error; | ||
82 | } | ||
83 | |||
84 | err = p9_conn_rpc(clnt->conn, tc, &rc); | ||
85 | if (err) | ||
86 | goto error; | ||
87 | |||
88 | version = &rc->params.rversion.version; | ||
89 | if (version->len == 8 && !memcmp(version->str, "9P2000.u", 8)) | ||
90 | clnt->dotu = 1; | ||
91 | else if (version->len == 6 && !memcmp(version->str, "9P2000", 6)) | ||
92 | clnt->dotu = 0; | ||
93 | else { | ||
94 | err = -EREMOTEIO; | ||
95 | goto error; | ||
96 | } | ||
97 | |||
98 | n = rc->params.rversion.msize; | ||
99 | if (n < clnt->msize) | ||
100 | clnt->msize = n; | ||
101 | |||
102 | kfree(tc); | ||
103 | kfree(rc); | ||
104 | return clnt; | ||
105 | |||
106 | error: | ||
107 | kfree(tc); | ||
108 | kfree(rc); | ||
109 | p9_client_destroy(clnt); | ||
110 | return ERR_PTR(err); | ||
111 | } | ||
112 | EXPORT_SYMBOL(p9_client_create); | ||
113 | |||
114 | void p9_client_destroy(struct p9_client *clnt) | ||
115 | { | ||
116 | struct p9_fid *fid, *fidptr; | ||
117 | |||
118 | P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); | ||
119 | if (clnt->conn) { | ||
120 | p9_conn_destroy(clnt->conn); | ||
121 | clnt->conn = NULL; | ||
122 | } | ||
123 | |||
124 | if (clnt->trans) { | ||
125 | clnt->trans->close(clnt->trans); | ||
126 | kfree(clnt->trans); | ||
127 | clnt->trans = NULL; | ||
128 | } | ||
129 | |||
130 | list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist) | ||
131 | p9_fid_destroy(fid); | ||
132 | |||
133 | if (clnt->fidpool) | ||
134 | p9_idpool_destroy(clnt->fidpool); | ||
135 | |||
136 | kfree(clnt); | ||
137 | } | ||
138 | EXPORT_SYMBOL(p9_client_destroy); | ||
139 | |||
140 | void p9_client_disconnect(struct p9_client *clnt) | ||
141 | { | ||
142 | P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); | ||
143 | clnt->trans->status = Disconnected; | ||
144 | p9_conn_cancel(clnt->conn, -EIO); | ||
145 | } | ||
146 | EXPORT_SYMBOL(p9_client_disconnect); | ||
147 | |||
148 | struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, | ||
149 | char *uname, char *aname) | ||
150 | { | ||
151 | int err; | ||
152 | struct p9_fcall *tc, *rc; | ||
153 | struct p9_fid *fid; | ||
154 | |||
155 | P9_DPRINTK(P9_DEBUG_9P, "clnt %p afid %d uname %s aname %s\n", | ||
156 | clnt, afid?afid->fid:-1, uname, aname); | ||
157 | err = 0; | ||
158 | tc = NULL; | ||
159 | rc = NULL; | ||
160 | |||
161 | fid = p9_fid_create(clnt); | ||
162 | if (IS_ERR(fid)) { | ||
163 | err = PTR_ERR(fid); | ||
164 | fid = NULL; | ||
165 | goto error; | ||
166 | } | ||
167 | |||
168 | tc = p9_create_tattach(fid->fid, afid?afid->fid:P9_NOFID, uname, aname); | ||
169 | if (IS_ERR(tc)) { | ||
170 | err = PTR_ERR(tc); | ||
171 | tc = NULL; | ||
172 | goto error; | ||
173 | } | ||
174 | |||
175 | err = p9_conn_rpc(clnt->conn, tc, &rc); | ||
176 | if (err) | ||
177 | goto error; | ||
178 | |||
179 | memmove(&fid->qid, &rc->params.rattach.qid, sizeof(struct p9_qid)); | ||
180 | kfree(tc); | ||
181 | kfree(rc); | ||
182 | return fid; | ||
183 | |||
184 | error: | ||
185 | kfree(tc); | ||
186 | kfree(rc); | ||
187 | if (fid) | ||
188 | p9_fid_destroy(fid); | ||
189 | return ERR_PTR(err); | ||
190 | } | ||
191 | EXPORT_SYMBOL(p9_client_attach); | ||
192 | |||
193 | struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, char *aname) | ||
194 | { | ||
195 | int err; | ||
196 | struct p9_fcall *tc, *rc; | ||
197 | struct p9_fid *fid; | ||
198 | |||
199 | P9_DPRINTK(P9_DEBUG_9P, "clnt %p uname %s aname %s\n", clnt, uname, | ||
200 | aname); | ||
201 | err = 0; | ||
202 | tc = NULL; | ||
203 | rc = NULL; | ||
204 | |||
205 | fid = p9_fid_create(clnt); | ||
206 | if (IS_ERR(fid)) { | ||
207 | err = PTR_ERR(fid); | ||
208 | fid = NULL; | ||
209 | goto error; | ||
210 | } | ||
211 | |||
212 | tc = p9_create_tauth(fid->fid, uname, aname); | ||
213 | if (IS_ERR(tc)) { | ||
214 | err = PTR_ERR(tc); | ||
215 | tc = NULL; | ||
216 | goto error; | ||
217 | } | ||
218 | |||
219 | err = p9_conn_rpc(clnt->conn, tc, &rc); | ||
220 | if (err) | ||
221 | goto error; | ||
222 | |||
223 | memmove(&fid->qid, &rc->params.rauth.qid, sizeof(struct p9_qid)); | ||
224 | kfree(tc); | ||
225 | kfree(rc); | ||
226 | return fid; | ||
227 | |||
228 | error: | ||
229 | kfree(tc); | ||
230 | kfree(rc); | ||
231 | if (fid) | ||
232 | p9_fid_destroy(fid); | ||
233 | return ERR_PTR(err); | ||
234 | } | ||
235 | EXPORT_SYMBOL(p9_client_auth); | ||
236 | |||
237 | struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, | ||
238 | int clone) | ||
239 | { | ||
240 | int err; | ||
241 | struct p9_fcall *tc, *rc; | ||
242 | struct p9_client *clnt; | ||
243 | struct p9_fid *fid; | ||
244 | |||
245 | P9_DPRINTK(P9_DEBUG_9P, "fid %d nwname %d wname[0] %s\n", | ||
246 | oldfid->fid, nwname, wnames?wnames[0]:NULL); | ||
247 | err = 0; | ||
248 | tc = NULL; | ||
249 | rc = NULL; | ||
250 | clnt = oldfid->clnt; | ||
251 | if (clone) { | ||
252 | fid = p9_fid_create(clnt); | ||
253 | if (IS_ERR(fid)) { | ||
254 | err = PTR_ERR(fid); | ||
255 | fid = NULL; | ||
256 | goto error; | ||
257 | } | ||
258 | |||
259 | fid->uid = oldfid->uid; | ||
260 | } else | ||
261 | fid = oldfid; | ||
262 | |||
263 | tc = p9_create_twalk(oldfid->fid, fid->fid, nwname, wnames); | ||
264 | if (IS_ERR(tc)) { | ||
265 | err = PTR_ERR(tc); | ||
266 | tc = NULL; | ||
267 | goto error; | ||
268 | } | ||
269 | |||
270 | err = p9_conn_rpc(clnt->conn, tc, &rc); | ||
271 | if (err) { | ||
272 | if (rc && rc->id == P9_RWALK) | ||
273 | goto clunk_fid; | ||
274 | else | ||
275 | goto error; | ||
276 | } | ||
277 | |||
278 | if (rc->params.rwalk.nwqid != nwname) { | ||
279 | err = -ENOENT; | ||
280 | goto clunk_fid; | ||
281 | } | ||
282 | |||
283 | if (nwname) | ||
284 | memmove(&fid->qid, | ||
285 | &rc->params.rwalk.wqids[rc->params.rwalk.nwqid - 1], | ||
286 | sizeof(struct p9_qid)); | ||
287 | else | ||
288 | fid->qid = oldfid->qid; | ||
289 | |||
290 | kfree(tc); | ||
291 | kfree(rc); | ||
292 | return fid; | ||
293 | |||
294 | clunk_fid: | ||
295 | kfree(tc); | ||
296 | kfree(rc); | ||
297 | rc = NULL; | ||
298 | tc = p9_create_tclunk(fid->fid); | ||
299 | if (IS_ERR(tc)) { | ||
300 | err = PTR_ERR(tc); | ||
301 | tc = NULL; | ||
302 | goto error; | ||
303 | } | ||
304 | |||
305 | p9_conn_rpc(clnt->conn, tc, &rc); | ||
306 | |||
307 | error: | ||
308 | kfree(tc); | ||
309 | kfree(rc); | ||
310 | if (fid && (fid != oldfid)) | ||
311 | p9_fid_destroy(fid); | ||
312 | |||
313 | return ERR_PTR(err); | ||
314 | } | ||
315 | EXPORT_SYMBOL(p9_client_walk); | ||
316 | |||
317 | int p9_client_open(struct p9_fid *fid, int mode) | ||
318 | { | ||
319 | int err; | ||
320 | struct p9_fcall *tc, *rc; | ||
321 | struct p9_client *clnt; | ||
322 | |||
323 | P9_DPRINTK(P9_DEBUG_9P, "fid %d mode %d\n", fid->fid, mode); | ||
324 | err = 0; | ||
325 | tc = NULL; | ||
326 | rc = NULL; | ||
327 | clnt = fid->clnt; | ||
328 | |||
329 | if (fid->mode != -1) | ||
330 | return -EINVAL; | ||
331 | |||
332 | tc = p9_create_topen(fid->fid, mode); | ||
333 | if (IS_ERR(tc)) { | ||
334 | err = PTR_ERR(tc); | ||
335 | tc = NULL; | ||
336 | goto done; | ||
337 | } | ||
338 | |||
339 | err = p9_conn_rpc(clnt->conn, tc, &rc); | ||
340 | if (err) | ||
341 | goto done; | ||
342 | |||
343 | fid->mode = mode; | ||
344 | fid->iounit = rc->params.ropen.iounit; | ||
345 | |||
346 | done: | ||
347 | kfree(tc); | ||
348 | kfree(rc); | ||
349 | return err; | ||
350 | } | ||
351 | EXPORT_SYMBOL(p9_client_open); | ||
352 | |||
353 | int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode, | ||
354 | char *extension) | ||
355 | { | ||
356 | int err; | ||
357 | struct p9_fcall *tc, *rc; | ||
358 | struct p9_client *clnt; | ||
359 | |||
360 | P9_DPRINTK(P9_DEBUG_9P, "fid %d name %s perm %d mode %d\n", fid->fid, | ||
361 | name, perm, mode); | ||
362 | err = 0; | ||
363 | tc = NULL; | ||
364 | rc = NULL; | ||
365 | clnt = fid->clnt; | ||
366 | |||
367 | if (fid->mode != -1) | ||
368 | return -EINVAL; | ||
369 | |||
370 | tc = p9_create_tcreate(fid->fid, name, perm, mode, extension, | ||
371 | clnt->dotu); | ||
372 | if (IS_ERR(tc)) { | ||
373 | err = PTR_ERR(tc); | ||
374 | tc = NULL; | ||
375 | goto done; | ||
376 | } | ||
377 | |||
378 | err = p9_conn_rpc(clnt->conn, tc, &rc); | ||
379 | if (err) | ||
380 | goto done; | ||
381 | |||
382 | fid->mode = mode; | ||
383 | fid->iounit = rc->params.ropen.iounit; | ||
384 | |||
385 | done: | ||
386 | kfree(tc); | ||
387 | kfree(rc); | ||
388 | return err; | ||
389 | } | ||
390 | EXPORT_SYMBOL(p9_client_fcreate); | ||
391 | |||
392 | int p9_client_clunk(struct p9_fid *fid) | ||
393 | { | ||
394 | int err; | ||
395 | struct p9_fcall *tc, *rc; | ||
396 | struct p9_client *clnt; | ||
397 | |||
398 | P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); | ||
399 | err = 0; | ||
400 | tc = NULL; | ||
401 | rc = NULL; | ||
402 | clnt = fid->clnt; | ||
403 | |||
404 | tc = p9_create_tclunk(fid->fid); | ||
405 | if (IS_ERR(tc)) { | ||
406 | err = PTR_ERR(tc); | ||
407 | tc = NULL; | ||
408 | goto done; | ||
409 | } | ||
410 | |||
411 | err = p9_conn_rpc(clnt->conn, tc, &rc); | ||
412 | if (err) | ||
413 | goto done; | ||
414 | |||
415 | p9_fid_destroy(fid); | ||
416 | |||
417 | done: | ||
418 | kfree(tc); | ||
419 | kfree(rc); | ||
420 | return err; | ||
421 | } | ||
422 | EXPORT_SYMBOL(p9_client_clunk); | ||
423 | |||
424 | int p9_client_remove(struct p9_fid *fid) | ||
425 | { | ||
426 | int err; | ||
427 | struct p9_fcall *tc, *rc; | ||
428 | struct p9_client *clnt; | ||
429 | |||
430 | P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); | ||
431 | err = 0; | ||
432 | tc = NULL; | ||
433 | rc = NULL; | ||
434 | clnt = fid->clnt; | ||
435 | |||
436 | tc = p9_create_tremove(fid->fid); | ||
437 | if (IS_ERR(tc)) { | ||
438 | err = PTR_ERR(tc); | ||
439 | tc = NULL; | ||
440 | goto done; | ||
441 | } | ||
442 | |||
443 | err = p9_conn_rpc(clnt->conn, tc, &rc); | ||
444 | if (err) | ||
445 | goto done; | ||
446 | |||
447 | p9_fid_destroy(fid); | ||
448 | |||
449 | done: | ||
450 | kfree(tc); | ||
451 | kfree(rc); | ||
452 | return err; | ||
453 | } | ||
454 | EXPORT_SYMBOL(p9_client_remove); | ||
455 | |||
456 | int p9_client_read(struct p9_fid *fid, char *data, u64 offset, u32 count) | ||
457 | { | ||
458 | int err, n, rsize, total; | ||
459 | struct p9_fcall *tc, *rc; | ||
460 | struct p9_client *clnt; | ||
461 | |||
462 | P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu %d\n", fid->fid, | ||
463 | (long long unsigned) offset, count); | ||
464 | err = 0; | ||
465 | tc = NULL; | ||
466 | rc = NULL; | ||
467 | clnt = fid->clnt; | ||
468 | total = 0; | ||
469 | |||
470 | rsize = fid->iounit; | ||
471 | if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) | ||
472 | rsize = clnt->msize - P9_IOHDRSZ; | ||
473 | |||
474 | do { | ||
475 | if (count < rsize) | ||
476 | rsize = count; | ||
477 | |||
478 | tc = p9_create_tread(fid->fid, offset, rsize); | ||
479 | if (IS_ERR(tc)) { | ||
480 | err = PTR_ERR(tc); | ||
481 | tc = NULL; | ||
482 | goto error; | ||
483 | } | ||
484 | |||
485 | err = p9_conn_rpc(clnt->conn, tc, &rc); | ||
486 | if (err) | ||
487 | goto error; | ||
488 | |||
489 | n = rc->params.rread.count; | ||
490 | if (n > count) | ||
491 | n = count; | ||
492 | |||
493 | memmove(data, rc->params.rread.data, n); | ||
494 | count -= n; | ||
495 | data += n; | ||
496 | offset += n; | ||
497 | total += n; | ||
498 | kfree(tc); | ||
499 | tc = NULL; | ||
500 | kfree(rc); | ||
501 | rc = NULL; | ||
502 | } while (count > 0 && n == rsize); | ||
503 | |||
504 | return total; | ||
505 | |||
506 | error: | ||
507 | kfree(tc); | ||
508 | kfree(rc); | ||
509 | return err; | ||
510 | } | ||
511 | EXPORT_SYMBOL(p9_client_read); | ||
512 | |||
513 | int p9_client_write(struct p9_fid *fid, char *data, u64 offset, u32 count) | ||
514 | { | ||
515 | int err, n, rsize, total; | ||
516 | struct p9_fcall *tc, *rc; | ||
517 | struct p9_client *clnt; | ||
518 | |||
519 | P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid, | ||
520 | (long long unsigned) offset, count); | ||
521 | err = 0; | ||
522 | tc = NULL; | ||
523 | rc = NULL; | ||
524 | clnt = fid->clnt; | ||
525 | total = 0; | ||
526 | |||
527 | rsize = fid->iounit; | ||
528 | if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) | ||
529 | rsize = clnt->msize - P9_IOHDRSZ; | ||
530 | |||
531 | do { | ||
532 | if (count < rsize) | ||
533 | rsize = count; | ||
534 | |||
535 | tc = p9_create_twrite(fid->fid, offset, rsize, data); | ||
536 | if (IS_ERR(tc)) { | ||
537 | err = PTR_ERR(tc); | ||
538 | tc = NULL; | ||
539 | goto error; | ||
540 | } | ||
541 | |||
542 | err = p9_conn_rpc(clnt->conn, tc, &rc); | ||
543 | if (err) | ||
544 | goto error; | ||
545 | |||
546 | n = rc->params.rread.count; | ||
547 | count -= n; | ||
548 | data += n; | ||
549 | offset += n; | ||
550 | total += n; | ||
551 | kfree(tc); | ||
552 | tc = NULL; | ||
553 | kfree(rc); | ||
554 | rc = NULL; | ||
555 | } while (count > 0); | ||
556 | |||
557 | return total; | ||
558 | |||
559 | error: | ||
560 | kfree(tc); | ||
561 | kfree(rc); | ||
562 | return err; | ||
563 | } | ||
564 | EXPORT_SYMBOL(p9_client_write); | ||
565 | |||
566 | int | ||
567 | p9_client_uread(struct p9_fid *fid, char __user *data, u64 offset, u32 count) | ||
568 | { | ||
569 | int err, n, rsize, total; | ||
570 | struct p9_fcall *tc, *rc; | ||
571 | struct p9_client *clnt; | ||
572 | |||
573 | P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid, | ||
574 | (long long unsigned) offset, count); | ||
575 | err = 0; | ||
576 | tc = NULL; | ||
577 | rc = NULL; | ||
578 | clnt = fid->clnt; | ||
579 | total = 0; | ||
580 | |||
581 | rsize = fid->iounit; | ||
582 | if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) | ||
583 | rsize = clnt->msize - P9_IOHDRSZ; | ||
584 | |||
585 | do { | ||
586 | if (count < rsize) | ||
587 | rsize = count; | ||
588 | |||
589 | tc = p9_create_tread(fid->fid, offset, rsize); | ||
590 | if (IS_ERR(tc)) { | ||
591 | err = PTR_ERR(tc); | ||
592 | tc = NULL; | ||
593 | goto error; | ||
594 | } | ||
595 | |||
596 | err = p9_conn_rpc(clnt->conn, tc, &rc); | ||
597 | if (err) | ||
598 | goto error; | ||
599 | |||
600 | n = rc->params.rread.count; | ||
601 | if (n > count) | ||
602 | n = count; | ||
603 | |||
604 | err = copy_to_user(data, rc->params.rread.data, n); | ||
605 | if (err) { | ||
606 | err = -EFAULT; | ||
607 | goto error; | ||
608 | } | ||
609 | |||
610 | count -= n; | ||
611 | data += n; | ||
612 | offset += n; | ||
613 | total += n; | ||
614 | kfree(tc); | ||
615 | tc = NULL; | ||
616 | kfree(rc); | ||
617 | rc = NULL; | ||
618 | } while (count > 0 && n == rsize); | ||
619 | |||
620 | return total; | ||
621 | |||
622 | error: | ||
623 | kfree(tc); | ||
624 | kfree(rc); | ||
625 | return err; | ||
626 | } | ||
627 | EXPORT_SYMBOL(p9_client_uread); | ||
628 | |||
629 | int | ||
630 | p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset, | ||
631 | u32 count) | ||
632 | { | ||
633 | int err, n, rsize, total; | ||
634 | struct p9_fcall *tc, *rc; | ||
635 | struct p9_client *clnt; | ||
636 | |||
637 | P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid, | ||
638 | (long long unsigned) offset, count); | ||
639 | err = 0; | ||
640 | tc = NULL; | ||
641 | rc = NULL; | ||
642 | clnt = fid->clnt; | ||
643 | total = 0; | ||
644 | |||
645 | rsize = fid->iounit; | ||
646 | if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) | ||
647 | rsize = clnt->msize - P9_IOHDRSZ; | ||
648 | |||
649 | do { | ||
650 | if (count < rsize) | ||
651 | rsize = count; | ||
652 | |||
653 | tc = p9_create_twrite_u(fid->fid, offset, rsize, data); | ||
654 | if (IS_ERR(tc)) { | ||
655 | err = PTR_ERR(tc); | ||
656 | tc = NULL; | ||
657 | goto error; | ||
658 | } | ||
659 | |||
660 | err = p9_conn_rpc(clnt->conn, tc, &rc); | ||
661 | if (err) | ||
662 | goto error; | ||
663 | |||
664 | n = rc->params.rread.count; | ||
665 | count -= n; | ||
666 | data += n; | ||
667 | offset += n; | ||
668 | total += n; | ||
669 | kfree(tc); | ||
670 | tc = NULL; | ||
671 | kfree(rc); | ||
672 | rc = NULL; | ||
673 | } while (count > 0); | ||
674 | |||
675 | return total; | ||
676 | |||
677 | error: | ||
678 | kfree(tc); | ||
679 | kfree(rc); | ||
680 | return err; | ||
681 | } | ||
682 | EXPORT_SYMBOL(p9_client_uwrite); | ||
683 | |||
684 | int p9_client_readn(struct p9_fid *fid, char *data, u64 offset, u32 count) | ||
685 | { | ||
686 | int n, total; | ||
687 | |||
688 | P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid, | ||
689 | (long long unsigned) offset, count); | ||
690 | n = 0; | ||
691 | total = 0; | ||
692 | while (count) { | ||
693 | n = p9_client_read(fid, data, offset, count); | ||
694 | if (n <= 0) | ||
695 | break; | ||
696 | |||
697 | data += n; | ||
698 | offset += n; | ||
699 | count -= n; | ||
700 | total += n; | ||
701 | } | ||
702 | |||
703 | if (n < 0) | ||
704 | total = n; | ||
705 | |||
706 | return total; | ||
707 | } | ||
708 | EXPORT_SYMBOL(p9_client_readn); | ||
709 | |||
710 | struct p9_stat *p9_client_stat(struct p9_fid *fid) | ||
711 | { | ||
712 | int err; | ||
713 | struct p9_fcall *tc, *rc; | ||
714 | struct p9_client *clnt; | ||
715 | struct p9_stat *ret; | ||
716 | |||
717 | P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); | ||
718 | err = 0; | ||
719 | tc = NULL; | ||
720 | rc = NULL; | ||
721 | ret = NULL; | ||
722 | clnt = fid->clnt; | ||
723 | |||
724 | tc = p9_create_tstat(fid->fid); | ||
725 | if (IS_ERR(tc)) { | ||
726 | err = PTR_ERR(tc); | ||
727 | tc = NULL; | ||
728 | goto error; | ||
729 | } | ||
730 | |||
731 | err = p9_conn_rpc(clnt->conn, tc, &rc); | ||
732 | if (err) | ||
733 | goto error; | ||
734 | |||
735 | ret = p9_clone_stat(&rc->params.rstat.stat, clnt->dotu); | ||
736 | if (IS_ERR(ret)) { | ||
737 | err = PTR_ERR(ret); | ||
738 | ret = NULL; | ||
739 | goto error; | ||
740 | } | ||
741 | |||
742 | kfree(tc); | ||
743 | kfree(rc); | ||
744 | return ret; | ||
745 | |||
746 | error: | ||
747 | kfree(tc); | ||
748 | kfree(rc); | ||
749 | kfree(ret); | ||
750 | return ERR_PTR(err); | ||
751 | } | ||
752 | EXPORT_SYMBOL(p9_client_stat); | ||
753 | |||
754 | int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) | ||
755 | { | ||
756 | int err; | ||
757 | struct p9_fcall *tc, *rc; | ||
758 | struct p9_client *clnt; | ||
759 | |||
760 | P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); | ||
761 | err = 0; | ||
762 | tc = NULL; | ||
763 | rc = NULL; | ||
764 | clnt = fid->clnt; | ||
765 | |||
766 | tc = p9_create_twstat(fid->fid, wst, clnt->dotu); | ||
767 | if (IS_ERR(tc)) { | ||
768 | err = PTR_ERR(tc); | ||
769 | tc = NULL; | ||
770 | goto done; | ||
771 | } | ||
772 | |||
773 | err = p9_conn_rpc(clnt->conn, tc, &rc); | ||
774 | |||
775 | done: | ||
776 | kfree(tc); | ||
777 | kfree(rc); | ||
778 | return err; | ||
779 | } | ||
780 | EXPORT_SYMBOL(p9_client_wstat); | ||
781 | |||
782 | struct p9_stat *p9_client_dirread(struct p9_fid *fid, u64 offset) | ||
783 | { | ||
784 | int err, n, m; | ||
785 | struct p9_fcall *tc, *rc; | ||
786 | struct p9_client *clnt; | ||
787 | struct p9_stat st, *ret; | ||
788 | |||
789 | P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu\n", fid->fid, | ||
790 | (long long unsigned) offset); | ||
791 | err = 0; | ||
792 | tc = NULL; | ||
793 | rc = NULL; | ||
794 | ret = NULL; | ||
795 | clnt = fid->clnt; | ||
796 | |||
797 | /* if the offset is below or above the current response, free it */ | ||
798 | if (offset < fid->rdir_fpos || (fid->rdir_fcall && | ||
799 | offset >= fid->rdir_fpos+fid->rdir_fcall->params.rread.count)) { | ||
800 | fid->rdir_pos = 0; | ||
801 | if (fid->rdir_fcall) | ||
802 | fid->rdir_fpos += fid->rdir_fcall->params.rread.count; | ||
803 | |||
804 | kfree(fid->rdir_fcall); | ||
805 | fid->rdir_fcall = NULL; | ||
806 | if (offset < fid->rdir_fpos) | ||
807 | fid->rdir_fpos = 0; | ||
808 | } | ||
809 | |||
810 | if (!fid->rdir_fcall) { | ||
811 | n = fid->iounit; | ||
812 | if (!n || n > clnt->msize-P9_IOHDRSZ) | ||
813 | n = clnt->msize - P9_IOHDRSZ; | ||
814 | |||
815 | while (1) { | ||
816 | if (fid->rdir_fcall) { | ||
817 | fid->rdir_fpos += | ||
818 | fid->rdir_fcall->params.rread.count; | ||
819 | kfree(fid->rdir_fcall); | ||
820 | fid->rdir_fcall = NULL; | ||
821 | } | ||
822 | |||
823 | tc = p9_create_tread(fid->fid, fid->rdir_fpos, n); | ||
824 | if (IS_ERR(tc)) { | ||
825 | err = PTR_ERR(tc); | ||
826 | tc = NULL; | ||
827 | goto error; | ||
828 | } | ||
829 | |||
830 | err = p9_conn_rpc(clnt->conn, tc, &rc); | ||
831 | if (err) | ||
832 | goto error; | ||
833 | |||
834 | n = rc->params.rread.count; | ||
835 | if (n == 0) | ||
836 | goto done; | ||
837 | |||
838 | fid->rdir_fcall = rc; | ||
839 | rc = NULL; | ||
840 | if (offset >= fid->rdir_fpos && | ||
841 | offset < fid->rdir_fpos+n) | ||
842 | break; | ||
843 | } | ||
844 | |||
845 | fid->rdir_pos = 0; | ||
846 | } | ||
847 | |||
848 | m = offset - fid->rdir_fpos; | ||
849 | if (m < 0) | ||
850 | goto done; | ||
851 | |||
852 | n = p9_deserialize_stat(fid->rdir_fcall->params.rread.data + m, | ||
853 | fid->rdir_fcall->params.rread.count - m, &st, clnt->dotu); | ||
854 | |||
855 | if (!n) { | ||
856 | err = -EIO; | ||
857 | goto error; | ||
858 | } | ||
859 | |||
860 | fid->rdir_pos += n; | ||
861 | st.size = n; | ||
862 | ret = p9_clone_stat(&st, clnt->dotu); | ||
863 | if (IS_ERR(ret)) { | ||
864 | err = PTR_ERR(ret); | ||
865 | ret = NULL; | ||
866 | goto error; | ||
867 | } | ||
868 | |||
869 | done: | ||
870 | kfree(tc); | ||
871 | kfree(rc); | ||
872 | return ret; | ||
873 | |||
874 | error: | ||
875 | kfree(tc); | ||
876 | kfree(rc); | ||
877 | kfree(ret); | ||
878 | return ERR_PTR(err); | ||
879 | } | ||
880 | EXPORT_SYMBOL(p9_client_dirread); | ||
881 | |||
882 | static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu) | ||
883 | { | ||
884 | int n; | ||
885 | char *p; | ||
886 | struct p9_stat *ret; | ||
887 | |||
888 | n = sizeof(struct p9_stat) + st->name.len + st->uid.len + st->gid.len + | ||
889 | st->muid.len; | ||
890 | |||
891 | if (dotu) | ||
892 | n += st->extension.len; | ||
893 | |||
894 | ret = kmalloc(n, GFP_KERNEL); | ||
895 | if (!ret) | ||
896 | return ERR_PTR(-ENOMEM); | ||
897 | |||
898 | memmove(ret, st, sizeof(struct p9_stat)); | ||
899 | p = ((char *) ret) + sizeof(struct p9_stat); | ||
900 | memmove(p, st->name.str, st->name.len); | ||
901 | p += st->name.len; | ||
902 | memmove(p, st->uid.str, st->uid.len); | ||
903 | p += st->uid.len; | ||
904 | memmove(p, st->gid.str, st->gid.len); | ||
905 | p += st->gid.len; | ||
906 | memmove(p, st->muid.str, st->muid.len); | ||
907 | p += st->muid.len; | ||
908 | |||
909 | if (dotu) { | ||
910 | memmove(p, st->extension.str, st->extension.len); | ||
911 | p += st->extension.len; | ||
912 | } | ||
913 | |||
914 | return ret; | ||
915 | } | ||
916 | |||
917 | static struct p9_fid *p9_fid_create(struct p9_client *clnt) | ||
918 | { | ||
919 | int err; | ||
920 | struct p9_fid *fid; | ||
921 | |||
922 | P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); | ||
923 | fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL); | ||
924 | if (!fid) | ||
925 | return ERR_PTR(-ENOMEM); | ||
926 | |||
927 | fid->fid = p9_idpool_get(clnt->fidpool); | ||
928 | if (fid->fid < 0) { | ||
929 | err = -ENOSPC; | ||
930 | goto error; | ||
931 | } | ||
932 | |||
933 | memset(&fid->qid, 0, sizeof(struct p9_qid)); | ||
934 | fid->mode = -1; | ||
935 | fid->rdir_fpos = 0; | ||
936 | fid->rdir_pos = 0; | ||
937 | fid->rdir_fcall = NULL; | ||
938 | fid->uid = current->fsuid; | ||
939 | fid->clnt = clnt; | ||
940 | fid->aux = NULL; | ||
941 | |||
942 | spin_lock(&clnt->lock); | ||
943 | list_add(&fid->flist, &clnt->fidlist); | ||
944 | spin_unlock(&clnt->lock); | ||
945 | |||
946 | return fid; | ||
947 | |||
948 | error: | ||
949 | kfree(fid); | ||
950 | return ERR_PTR(err); | ||
951 | } | ||
952 | |||
953 | static void p9_fid_destroy(struct p9_fid *fid) | ||
954 | { | ||
955 | struct p9_client *clnt; | ||
956 | |||
957 | P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); | ||
958 | clnt = fid->clnt; | ||
959 | p9_idpool_put(fid->fid, clnt->fidpool); | ||
960 | spin_lock(&clnt->lock); | ||
961 | list_del(&fid->flist); | ||
962 | spin_unlock(&clnt->lock); | ||
963 | kfree(fid->rdir_fcall); | ||
964 | kfree(fid); | ||
965 | } | ||
diff --git a/net/9p/conv.c b/net/9p/conv.c new file mode 100644 index 000000000000..37451178e761 --- /dev/null +++ b/net/9p/conv.c | |||
@@ -0,0 +1,903 @@ | |||
1 | /* | ||
2 | * net/9p/conv.c | ||
3 | * | ||
4 | * 9P protocol conversion functions | ||
5 | * | ||
6 | * Copyright (C) 2004, 2005 by Latchesar Ionkov <lucho@ionkov.net> | ||
7 | * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> | ||
8 | * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 | ||
12 | * as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to: | ||
21 | * Free Software Foundation | ||
22 | * 51 Franklin Street, Fifth Floor | ||
23 | * Boston, MA 02111-1301 USA | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include <linux/module.h> | ||
28 | #include <linux/errno.h> | ||
29 | #include <linux/fs.h> | ||
30 | #include <linux/sched.h> | ||
31 | #include <linux/idr.h> | ||
32 | #include <linux/uaccess.h> | ||
33 | #include <net/9p/9p.h> | ||
34 | |||
35 | /* | ||
36 | * Buffer to help with string parsing | ||
37 | */ | ||
38 | struct cbuf { | ||
39 | unsigned char *sp; | ||
40 | unsigned char *p; | ||
41 | unsigned char *ep; | ||
42 | }; | ||
43 | |||
44 | static inline void buf_init(struct cbuf *buf, void *data, int datalen) | ||
45 | { | ||
46 | buf->sp = buf->p = data; | ||
47 | buf->ep = data + datalen; | ||
48 | } | ||
49 | |||
50 | static inline int buf_check_overflow(struct cbuf *buf) | ||
51 | { | ||
52 | return buf->p > buf->ep; | ||
53 | } | ||
54 | |||
55 | static int buf_check_size(struct cbuf *buf, int len) | ||
56 | { | ||
57 | if (buf->p + len > buf->ep) { | ||
58 | if (buf->p < buf->ep) { | ||
59 | P9_EPRINTK(KERN_ERR, | ||
60 | "buffer overflow: want %d has %d\n", len, | ||
61 | (int)(buf->ep - buf->p)); | ||
62 | dump_stack(); | ||
63 | buf->p = buf->ep + 1; | ||
64 | } | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | return 1; | ||
70 | } | ||
71 | |||
72 | static void *buf_alloc(struct cbuf *buf, int len) | ||
73 | { | ||
74 | void *ret = NULL; | ||
75 | |||
76 | if (buf_check_size(buf, len)) { | ||
77 | ret = buf->p; | ||
78 | buf->p += len; | ||
79 | } | ||
80 | |||
81 | return ret; | ||
82 | } | ||
83 | |||
84 | static void buf_put_int8(struct cbuf *buf, u8 val) | ||
85 | { | ||
86 | if (buf_check_size(buf, 1)) { | ||
87 | buf->p[0] = val; | ||
88 | buf->p++; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | static void buf_put_int16(struct cbuf *buf, u16 val) | ||
93 | { | ||
94 | if (buf_check_size(buf, 2)) { | ||
95 | *(__le16 *) buf->p = cpu_to_le16(val); | ||
96 | buf->p += 2; | ||
97 | } | ||
98 | } | ||
99 | |||
100 | static void buf_put_int32(struct cbuf *buf, u32 val) | ||
101 | { | ||
102 | if (buf_check_size(buf, 4)) { | ||
103 | *(__le32 *)buf->p = cpu_to_le32(val); | ||
104 | buf->p += 4; | ||
105 | } | ||
106 | } | ||
107 | |||
108 | static void buf_put_int64(struct cbuf *buf, u64 val) | ||
109 | { | ||
110 | if (buf_check_size(buf, 8)) { | ||
111 | *(__le64 *)buf->p = cpu_to_le64(val); | ||
112 | buf->p += 8; | ||
113 | } | ||
114 | } | ||
115 | |||
116 | static char *buf_put_stringn(struct cbuf *buf, const char *s, u16 slen) | ||
117 | { | ||
118 | char *ret; | ||
119 | |||
120 | ret = NULL; | ||
121 | if (buf_check_size(buf, slen + 2)) { | ||
122 | buf_put_int16(buf, slen); | ||
123 | ret = buf->p; | ||
124 | memcpy(buf->p, s, slen); | ||
125 | buf->p += slen; | ||
126 | } | ||
127 | |||
128 | return ret; | ||
129 | } | ||
130 | |||
131 | static inline void buf_put_string(struct cbuf *buf, const char *s) | ||
132 | { | ||
133 | buf_put_stringn(buf, s, strlen(s)); | ||
134 | } | ||
135 | |||
136 | static u8 buf_get_int8(struct cbuf *buf) | ||
137 | { | ||
138 | u8 ret = 0; | ||
139 | |||
140 | if (buf_check_size(buf, 1)) { | ||
141 | ret = buf->p[0]; | ||
142 | buf->p++; | ||
143 | } | ||
144 | |||
145 | return ret; | ||
146 | } | ||
147 | |||
148 | static u16 buf_get_int16(struct cbuf *buf) | ||
149 | { | ||
150 | u16 ret = 0; | ||
151 | |||
152 | if (buf_check_size(buf, 2)) { | ||
153 | ret = le16_to_cpu(*(__le16 *)buf->p); | ||
154 | buf->p += 2; | ||
155 | } | ||
156 | |||
157 | return ret; | ||
158 | } | ||
159 | |||
160 | static u32 buf_get_int32(struct cbuf *buf) | ||
161 | { | ||
162 | u32 ret = 0; | ||
163 | |||
164 | if (buf_check_size(buf, 4)) { | ||
165 | ret = le32_to_cpu(*(__le32 *)buf->p); | ||
166 | buf->p += 4; | ||
167 | } | ||
168 | |||
169 | return ret; | ||
170 | } | ||
171 | |||
172 | static u64 buf_get_int64(struct cbuf *buf) | ||
173 | { | ||
174 | u64 ret = 0; | ||
175 | |||
176 | if (buf_check_size(buf, 8)) { | ||
177 | ret = le64_to_cpu(*(__le64 *)buf->p); | ||
178 | buf->p += 8; | ||
179 | } | ||
180 | |||
181 | return ret; | ||
182 | } | ||
183 | |||
184 | static void buf_get_str(struct cbuf *buf, struct p9_str *vstr) | ||
185 | { | ||
186 | vstr->len = buf_get_int16(buf); | ||
187 | if (!buf_check_overflow(buf) && buf_check_size(buf, vstr->len)) { | ||
188 | vstr->str = buf->p; | ||
189 | buf->p += vstr->len; | ||
190 | } else { | ||
191 | vstr->len = 0; | ||
192 | vstr->str = NULL; | ||
193 | } | ||
194 | } | ||
195 | |||
196 | static void buf_get_qid(struct cbuf *bufp, struct p9_qid *qid) | ||
197 | { | ||
198 | qid->type = buf_get_int8(bufp); | ||
199 | qid->version = buf_get_int32(bufp); | ||
200 | qid->path = buf_get_int64(bufp); | ||
201 | } | ||
202 | |||
203 | /** | ||
204 | * p9_size_wstat - calculate the size of a variable length stat struct | ||
205 | * @stat: metadata (stat) structure | ||
206 | * @dotu: non-zero if 9P2000.u | ||
207 | * | ||
208 | */ | ||
209 | |||
210 | static int p9_size_wstat(struct p9_wstat *wstat, int dotu) | ||
211 | { | ||
212 | int size = 0; | ||
213 | |||
214 | if (wstat == NULL) { | ||
215 | P9_EPRINTK(KERN_ERR, "p9_size_stat: got a NULL stat pointer\n"); | ||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | size = /* 2 + *//* size[2] */ | ||
220 | 2 + /* type[2] */ | ||
221 | 4 + /* dev[4] */ | ||
222 | 1 + /* qid.type[1] */ | ||
223 | 4 + /* qid.vers[4] */ | ||
224 | 8 + /* qid.path[8] */ | ||
225 | 4 + /* mode[4] */ | ||
226 | 4 + /* atime[4] */ | ||
227 | 4 + /* mtime[4] */ | ||
228 | 8 + /* length[8] */ | ||
229 | 8; /* minimum sum of string lengths */ | ||
230 | |||
231 | if (wstat->name) | ||
232 | size += strlen(wstat->name); | ||
233 | if (wstat->uid) | ||
234 | size += strlen(wstat->uid); | ||
235 | if (wstat->gid) | ||
236 | size += strlen(wstat->gid); | ||
237 | if (wstat->muid) | ||
238 | size += strlen(wstat->muid); | ||
239 | |||
240 | if (dotu) { | ||
241 | size += 4 + /* n_uid[4] */ | ||
242 | 4 + /* n_gid[4] */ | ||
243 | 4 + /* n_muid[4] */ | ||
244 | 2; /* string length of extension[4] */ | ||
245 | if (wstat->extension) | ||
246 | size += strlen(wstat->extension); | ||
247 | } | ||
248 | |||
249 | return size; | ||
250 | } | ||
251 | |||
252 | /** | ||
253 | * buf_get_stat - safely decode a recieved metadata (stat) structure | ||
254 | * @bufp: buffer to deserialize | ||
255 | * @stat: metadata (stat) structure | ||
256 | * @dotu: non-zero if 9P2000.u | ||
257 | * | ||
258 | */ | ||
259 | |||
260 | static void | ||
261 | buf_get_stat(struct cbuf *bufp, struct p9_stat *stat, int dotu) | ||
262 | { | ||
263 | stat->size = buf_get_int16(bufp); | ||
264 | stat->type = buf_get_int16(bufp); | ||
265 | stat->dev = buf_get_int32(bufp); | ||
266 | stat->qid.type = buf_get_int8(bufp); | ||
267 | stat->qid.version = buf_get_int32(bufp); | ||
268 | stat->qid.path = buf_get_int64(bufp); | ||
269 | stat->mode = buf_get_int32(bufp); | ||
270 | stat->atime = buf_get_int32(bufp); | ||
271 | stat->mtime = buf_get_int32(bufp); | ||
272 | stat->length = buf_get_int64(bufp); | ||
273 | buf_get_str(bufp, &stat->name); | ||
274 | buf_get_str(bufp, &stat->uid); | ||
275 | buf_get_str(bufp, &stat->gid); | ||
276 | buf_get_str(bufp, &stat->muid); | ||
277 | |||
278 | if (dotu) { | ||
279 | buf_get_str(bufp, &stat->extension); | ||
280 | stat->n_uid = buf_get_int32(bufp); | ||
281 | stat->n_gid = buf_get_int32(bufp); | ||
282 | stat->n_muid = buf_get_int32(bufp); | ||
283 | } | ||
284 | } | ||
285 | |||
286 | /** | ||
287 | * p9_deserialize_stat - decode a received metadata structure | ||
288 | * @buf: buffer to deserialize | ||
289 | * @buflen: length of received buffer | ||
290 | * @stat: metadata structure to decode into | ||
291 | * @dotu: non-zero if 9P2000.u | ||
292 | * | ||
293 | * Note: stat will point to the buf region. | ||
294 | */ | ||
295 | |||
296 | int | ||
297 | p9_deserialize_stat(void *buf, u32 buflen, struct p9_stat *stat, | ||
298 | int dotu) | ||
299 | { | ||
300 | struct cbuf buffer; | ||
301 | struct cbuf *bufp = &buffer; | ||
302 | unsigned char *p; | ||
303 | |||
304 | buf_init(bufp, buf, buflen); | ||
305 | p = bufp->p; | ||
306 | buf_get_stat(bufp, stat, dotu); | ||
307 | |||
308 | if (buf_check_overflow(bufp)) | ||
309 | return 0; | ||
310 | else | ||
311 | return bufp->p - p; | ||
312 | } | ||
313 | EXPORT_SYMBOL(p9_deserialize_stat); | ||
314 | |||
315 | /** | ||
316 | * deserialize_fcall - unmarshal a response | ||
317 | * @buf: recieved buffer | ||
318 | * @buflen: length of received buffer | ||
319 | * @rcall: fcall structure to populate | ||
320 | * @rcalllen: length of fcall structure to populate | ||
321 | * @dotu: non-zero if 9P2000.u | ||
322 | * | ||
323 | */ | ||
324 | |||
325 | int | ||
326 | p9_deserialize_fcall(void *buf, u32 buflen, struct p9_fcall *rcall, | ||
327 | int dotu) | ||
328 | { | ||
329 | |||
330 | struct cbuf buffer; | ||
331 | struct cbuf *bufp = &buffer; | ||
332 | int i = 0; | ||
333 | |||
334 | buf_init(bufp, buf, buflen); | ||
335 | |||
336 | rcall->size = buf_get_int32(bufp); | ||
337 | rcall->id = buf_get_int8(bufp); | ||
338 | rcall->tag = buf_get_int16(bufp); | ||
339 | |||
340 | P9_DPRINTK(P9_DEBUG_CONV, "size %d id %d tag %d\n", rcall->size, | ||
341 | rcall->id, rcall->tag); | ||
342 | |||
343 | switch (rcall->id) { | ||
344 | default: | ||
345 | P9_EPRINTK(KERN_ERR, "unknown message type: %d\n", rcall->id); | ||
346 | return -EPROTO; | ||
347 | case P9_RVERSION: | ||
348 | rcall->params.rversion.msize = buf_get_int32(bufp); | ||
349 | buf_get_str(bufp, &rcall->params.rversion.version); | ||
350 | break; | ||
351 | case P9_RFLUSH: | ||
352 | break; | ||
353 | case P9_RATTACH: | ||
354 | rcall->params.rattach.qid.type = buf_get_int8(bufp); | ||
355 | rcall->params.rattach.qid.version = buf_get_int32(bufp); | ||
356 | rcall->params.rattach.qid.path = buf_get_int64(bufp); | ||
357 | break; | ||
358 | case P9_RWALK: | ||
359 | rcall->params.rwalk.nwqid = buf_get_int16(bufp); | ||
360 | if (rcall->params.rwalk.nwqid > P9_MAXWELEM) { | ||
361 | P9_EPRINTK(KERN_ERR, | ||
362 | "Rwalk with more than %d qids: %d\n", | ||
363 | P9_MAXWELEM, rcall->params.rwalk.nwqid); | ||
364 | return -EPROTO; | ||
365 | } | ||
366 | |||
367 | for (i = 0; i < rcall->params.rwalk.nwqid; i++) | ||
368 | buf_get_qid(bufp, &rcall->params.rwalk.wqids[i]); | ||
369 | break; | ||
370 | case P9_ROPEN: | ||
371 | buf_get_qid(bufp, &rcall->params.ropen.qid); | ||
372 | rcall->params.ropen.iounit = buf_get_int32(bufp); | ||
373 | break; | ||
374 | case P9_RCREATE: | ||
375 | buf_get_qid(bufp, &rcall->params.rcreate.qid); | ||
376 | rcall->params.rcreate.iounit = buf_get_int32(bufp); | ||
377 | break; | ||
378 | case P9_RREAD: | ||
379 | rcall->params.rread.count = buf_get_int32(bufp); | ||
380 | rcall->params.rread.data = bufp->p; | ||
381 | buf_check_size(bufp, rcall->params.rread.count); | ||
382 | break; | ||
383 | case P9_RWRITE: | ||
384 | rcall->params.rwrite.count = buf_get_int32(bufp); | ||
385 | break; | ||
386 | case P9_RCLUNK: | ||
387 | break; | ||
388 | case P9_RREMOVE: | ||
389 | break; | ||
390 | case P9_RSTAT: | ||
391 | buf_get_int16(bufp); | ||
392 | buf_get_stat(bufp, &rcall->params.rstat.stat, dotu); | ||
393 | break; | ||
394 | case P9_RWSTAT: | ||
395 | break; | ||
396 | case P9_RERROR: | ||
397 | buf_get_str(bufp, &rcall->params.rerror.error); | ||
398 | if (dotu) | ||
399 | rcall->params.rerror.errno = buf_get_int16(bufp); | ||
400 | break; | ||
401 | } | ||
402 | |||
403 | if (buf_check_overflow(bufp)) { | ||
404 | P9_DPRINTK(P9_DEBUG_ERROR, "buffer overflow\n"); | ||
405 | return -EIO; | ||
406 | } | ||
407 | |||
408 | return bufp->p - bufp->sp; | ||
409 | } | ||
410 | EXPORT_SYMBOL(p9_deserialize_fcall); | ||
411 | |||
412 | static inline void p9_put_int8(struct cbuf *bufp, u8 val, u8 * p) | ||
413 | { | ||
414 | *p = val; | ||
415 | buf_put_int8(bufp, val); | ||
416 | } | ||
417 | |||
418 | static inline void p9_put_int16(struct cbuf *bufp, u16 val, u16 * p) | ||
419 | { | ||
420 | *p = val; | ||
421 | buf_put_int16(bufp, val); | ||
422 | } | ||
423 | |||
424 | static inline void p9_put_int32(struct cbuf *bufp, u32 val, u32 * p) | ||
425 | { | ||
426 | *p = val; | ||
427 | buf_put_int32(bufp, val); | ||
428 | } | ||
429 | |||
430 | static inline void p9_put_int64(struct cbuf *bufp, u64 val, u64 * p) | ||
431 | { | ||
432 | *p = val; | ||
433 | buf_put_int64(bufp, val); | ||
434 | } | ||
435 | |||
436 | static void | ||
437 | p9_put_str(struct cbuf *bufp, char *data, struct p9_str *str) | ||
438 | { | ||
439 | int len; | ||
440 | char *s; | ||
441 | |||
442 | if (data) | ||
443 | len = strlen(data); | ||
444 | else | ||
445 | len = 0; | ||
446 | |||
447 | s = buf_put_stringn(bufp, data, len); | ||
448 | if (str) { | ||
449 | str->len = len; | ||
450 | str->str = s; | ||
451 | } | ||
452 | } | ||
453 | |||
454 | static int | ||
455 | p9_put_data(struct cbuf *bufp, const char *data, int count, | ||
456 | unsigned char **pdata) | ||
457 | { | ||
458 | *pdata = buf_alloc(bufp, count); | ||
459 | memmove(*pdata, data, count); | ||
460 | return count; | ||
461 | } | ||
462 | |||
463 | static int | ||
464 | p9_put_user_data(struct cbuf *bufp, const char __user *data, int count, | ||
465 | unsigned char **pdata) | ||
466 | { | ||
467 | *pdata = buf_alloc(bufp, count); | ||
468 | return copy_from_user(*pdata, data, count); | ||
469 | } | ||
470 | |||
471 | static void | ||
472 | p9_put_wstat(struct cbuf *bufp, struct p9_wstat *wstat, | ||
473 | struct p9_stat *stat, int statsz, int dotu) | ||
474 | { | ||
475 | p9_put_int16(bufp, statsz, &stat->size); | ||
476 | p9_put_int16(bufp, wstat->type, &stat->type); | ||
477 | p9_put_int32(bufp, wstat->dev, &stat->dev); | ||
478 | p9_put_int8(bufp, wstat->qid.type, &stat->qid.type); | ||
479 | p9_put_int32(bufp, wstat->qid.version, &stat->qid.version); | ||
480 | p9_put_int64(bufp, wstat->qid.path, &stat->qid.path); | ||
481 | p9_put_int32(bufp, wstat->mode, &stat->mode); | ||
482 | p9_put_int32(bufp, wstat->atime, &stat->atime); | ||
483 | p9_put_int32(bufp, wstat->mtime, &stat->mtime); | ||
484 | p9_put_int64(bufp, wstat->length, &stat->length); | ||
485 | |||
486 | p9_put_str(bufp, wstat->name, &stat->name); | ||
487 | p9_put_str(bufp, wstat->uid, &stat->uid); | ||
488 | p9_put_str(bufp, wstat->gid, &stat->gid); | ||
489 | p9_put_str(bufp, wstat->muid, &stat->muid); | ||
490 | |||
491 | if (dotu) { | ||
492 | p9_put_str(bufp, wstat->extension, &stat->extension); | ||
493 | p9_put_int32(bufp, wstat->n_uid, &stat->n_uid); | ||
494 | p9_put_int32(bufp, wstat->n_gid, &stat->n_gid); | ||
495 | p9_put_int32(bufp, wstat->n_muid, &stat->n_muid); | ||
496 | } | ||
497 | } | ||
498 | |||
499 | static struct p9_fcall * | ||
500 | p9_create_common(struct cbuf *bufp, u32 size, u8 id) | ||
501 | { | ||
502 | struct p9_fcall *fc; | ||
503 | |||
504 | size += 4 + 1 + 2; /* size[4] id[1] tag[2] */ | ||
505 | fc = kmalloc(sizeof(struct p9_fcall) + size, GFP_KERNEL); | ||
506 | if (!fc) | ||
507 | return ERR_PTR(-ENOMEM); | ||
508 | |||
509 | fc->sdata = (char *)fc + sizeof(*fc); | ||
510 | |||
511 | buf_init(bufp, (char *)fc->sdata, size); | ||
512 | p9_put_int32(bufp, size, &fc->size); | ||
513 | p9_put_int8(bufp, id, &fc->id); | ||
514 | p9_put_int16(bufp, P9_NOTAG, &fc->tag); | ||
515 | |||
516 | return fc; | ||
517 | } | ||
518 | |||
519 | void p9_set_tag(struct p9_fcall *fc, u16 tag) | ||
520 | { | ||
521 | fc->tag = tag; | ||
522 | *(__le16 *) (fc->sdata + 5) = cpu_to_le16(tag); | ||
523 | } | ||
524 | EXPORT_SYMBOL(p9_set_tag); | ||
525 | |||
526 | struct p9_fcall *p9_create_tversion(u32 msize, char *version) | ||
527 | { | ||
528 | int size; | ||
529 | struct p9_fcall *fc; | ||
530 | struct cbuf buffer; | ||
531 | struct cbuf *bufp = &buffer; | ||
532 | |||
533 | size = 4 + 2 + strlen(version); /* msize[4] version[s] */ | ||
534 | fc = p9_create_common(bufp, size, P9_TVERSION); | ||
535 | if (IS_ERR(fc)) | ||
536 | goto error; | ||
537 | |||
538 | p9_put_int32(bufp, msize, &fc->params.tversion.msize); | ||
539 | p9_put_str(bufp, version, &fc->params.tversion.version); | ||
540 | |||
541 | if (buf_check_overflow(bufp)) { | ||
542 | kfree(fc); | ||
543 | fc = ERR_PTR(-ENOMEM); | ||
544 | } | ||
545 | error: | ||
546 | return fc; | ||
547 | } | ||
548 | EXPORT_SYMBOL(p9_create_tversion); | ||
549 | |||
550 | struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname) | ||
551 | { | ||
552 | int size; | ||
553 | struct p9_fcall *fc; | ||
554 | struct cbuf buffer; | ||
555 | struct cbuf *bufp = &buffer; | ||
556 | |||
557 | /* afid[4] uname[s] aname[s] */ | ||
558 | size = 4 + 2 + strlen(uname) + 2 + strlen(aname); | ||
559 | fc = p9_create_common(bufp, size, P9_TAUTH); | ||
560 | if (IS_ERR(fc)) | ||
561 | goto error; | ||
562 | |||
563 | p9_put_int32(bufp, afid, &fc->params.tauth.afid); | ||
564 | p9_put_str(bufp, uname, &fc->params.tauth.uname); | ||
565 | p9_put_str(bufp, aname, &fc->params.tauth.aname); | ||
566 | |||
567 | if (buf_check_overflow(bufp)) { | ||
568 | kfree(fc); | ||
569 | fc = ERR_PTR(-ENOMEM); | ||
570 | } | ||
571 | error: | ||
572 | return fc; | ||
573 | } | ||
574 | EXPORT_SYMBOL(p9_create_tauth); | ||
575 | |||
576 | struct p9_fcall * | ||
577 | p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname) | ||
578 | { | ||
579 | int size; | ||
580 | struct p9_fcall *fc; | ||
581 | struct cbuf buffer; | ||
582 | struct cbuf *bufp = &buffer; | ||
583 | |||
584 | /* fid[4] afid[4] uname[s] aname[s] */ | ||
585 | size = 4 + 4 + 2 + strlen(uname) + 2 + strlen(aname); | ||
586 | fc = p9_create_common(bufp, size, P9_TATTACH); | ||
587 | if (IS_ERR(fc)) | ||
588 | goto error; | ||
589 | |||
590 | p9_put_int32(bufp, fid, &fc->params.tattach.fid); | ||
591 | p9_put_int32(bufp, afid, &fc->params.tattach.afid); | ||
592 | p9_put_str(bufp, uname, &fc->params.tattach.uname); | ||
593 | p9_put_str(bufp, aname, &fc->params.tattach.aname); | ||
594 | |||
595 | error: | ||
596 | return fc; | ||
597 | } | ||
598 | EXPORT_SYMBOL(p9_create_tattach); | ||
599 | |||
600 | struct p9_fcall *p9_create_tflush(u16 oldtag) | ||
601 | { | ||
602 | int size; | ||
603 | struct p9_fcall *fc; | ||
604 | struct cbuf buffer; | ||
605 | struct cbuf *bufp = &buffer; | ||
606 | |||
607 | size = 2; /* oldtag[2] */ | ||
608 | fc = p9_create_common(bufp, size, P9_TFLUSH); | ||
609 | if (IS_ERR(fc)) | ||
610 | goto error; | ||
611 | |||
612 | p9_put_int16(bufp, oldtag, &fc->params.tflush.oldtag); | ||
613 | |||
614 | if (buf_check_overflow(bufp)) { | ||
615 | kfree(fc); | ||
616 | fc = ERR_PTR(-ENOMEM); | ||
617 | } | ||
618 | error: | ||
619 | return fc; | ||
620 | } | ||
621 | EXPORT_SYMBOL(p9_create_tflush); | ||
622 | |||
623 | struct p9_fcall *p9_create_twalk(u32 fid, u32 newfid, u16 nwname, | ||
624 | char **wnames) | ||
625 | { | ||
626 | int i, size; | ||
627 | struct p9_fcall *fc; | ||
628 | struct cbuf buffer; | ||
629 | struct cbuf *bufp = &buffer; | ||
630 | |||
631 | if (nwname > P9_MAXWELEM) { | ||
632 | P9_DPRINTK(P9_DEBUG_ERROR, "nwname > %d\n", P9_MAXWELEM); | ||
633 | return NULL; | ||
634 | } | ||
635 | |||
636 | size = 4 + 4 + 2; /* fid[4] newfid[4] nwname[2] ... */ | ||
637 | for (i = 0; i < nwname; i++) { | ||
638 | size += 2 + strlen(wnames[i]); /* wname[s] */ | ||
639 | } | ||
640 | |||
641 | fc = p9_create_common(bufp, size, P9_TWALK); | ||
642 | if (IS_ERR(fc)) | ||
643 | goto error; | ||
644 | |||
645 | p9_put_int32(bufp, fid, &fc->params.twalk.fid); | ||
646 | p9_put_int32(bufp, newfid, &fc->params.twalk.newfid); | ||
647 | p9_put_int16(bufp, nwname, &fc->params.twalk.nwname); | ||
648 | for (i = 0; i < nwname; i++) { | ||
649 | p9_put_str(bufp, wnames[i], &fc->params.twalk.wnames[i]); | ||
650 | } | ||
651 | |||
652 | if (buf_check_overflow(bufp)) { | ||
653 | kfree(fc); | ||
654 | fc = ERR_PTR(-ENOMEM); | ||
655 | } | ||
656 | error: | ||
657 | return fc; | ||
658 | } | ||
659 | EXPORT_SYMBOL(p9_create_twalk); | ||
660 | |||
661 | struct p9_fcall *p9_create_topen(u32 fid, u8 mode) | ||
662 | { | ||
663 | int size; | ||
664 | struct p9_fcall *fc; | ||
665 | struct cbuf buffer; | ||
666 | struct cbuf *bufp = &buffer; | ||
667 | |||
668 | size = 4 + 1; /* fid[4] mode[1] */ | ||
669 | fc = p9_create_common(bufp, size, P9_TOPEN); | ||
670 | if (IS_ERR(fc)) | ||
671 | goto error; | ||
672 | |||
673 | p9_put_int32(bufp, fid, &fc->params.topen.fid); | ||
674 | p9_put_int8(bufp, mode, &fc->params.topen.mode); | ||
675 | |||
676 | if (buf_check_overflow(bufp)) { | ||
677 | kfree(fc); | ||
678 | fc = ERR_PTR(-ENOMEM); | ||
679 | } | ||
680 | error: | ||
681 | return fc; | ||
682 | } | ||
683 | EXPORT_SYMBOL(p9_create_topen); | ||
684 | |||
685 | struct p9_fcall *p9_create_tcreate(u32 fid, char *name, u32 perm, u8 mode, | ||
686 | char *extension, int dotu) | ||
687 | { | ||
688 | int size; | ||
689 | struct p9_fcall *fc; | ||
690 | struct cbuf buffer; | ||
691 | struct cbuf *bufp = &buffer; | ||
692 | |||
693 | /* fid[4] name[s] perm[4] mode[1] */ | ||
694 | size = 4 + 2 + strlen(name) + 4 + 1; | ||
695 | if (dotu) { | ||
696 | size += 2 + /* extension[s] */ | ||
697 | (extension == NULL ? 0 : strlen(extension)); | ||
698 | } | ||
699 | |||
700 | fc = p9_create_common(bufp, size, P9_TCREATE); | ||
701 | if (IS_ERR(fc)) | ||
702 | goto error; | ||
703 | |||
704 | p9_put_int32(bufp, fid, &fc->params.tcreate.fid); | ||
705 | p9_put_str(bufp, name, &fc->params.tcreate.name); | ||
706 | p9_put_int32(bufp, perm, &fc->params.tcreate.perm); | ||
707 | p9_put_int8(bufp, mode, &fc->params.tcreate.mode); | ||
708 | if (dotu) | ||
709 | p9_put_str(bufp, extension, &fc->params.tcreate.extension); | ||
710 | |||
711 | if (buf_check_overflow(bufp)) { | ||
712 | kfree(fc); | ||
713 | fc = ERR_PTR(-ENOMEM); | ||
714 | } | ||
715 | error: | ||
716 | return fc; | ||
717 | } | ||
718 | EXPORT_SYMBOL(p9_create_tcreate); | ||
719 | |||
720 | struct p9_fcall *p9_create_tread(u32 fid, u64 offset, u32 count) | ||
721 | { | ||
722 | int size; | ||
723 | struct p9_fcall *fc; | ||
724 | struct cbuf buffer; | ||
725 | struct cbuf *bufp = &buffer; | ||
726 | |||
727 | size = 4 + 8 + 4; /* fid[4] offset[8] count[4] */ | ||
728 | fc = p9_create_common(bufp, size, P9_TREAD); | ||
729 | if (IS_ERR(fc)) | ||
730 | goto error; | ||
731 | |||
732 | p9_put_int32(bufp, fid, &fc->params.tread.fid); | ||
733 | p9_put_int64(bufp, offset, &fc->params.tread.offset); | ||
734 | p9_put_int32(bufp, count, &fc->params.tread.count); | ||
735 | |||
736 | if (buf_check_overflow(bufp)) { | ||
737 | kfree(fc); | ||
738 | fc = ERR_PTR(-ENOMEM); | ||
739 | } | ||
740 | error: | ||
741 | return fc; | ||
742 | } | ||
743 | EXPORT_SYMBOL(p9_create_tread); | ||
744 | |||
745 | struct p9_fcall *p9_create_twrite(u32 fid, u64 offset, u32 count, | ||
746 | const char *data) | ||
747 | { | ||
748 | int size, err; | ||
749 | struct p9_fcall *fc; | ||
750 | struct cbuf buffer; | ||
751 | struct cbuf *bufp = &buffer; | ||
752 | |||
753 | /* fid[4] offset[8] count[4] data[count] */ | ||
754 | size = 4 + 8 + 4 + count; | ||
755 | fc = p9_create_common(bufp, size, P9_TWRITE); | ||
756 | if (IS_ERR(fc)) | ||
757 | goto error; | ||
758 | |||
759 | p9_put_int32(bufp, fid, &fc->params.twrite.fid); | ||
760 | p9_put_int64(bufp, offset, &fc->params.twrite.offset); | ||
761 | p9_put_int32(bufp, count, &fc->params.twrite.count); | ||
762 | err = p9_put_data(bufp, data, count, &fc->params.twrite.data); | ||
763 | if (err) { | ||
764 | kfree(fc); | ||
765 | fc = ERR_PTR(err); | ||
766 | } | ||
767 | |||
768 | if (buf_check_overflow(bufp)) { | ||
769 | kfree(fc); | ||
770 | fc = ERR_PTR(-ENOMEM); | ||
771 | } | ||
772 | error: | ||
773 | return fc; | ||
774 | } | ||
775 | EXPORT_SYMBOL(p9_create_twrite); | ||
776 | |||
777 | struct p9_fcall *p9_create_twrite_u(u32 fid, u64 offset, u32 count, | ||
778 | const char __user *data) | ||
779 | { | ||
780 | int size, err; | ||
781 | struct p9_fcall *fc; | ||
782 | struct cbuf buffer; | ||
783 | struct cbuf *bufp = &buffer; | ||
784 | |||
785 | /* fid[4] offset[8] count[4] data[count] */ | ||
786 | size = 4 + 8 + 4 + count; | ||
787 | fc = p9_create_common(bufp, size, P9_TWRITE); | ||
788 | if (IS_ERR(fc)) | ||
789 | goto error; | ||
790 | |||
791 | p9_put_int32(bufp, fid, &fc->params.twrite.fid); | ||
792 | p9_put_int64(bufp, offset, &fc->params.twrite.offset); | ||
793 | p9_put_int32(bufp, count, &fc->params.twrite.count); | ||
794 | err = p9_put_user_data(bufp, data, count, &fc->params.twrite.data); | ||
795 | if (err) { | ||
796 | kfree(fc); | ||
797 | fc = ERR_PTR(err); | ||
798 | } | ||
799 | |||
800 | if (buf_check_overflow(bufp)) { | ||
801 | kfree(fc); | ||
802 | fc = ERR_PTR(-ENOMEM); | ||
803 | } | ||
804 | error: | ||
805 | return fc; | ||
806 | } | ||
807 | EXPORT_SYMBOL(p9_create_twrite_u); | ||
808 | |||
809 | struct p9_fcall *p9_create_tclunk(u32 fid) | ||
810 | { | ||
811 | int size; | ||
812 | struct p9_fcall *fc; | ||
813 | struct cbuf buffer; | ||
814 | struct cbuf *bufp = &buffer; | ||
815 | |||
816 | size = 4; /* fid[4] */ | ||
817 | fc = p9_create_common(bufp, size, P9_TCLUNK); | ||
818 | if (IS_ERR(fc)) | ||
819 | goto error; | ||
820 | |||
821 | p9_put_int32(bufp, fid, &fc->params.tclunk.fid); | ||
822 | |||
823 | if (buf_check_overflow(bufp)) { | ||
824 | kfree(fc); | ||
825 | fc = ERR_PTR(-ENOMEM); | ||
826 | } | ||
827 | error: | ||
828 | return fc; | ||
829 | } | ||
830 | EXPORT_SYMBOL(p9_create_tclunk); | ||
831 | |||
832 | struct p9_fcall *p9_create_tremove(u32 fid) | ||
833 | { | ||
834 | int size; | ||
835 | struct p9_fcall *fc; | ||
836 | struct cbuf buffer; | ||
837 | struct cbuf *bufp = &buffer; | ||
838 | |||
839 | size = 4; /* fid[4] */ | ||
840 | fc = p9_create_common(bufp, size, P9_TREMOVE); | ||
841 | if (IS_ERR(fc)) | ||
842 | goto error; | ||
843 | |||
844 | p9_put_int32(bufp, fid, &fc->params.tremove.fid); | ||
845 | |||
846 | if (buf_check_overflow(bufp)) { | ||
847 | kfree(fc); | ||
848 | fc = ERR_PTR(-ENOMEM); | ||
849 | } | ||
850 | error: | ||
851 | return fc; | ||
852 | } | ||
853 | EXPORT_SYMBOL(p9_create_tremove); | ||
854 | |||
855 | struct p9_fcall *p9_create_tstat(u32 fid) | ||
856 | { | ||
857 | int size; | ||
858 | struct p9_fcall *fc; | ||
859 | struct cbuf buffer; | ||
860 | struct cbuf *bufp = &buffer; | ||
861 | |||
862 | size = 4; /* fid[4] */ | ||
863 | fc = p9_create_common(bufp, size, P9_TSTAT); | ||
864 | if (IS_ERR(fc)) | ||
865 | goto error; | ||
866 | |||
867 | p9_put_int32(bufp, fid, &fc->params.tstat.fid); | ||
868 | |||
869 | if (buf_check_overflow(bufp)) { | ||
870 | kfree(fc); | ||
871 | fc = ERR_PTR(-ENOMEM); | ||
872 | } | ||
873 | error: | ||
874 | return fc; | ||
875 | } | ||
876 | EXPORT_SYMBOL(p9_create_tstat); | ||
877 | |||
878 | struct p9_fcall *p9_create_twstat(u32 fid, struct p9_wstat *wstat, | ||
879 | int dotu) | ||
880 | { | ||
881 | int size, statsz; | ||
882 | struct p9_fcall *fc; | ||
883 | struct cbuf buffer; | ||
884 | struct cbuf *bufp = &buffer; | ||
885 | |||
886 | statsz = p9_size_wstat(wstat, dotu); | ||
887 | size = 4 + 2 + 2 + statsz; /* fid[4] stat[n] */ | ||
888 | fc = p9_create_common(bufp, size, P9_TWSTAT); | ||
889 | if (IS_ERR(fc)) | ||
890 | goto error; | ||
891 | |||
892 | p9_put_int32(bufp, fid, &fc->params.twstat.fid); | ||
893 | buf_put_int16(bufp, statsz + 2); | ||
894 | p9_put_wstat(bufp, wstat, &fc->params.twstat.stat, statsz, dotu); | ||
895 | |||
896 | if (buf_check_overflow(bufp)) { | ||
897 | kfree(fc); | ||
898 | fc = ERR_PTR(-ENOMEM); | ||
899 | } | ||
900 | error: | ||
901 | return fc; | ||
902 | } | ||
903 | EXPORT_SYMBOL(p9_create_twstat); | ||
diff --git a/net/9p/error.c b/net/9p/error.c new file mode 100644 index 000000000000..ab2458b6c903 --- /dev/null +++ b/net/9p/error.c | |||
@@ -0,0 +1,240 @@ | |||
1 | /* | ||
2 | * linux/fs/9p/error.c | ||
3 | * | ||
4 | * Error string handling | ||
5 | * | ||
6 | * Plan 9 uses error strings, Unix uses error numbers. These functions | ||
7 | * try to help manage that and provide for dynamically adding error | ||
8 | * mappings. | ||
9 | * | ||
10 | * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> | ||
11 | * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 | ||
15 | * as published by the Free Software Foundation. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to: | ||
24 | * Free Software Foundation | ||
25 | * 51 Franklin Street, Fifth Floor | ||
26 | * Boston, MA 02111-1301 USA | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | #include <linux/module.h> | ||
31 | #include <linux/list.h> | ||
32 | #include <linux/jhash.h> | ||
33 | #include <linux/errno.h> | ||
34 | #include <net/9p/9p.h> | ||
35 | |||
36 | struct errormap { | ||
37 | char *name; | ||
38 | int val; | ||
39 | |||
40 | int namelen; | ||
41 | struct hlist_node list; | ||
42 | }; | ||
43 | |||
44 | #define ERRHASHSZ 32 | ||
45 | static struct hlist_head hash_errmap[ERRHASHSZ]; | ||
46 | |||
47 | /* FixMe - reduce to a reasonable size */ | ||
48 | static struct errormap errmap[] = { | ||
49 | {"Operation not permitted", EPERM}, | ||
50 | {"wstat prohibited", EPERM}, | ||
51 | {"No such file or directory", ENOENT}, | ||
52 | {"directory entry not found", ENOENT}, | ||
53 | {"file not found", ENOENT}, | ||
54 | {"Interrupted system call", EINTR}, | ||
55 | {"Input/output error", EIO}, | ||
56 | {"No such device or address", ENXIO}, | ||
57 | {"Argument list too long", E2BIG}, | ||
58 | {"Bad file descriptor", EBADF}, | ||
59 | {"Resource temporarily unavailable", EAGAIN}, | ||
60 | {"Cannot allocate memory", ENOMEM}, | ||
61 | {"Permission denied", EACCES}, | ||
62 | {"Bad address", EFAULT}, | ||
63 | {"Block device required", ENOTBLK}, | ||
64 | {"Device or resource busy", EBUSY}, | ||
65 | {"File exists", EEXIST}, | ||
66 | {"Invalid cross-device link", EXDEV}, | ||
67 | {"No such device", ENODEV}, | ||
68 | {"Not a directory", ENOTDIR}, | ||
69 | {"Is a directory", EISDIR}, | ||
70 | {"Invalid argument", EINVAL}, | ||
71 | {"Too many open files in system", ENFILE}, | ||
72 | {"Too many open files", EMFILE}, | ||
73 | {"Text file busy", ETXTBSY}, | ||
74 | {"File too large", EFBIG}, | ||
75 | {"No space left on device", ENOSPC}, | ||
76 | {"Illegal seek", ESPIPE}, | ||
77 | {"Read-only file system", EROFS}, | ||
78 | {"Too many links", EMLINK}, | ||
79 | {"Broken pipe", EPIPE}, | ||
80 | {"Numerical argument out of domain", EDOM}, | ||
81 | {"Numerical result out of range", ERANGE}, | ||
82 | {"Resource deadlock avoided", EDEADLK}, | ||
83 | {"File name too long", ENAMETOOLONG}, | ||
84 | {"No locks available", ENOLCK}, | ||
85 | {"Function not implemented", ENOSYS}, | ||
86 | {"Directory not empty", ENOTEMPTY}, | ||
87 | {"Too many levels of symbolic links", ELOOP}, | ||
88 | {"No message of desired type", ENOMSG}, | ||
89 | {"Identifier removed", EIDRM}, | ||
90 | {"No data available", ENODATA}, | ||
91 | {"Machine is not on the network", ENONET}, | ||
92 | {"Package not installed", ENOPKG}, | ||
93 | {"Object is remote", EREMOTE}, | ||
94 | {"Link has been severed", ENOLINK}, | ||
95 | {"Communication error on send", ECOMM}, | ||
96 | {"Protocol error", EPROTO}, | ||
97 | {"Bad message", EBADMSG}, | ||
98 | {"File descriptor in bad state", EBADFD}, | ||
99 | {"Streams pipe error", ESTRPIPE}, | ||
100 | {"Too many users", EUSERS}, | ||
101 | {"Socket operation on non-socket", ENOTSOCK}, | ||
102 | {"Message too long", EMSGSIZE}, | ||
103 | {"Protocol not available", ENOPROTOOPT}, | ||
104 | {"Protocol not supported", EPROTONOSUPPORT}, | ||
105 | {"Socket type not supported", ESOCKTNOSUPPORT}, | ||
106 | {"Operation not supported", EOPNOTSUPP}, | ||
107 | {"Protocol family not supported", EPFNOSUPPORT}, | ||
108 | {"Network is down", ENETDOWN}, | ||
109 | {"Network is unreachable", ENETUNREACH}, | ||
110 | {"Network dropped connection on reset", ENETRESET}, | ||
111 | {"Software caused connection abort", ECONNABORTED}, | ||
112 | {"Connection reset by peer", ECONNRESET}, | ||
113 | {"No buffer space available", ENOBUFS}, | ||
114 | {"Transport endpoint is already connected", EISCONN}, | ||
115 | {"Transport endpoint is not connected", ENOTCONN}, | ||
116 | {"Cannot send after transport endpoint shutdown", ESHUTDOWN}, | ||
117 | {"Connection timed out", ETIMEDOUT}, | ||
118 | {"Connection refused", ECONNREFUSED}, | ||
119 | {"Host is down", EHOSTDOWN}, | ||
120 | {"No route to host", EHOSTUNREACH}, | ||
121 | {"Operation already in progress", EALREADY}, | ||
122 | {"Operation now in progress", EINPROGRESS}, | ||
123 | {"Is a named type file", EISNAM}, | ||
124 | {"Remote I/O error", EREMOTEIO}, | ||
125 | {"Disk quota exceeded", EDQUOT}, | ||
126 | /* errors from fossil, vacfs, and u9fs */ | ||
127 | {"fid unknown or out of range", EBADF}, | ||
128 | {"permission denied", EACCES}, | ||
129 | {"file does not exist", ENOENT}, | ||
130 | {"authentication failed", ECONNREFUSED}, | ||
131 | {"bad offset in directory read", ESPIPE}, | ||
132 | {"bad use of fid", EBADF}, | ||
133 | {"wstat can't convert between files and directories", EPERM}, | ||
134 | {"directory is not empty", ENOTEMPTY}, | ||
135 | {"file exists", EEXIST}, | ||
136 | {"file already exists", EEXIST}, | ||
137 | {"file or directory already exists", EEXIST}, | ||
138 | {"fid already in use", EBADF}, | ||
139 | {"file in use", ETXTBSY}, | ||
140 | {"i/o error", EIO}, | ||
141 | {"file already open for I/O", ETXTBSY}, | ||
142 | {"illegal mode", EINVAL}, | ||
143 | {"illegal name", ENAMETOOLONG}, | ||
144 | {"not a directory", ENOTDIR}, | ||
145 | {"not a member of proposed group", EPERM}, | ||
146 | {"not owner", EACCES}, | ||
147 | {"only owner can change group in wstat", EACCES}, | ||
148 | {"read only file system", EROFS}, | ||
149 | {"no access to special file", EPERM}, | ||
150 | {"i/o count too large", EIO}, | ||
151 | {"unknown group", EINVAL}, | ||
152 | {"unknown user", EINVAL}, | ||
153 | {"bogus wstat buffer", EPROTO}, | ||
154 | {"exclusive use file already open", EAGAIN}, | ||
155 | {"corrupted directory entry", EIO}, | ||
156 | {"corrupted file entry", EIO}, | ||
157 | {"corrupted block label", EIO}, | ||
158 | {"corrupted meta data", EIO}, | ||
159 | {"illegal offset", EINVAL}, | ||
160 | {"illegal path element", ENOENT}, | ||
161 | {"root of file system is corrupted", EIO}, | ||
162 | {"corrupted super block", EIO}, | ||
163 | {"protocol botch", EPROTO}, | ||
164 | {"file system is full", ENOSPC}, | ||
165 | {"file is in use", EAGAIN}, | ||
166 | {"directory entry is not allocated", ENOENT}, | ||
167 | {"file is read only", EROFS}, | ||
168 | {"file has been removed", EIDRM}, | ||
169 | {"only support truncation to zero length", EPERM}, | ||
170 | {"cannot remove root", EPERM}, | ||
171 | {"file too big", EFBIG}, | ||
172 | {"venti i/o error", EIO}, | ||
173 | /* these are not errors */ | ||
174 | {"u9fs rhostsauth: no authentication required", 0}, | ||
175 | {"u9fs authnone: no authentication required", 0}, | ||
176 | {NULL, -1} | ||
177 | }; | ||
178 | |||
179 | /** | ||
180 | * p9_error_init - preload | ||
181 | * @errstr: error string | ||
182 | * | ||
183 | */ | ||
184 | |||
185 | int p9_error_init(void) | ||
186 | { | ||
187 | struct errormap *c; | ||
188 | int bucket; | ||
189 | |||
190 | /* initialize hash table */ | ||
191 | for (bucket = 0; bucket < ERRHASHSZ; bucket++) | ||
192 | INIT_HLIST_HEAD(&hash_errmap[bucket]); | ||
193 | |||
194 | /* load initial error map into hash table */ | ||
195 | for (c = errmap; c->name != NULL; c++) { | ||
196 | c->namelen = strlen(c->name); | ||
197 | bucket = jhash(c->name, c->namelen, 0) % ERRHASHSZ; | ||
198 | INIT_HLIST_NODE(&c->list); | ||
199 | hlist_add_head(&c->list, &hash_errmap[bucket]); | ||
200 | } | ||
201 | |||
202 | return 1; | ||
203 | } | ||
204 | EXPORT_SYMBOL(p9_error_init); | ||
205 | |||
206 | /** | ||
207 | * errstr2errno - convert error string to error number | ||
208 | * @errstr: error string | ||
209 | * | ||
210 | */ | ||
211 | |||
212 | int p9_errstr2errno(char *errstr, int len) | ||
213 | { | ||
214 | int errno; | ||
215 | struct hlist_node *p; | ||
216 | struct errormap *c; | ||
217 | int bucket; | ||
218 | |||
219 | errno = 0; | ||
220 | p = NULL; | ||
221 | c = NULL; | ||
222 | bucket = jhash(errstr, len, 0) % ERRHASHSZ; | ||
223 | hlist_for_each_entry(c, p, &hash_errmap[bucket], list) { | ||
224 | if (c->namelen == len && !memcmp(c->name, errstr, len)) { | ||
225 | errno = c->val; | ||
226 | break; | ||
227 | } | ||
228 | } | ||
229 | |||
230 | if (errno == 0) { | ||
231 | /* TODO: if error isn't found, add it dynamically */ | ||
232 | errstr[len] = 0; | ||
233 | printk(KERN_ERR "%s: errstr :%s: not found\n", __FUNCTION__, | ||
234 | errstr); | ||
235 | errno = 1; | ||
236 | } | ||
237 | |||
238 | return -errno; | ||
239 | } | ||
240 | EXPORT_SYMBOL(p9_errstr2errno); | ||
diff --git a/net/9p/fcprint.c b/net/9p/fcprint.c new file mode 100644 index 000000000000..b1ae8ec57d54 --- /dev/null +++ b/net/9p/fcprint.c | |||
@@ -0,0 +1,358 @@ | |||
1 | /* | ||
2 | * net/9p/fcprint.c | ||
3 | * | ||
4 | * Print 9P call. | ||
5 | * | ||
6 | * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 | ||
10 | * as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to: | ||
19 | * Free Software Foundation | ||
20 | * 51 Franklin Street, Fifth Floor | ||
21 | * Boston, MA 02111-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/errno.h> | ||
26 | #include <linux/fs.h> | ||
27 | #include <linux/idr.h> | ||
28 | #include <net/9p/9p.h> | ||
29 | |||
30 | #ifdef CONFIG_NET_9P_DEBUG | ||
31 | |||
32 | static int | ||
33 | p9_printqid(char *buf, int buflen, struct p9_qid *q) | ||
34 | { | ||
35 | int n; | ||
36 | char b[10]; | ||
37 | |||
38 | n = 0; | ||
39 | if (q->type & P9_QTDIR) | ||
40 | b[n++] = 'd'; | ||
41 | if (q->type & P9_QTAPPEND) | ||
42 | b[n++] = 'a'; | ||
43 | if (q->type & P9_QTAUTH) | ||
44 | b[n++] = 'A'; | ||
45 | if (q->type & P9_QTEXCL) | ||
46 | b[n++] = 'l'; | ||
47 | if (q->type & P9_QTTMP) | ||
48 | b[n++] = 't'; | ||
49 | if (q->type & P9_QTSYMLINK) | ||
50 | b[n++] = 'L'; | ||
51 | b[n] = '\0'; | ||
52 | |||
53 | return scnprintf(buf, buflen, "(%.16llx %x %s)", | ||
54 | (long long int) q->path, q->version, b); | ||
55 | } | ||
56 | |||
57 | static int | ||
58 | p9_printperm(char *buf, int buflen, int perm) | ||
59 | { | ||
60 | int n; | ||
61 | char b[15]; | ||
62 | |||
63 | n = 0; | ||
64 | if (perm & P9_DMDIR) | ||
65 | b[n++] = 'd'; | ||
66 | if (perm & P9_DMAPPEND) | ||
67 | b[n++] = 'a'; | ||
68 | if (perm & P9_DMAUTH) | ||
69 | b[n++] = 'A'; | ||
70 | if (perm & P9_DMEXCL) | ||
71 | b[n++] = 'l'; | ||
72 | if (perm & P9_DMTMP) | ||
73 | b[n++] = 't'; | ||
74 | if (perm & P9_DMDEVICE) | ||
75 | b[n++] = 'D'; | ||
76 | if (perm & P9_DMSOCKET) | ||
77 | b[n++] = 'S'; | ||
78 | if (perm & P9_DMNAMEDPIPE) | ||
79 | b[n++] = 'P'; | ||
80 | if (perm & P9_DMSYMLINK) | ||
81 | b[n++] = 'L'; | ||
82 | b[n] = '\0'; | ||
83 | |||
84 | return scnprintf(buf, buflen, "%s%03o", b, perm&077); | ||
85 | } | ||
86 | |||
87 | static int | ||
88 | p9_printstat(char *buf, int buflen, struct p9_stat *st, int extended) | ||
89 | { | ||
90 | int n; | ||
91 | |||
92 | n = scnprintf(buf, buflen, "'%.*s' '%.*s'", st->name.len, | ||
93 | st->name.str, st->uid.len, st->uid.str); | ||
94 | if (extended) | ||
95 | n += scnprintf(buf+n, buflen-n, "(%d)", st->n_uid); | ||
96 | |||
97 | n += scnprintf(buf+n, buflen-n, " '%.*s'", st->gid.len, st->gid.str); | ||
98 | if (extended) | ||
99 | n += scnprintf(buf+n, buflen-n, "(%d)", st->n_gid); | ||
100 | |||
101 | n += scnprintf(buf+n, buflen-n, " '%.*s'", st->muid.len, st->muid.str); | ||
102 | if (extended) | ||
103 | n += scnprintf(buf+n, buflen-n, "(%d)", st->n_muid); | ||
104 | |||
105 | n += scnprintf(buf+n, buflen-n, " q "); | ||
106 | n += p9_printqid(buf+n, buflen-n, &st->qid); | ||
107 | n += scnprintf(buf+n, buflen-n, " m "); | ||
108 | n += p9_printperm(buf+n, buflen-n, st->mode); | ||
109 | n += scnprintf(buf+n, buflen-n, " at %d mt %d l %lld", | ||
110 | st->atime, st->mtime, (long long int) st->length); | ||
111 | |||
112 | if (extended) | ||
113 | n += scnprintf(buf+n, buflen-n, " ext '%.*s'", | ||
114 | st->extension.len, st->extension.str); | ||
115 | |||
116 | return n; | ||
117 | } | ||
118 | |||
119 | static int | ||
120 | p9_dumpdata(char *buf, int buflen, u8 *data, int datalen) | ||
121 | { | ||
122 | int i, n; | ||
123 | |||
124 | i = n = 0; | ||
125 | while (i < datalen) { | ||
126 | n += scnprintf(buf + n, buflen - n, "%02x", data[i]); | ||
127 | if (i%4 == 3) | ||
128 | n += scnprintf(buf + n, buflen - n, " "); | ||
129 | if (i%32 == 31) | ||
130 | n += scnprintf(buf + n, buflen - n, "\n"); | ||
131 | |||
132 | i++; | ||
133 | } | ||
134 | n += scnprintf(buf + n, buflen - n, "\n"); | ||
135 | |||
136 | return n; | ||
137 | } | ||
138 | |||
139 | static int | ||
140 | p9_printdata(char *buf, int buflen, u8 *data, int datalen) | ||
141 | { | ||
142 | return p9_dumpdata(buf, buflen, data, datalen < 16?datalen:16); | ||
143 | } | ||
144 | |||
145 | int | ||
146 | p9_printfcall(char *buf, int buflen, struct p9_fcall *fc, int extended) | ||
147 | { | ||
148 | int i, ret, type, tag; | ||
149 | |||
150 | if (!fc) | ||
151 | return scnprintf(buf, buflen, "<NULL>"); | ||
152 | |||
153 | type = fc->id; | ||
154 | tag = fc->tag; | ||
155 | |||
156 | ret = 0; | ||
157 | switch (type) { | ||
158 | case P9_TVERSION: | ||
159 | ret += scnprintf(buf+ret, buflen-ret, | ||
160 | "Tversion tag %u msize %u version '%.*s'", tag, | ||
161 | fc->params.tversion.msize, | ||
162 | fc->params.tversion.version.len, | ||
163 | fc->params.tversion.version.str); | ||
164 | break; | ||
165 | |||
166 | case P9_RVERSION: | ||
167 | ret += scnprintf(buf+ret, buflen-ret, | ||
168 | "Rversion tag %u msize %u version '%.*s'", tag, | ||
169 | fc->params.rversion.msize, | ||
170 | fc->params.rversion.version.len, | ||
171 | fc->params.rversion.version.str); | ||
172 | break; | ||
173 | |||
174 | case P9_TAUTH: | ||
175 | ret += scnprintf(buf+ret, buflen-ret, | ||
176 | "Tauth tag %u afid %d uname '%.*s' aname '%.*s'", tag, | ||
177 | fc->params.tauth.afid, fc->params.tauth.uname.len, | ||
178 | fc->params.tauth.uname.str, fc->params.tauth.aname.len, | ||
179 | fc->params.tauth.aname.str); | ||
180 | break; | ||
181 | |||
182 | case P9_RAUTH: | ||
183 | ret += scnprintf(buf+ret, buflen-ret, "Rauth tag %u qid ", tag); | ||
184 | p9_printqid(buf+ret, buflen-ret, &fc->params.rauth.qid); | ||
185 | break; | ||
186 | |||
187 | case P9_TATTACH: | ||
188 | ret += scnprintf(buf+ret, buflen-ret, | ||
189 | "Tattach tag %u fid %d afid %d uname '%.*s' aname '%.*s'", tag, | ||
190 | fc->params.tattach.fid, fc->params.tattach.afid, | ||
191 | fc->params.tattach.uname.len, fc->params.tattach.uname.str, | ||
192 | fc->params.tattach.aname.len, fc->params.tattach.aname.str); | ||
193 | break; | ||
194 | |||
195 | case P9_RATTACH: | ||
196 | ret += scnprintf(buf+ret, buflen-ret, "Rattach tag %u qid ", | ||
197 | tag); | ||
198 | p9_printqid(buf+ret, buflen-ret, &fc->params.rattach.qid); | ||
199 | break; | ||
200 | |||
201 | case P9_RERROR: | ||
202 | ret += scnprintf(buf+ret, buflen-ret, | ||
203 | "Rerror tag %u ename '%.*s'", tag, | ||
204 | fc->params.rerror.error.len, | ||
205 | fc->params.rerror.error.str); | ||
206 | if (extended) | ||
207 | ret += scnprintf(buf+ret, buflen-ret, " ecode %d\n", | ||
208 | fc->params.rerror.errno); | ||
209 | break; | ||
210 | |||
211 | case P9_TFLUSH: | ||
212 | ret += scnprintf(buf+ret, buflen-ret, "Tflush tag %u oldtag %u", | ||
213 | tag, fc->params.tflush.oldtag); | ||
214 | break; | ||
215 | |||
216 | case P9_RFLUSH: | ||
217 | ret += scnprintf(buf+ret, buflen-ret, "Rflush tag %u", tag); | ||
218 | break; | ||
219 | |||
220 | case P9_TWALK: | ||
221 | ret += scnprintf(buf+ret, buflen-ret, | ||
222 | "Twalk tag %u fid %d newfid %d nwname %d", tag, | ||
223 | fc->params.twalk.fid, fc->params.twalk.newfid, | ||
224 | fc->params.twalk.nwname); | ||
225 | for (i = 0; i < fc->params.twalk.nwname; i++) | ||
226 | ret += scnprintf(buf+ret, buflen-ret, " '%.*s'", | ||
227 | fc->params.twalk.wnames[i].len, | ||
228 | fc->params.twalk.wnames[i].str); | ||
229 | break; | ||
230 | |||
231 | case P9_RWALK: | ||
232 | ret += scnprintf(buf+ret, buflen-ret, "Rwalk tag %u nwqid %d", | ||
233 | tag, fc->params.rwalk.nwqid); | ||
234 | for (i = 0; i < fc->params.rwalk.nwqid; i++) | ||
235 | ret += p9_printqid(buf+ret, buflen-ret, | ||
236 | &fc->params.rwalk.wqids[i]); | ||
237 | break; | ||
238 | |||
239 | case P9_TOPEN: | ||
240 | ret += scnprintf(buf+ret, buflen-ret, | ||
241 | "Topen tag %u fid %d mode %d", tag, | ||
242 | fc->params.topen.fid, fc->params.topen.mode); | ||
243 | break; | ||
244 | |||
245 | case P9_ROPEN: | ||
246 | ret += scnprintf(buf+ret, buflen-ret, "Ropen tag %u", tag); | ||
247 | ret += p9_printqid(buf+ret, buflen-ret, &fc->params.ropen.qid); | ||
248 | ret += scnprintf(buf+ret, buflen-ret, " iounit %d", | ||
249 | fc->params.ropen.iounit); | ||
250 | break; | ||
251 | |||
252 | case P9_TCREATE: | ||
253 | ret += scnprintf(buf+ret, buflen-ret, | ||
254 | "Tcreate tag %u fid %d name '%.*s' perm ", tag, | ||
255 | fc->params.tcreate.fid, fc->params.tcreate.name.len, | ||
256 | fc->params.tcreate.name.str); | ||
257 | |||
258 | ret += p9_printperm(buf+ret, buflen-ret, | ||
259 | fc->params.tcreate.perm); | ||
260 | ret += scnprintf(buf+ret, buflen-ret, " mode %d", | ||
261 | fc->params.tcreate.mode); | ||
262 | break; | ||
263 | |||
264 | case P9_RCREATE: | ||
265 | ret += scnprintf(buf+ret, buflen-ret, "Rcreate tag %u", tag); | ||
266 | ret += p9_printqid(buf+ret, buflen-ret, | ||
267 | &fc->params.rcreate.qid); | ||
268 | ret += scnprintf(buf+ret, buflen-ret, " iounit %d", | ||
269 | fc->params.rcreate.iounit); | ||
270 | break; | ||
271 | |||
272 | case P9_TREAD: | ||
273 | ret += scnprintf(buf+ret, buflen-ret, | ||
274 | "Tread tag %u fid %d offset %lld count %u", tag, | ||
275 | fc->params.tread.fid, | ||
276 | (long long int) fc->params.tread.offset, | ||
277 | fc->params.tread.count); | ||
278 | break; | ||
279 | |||
280 | case P9_RREAD: | ||
281 | ret += scnprintf(buf+ret, buflen-ret, | ||
282 | "Rread tag %u count %u data ", tag, | ||
283 | fc->params.rread.count); | ||
284 | ret += p9_printdata(buf+ret, buflen-ret, fc->params.rread.data, | ||
285 | fc->params.rread.count); | ||
286 | break; | ||
287 | |||
288 | case P9_TWRITE: | ||
289 | ret += scnprintf(buf+ret, buflen-ret, | ||
290 | "Twrite tag %u fid %d offset %lld count %u data ", | ||
291 | tag, fc->params.twrite.fid, | ||
292 | (long long int) fc->params.twrite.offset, | ||
293 | fc->params.twrite.count); | ||
294 | ret += p9_printdata(buf+ret, buflen-ret, fc->params.twrite.data, | ||
295 | fc->params.twrite.count); | ||
296 | break; | ||
297 | |||
298 | case P9_RWRITE: | ||
299 | ret += scnprintf(buf+ret, buflen-ret, "Rwrite tag %u count %u", | ||
300 | tag, fc->params.rwrite.count); | ||
301 | break; | ||
302 | |||
303 | case P9_TCLUNK: | ||
304 | ret += scnprintf(buf+ret, buflen-ret, "Tclunk tag %u fid %d", | ||
305 | tag, fc->params.tclunk.fid); | ||
306 | break; | ||
307 | |||
308 | case P9_RCLUNK: | ||
309 | ret += scnprintf(buf+ret, buflen-ret, "Rclunk tag %u", tag); | ||
310 | break; | ||
311 | |||
312 | case P9_TREMOVE: | ||
313 | ret += scnprintf(buf+ret, buflen-ret, "Tremove tag %u fid %d", | ||
314 | tag, fc->params.tremove.fid); | ||
315 | break; | ||
316 | |||
317 | case P9_RREMOVE: | ||
318 | ret += scnprintf(buf+ret, buflen-ret, "Rremove tag %u", tag); | ||
319 | break; | ||
320 | |||
321 | case P9_TSTAT: | ||
322 | ret += scnprintf(buf+ret, buflen-ret, "Tstat tag %u fid %d", | ||
323 | tag, fc->params.tstat.fid); | ||
324 | break; | ||
325 | |||
326 | case P9_RSTAT: | ||
327 | ret += scnprintf(buf+ret, buflen-ret, "Rstat tag %u ", tag); | ||
328 | ret += p9_printstat(buf+ret, buflen-ret, &fc->params.rstat.stat, | ||
329 | extended); | ||
330 | break; | ||
331 | |||
332 | case P9_TWSTAT: | ||
333 | ret += scnprintf(buf+ret, buflen-ret, "Twstat tag %u fid %d ", | ||
334 | tag, fc->params.twstat.fid); | ||
335 | ret += p9_printstat(buf+ret, buflen-ret, | ||
336 | &fc->params.twstat.stat, extended); | ||
337 | break; | ||
338 | |||
339 | case P9_RWSTAT: | ||
340 | ret += scnprintf(buf+ret, buflen-ret, "Rwstat tag %u", tag); | ||
341 | break; | ||
342 | |||
343 | default: | ||
344 | ret += scnprintf(buf+ret, buflen-ret, "unknown type %d", type); | ||
345 | break; | ||
346 | } | ||
347 | |||
348 | return ret; | ||
349 | } | ||
350 | |||
351 | #else | ||
352 | int | ||
353 | p9_printfcall(char *buf, int buflen, struct p9_fcall *fc, int extended) | ||
354 | { | ||
355 | return 0; | ||
356 | } | ||
357 | EXPORT_SYMBOL(p9_printfcall); | ||
358 | #endif /* CONFIG_NET_9P_DEBUG */ | ||
diff --git a/net/9p/mod.c b/net/9p/mod.c new file mode 100644 index 000000000000..4f9e1d2ac257 --- /dev/null +++ b/net/9p/mod.c | |||
@@ -0,0 +1,85 @@ | |||
1 | /* | ||
2 | * net/9p/9p.c | ||
3 | * | ||
4 | * 9P entry point | ||
5 | * | ||
6 | * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net> | ||
7 | * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> | ||
8 | * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 | ||
12 | * as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to: | ||
21 | * Free Software Foundation | ||
22 | * 51 Franklin Street, Fifth Floor | ||
23 | * Boston, MA 02111-1301 USA | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include <linux/module.h> | ||
28 | #include <linux/moduleparam.h> | ||
29 | #include <net/9p/9p.h> | ||
30 | |||
31 | #ifdef CONFIG_NET_9P_DEBUG | ||
32 | unsigned int p9_debug_level = 0; /* feature-rific global debug level */ | ||
33 | EXPORT_SYMBOL(p9_debug_level); | ||
34 | module_param_named(debug, p9_debug_level, uint, 0); | ||
35 | MODULE_PARM_DESC(debug, "9P debugging level"); | ||
36 | #endif | ||
37 | |||
38 | extern int p9_mux_global_init(void); | ||
39 | extern void p9_mux_global_exit(void); | ||
40 | extern int p9_sysctl_register(void); | ||
41 | extern void p9_sysctl_unregister(void); | ||
42 | |||
43 | /** | ||
44 | * v9fs_init - Initialize module | ||
45 | * | ||
46 | */ | ||
47 | static int __init init_p9(void) | ||
48 | { | ||
49 | int ret; | ||
50 | |||
51 | p9_error_init(); | ||
52 | printk(KERN_INFO "Installing 9P2000 support\n"); | ||
53 | ret = p9_mux_global_init(); | ||
54 | if (ret) { | ||
55 | printk(KERN_WARNING "9p: starting mux failed\n"); | ||
56 | return ret; | ||
57 | } | ||
58 | |||
59 | ret = p9_sysctl_register(); | ||
60 | if (ret) { | ||
61 | printk(KERN_WARNING "9p: registering sysctl failed\n"); | ||
62 | return ret; | ||
63 | } | ||
64 | |||
65 | return ret; | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * v9fs_init - shutdown module | ||
70 | * | ||
71 | */ | ||
72 | |||
73 | static void __exit exit_p9(void) | ||
74 | { | ||
75 | p9_sysctl_unregister(); | ||
76 | p9_mux_global_exit(); | ||
77 | } | ||
78 | |||
79 | module_init(init_p9) | ||
80 | module_exit(exit_p9) | ||
81 | |||
82 | MODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>"); | ||
83 | MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>"); | ||
84 | MODULE_AUTHOR("Ron Minnich <rminnich@lanl.gov>"); | ||
85 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/9p/mux.c b/net/9p/mux.c new file mode 100644 index 000000000000..acb038810f39 --- /dev/null +++ b/net/9p/mux.c | |||
@@ -0,0 +1,1054 @@ | |||
1 | /* | ||
2 | * net/9p/mux.c | ||
3 | * | ||
4 | * Protocol Multiplexer | ||
5 | * | ||
6 | * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> | ||
7 | * Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 | ||
11 | * as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to: | ||
20 | * Free Software Foundation | ||
21 | * 51 Franklin Street, Fifth Floor | ||
22 | * Boston, MA 02111-1301 USA | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/errno.h> | ||
28 | #include <linux/fs.h> | ||
29 | #include <linux/poll.h> | ||
30 | #include <linux/kthread.h> | ||
31 | #include <linux/idr.h> | ||
32 | #include <linux/mutex.h> | ||
33 | #include <net/9p/9p.h> | ||
34 | #include <net/9p/transport.h> | ||
35 | #include <net/9p/conn.h> | ||
36 | |||
37 | #define ERREQFLUSH 1 | ||
38 | #define SCHED_TIMEOUT 10 | ||
39 | #define MAXPOLLWADDR 2 | ||
40 | |||
41 | enum { | ||
42 | Rworksched = 1, /* read work scheduled or running */ | ||
43 | Rpending = 2, /* can read */ | ||
44 | Wworksched = 4, /* write work scheduled or running */ | ||
45 | Wpending = 8, /* can write */ | ||
46 | }; | ||
47 | |||
48 | enum { | ||
49 | None, | ||
50 | Flushing, | ||
51 | Flushed, | ||
52 | }; | ||
53 | |||
54 | struct p9_mux_poll_task; | ||
55 | |||
56 | struct p9_req { | ||
57 | spinlock_t lock; /* protect request structure */ | ||
58 | int tag; | ||
59 | struct p9_fcall *tcall; | ||
60 | struct p9_fcall *rcall; | ||
61 | int err; | ||
62 | p9_conn_req_callback cb; | ||
63 | void *cba; | ||
64 | int flush; | ||
65 | struct list_head req_list; | ||
66 | }; | ||
67 | |||
68 | struct p9_conn { | ||
69 | spinlock_t lock; /* protect lock structure */ | ||
70 | struct list_head mux_list; | ||
71 | struct p9_mux_poll_task *poll_task; | ||
72 | int msize; | ||
73 | unsigned char *extended; | ||
74 | struct p9_transport *trans; | ||
75 | struct p9_idpool *tagpool; | ||
76 | int err; | ||
77 | wait_queue_head_t equeue; | ||
78 | struct list_head req_list; | ||
79 | struct list_head unsent_req_list; | ||
80 | struct p9_fcall *rcall; | ||
81 | int rpos; | ||
82 | char *rbuf; | ||
83 | int wpos; | ||
84 | int wsize; | ||
85 | char *wbuf; | ||
86 | wait_queue_t poll_wait[MAXPOLLWADDR]; | ||
87 | wait_queue_head_t *poll_waddr[MAXPOLLWADDR]; | ||
88 | poll_table pt; | ||
89 | struct work_struct rq; | ||
90 | struct work_struct wq; | ||
91 | unsigned long wsched; | ||
92 | }; | ||
93 | |||
94 | struct p9_mux_poll_task { | ||
95 | struct task_struct *task; | ||
96 | struct list_head mux_list; | ||
97 | int muxnum; | ||
98 | }; | ||
99 | |||
100 | struct p9_mux_rpc { | ||
101 | struct p9_conn *m; | ||
102 | int err; | ||
103 | struct p9_fcall *tcall; | ||
104 | struct p9_fcall *rcall; | ||
105 | wait_queue_head_t wqueue; | ||
106 | }; | ||
107 | |||
108 | static int p9_poll_proc(void *); | ||
109 | static void p9_read_work(struct work_struct *work); | ||
110 | static void p9_write_work(struct work_struct *work); | ||
111 | static void p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, | ||
112 | poll_table * p); | ||
113 | static u16 p9_mux_get_tag(struct p9_conn *); | ||
114 | static void p9_mux_put_tag(struct p9_conn *, u16); | ||
115 | |||
116 | static DEFINE_MUTEX(p9_mux_task_lock); | ||
117 | static struct workqueue_struct *p9_mux_wq; | ||
118 | |||
119 | static int p9_mux_num; | ||
120 | static int p9_mux_poll_task_num; | ||
121 | static struct p9_mux_poll_task p9_mux_poll_tasks[100]; | ||
122 | |||
123 | int p9_mux_global_init(void) | ||
124 | { | ||
125 | int i; | ||
126 | |||
127 | for (i = 0; i < ARRAY_SIZE(p9_mux_poll_tasks); i++) | ||
128 | p9_mux_poll_tasks[i].task = NULL; | ||
129 | |||
130 | p9_mux_wq = create_workqueue("v9fs"); | ||
131 | if (!p9_mux_wq) { | ||
132 | printk(KERN_WARNING "v9fs: mux: creating workqueue failed\n"); | ||
133 | return -ENOMEM; | ||
134 | } | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | void p9_mux_global_exit(void) | ||
140 | { | ||
141 | destroy_workqueue(p9_mux_wq); | ||
142 | } | ||
143 | |||
144 | /** | ||
145 | * p9_mux_calc_poll_procs - calculates the number of polling procs | ||
146 | * based on the number of mounted v9fs filesystems. | ||
147 | * | ||
148 | * The current implementation returns sqrt of the number of mounts. | ||
149 | */ | ||
150 | static int p9_mux_calc_poll_procs(int muxnum) | ||
151 | { | ||
152 | int n; | ||
153 | |||
154 | if (p9_mux_poll_task_num) | ||
155 | n = muxnum / p9_mux_poll_task_num + | ||
156 | (muxnum % p9_mux_poll_task_num ? 1 : 0); | ||
157 | else | ||
158 | n = 1; | ||
159 | |||
160 | if (n > ARRAY_SIZE(p9_mux_poll_tasks)) | ||
161 | n = ARRAY_SIZE(p9_mux_poll_tasks); | ||
162 | |||
163 | return n; | ||
164 | } | ||
165 | |||
166 | static int p9_mux_poll_start(struct p9_conn *m) | ||
167 | { | ||
168 | int i, n; | ||
169 | struct p9_mux_poll_task *vpt, *vptlast; | ||
170 | struct task_struct *pproc; | ||
171 | |||
172 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p muxnum %d procnum %d\n", m, p9_mux_num, | ||
173 | p9_mux_poll_task_num); | ||
174 | mutex_lock(&p9_mux_task_lock); | ||
175 | |||
176 | n = p9_mux_calc_poll_procs(p9_mux_num + 1); | ||
177 | if (n > p9_mux_poll_task_num) { | ||
178 | for (i = 0; i < ARRAY_SIZE(p9_mux_poll_tasks); i++) { | ||
179 | if (p9_mux_poll_tasks[i].task == NULL) { | ||
180 | vpt = &p9_mux_poll_tasks[i]; | ||
181 | P9_DPRINTK(P9_DEBUG_MUX, "create proc %p\n", | ||
182 | vpt); | ||
183 | pproc = kthread_create(p9_poll_proc, vpt, | ||
184 | "v9fs-poll"); | ||
185 | |||
186 | if (!IS_ERR(pproc)) { | ||
187 | vpt->task = pproc; | ||
188 | INIT_LIST_HEAD(&vpt->mux_list); | ||
189 | vpt->muxnum = 0; | ||
190 | p9_mux_poll_task_num++; | ||
191 | wake_up_process(vpt->task); | ||
192 | } | ||
193 | break; | ||
194 | } | ||
195 | } | ||
196 | |||
197 | if (i >= ARRAY_SIZE(p9_mux_poll_tasks)) | ||
198 | P9_DPRINTK(P9_DEBUG_ERROR, | ||
199 | "warning: no free poll slots\n"); | ||
200 | } | ||
201 | |||
202 | n = (p9_mux_num + 1) / p9_mux_poll_task_num + | ||
203 | ((p9_mux_num + 1) % p9_mux_poll_task_num ? 1 : 0); | ||
204 | |||
205 | vptlast = NULL; | ||
206 | for (i = 0; i < ARRAY_SIZE(p9_mux_poll_tasks); i++) { | ||
207 | vpt = &p9_mux_poll_tasks[i]; | ||
208 | if (vpt->task != NULL) { | ||
209 | vptlast = vpt; | ||
210 | if (vpt->muxnum < n) { | ||
211 | P9_DPRINTK(P9_DEBUG_MUX, "put in proc %d\n", i); | ||
212 | list_add(&m->mux_list, &vpt->mux_list); | ||
213 | vpt->muxnum++; | ||
214 | m->poll_task = vpt; | ||
215 | memset(&m->poll_waddr, 0, | ||
216 | sizeof(m->poll_waddr)); | ||
217 | init_poll_funcptr(&m->pt, p9_pollwait); | ||
218 | break; | ||
219 | } | ||
220 | } | ||
221 | } | ||
222 | |||
223 | if (i >= ARRAY_SIZE(p9_mux_poll_tasks)) { | ||
224 | if (vptlast == NULL) | ||
225 | return -ENOMEM; | ||
226 | |||
227 | P9_DPRINTK(P9_DEBUG_MUX, "put in proc %d\n", i); | ||
228 | list_add(&m->mux_list, &vptlast->mux_list); | ||
229 | vptlast->muxnum++; | ||
230 | m->poll_task = vptlast; | ||
231 | memset(&m->poll_waddr, 0, sizeof(m->poll_waddr)); | ||
232 | init_poll_funcptr(&m->pt, p9_pollwait); | ||
233 | } | ||
234 | |||
235 | p9_mux_num++; | ||
236 | mutex_unlock(&p9_mux_task_lock); | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | static void p9_mux_poll_stop(struct p9_conn *m) | ||
242 | { | ||
243 | int i; | ||
244 | struct p9_mux_poll_task *vpt; | ||
245 | |||
246 | mutex_lock(&p9_mux_task_lock); | ||
247 | vpt = m->poll_task; | ||
248 | list_del(&m->mux_list); | ||
249 | for (i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) { | ||
250 | if (m->poll_waddr[i] != NULL) { | ||
251 | remove_wait_queue(m->poll_waddr[i], &m->poll_wait[i]); | ||
252 | m->poll_waddr[i] = NULL; | ||
253 | } | ||
254 | } | ||
255 | vpt->muxnum--; | ||
256 | if (!vpt->muxnum) { | ||
257 | P9_DPRINTK(P9_DEBUG_MUX, "destroy proc %p\n", vpt); | ||
258 | kthread_stop(vpt->task); | ||
259 | vpt->task = NULL; | ||
260 | p9_mux_poll_task_num--; | ||
261 | } | ||
262 | p9_mux_num--; | ||
263 | mutex_unlock(&p9_mux_task_lock); | ||
264 | } | ||
265 | |||
266 | /** | ||
267 | * p9_conn_create - allocate and initialize the per-session mux data | ||
268 | * Creates the polling task if this is the first session. | ||
269 | * | ||
270 | * @trans - transport structure | ||
271 | * @msize - maximum message size | ||
272 | * @extended - pointer to the extended flag | ||
273 | */ | ||
274 | struct p9_conn *p9_conn_create(struct p9_transport *trans, int msize, | ||
275 | unsigned char *extended) | ||
276 | { | ||
277 | int i, n; | ||
278 | struct p9_conn *m, *mtmp; | ||
279 | |||
280 | P9_DPRINTK(P9_DEBUG_MUX, "transport %p msize %d\n", trans, msize); | ||
281 | m = kmalloc(sizeof(struct p9_conn), GFP_KERNEL); | ||
282 | if (!m) | ||
283 | return ERR_PTR(-ENOMEM); | ||
284 | |||
285 | spin_lock_init(&m->lock); | ||
286 | INIT_LIST_HEAD(&m->mux_list); | ||
287 | m->msize = msize; | ||
288 | m->extended = extended; | ||
289 | m->trans = trans; | ||
290 | m->tagpool = p9_idpool_create(); | ||
291 | if (!m->tagpool) { | ||
292 | kfree(m); | ||
293 | return ERR_PTR(PTR_ERR(m->tagpool)); | ||
294 | } | ||
295 | |||
296 | m->err = 0; | ||
297 | init_waitqueue_head(&m->equeue); | ||
298 | INIT_LIST_HEAD(&m->req_list); | ||
299 | INIT_LIST_HEAD(&m->unsent_req_list); | ||
300 | m->rcall = NULL; | ||
301 | m->rpos = 0; | ||
302 | m->rbuf = NULL; | ||
303 | m->wpos = m->wsize = 0; | ||
304 | m->wbuf = NULL; | ||
305 | INIT_WORK(&m->rq, p9_read_work); | ||
306 | INIT_WORK(&m->wq, p9_write_work); | ||
307 | m->wsched = 0; | ||
308 | memset(&m->poll_waddr, 0, sizeof(m->poll_waddr)); | ||
309 | m->poll_task = NULL; | ||
310 | n = p9_mux_poll_start(m); | ||
311 | if (n) | ||
312 | return ERR_PTR(n); | ||
313 | |||
314 | n = trans->poll(trans, &m->pt); | ||
315 | if (n & POLLIN) { | ||
316 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p can read\n", m); | ||
317 | set_bit(Rpending, &m->wsched); | ||
318 | } | ||
319 | |||
320 | if (n & POLLOUT) { | ||
321 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p can write\n", m); | ||
322 | set_bit(Wpending, &m->wsched); | ||
323 | } | ||
324 | |||
325 | for (i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) { | ||
326 | if (IS_ERR(m->poll_waddr[i])) { | ||
327 | p9_mux_poll_stop(m); | ||
328 | mtmp = (void *)m->poll_waddr; /* the error code */ | ||
329 | kfree(m); | ||
330 | m = mtmp; | ||
331 | break; | ||
332 | } | ||
333 | } | ||
334 | |||
335 | return m; | ||
336 | } | ||
337 | EXPORT_SYMBOL(p9_conn_create); | ||
338 | |||
339 | /** | ||
340 | * p9_mux_destroy - cancels all pending requests and frees mux resources | ||
341 | */ | ||
342 | void p9_conn_destroy(struct p9_conn *m) | ||
343 | { | ||
344 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p prev %p next %p\n", m, | ||
345 | m->mux_list.prev, m->mux_list.next); | ||
346 | p9_conn_cancel(m, -ECONNRESET); | ||
347 | |||
348 | if (!list_empty(&m->req_list)) { | ||
349 | /* wait until all processes waiting on this session exit */ | ||
350 | P9_DPRINTK(P9_DEBUG_MUX, | ||
351 | "mux %p waiting for empty request queue\n", m); | ||
352 | wait_event_timeout(m->equeue, (list_empty(&m->req_list)), 5000); | ||
353 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p request queue empty: %d\n", m, | ||
354 | list_empty(&m->req_list)); | ||
355 | } | ||
356 | |||
357 | p9_mux_poll_stop(m); | ||
358 | m->trans = NULL; | ||
359 | p9_idpool_destroy(m->tagpool); | ||
360 | kfree(m); | ||
361 | } | ||
362 | EXPORT_SYMBOL(p9_conn_destroy); | ||
363 | |||
364 | /** | ||
365 | * p9_pollwait - called by files poll operation to add v9fs-poll task | ||
366 | * to files wait queue | ||
367 | */ | ||
368 | static void | ||
369 | p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, | ||
370 | poll_table * p) | ||
371 | { | ||
372 | int i; | ||
373 | struct p9_conn *m; | ||
374 | |||
375 | m = container_of(p, struct p9_conn, pt); | ||
376 | for (i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) | ||
377 | if (m->poll_waddr[i] == NULL) | ||
378 | break; | ||
379 | |||
380 | if (i >= ARRAY_SIZE(m->poll_waddr)) { | ||
381 | P9_DPRINTK(P9_DEBUG_ERROR, "not enough wait_address slots\n"); | ||
382 | return; | ||
383 | } | ||
384 | |||
385 | m->poll_waddr[i] = wait_address; | ||
386 | |||
387 | if (!wait_address) { | ||
388 | P9_DPRINTK(P9_DEBUG_ERROR, "no wait_address\n"); | ||
389 | m->poll_waddr[i] = ERR_PTR(-EIO); | ||
390 | return; | ||
391 | } | ||
392 | |||
393 | init_waitqueue_entry(&m->poll_wait[i], m->poll_task->task); | ||
394 | add_wait_queue(wait_address, &m->poll_wait[i]); | ||
395 | } | ||
396 | |||
397 | /** | ||
398 | * p9_poll_mux - polls a mux and schedules read or write works if necessary | ||
399 | */ | ||
400 | static void p9_poll_mux(struct p9_conn *m) | ||
401 | { | ||
402 | int n; | ||
403 | |||
404 | if (m->err < 0) | ||
405 | return; | ||
406 | |||
407 | n = m->trans->poll(m->trans, NULL); | ||
408 | if (n < 0 || n & (POLLERR | POLLHUP | POLLNVAL)) { | ||
409 | P9_DPRINTK(P9_DEBUG_MUX, "error mux %p err %d\n", m, n); | ||
410 | if (n >= 0) | ||
411 | n = -ECONNRESET; | ||
412 | p9_conn_cancel(m, n); | ||
413 | } | ||
414 | |||
415 | if (n & POLLIN) { | ||
416 | set_bit(Rpending, &m->wsched); | ||
417 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p can read\n", m); | ||
418 | if (!test_and_set_bit(Rworksched, &m->wsched)) { | ||
419 | P9_DPRINTK(P9_DEBUG_MUX, "schedule read work %p\n", m); | ||
420 | queue_work(p9_mux_wq, &m->rq); | ||
421 | } | ||
422 | } | ||
423 | |||
424 | if (n & POLLOUT) { | ||
425 | set_bit(Wpending, &m->wsched); | ||
426 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p can write\n", m); | ||
427 | if ((m->wsize || !list_empty(&m->unsent_req_list)) | ||
428 | && !test_and_set_bit(Wworksched, &m->wsched)) { | ||
429 | P9_DPRINTK(P9_DEBUG_MUX, "schedule write work %p\n", m); | ||
430 | queue_work(p9_mux_wq, &m->wq); | ||
431 | } | ||
432 | } | ||
433 | } | ||
434 | |||
435 | /** | ||
436 | * p9_poll_proc - polls all v9fs transports for new events and queues | ||
437 | * the appropriate work to the work queue | ||
438 | */ | ||
439 | static int p9_poll_proc(void *a) | ||
440 | { | ||
441 | struct p9_conn *m, *mtmp; | ||
442 | struct p9_mux_poll_task *vpt; | ||
443 | |||
444 | vpt = a; | ||
445 | P9_DPRINTK(P9_DEBUG_MUX, "start %p %p\n", current, vpt); | ||
446 | while (!kthread_should_stop()) { | ||
447 | set_current_state(TASK_INTERRUPTIBLE); | ||
448 | |||
449 | list_for_each_entry_safe(m, mtmp, &vpt->mux_list, mux_list) { | ||
450 | p9_poll_mux(m); | ||
451 | } | ||
452 | |||
453 | P9_DPRINTK(P9_DEBUG_MUX, "sleeping...\n"); | ||
454 | schedule_timeout(SCHED_TIMEOUT * HZ); | ||
455 | } | ||
456 | |||
457 | __set_current_state(TASK_RUNNING); | ||
458 | P9_DPRINTK(P9_DEBUG_MUX, "finish\n"); | ||
459 | return 0; | ||
460 | } | ||
461 | |||
462 | /** | ||
463 | * p9_write_work - called when a transport can send some data | ||
464 | */ | ||
465 | static void p9_write_work(struct work_struct *work) | ||
466 | { | ||
467 | int n, err; | ||
468 | struct p9_conn *m; | ||
469 | struct p9_req *req; | ||
470 | |||
471 | m = container_of(work, struct p9_conn, wq); | ||
472 | |||
473 | if (m->err < 0) { | ||
474 | clear_bit(Wworksched, &m->wsched); | ||
475 | return; | ||
476 | } | ||
477 | |||
478 | if (!m->wsize) { | ||
479 | if (list_empty(&m->unsent_req_list)) { | ||
480 | clear_bit(Wworksched, &m->wsched); | ||
481 | return; | ||
482 | } | ||
483 | |||
484 | spin_lock(&m->lock); | ||
485 | again: | ||
486 | req = list_entry(m->unsent_req_list.next, struct p9_req, | ||
487 | req_list); | ||
488 | list_move_tail(&req->req_list, &m->req_list); | ||
489 | if (req->err == ERREQFLUSH) | ||
490 | goto again; | ||
491 | |||
492 | m->wbuf = req->tcall->sdata; | ||
493 | m->wsize = req->tcall->size; | ||
494 | m->wpos = 0; | ||
495 | spin_unlock(&m->lock); | ||
496 | } | ||
497 | |||
498 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p pos %d size %d\n", m, m->wpos, | ||
499 | m->wsize); | ||
500 | clear_bit(Wpending, &m->wsched); | ||
501 | err = m->trans->write(m->trans, m->wbuf + m->wpos, m->wsize - m->wpos); | ||
502 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p sent %d bytes\n", m, err); | ||
503 | if (err == -EAGAIN) { | ||
504 | clear_bit(Wworksched, &m->wsched); | ||
505 | return; | ||
506 | } | ||
507 | |||
508 | if (err < 0) | ||
509 | goto error; | ||
510 | else if (err == 0) { | ||
511 | err = -EREMOTEIO; | ||
512 | goto error; | ||
513 | } | ||
514 | |||
515 | m->wpos += err; | ||
516 | if (m->wpos == m->wsize) | ||
517 | m->wpos = m->wsize = 0; | ||
518 | |||
519 | if (m->wsize == 0 && !list_empty(&m->unsent_req_list)) { | ||
520 | if (test_and_clear_bit(Wpending, &m->wsched)) | ||
521 | n = POLLOUT; | ||
522 | else | ||
523 | n = m->trans->poll(m->trans, NULL); | ||
524 | |||
525 | if (n & POLLOUT) { | ||
526 | P9_DPRINTK(P9_DEBUG_MUX, "schedule write work %p\n", m); | ||
527 | queue_work(p9_mux_wq, &m->wq); | ||
528 | } else | ||
529 | clear_bit(Wworksched, &m->wsched); | ||
530 | } else | ||
531 | clear_bit(Wworksched, &m->wsched); | ||
532 | |||
533 | return; | ||
534 | |||
535 | error: | ||
536 | p9_conn_cancel(m, err); | ||
537 | clear_bit(Wworksched, &m->wsched); | ||
538 | } | ||
539 | |||
540 | static void process_request(struct p9_conn *m, struct p9_req *req) | ||
541 | { | ||
542 | int ecode; | ||
543 | struct p9_str *ename; | ||
544 | |||
545 | if (!req->err && req->rcall->id == P9_RERROR) { | ||
546 | ecode = req->rcall->params.rerror.errno; | ||
547 | ename = &req->rcall->params.rerror.error; | ||
548 | |||
549 | P9_DPRINTK(P9_DEBUG_MUX, "Rerror %.*s\n", ename->len, | ||
550 | ename->str); | ||
551 | |||
552 | if (*m->extended) | ||
553 | req->err = -ecode; | ||
554 | |||
555 | if (!req->err) { | ||
556 | req->err = p9_errstr2errno(ename->str, ename->len); | ||
557 | |||
558 | if (!req->err) { /* string match failed */ | ||
559 | PRINT_FCALL_ERROR("unknown error", req->rcall); | ||
560 | } | ||
561 | |||
562 | if (!req->err) | ||
563 | req->err = -ESERVERFAULT; | ||
564 | } | ||
565 | } else if (req->tcall && req->rcall->id != req->tcall->id + 1) { | ||
566 | P9_DPRINTK(P9_DEBUG_ERROR, | ||
567 | "fcall mismatch: expected %d, got %d\n", | ||
568 | req->tcall->id + 1, req->rcall->id); | ||
569 | if (!req->err) | ||
570 | req->err = -EIO; | ||
571 | } | ||
572 | } | ||
573 | |||
574 | /** | ||
575 | * p9_read_work - called when there is some data to be read from a transport | ||
576 | */ | ||
577 | static void p9_read_work(struct work_struct *work) | ||
578 | { | ||
579 | int n, err; | ||
580 | struct p9_conn *m; | ||
581 | struct p9_req *req, *rptr, *rreq; | ||
582 | struct p9_fcall *rcall; | ||
583 | char *rbuf; | ||
584 | |||
585 | m = container_of(work, struct p9_conn, rq); | ||
586 | |||
587 | if (m->err < 0) | ||
588 | return; | ||
589 | |||
590 | rcall = NULL; | ||
591 | P9_DPRINTK(P9_DEBUG_MUX, "start mux %p pos %d\n", m, m->rpos); | ||
592 | |||
593 | if (!m->rcall) { | ||
594 | m->rcall = | ||
595 | kmalloc(sizeof(struct p9_fcall) + m->msize, GFP_KERNEL); | ||
596 | if (!m->rcall) { | ||
597 | err = -ENOMEM; | ||
598 | goto error; | ||
599 | } | ||
600 | |||
601 | m->rbuf = (char *)m->rcall + sizeof(struct p9_fcall); | ||
602 | m->rpos = 0; | ||
603 | } | ||
604 | |||
605 | clear_bit(Rpending, &m->wsched); | ||
606 | err = m->trans->read(m->trans, m->rbuf + m->rpos, m->msize - m->rpos); | ||
607 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p got %d bytes\n", m, err); | ||
608 | if (err == -EAGAIN) { | ||
609 | clear_bit(Rworksched, &m->wsched); | ||
610 | return; | ||
611 | } | ||
612 | |||
613 | if (err <= 0) | ||
614 | goto error; | ||
615 | |||
616 | m->rpos += err; | ||
617 | while (m->rpos > 4) { | ||
618 | n = le32_to_cpu(*(__le32 *) m->rbuf); | ||
619 | if (n >= m->msize) { | ||
620 | P9_DPRINTK(P9_DEBUG_ERROR, | ||
621 | "requested packet size too big: %d\n", n); | ||
622 | err = -EIO; | ||
623 | goto error; | ||
624 | } | ||
625 | |||
626 | if (m->rpos < n) | ||
627 | break; | ||
628 | |||
629 | err = | ||
630 | p9_deserialize_fcall(m->rbuf, n, m->rcall, *m->extended); | ||
631 | if (err < 0) { | ||
632 | goto error; | ||
633 | } | ||
634 | |||
635 | #ifdef CONFIG_NET_9P_DEBUG | ||
636 | if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) { | ||
637 | char buf[150]; | ||
638 | |||
639 | p9_printfcall(buf, sizeof(buf), m->rcall, | ||
640 | *m->extended); | ||
641 | printk(KERN_NOTICE ">>> %p %s\n", m, buf); | ||
642 | } | ||
643 | #endif | ||
644 | |||
645 | rcall = m->rcall; | ||
646 | rbuf = m->rbuf; | ||
647 | if (m->rpos > n) { | ||
648 | m->rcall = kmalloc(sizeof(struct p9_fcall) + m->msize, | ||
649 | GFP_KERNEL); | ||
650 | if (!m->rcall) { | ||
651 | err = -ENOMEM; | ||
652 | goto error; | ||
653 | } | ||
654 | |||
655 | m->rbuf = (char *)m->rcall + sizeof(struct p9_fcall); | ||
656 | memmove(m->rbuf, rbuf + n, m->rpos - n); | ||
657 | m->rpos -= n; | ||
658 | } else { | ||
659 | m->rcall = NULL; | ||
660 | m->rbuf = NULL; | ||
661 | m->rpos = 0; | ||
662 | } | ||
663 | |||
664 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p fcall id %d tag %d\n", m, | ||
665 | rcall->id, rcall->tag); | ||
666 | |||
667 | req = NULL; | ||
668 | spin_lock(&m->lock); | ||
669 | list_for_each_entry_safe(rreq, rptr, &m->req_list, req_list) { | ||
670 | if (rreq->tag == rcall->tag) { | ||
671 | req = rreq; | ||
672 | if (req->flush != Flushing) | ||
673 | list_del(&req->req_list); | ||
674 | break; | ||
675 | } | ||
676 | } | ||
677 | spin_unlock(&m->lock); | ||
678 | |||
679 | if (req) { | ||
680 | req->rcall = rcall; | ||
681 | process_request(m, req); | ||
682 | |||
683 | if (req->flush != Flushing) { | ||
684 | if (req->cb) | ||
685 | (*req->cb) (req, req->cba); | ||
686 | else | ||
687 | kfree(req->rcall); | ||
688 | |||
689 | wake_up(&m->equeue); | ||
690 | } | ||
691 | } else { | ||
692 | if (err >= 0 && rcall->id != P9_RFLUSH) | ||
693 | P9_DPRINTK(P9_DEBUG_ERROR, | ||
694 | "unexpected response mux %p id %d tag %d\n", | ||
695 | m, rcall->id, rcall->tag); | ||
696 | kfree(rcall); | ||
697 | } | ||
698 | } | ||
699 | |||
700 | if (!list_empty(&m->req_list)) { | ||
701 | if (test_and_clear_bit(Rpending, &m->wsched)) | ||
702 | n = POLLIN; | ||
703 | else | ||
704 | n = m->trans->poll(m->trans, NULL); | ||
705 | |||
706 | if (n & POLLIN) { | ||
707 | P9_DPRINTK(P9_DEBUG_MUX, "schedule read work %p\n", m); | ||
708 | queue_work(p9_mux_wq, &m->rq); | ||
709 | } else | ||
710 | clear_bit(Rworksched, &m->wsched); | ||
711 | } else | ||
712 | clear_bit(Rworksched, &m->wsched); | ||
713 | |||
714 | return; | ||
715 | |||
716 | error: | ||
717 | p9_conn_cancel(m, err); | ||
718 | clear_bit(Rworksched, &m->wsched); | ||
719 | } | ||
720 | |||
721 | /** | ||
722 | * p9_send_request - send 9P request | ||
723 | * The function can sleep until the request is scheduled for sending. | ||
724 | * The function can be interrupted. Return from the function is not | ||
725 | * a guarantee that the request is sent successfully. Can return errors | ||
726 | * that can be retrieved by PTR_ERR macros. | ||
727 | * | ||
728 | * @m: mux data | ||
729 | * @tc: request to be sent | ||
730 | * @cb: callback function to call when response is received | ||
731 | * @cba: parameter to pass to the callback function | ||
732 | */ | ||
733 | static struct p9_req *p9_send_request(struct p9_conn *m, | ||
734 | struct p9_fcall *tc, | ||
735 | p9_conn_req_callback cb, void *cba) | ||
736 | { | ||
737 | int n; | ||
738 | struct p9_req *req; | ||
739 | |||
740 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p task %p tcall %p id %d\n", m, current, | ||
741 | tc, tc->id); | ||
742 | if (m->err < 0) | ||
743 | return ERR_PTR(m->err); | ||
744 | |||
745 | req = kmalloc(sizeof(struct p9_req), GFP_KERNEL); | ||
746 | if (!req) | ||
747 | return ERR_PTR(-ENOMEM); | ||
748 | |||
749 | if (tc->id == P9_TVERSION) | ||
750 | n = P9_NOTAG; | ||
751 | else | ||
752 | n = p9_mux_get_tag(m); | ||
753 | |||
754 | if (n < 0) | ||
755 | return ERR_PTR(-ENOMEM); | ||
756 | |||
757 | p9_set_tag(tc, n); | ||
758 | |||
759 | #ifdef CONFIG_NET_9P_DEBUG | ||
760 | if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) { | ||
761 | char buf[150]; | ||
762 | |||
763 | p9_printfcall(buf, sizeof(buf), tc, *m->extended); | ||
764 | printk(KERN_NOTICE "<<< %p %s\n", m, buf); | ||
765 | } | ||
766 | #endif | ||
767 | |||
768 | spin_lock_init(&req->lock); | ||
769 | req->tag = n; | ||
770 | req->tcall = tc; | ||
771 | req->rcall = NULL; | ||
772 | req->err = 0; | ||
773 | req->cb = cb; | ||
774 | req->cba = cba; | ||
775 | req->flush = None; | ||
776 | |||
777 | spin_lock(&m->lock); | ||
778 | list_add_tail(&req->req_list, &m->unsent_req_list); | ||
779 | spin_unlock(&m->lock); | ||
780 | |||
781 | if (test_and_clear_bit(Wpending, &m->wsched)) | ||
782 | n = POLLOUT; | ||
783 | else | ||
784 | n = m->trans->poll(m->trans, NULL); | ||
785 | |||
786 | if (n & POLLOUT && !test_and_set_bit(Wworksched, &m->wsched)) | ||
787 | queue_work(p9_mux_wq, &m->wq); | ||
788 | |||
789 | return req; | ||
790 | } | ||
791 | |||
792 | static void p9_mux_free_request(struct p9_conn *m, struct p9_req *req) | ||
793 | { | ||
794 | p9_mux_put_tag(m, req->tag); | ||
795 | kfree(req); | ||
796 | } | ||
797 | |||
798 | static void p9_mux_flush_cb(struct p9_req *freq, void *a) | ||
799 | { | ||
800 | p9_conn_req_callback cb; | ||
801 | int tag; | ||
802 | struct p9_conn *m; | ||
803 | struct p9_req *req, *rreq, *rptr; | ||
804 | |||
805 | m = a; | ||
806 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p tc %p rc %p err %d oldtag %d\n", m, | ||
807 | freq->tcall, freq->rcall, freq->err, | ||
808 | freq->tcall->params.tflush.oldtag); | ||
809 | |||
810 | spin_lock(&m->lock); | ||
811 | cb = NULL; | ||
812 | tag = freq->tcall->params.tflush.oldtag; | ||
813 | req = NULL; | ||
814 | list_for_each_entry_safe(rreq, rptr, &m->req_list, req_list) { | ||
815 | if (rreq->tag == tag) { | ||
816 | req = rreq; | ||
817 | list_del(&req->req_list); | ||
818 | break; | ||
819 | } | ||
820 | } | ||
821 | spin_unlock(&m->lock); | ||
822 | |||
823 | if (req) { | ||
824 | spin_lock(&req->lock); | ||
825 | req->flush = Flushed; | ||
826 | spin_unlock(&req->lock); | ||
827 | |||
828 | if (req->cb) | ||
829 | (*req->cb) (req, req->cba); | ||
830 | else | ||
831 | kfree(req->rcall); | ||
832 | |||
833 | wake_up(&m->equeue); | ||
834 | } | ||
835 | |||
836 | kfree(freq->tcall); | ||
837 | kfree(freq->rcall); | ||
838 | p9_mux_free_request(m, freq); | ||
839 | } | ||
840 | |||
841 | static int | ||
842 | p9_mux_flush_request(struct p9_conn *m, struct p9_req *req) | ||
843 | { | ||
844 | struct p9_fcall *fc; | ||
845 | struct p9_req *rreq, *rptr; | ||
846 | |||
847 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag); | ||
848 | |||
849 | /* if a response was received for a request, do nothing */ | ||
850 | spin_lock(&req->lock); | ||
851 | if (req->rcall || req->err) { | ||
852 | spin_unlock(&req->lock); | ||
853 | P9_DPRINTK(P9_DEBUG_MUX, | ||
854 | "mux %p req %p response already received\n", m, req); | ||
855 | return 0; | ||
856 | } | ||
857 | |||
858 | req->flush = Flushing; | ||
859 | spin_unlock(&req->lock); | ||
860 | |||
861 | spin_lock(&m->lock); | ||
862 | /* if the request is not sent yet, just remove it from the list */ | ||
863 | list_for_each_entry_safe(rreq, rptr, &m->unsent_req_list, req_list) { | ||
864 | if (rreq->tag == req->tag) { | ||
865 | P9_DPRINTK(P9_DEBUG_MUX, | ||
866 | "mux %p req %p request is not sent yet\n", m, req); | ||
867 | list_del(&rreq->req_list); | ||
868 | req->flush = Flushed; | ||
869 | spin_unlock(&m->lock); | ||
870 | if (req->cb) | ||
871 | (*req->cb) (req, req->cba); | ||
872 | return 0; | ||
873 | } | ||
874 | } | ||
875 | spin_unlock(&m->lock); | ||
876 | |||
877 | clear_thread_flag(TIF_SIGPENDING); | ||
878 | fc = p9_create_tflush(req->tag); | ||
879 | p9_send_request(m, fc, p9_mux_flush_cb, m); | ||
880 | return 1; | ||
881 | } | ||
882 | |||
883 | static void | ||
884 | p9_conn_rpc_cb(struct p9_req *req, void *a) | ||
885 | { | ||
886 | struct p9_mux_rpc *r; | ||
887 | |||
888 | P9_DPRINTK(P9_DEBUG_MUX, "req %p r %p\n", req, a); | ||
889 | r = a; | ||
890 | r->rcall = req->rcall; | ||
891 | r->err = req->err; | ||
892 | |||
893 | if (req->flush != None && !req->err) | ||
894 | r->err = -ERESTARTSYS; | ||
895 | |||
896 | wake_up(&r->wqueue); | ||
897 | } | ||
898 | |||
899 | /** | ||
900 | * p9_mux_rpc - sends 9P request and waits until a response is available. | ||
901 | * The function can be interrupted. | ||
902 | * @m: mux data | ||
903 | * @tc: request to be sent | ||
904 | * @rc: pointer where a pointer to the response is stored | ||
905 | */ | ||
906 | int | ||
907 | p9_conn_rpc(struct p9_conn *m, struct p9_fcall *tc, | ||
908 | struct p9_fcall **rc) | ||
909 | { | ||
910 | int err, sigpending; | ||
911 | unsigned long flags; | ||
912 | struct p9_req *req; | ||
913 | struct p9_mux_rpc r; | ||
914 | |||
915 | r.err = 0; | ||
916 | r.tcall = tc; | ||
917 | r.rcall = NULL; | ||
918 | r.m = m; | ||
919 | init_waitqueue_head(&r.wqueue); | ||
920 | |||
921 | if (rc) | ||
922 | *rc = NULL; | ||
923 | |||
924 | sigpending = 0; | ||
925 | if (signal_pending(current)) { | ||
926 | sigpending = 1; | ||
927 | clear_thread_flag(TIF_SIGPENDING); | ||
928 | } | ||
929 | |||
930 | req = p9_send_request(m, tc, p9_conn_rpc_cb, &r); | ||
931 | if (IS_ERR(req)) { | ||
932 | err = PTR_ERR(req); | ||
933 | P9_DPRINTK(P9_DEBUG_MUX, "error %d\n", err); | ||
934 | return err; | ||
935 | } | ||
936 | |||
937 | err = wait_event_interruptible(r.wqueue, r.rcall != NULL || r.err < 0); | ||
938 | if (r.err < 0) | ||
939 | err = r.err; | ||
940 | |||
941 | if (err == -ERESTARTSYS && m->trans->status == Connected | ||
942 | && m->err == 0) { | ||
943 | if (p9_mux_flush_request(m, req)) { | ||
944 | /* wait until we get response of the flush message */ | ||
945 | do { | ||
946 | clear_thread_flag(TIF_SIGPENDING); | ||
947 | err = wait_event_interruptible(r.wqueue, | ||
948 | r.rcall || r.err); | ||
949 | } while (!r.rcall && !r.err && err == -ERESTARTSYS && | ||
950 | m->trans->status == Connected && !m->err); | ||
951 | |||
952 | err = -ERESTARTSYS; | ||
953 | } | ||
954 | sigpending = 1; | ||
955 | } | ||
956 | |||
957 | if (sigpending) { | ||
958 | spin_lock_irqsave(¤t->sighand->siglock, flags); | ||
959 | recalc_sigpending(); | ||
960 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); | ||
961 | } | ||
962 | |||
963 | if (rc) | ||
964 | *rc = r.rcall; | ||
965 | else | ||
966 | kfree(r.rcall); | ||
967 | |||
968 | p9_mux_free_request(m, req); | ||
969 | if (err > 0) | ||
970 | err = -EIO; | ||
971 | |||
972 | return err; | ||
973 | } | ||
974 | EXPORT_SYMBOL(p9_conn_rpc); | ||
975 | |||
976 | #ifdef P9_NONBLOCK | ||
977 | /** | ||
978 | * p9_conn_rpcnb - sends 9P request without waiting for response. | ||
979 | * @m: mux data | ||
980 | * @tc: request to be sent | ||
981 | * @cb: callback function to be called when response arrives | ||
982 | * @cba: value to pass to the callback function | ||
983 | */ | ||
984 | int p9_conn_rpcnb(struct p9_conn *m, struct p9_fcall *tc, | ||
985 | p9_conn_req_callback cb, void *a) | ||
986 | { | ||
987 | int err; | ||
988 | struct p9_req *req; | ||
989 | |||
990 | req = p9_send_request(m, tc, cb, a); | ||
991 | if (IS_ERR(req)) { | ||
992 | err = PTR_ERR(req); | ||
993 | P9_DPRINTK(P9_DEBUG_MUX, "error %d\n", err); | ||
994 | return PTR_ERR(req); | ||
995 | } | ||
996 | |||
997 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p tc %p tag %d\n", m, tc, req->tag); | ||
998 | return 0; | ||
999 | } | ||
1000 | EXPORT_SYMBOL(p9_conn_rpcnb); | ||
1001 | #endif /* P9_NONBLOCK */ | ||
1002 | |||
1003 | /** | ||
1004 | * p9_conn_cancel - cancel all pending requests with error | ||
1005 | * @m: mux data | ||
1006 | * @err: error code | ||
1007 | */ | ||
1008 | void p9_conn_cancel(struct p9_conn *m, int err) | ||
1009 | { | ||
1010 | struct p9_req *req, *rtmp; | ||
1011 | LIST_HEAD(cancel_list); | ||
1012 | |||
1013 | P9_DPRINTK(P9_DEBUG_ERROR, "mux %p err %d\n", m, err); | ||
1014 | m->err = err; | ||
1015 | spin_lock(&m->lock); | ||
1016 | list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) { | ||
1017 | list_move(&req->req_list, &cancel_list); | ||
1018 | } | ||
1019 | list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) { | ||
1020 | list_move(&req->req_list, &cancel_list); | ||
1021 | } | ||
1022 | spin_unlock(&m->lock); | ||
1023 | |||
1024 | list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) { | ||
1025 | list_del(&req->req_list); | ||
1026 | if (!req->err) | ||
1027 | req->err = err; | ||
1028 | |||
1029 | if (req->cb) | ||
1030 | (*req->cb) (req, req->cba); | ||
1031 | else | ||
1032 | kfree(req->rcall); | ||
1033 | } | ||
1034 | |||
1035 | wake_up(&m->equeue); | ||
1036 | } | ||
1037 | EXPORT_SYMBOL(p9_conn_cancel); | ||
1038 | |||
1039 | static u16 p9_mux_get_tag(struct p9_conn *m) | ||
1040 | { | ||
1041 | int tag; | ||
1042 | |||
1043 | tag = p9_idpool_get(m->tagpool); | ||
1044 | if (tag < 0) | ||
1045 | return P9_NOTAG; | ||
1046 | else | ||
1047 | return (u16) tag; | ||
1048 | } | ||
1049 | |||
1050 | static void p9_mux_put_tag(struct p9_conn *m, u16 tag) | ||
1051 | { | ||
1052 | if (tag != P9_NOTAG && p9_idpool_check(tag, m->tagpool)) | ||
1053 | p9_idpool_put(tag, m->tagpool); | ||
1054 | } | ||
diff --git a/net/9p/sysctl.c b/net/9p/sysctl.c new file mode 100644 index 000000000000..e7fe706ab95a --- /dev/null +++ b/net/9p/sysctl.c | |||
@@ -0,0 +1,86 @@ | |||
1 | /* | ||
2 | * net/9p/sysctl.c | ||
3 | * | ||
4 | * 9P sysctl interface | ||
5 | * | ||
6 | * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 | ||
10 | * as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to: | ||
19 | * Free Software Foundation | ||
20 | * 51 Franklin Street, Fifth Floor | ||
21 | * Boston, MA 02111-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/mm.h> | ||
27 | #include <linux/sysctl.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <net/9p/9p.h> | ||
30 | |||
31 | enum { | ||
32 | P9_SYSCTL_NET = 487, | ||
33 | P9_SYSCTL_DEBUG = 1, | ||
34 | }; | ||
35 | |||
36 | static ctl_table p9_table[] = { | ||
37 | #ifdef CONFIG_NET_9P_DEBUG | ||
38 | { | ||
39 | .ctl_name = P9_SYSCTL_DEBUG, | ||
40 | .procname = "debug", | ||
41 | .data = &p9_debug_level, | ||
42 | .maxlen = sizeof(int), | ||
43 | .mode = 0644, | ||
44 | .proc_handler = &proc_dointvec | ||
45 | }, | ||
46 | #endif | ||
47 | { .ctl_name = 0 }, | ||
48 | }; | ||
49 | |||
50 | static ctl_table p9_net_table[] = { | ||
51 | { | ||
52 | .ctl_name = P9_SYSCTL_NET, | ||
53 | .procname = "9p", | ||
54 | .maxlen = 0, | ||
55 | .mode = 0555, | ||
56 | .child = p9_table, | ||
57 | }, | ||
58 | { .ctl_name = 0 }, | ||
59 | }; | ||
60 | |||
61 | static ctl_table p9_ctl_table[] = { | ||
62 | { | ||
63 | .ctl_name = CTL_NET, | ||
64 | .procname = "net", | ||
65 | .maxlen = 0, | ||
66 | .mode = 0555, | ||
67 | .child = p9_net_table, | ||
68 | }, | ||
69 | { .ctl_name = 0 }, | ||
70 | }; | ||
71 | |||
72 | static struct ctl_table_header *p9_table_header; | ||
73 | |||
74 | int __init p9_sysctl_register(void) | ||
75 | { | ||
76 | p9_table_header = register_sysctl_table(p9_ctl_table); | ||
77 | if (!p9_table_header) | ||
78 | return -ENOMEM; | ||
79 | |||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | void __exit p9_sysctl_unregister(void) | ||
84 | { | ||
85 | unregister_sysctl_table(p9_table_header); | ||
86 | } | ||
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c new file mode 100644 index 000000000000..fd636e94358f --- /dev/null +++ b/net/9p/trans_fd.c | |||
@@ -0,0 +1,363 @@ | |||
1 | /* | ||
2 | * linux/fs/9p/trans_fd.c | ||
3 | * | ||
4 | * Fd transport layer. Includes deprecated socket layer. | ||
5 | * | ||
6 | * Copyright (C) 2006 by Russ Cox <rsc@swtch.com> | ||
7 | * Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net> | ||
8 | * Copyright (C) 2004-2005 by Eric Van Hensbergen <ericvh@gmail.com> | ||
9 | * Copyright (C) 1997-2002 by Ron Minnich <rminnich@sarnoff.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 | ||
13 | * as published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to: | ||
22 | * Free Software Foundation | ||
23 | * 51 Franklin Street, Fifth Floor | ||
24 | * Boston, MA 02111-1301 USA | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | #include <linux/in.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/net.h> | ||
31 | #include <linux/ipv6.h> | ||
32 | #include <linux/errno.h> | ||
33 | #include <linux/kernel.h> | ||
34 | #include <linux/un.h> | ||
35 | #include <linux/uaccess.h> | ||
36 | #include <linux/inet.h> | ||
37 | #include <linux/idr.h> | ||
38 | #include <linux/file.h> | ||
39 | #include <net/9p/9p.h> | ||
40 | #include <net/9p/transport.h> | ||
41 | |||
42 | #define P9_PORT 564 | ||
43 | |||
44 | struct p9_trans_fd { | ||
45 | struct file *rd; | ||
46 | struct file *wr; | ||
47 | }; | ||
48 | |||
49 | static int p9_socket_open(struct p9_transport *trans, struct socket *csocket); | ||
50 | static int p9_fd_open(struct p9_transport *trans, int rfd, int wfd); | ||
51 | static int p9_fd_read(struct p9_transport *trans, void *v, int len); | ||
52 | static int p9_fd_write(struct p9_transport *trans, void *v, int len); | ||
53 | static unsigned int p9_fd_poll(struct p9_transport *trans, | ||
54 | struct poll_table_struct *pt); | ||
55 | static void p9_fd_close(struct p9_transport *trans); | ||
56 | |||
57 | struct p9_transport *p9_trans_create_tcp(const char *addr, int port) | ||
58 | { | ||
59 | int err; | ||
60 | struct p9_transport *trans; | ||
61 | struct socket *csocket; | ||
62 | struct sockaddr_in sin_server; | ||
63 | |||
64 | csocket = NULL; | ||
65 | trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL); | ||
66 | if (!trans) | ||
67 | return ERR_PTR(-ENOMEM); | ||
68 | |||
69 | trans->write = p9_fd_write; | ||
70 | trans->read = p9_fd_read; | ||
71 | trans->close = p9_fd_close; | ||
72 | trans->poll = p9_fd_poll; | ||
73 | |||
74 | sin_server.sin_family = AF_INET; | ||
75 | sin_server.sin_addr.s_addr = in_aton(addr); | ||
76 | sin_server.sin_port = htons(port); | ||
77 | sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket); | ||
78 | |||
79 | if (!csocket) { | ||
80 | P9_EPRINTK(KERN_ERR, "p9_trans_tcp: problem creating socket\n"); | ||
81 | err = -EIO; | ||
82 | goto error; | ||
83 | } | ||
84 | |||
85 | err = csocket->ops->connect(csocket, | ||
86 | (struct sockaddr *)&sin_server, | ||
87 | sizeof(struct sockaddr_in), 0); | ||
88 | if (err < 0) { | ||
89 | P9_EPRINTK(KERN_ERR, | ||
90 | "p9_trans_tcp: problem connecting socket to %s\n", | ||
91 | addr); | ||
92 | goto error; | ||
93 | } | ||
94 | |||
95 | err = p9_socket_open(trans, csocket); | ||
96 | if (err < 0) | ||
97 | goto error; | ||
98 | |||
99 | return trans; | ||
100 | |||
101 | error: | ||
102 | if (csocket) | ||
103 | sock_release(csocket); | ||
104 | |||
105 | kfree(trans); | ||
106 | return ERR_PTR(err); | ||
107 | } | ||
108 | EXPORT_SYMBOL(p9_trans_create_tcp); | ||
109 | |||
110 | struct p9_transport *p9_trans_create_unix(const char *addr) | ||
111 | { | ||
112 | int err; | ||
113 | struct socket *csocket; | ||
114 | struct sockaddr_un sun_server; | ||
115 | struct p9_transport *trans; | ||
116 | |||
117 | csocket = NULL; | ||
118 | trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL); | ||
119 | if (!trans) | ||
120 | return ERR_PTR(-ENOMEM); | ||
121 | |||
122 | trans->write = p9_fd_write; | ||
123 | trans->read = p9_fd_read; | ||
124 | trans->close = p9_fd_close; | ||
125 | trans->poll = p9_fd_poll; | ||
126 | |||
127 | if (strlen(addr) > UNIX_PATH_MAX) { | ||
128 | P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n", | ||
129 | addr); | ||
130 | err = -ENAMETOOLONG; | ||
131 | goto error; | ||
132 | } | ||
133 | |||
134 | sun_server.sun_family = PF_UNIX; | ||
135 | strcpy(sun_server.sun_path, addr); | ||
136 | sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket); | ||
137 | err = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server, | ||
138 | sizeof(struct sockaddr_un) - 1, 0); | ||
139 | if (err < 0) { | ||
140 | P9_EPRINTK(KERN_ERR, | ||
141 | "p9_trans_unix: problem connecting socket: %s: %d\n", | ||
142 | addr, err); | ||
143 | goto error; | ||
144 | } | ||
145 | |||
146 | err = p9_socket_open(trans, csocket); | ||
147 | if (err < 0) | ||
148 | goto error; | ||
149 | |||
150 | return trans; | ||
151 | |||
152 | error: | ||
153 | if (csocket) | ||
154 | sock_release(csocket); | ||
155 | |||
156 | kfree(trans); | ||
157 | return ERR_PTR(err); | ||
158 | } | ||
159 | EXPORT_SYMBOL(p9_trans_create_unix); | ||
160 | |||
161 | struct p9_transport *p9_trans_create_fd(int rfd, int wfd) | ||
162 | { | ||
163 | int err; | ||
164 | struct p9_transport *trans; | ||
165 | |||
166 | if (rfd == ~0 || wfd == ~0) { | ||
167 | printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n"); | ||
168 | return ERR_PTR(-ENOPROTOOPT); | ||
169 | } | ||
170 | |||
171 | trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL); | ||
172 | if (!trans) | ||
173 | return ERR_PTR(-ENOMEM); | ||
174 | |||
175 | trans->write = p9_fd_write; | ||
176 | trans->read = p9_fd_read; | ||
177 | trans->close = p9_fd_close; | ||
178 | trans->poll = p9_fd_poll; | ||
179 | |||
180 | err = p9_fd_open(trans, rfd, wfd); | ||
181 | if (err < 0) | ||
182 | goto error; | ||
183 | |||
184 | return trans; | ||
185 | |||
186 | error: | ||
187 | kfree(trans); | ||
188 | return ERR_PTR(err); | ||
189 | } | ||
190 | EXPORT_SYMBOL(p9_trans_create_fd); | ||
191 | |||
192 | static int p9_socket_open(struct p9_transport *trans, struct socket *csocket) | ||
193 | { | ||
194 | int fd, ret; | ||
195 | |||
196 | csocket->sk->sk_allocation = GFP_NOIO; | ||
197 | fd = sock_map_fd(csocket); | ||
198 | if (fd < 0) { | ||
199 | P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to map fd\n"); | ||
200 | return fd; | ||
201 | } | ||
202 | |||
203 | ret = p9_fd_open(trans, fd, fd); | ||
204 | if (ret < 0) { | ||
205 | P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to open fd\n"); | ||
206 | sockfd_put(csocket); | ||
207 | return ret; | ||
208 | } | ||
209 | |||
210 | ((struct p9_trans_fd *)trans->priv)->rd->f_flags |= O_NONBLOCK; | ||
211 | |||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | static int p9_fd_open(struct p9_transport *trans, int rfd, int wfd) | ||
216 | { | ||
217 | struct p9_trans_fd *ts = kmalloc(sizeof(struct p9_trans_fd), | ||
218 | GFP_KERNEL); | ||
219 | if (!ts) | ||
220 | return -ENOMEM; | ||
221 | |||
222 | ts->rd = fget(rfd); | ||
223 | ts->wr = fget(wfd); | ||
224 | if (!ts->rd || !ts->wr) { | ||
225 | if (ts->rd) | ||
226 | fput(ts->rd); | ||
227 | if (ts->wr) | ||
228 | fput(ts->wr); | ||
229 | kfree(ts); | ||
230 | return -EIO; | ||
231 | } | ||
232 | |||
233 | trans->priv = ts; | ||
234 | trans->status = Connected; | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | /** | ||
240 | * p9_fd_read- read from a fd | ||
241 | * @v9ses: session information | ||
242 | * @v: buffer to receive data into | ||
243 | * @len: size of receive buffer | ||
244 | * | ||
245 | */ | ||
246 | static int p9_fd_read(struct p9_transport *trans, void *v, int len) | ||
247 | { | ||
248 | int ret; | ||
249 | struct p9_trans_fd *ts = NULL; | ||
250 | |||
251 | if (trans && trans->status != Disconnected) | ||
252 | ts = trans->priv; | ||
253 | |||
254 | if (!ts) | ||
255 | return -EREMOTEIO; | ||
256 | |||
257 | if (!(ts->rd->f_flags & O_NONBLOCK)) | ||
258 | P9_DPRINTK(P9_DEBUG_ERROR, "blocking read ...\n"); | ||
259 | |||
260 | ret = kernel_read(ts->rd, ts->rd->f_pos, v, len); | ||
261 | if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN) | ||
262 | trans->status = Disconnected; | ||
263 | return ret; | ||
264 | } | ||
265 | |||
266 | /** | ||
267 | * p9_fd_write - write to a socket | ||
268 | * @v9ses: session information | ||
269 | * @v: buffer to send data from | ||
270 | * @len: size of send buffer | ||
271 | * | ||
272 | */ | ||
273 | static int p9_fd_write(struct p9_transport *trans, void *v, int len) | ||
274 | { | ||
275 | int ret; | ||
276 | mm_segment_t oldfs; | ||
277 | struct p9_trans_fd *ts = NULL; | ||
278 | |||
279 | if (trans && trans->status != Disconnected) | ||
280 | ts = trans->priv; | ||
281 | |||
282 | if (!ts) | ||
283 | return -EREMOTEIO; | ||
284 | |||
285 | if (!(ts->wr->f_flags & O_NONBLOCK)) | ||
286 | P9_DPRINTK(P9_DEBUG_ERROR, "blocking write ...\n"); | ||
287 | |||
288 | oldfs = get_fs(); | ||
289 | set_fs(get_ds()); | ||
290 | /* The cast to a user pointer is valid due to the set_fs() */ | ||
291 | ret = vfs_write(ts->wr, (void __user *)v, len, &ts->wr->f_pos); | ||
292 | set_fs(oldfs); | ||
293 | |||
294 | if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN) | ||
295 | trans->status = Disconnected; | ||
296 | return ret; | ||
297 | } | ||
298 | |||
299 | static unsigned int | ||
300 | p9_fd_poll(struct p9_transport *trans, struct poll_table_struct *pt) | ||
301 | { | ||
302 | int ret, n; | ||
303 | struct p9_trans_fd *ts = NULL; | ||
304 | mm_segment_t oldfs; | ||
305 | |||
306 | if (trans && trans->status == Connected) | ||
307 | ts = trans->priv; | ||
308 | |||
309 | if (!ts) | ||
310 | return -EREMOTEIO; | ||
311 | |||
312 | if (!ts->rd->f_op || !ts->rd->f_op->poll) | ||
313 | return -EIO; | ||
314 | |||
315 | if (!ts->wr->f_op || !ts->wr->f_op->poll) | ||
316 | return -EIO; | ||
317 | |||
318 | oldfs = get_fs(); | ||
319 | set_fs(get_ds()); | ||
320 | |||
321 | ret = ts->rd->f_op->poll(ts->rd, pt); | ||
322 | if (ret < 0) | ||
323 | goto end; | ||
324 | |||
325 | if (ts->rd != ts->wr) { | ||
326 | n = ts->wr->f_op->poll(ts->wr, pt); | ||
327 | if (n < 0) { | ||
328 | ret = n; | ||
329 | goto end; | ||
330 | } | ||
331 | ret = (ret & ~POLLOUT) | (n & ~POLLIN); | ||
332 | } | ||
333 | |||
334 | end: | ||
335 | set_fs(oldfs); | ||
336 | return ret; | ||
337 | } | ||
338 | |||
339 | /** | ||
340 | * p9_sock_close - shutdown socket | ||
341 | * @trans: private socket structure | ||
342 | * | ||
343 | */ | ||
344 | static void p9_fd_close(struct p9_transport *trans) | ||
345 | { | ||
346 | struct p9_trans_fd *ts; | ||
347 | |||
348 | if (!trans) | ||
349 | return; | ||
350 | |||
351 | ts = xchg(&trans->priv, NULL); | ||
352 | |||
353 | if (!ts) | ||
354 | return; | ||
355 | |||
356 | trans->status = Disconnected; | ||
357 | if (ts->rd) | ||
358 | fput(ts->rd); | ||
359 | if (ts->wr) | ||
360 | fput(ts->wr); | ||
361 | kfree(ts); | ||
362 | } | ||
363 | |||
diff --git a/net/9p/util.c b/net/9p/util.c new file mode 100644 index 000000000000..22077b79395d --- /dev/null +++ b/net/9p/util.c | |||
@@ -0,0 +1,125 @@ | |||
1 | /* | ||
2 | * net/9p/util.c | ||
3 | * | ||
4 | * This file contains some helper functions | ||
5 | * | ||
6 | * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net> | ||
7 | * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> | ||
8 | * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 | ||
12 | * as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to: | ||
21 | * Free Software Foundation | ||
22 | * 51 Franklin Street, Fifth Floor | ||
23 | * Boston, MA 02111-1301 USA | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include <linux/module.h> | ||
28 | #include <linux/errno.h> | ||
29 | #include <linux/fs.h> | ||
30 | #include <linux/sched.h> | ||
31 | #include <linux/parser.h> | ||
32 | #include <linux/idr.h> | ||
33 | #include <net/9p/9p.h> | ||
34 | |||
35 | struct p9_idpool { | ||
36 | struct semaphore lock; | ||
37 | struct idr pool; | ||
38 | }; | ||
39 | |||
40 | struct p9_idpool *p9_idpool_create(void) | ||
41 | { | ||
42 | struct p9_idpool *p; | ||
43 | |||
44 | p = kmalloc(sizeof(struct p9_idpool), GFP_KERNEL); | ||
45 | if (!p) | ||
46 | return ERR_PTR(-ENOMEM); | ||
47 | |||
48 | init_MUTEX(&p->lock); | ||
49 | idr_init(&p->pool); | ||
50 | |||
51 | return p; | ||
52 | } | ||
53 | EXPORT_SYMBOL(p9_idpool_create); | ||
54 | |||
55 | void p9_idpool_destroy(struct p9_idpool *p) | ||
56 | { | ||
57 | idr_destroy(&p->pool); | ||
58 | kfree(p); | ||
59 | } | ||
60 | EXPORT_SYMBOL(p9_idpool_destroy); | ||
61 | |||
62 | /** | ||
63 | * p9_idpool_get - allocate numeric id from pool | ||
64 | * @p - pool to allocate from | ||
65 | * | ||
66 | * XXX - This seems to be an awful generic function, should it be in idr.c with | ||
67 | * the lock included in struct idr? | ||
68 | */ | ||
69 | |||
70 | int p9_idpool_get(struct p9_idpool *p) | ||
71 | { | ||
72 | int i = 0; | ||
73 | int error; | ||
74 | |||
75 | retry: | ||
76 | if (idr_pre_get(&p->pool, GFP_KERNEL) == 0) | ||
77 | return 0; | ||
78 | |||
79 | if (down_interruptible(&p->lock) == -EINTR) { | ||
80 | P9_EPRINTK(KERN_WARNING, "Interrupted while locking\n"); | ||
81 | return -1; | ||
82 | } | ||
83 | |||
84 | /* no need to store exactly p, we just need something non-null */ | ||
85 | error = idr_get_new(&p->pool, p, &i); | ||
86 | up(&p->lock); | ||
87 | |||
88 | if (error == -EAGAIN) | ||
89 | goto retry; | ||
90 | else if (error) | ||
91 | return -1; | ||
92 | |||
93 | return i; | ||
94 | } | ||
95 | EXPORT_SYMBOL(p9_idpool_get); | ||
96 | |||
97 | /** | ||
98 | * p9_idpool_put - release numeric id from pool | ||
99 | * @p - pool to allocate from | ||
100 | * | ||
101 | * XXX - This seems to be an awful generic function, should it be in idr.c with | ||
102 | * the lock included in struct idr? | ||
103 | */ | ||
104 | |||
105 | void p9_idpool_put(int id, struct p9_idpool *p) | ||
106 | { | ||
107 | if (down_interruptible(&p->lock) == -EINTR) { | ||
108 | P9_EPRINTK(KERN_WARNING, "Interrupted while locking\n"); | ||
109 | return; | ||
110 | } | ||
111 | idr_remove(&p->pool, id); | ||
112 | up(&p->lock); | ||
113 | } | ||
114 | EXPORT_SYMBOL(p9_idpool_put); | ||
115 | |||
116 | /** | ||
117 | * p9_idpool_check - check if the specified id is available | ||
118 | * @id - id to check | ||
119 | * @p - pool | ||
120 | */ | ||
121 | int p9_idpool_check(int id, struct p9_idpool *p) | ||
122 | { | ||
123 | return idr_find(&p->pool, id) != NULL; | ||
124 | } | ||
125 | EXPORT_SYMBOL(p9_idpool_check); | ||
diff --git a/net/Kconfig b/net/Kconfig index f3de72978ab6..cdba08ca2efe 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
@@ -227,6 +227,7 @@ source "net/ieee80211/Kconfig" | |||
227 | endmenu | 227 | endmenu |
228 | 228 | ||
229 | source "net/rfkill/Kconfig" | 229 | source "net/rfkill/Kconfig" |
230 | source "net/9p/Kconfig" | ||
230 | 231 | ||
231 | endif # if NET | 232 | endif # if NET |
232 | endmenu # Networking | 233 | endmenu # Networking |
diff --git a/net/Makefile b/net/Makefile index 34e5b2d7f877..bbe7d2a41486 100644 --- a/net/Makefile +++ b/net/Makefile | |||
@@ -37,7 +37,6 @@ obj-$(CONFIG_AX25) += ax25/ | |||
37 | obj-$(CONFIG_IRDA) += irda/ | 37 | obj-$(CONFIG_IRDA) += irda/ |
38 | obj-$(CONFIG_BT) += bluetooth/ | 38 | obj-$(CONFIG_BT) += bluetooth/ |
39 | obj-$(CONFIG_SUNRPC) += sunrpc/ | 39 | obj-$(CONFIG_SUNRPC) += sunrpc/ |
40 | obj-$(CONFIG_RXRPC) += rxrpc/ | ||
41 | obj-$(CONFIG_AF_RXRPC) += rxrpc/ | 40 | obj-$(CONFIG_AF_RXRPC) += rxrpc/ |
42 | obj-$(CONFIG_ATM) += atm/ | 41 | obj-$(CONFIG_ATM) += atm/ |
43 | obj-$(CONFIG_DECNET) += decnet/ | 42 | obj-$(CONFIG_DECNET) += decnet/ |
@@ -52,6 +51,7 @@ obj-$(CONFIG_TIPC) += tipc/ | |||
52 | obj-$(CONFIG_NETLABEL) += netlabel/ | 51 | obj-$(CONFIG_NETLABEL) += netlabel/ |
53 | obj-$(CONFIG_IUCV) += iucv/ | 52 | obj-$(CONFIG_IUCV) += iucv/ |
54 | obj-$(CONFIG_RFKILL) += rfkill/ | 53 | obj-$(CONFIG_RFKILL) += rfkill/ |
54 | obj-$(CONFIG_NET_9P) += 9p/ | ||
55 | 55 | ||
56 | ifeq ($(CONFIG_NET),y) | 56 | ifeq ($(CONFIG_NET),y) |
57 | obj-$(CONFIG_SYSCTL) += sysctl_net.o | 57 | obj-$(CONFIG_SYSCTL) += sysctl_net.o |
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c index 5ef6a238bdbc..3d1655f98388 100644 --- a/net/appletalk/aarp.c +++ b/net/appletalk/aarp.c | |||
@@ -1024,7 +1024,7 @@ static int aarp_seq_show(struct seq_file *seq, void *v) | |||
1024 | return 0; | 1024 | return 0; |
1025 | } | 1025 | } |
1026 | 1026 | ||
1027 | static struct seq_operations aarp_seq_ops = { | 1027 | static const struct seq_operations aarp_seq_ops = { |
1028 | .start = aarp_seq_start, | 1028 | .start = aarp_seq_start, |
1029 | .next = aarp_seq_next, | 1029 | .next = aarp_seq_next, |
1030 | .stop = aarp_seq_stop, | 1030 | .stop = aarp_seq_stop, |
diff --git a/net/appletalk/atalk_proc.c b/net/appletalk/atalk_proc.c index 57ff8122b5c5..87a582cc8111 100644 --- a/net/appletalk/atalk_proc.c +++ b/net/appletalk/atalk_proc.c | |||
@@ -204,21 +204,21 @@ out: | |||
204 | return 0; | 204 | return 0; |
205 | } | 205 | } |
206 | 206 | ||
207 | static struct seq_operations atalk_seq_interface_ops = { | 207 | static const struct seq_operations atalk_seq_interface_ops = { |
208 | .start = atalk_seq_interface_start, | 208 | .start = atalk_seq_interface_start, |
209 | .next = atalk_seq_interface_next, | 209 | .next = atalk_seq_interface_next, |
210 | .stop = atalk_seq_interface_stop, | 210 | .stop = atalk_seq_interface_stop, |
211 | .show = atalk_seq_interface_show, | 211 | .show = atalk_seq_interface_show, |
212 | }; | 212 | }; |
213 | 213 | ||
214 | static struct seq_operations atalk_seq_route_ops = { | 214 | static const struct seq_operations atalk_seq_route_ops = { |
215 | .start = atalk_seq_route_start, | 215 | .start = atalk_seq_route_start, |
216 | .next = atalk_seq_route_next, | 216 | .next = atalk_seq_route_next, |
217 | .stop = atalk_seq_route_stop, | 217 | .stop = atalk_seq_route_stop, |
218 | .show = atalk_seq_route_show, | 218 | .show = atalk_seq_route_show, |
219 | }; | 219 | }; |
220 | 220 | ||
221 | static struct seq_operations atalk_seq_socket_ops = { | 221 | static const struct seq_operations atalk_seq_socket_ops = { |
222 | .start = atalk_seq_socket_start, | 222 | .start = atalk_seq_socket_start, |
223 | .next = atalk_seq_socket_next, | 223 | .next = atalk_seq_socket_next, |
224 | .stop = atalk_seq_socket_stop, | 224 | .stop = atalk_seq_socket_stop, |
diff --git a/net/atm/br2684.c b/net/atm/br2684.c index 0e9f00c5c899..faa6aaf67563 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c | |||
@@ -699,28 +699,13 @@ static struct atm_ioctl br2684_ioctl_ops = { | |||
699 | #ifdef CONFIG_PROC_FS | 699 | #ifdef CONFIG_PROC_FS |
700 | static void *br2684_seq_start(struct seq_file *seq, loff_t *pos) | 700 | static void *br2684_seq_start(struct seq_file *seq, loff_t *pos) |
701 | { | 701 | { |
702 | loff_t offs = 0; | ||
703 | struct br2684_dev *brd; | ||
704 | |||
705 | read_lock(&devs_lock); | 702 | read_lock(&devs_lock); |
706 | 703 | return seq_list_start(&br2684_devs, *pos); | |
707 | list_for_each_entry(brd, &br2684_devs, br2684_devs) { | ||
708 | if (offs == *pos) | ||
709 | return brd; | ||
710 | ++offs; | ||
711 | } | ||
712 | return NULL; | ||
713 | } | 704 | } |
714 | 705 | ||
715 | static void *br2684_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 706 | static void *br2684_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
716 | { | 707 | { |
717 | struct br2684_dev *brd = v; | 708 | return seq_list_next(v, &br2684_devs, pos); |
718 | |||
719 | ++*pos; | ||
720 | |||
721 | brd = list_entry(brd->br2684_devs.next, | ||
722 | struct br2684_dev, br2684_devs); | ||
723 | return (&brd->br2684_devs != &br2684_devs) ? brd : NULL; | ||
724 | } | 709 | } |
725 | 710 | ||
726 | static void br2684_seq_stop(struct seq_file *seq, void *v) | 711 | static void br2684_seq_stop(struct seq_file *seq, void *v) |
@@ -730,7 +715,8 @@ static void br2684_seq_stop(struct seq_file *seq, void *v) | |||
730 | 715 | ||
731 | static int br2684_seq_show(struct seq_file *seq, void *v) | 716 | static int br2684_seq_show(struct seq_file *seq, void *v) |
732 | { | 717 | { |
733 | const struct br2684_dev *brdev = v; | 718 | const struct br2684_dev *brdev = list_entry(v, struct br2684_dev, |
719 | br2684_devs); | ||
734 | const struct net_device *net_dev = brdev->net_dev; | 720 | const struct net_device *net_dev = brdev->net_dev; |
735 | const struct br2684_vcc *brvcc; | 721 | const struct br2684_vcc *brvcc; |
736 | 722 | ||
@@ -772,7 +758,7 @@ static int br2684_seq_show(struct seq_file *seq, void *v) | |||
772 | return 0; | 758 | return 0; |
773 | } | 759 | } |
774 | 760 | ||
775 | static struct seq_operations br2684_seq_ops = { | 761 | static const struct seq_operations br2684_seq_ops = { |
776 | .start = br2684_seq_start, | 762 | .start = br2684_seq_start, |
777 | .next = br2684_seq_next, | 763 | .next = br2684_seq_next, |
778 | .stop = br2684_seq_stop, | 764 | .stop = br2684_seq_stop, |
diff --git a/net/atm/clip.c b/net/atm/clip.c index 876b77f14745..ecf0f79b94ae 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c | |||
@@ -928,7 +928,7 @@ static int clip_seq_show(struct seq_file *seq, void *v) | |||
928 | return 0; | 928 | return 0; |
929 | } | 929 | } |
930 | 930 | ||
931 | static struct seq_operations arp_seq_ops = { | 931 | static const struct seq_operations arp_seq_ops = { |
932 | .start = clip_seq_start, | 932 | .start = clip_seq_start, |
933 | .next = neigh_seq_next, | 933 | .next = neigh_seq_next, |
934 | .stop = neigh_seq_stop, | 934 | .stop = neigh_seq_stop, |
diff --git a/net/atm/lec.c b/net/atm/lec.c index 4dc5f2b8c43c..2770fb451ae8 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c | |||
@@ -1174,7 +1174,7 @@ static int lec_seq_show(struct seq_file *seq, void *v) | |||
1174 | return 0; | 1174 | return 0; |
1175 | } | 1175 | } |
1176 | 1176 | ||
1177 | static struct seq_operations lec_seq_ops = { | 1177 | static const struct seq_operations lec_seq_ops = { |
1178 | .start = lec_seq_start, | 1178 | .start = lec_seq_start, |
1179 | .next = lec_seq_next, | 1179 | .next = lec_seq_next, |
1180 | .stop = lec_seq_stop, | 1180 | .stop = lec_seq_stop, |
diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c index 4b05cbec7a58..91f3ffc90dbd 100644 --- a/net/atm/mpoa_proc.c +++ b/net/atm/mpoa_proc.c | |||
@@ -177,7 +177,7 @@ static int mpc_show(struct seq_file *m, void *v) | |||
177 | return 0; | 177 | return 0; |
178 | } | 178 | } |
179 | 179 | ||
180 | static struct seq_operations mpc_op = { | 180 | static const struct seq_operations mpc_op = { |
181 | .start = mpc_start, | 181 | .start = mpc_start, |
182 | .next = mpc_next, | 182 | .next = mpc_next, |
183 | .stop = mpc_stop, | 183 | .stop = mpc_stop, |
diff --git a/net/atm/proc.c b/net/atm/proc.c index 9e61e512f667..99fc1fe950ee 100644 --- a/net/atm/proc.c +++ b/net/atm/proc.c | |||
@@ -110,7 +110,7 @@ static inline void *vcc_walk(struct vcc_state *state, loff_t l) | |||
110 | } | 110 | } |
111 | 111 | ||
112 | static int __vcc_seq_open(struct inode *inode, struct file *file, | 112 | static int __vcc_seq_open(struct inode *inode, struct file *file, |
113 | int family, struct seq_operations *ops) | 113 | int family, const struct seq_operations *ops) |
114 | { | 114 | { |
115 | struct vcc_state *state; | 115 | struct vcc_state *state; |
116 | struct seq_file *seq; | 116 | struct seq_file *seq; |
@@ -260,7 +260,7 @@ static int atm_dev_seq_show(struct seq_file *seq, void *v) | |||
260 | return 0; | 260 | return 0; |
261 | } | 261 | } |
262 | 262 | ||
263 | static struct seq_operations atm_dev_seq_ops = { | 263 | static const struct seq_operations atm_dev_seq_ops = { |
264 | .start = atm_dev_seq_start, | 264 | .start = atm_dev_seq_start, |
265 | .next = atm_dev_seq_next, | 265 | .next = atm_dev_seq_next, |
266 | .stop = atm_dev_seq_stop, | 266 | .stop = atm_dev_seq_stop, |
@@ -295,7 +295,7 @@ static int pvc_seq_show(struct seq_file *seq, void *v) | |||
295 | return 0; | 295 | return 0; |
296 | } | 296 | } |
297 | 297 | ||
298 | static struct seq_operations pvc_seq_ops = { | 298 | static const struct seq_operations pvc_seq_ops = { |
299 | .start = vcc_seq_start, | 299 | .start = vcc_seq_start, |
300 | .next = vcc_seq_next, | 300 | .next = vcc_seq_next, |
301 | .stop = vcc_seq_stop, | 301 | .stop = vcc_seq_stop, |
@@ -329,7 +329,7 @@ static int vcc_seq_show(struct seq_file *seq, void *v) | |||
329 | return 0; | 329 | return 0; |
330 | } | 330 | } |
331 | 331 | ||
332 | static struct seq_operations vcc_seq_ops = { | 332 | static const struct seq_operations vcc_seq_ops = { |
333 | .start = vcc_seq_start, | 333 | .start = vcc_seq_start, |
334 | .next = vcc_seq_next, | 334 | .next = vcc_seq_next, |
335 | .stop = vcc_seq_stop, | 335 | .stop = vcc_seq_stop, |
@@ -364,7 +364,7 @@ static int svc_seq_show(struct seq_file *seq, void *v) | |||
364 | return 0; | 364 | return 0; |
365 | } | 365 | } |
366 | 366 | ||
367 | static struct seq_operations svc_seq_ops = { | 367 | static const struct seq_operations svc_seq_ops = { |
368 | .start = vcc_seq_start, | 368 | .start = vcc_seq_start, |
369 | .next = vcc_seq_next, | 369 | .next = vcc_seq_next, |
370 | .stop = vcc_seq_stop, | 370 | .stop = vcc_seq_stop, |
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 429e13a6c6ad..c83cf8432970 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c | |||
@@ -1924,7 +1924,7 @@ static int ax25_info_show(struct seq_file *seq, void *v) | |||
1924 | return 0; | 1924 | return 0; |
1925 | } | 1925 | } |
1926 | 1926 | ||
1927 | static struct seq_operations ax25_info_seqops = { | 1927 | static const struct seq_operations ax25_info_seqops = { |
1928 | .start = ax25_info_start, | 1928 | .start = ax25_info_start, |
1929 | .next = ax25_info_next, | 1929 | .next = ax25_info_next, |
1930 | .stop = ax25_info_stop, | 1930 | .stop = ax25_info_stop, |
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c index d65b8e22868d..9ecf6f1df863 100644 --- a/net/ax25/ax25_route.c +++ b/net/ax25/ax25_route.c | |||
@@ -320,7 +320,7 @@ static int ax25_rt_seq_show(struct seq_file *seq, void *v) | |||
320 | return 0; | 320 | return 0; |
321 | } | 321 | } |
322 | 322 | ||
323 | static struct seq_operations ax25_rt_seqops = { | 323 | static const struct seq_operations ax25_rt_seqops = { |
324 | .start = ax25_rt_seq_start, | 324 | .start = ax25_rt_seq_start, |
325 | .next = ax25_rt_seq_next, | 325 | .next = ax25_rt_seq_next, |
326 | .stop = ax25_rt_seq_stop, | 326 | .stop = ax25_rt_seq_stop, |
diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c index 75c76647b2cb..ce0b13d44385 100644 --- a/net/ax25/ax25_uid.c +++ b/net/ax25/ax25_uid.c | |||
@@ -185,7 +185,7 @@ static int ax25_uid_seq_show(struct seq_file *seq, void *v) | |||
185 | return 0; | 185 | return 0; |
186 | } | 186 | } |
187 | 187 | ||
188 | static struct seq_operations ax25_uid_seqops = { | 188 | static const struct seq_operations ax25_uid_seqops = { |
189 | .start = ax25_uid_seq_start, | 189 | .start = ax25_uid_seq_start, |
190 | .next = ax25_uid_seq_next, | 190 | .next = ax25_uid_seq_next, |
191 | .stop = ax25_uid_seq_stop, | 191 | .stop = ax25_uid_seq_stop, |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 63980bd6b5f2..5fdfc9a67d39 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -123,8 +123,8 @@ void hci_add_sco(struct hci_conn *conn, __u16 handle) | |||
123 | conn->state = BT_CONNECT; | 123 | conn->state = BT_CONNECT; |
124 | conn->out = 1; | 124 | conn->out = 1; |
125 | 125 | ||
126 | cp.pkt_type = cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK); | ||
127 | cp.handle = cpu_to_le16(handle); | 126 | cp.handle = cpu_to_le16(handle); |
127 | cp.pkt_type = cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK); | ||
128 | 128 | ||
129 | hci_send_cmd(hdev, OGF_LINK_CTL, OCF_ADD_SCO, sizeof(cp), &cp); | 129 | hci_send_cmd(hdev, OGF_LINK_CTL, OCF_ADD_SCO, sizeof(cp), &cp); |
130 | } | 130 | } |
@@ -220,19 +220,19 @@ int hci_conn_del(struct hci_conn *conn) | |||
220 | 220 | ||
221 | del_timer(&conn->disc_timer); | 221 | del_timer(&conn->disc_timer); |
222 | 222 | ||
223 | if (conn->type == SCO_LINK) { | 223 | if (conn->type == ACL_LINK) { |
224 | struct hci_conn *acl = conn->link; | ||
225 | if (acl) { | ||
226 | acl->link = NULL; | ||
227 | hci_conn_put(acl); | ||
228 | } | ||
229 | } else { | ||
230 | struct hci_conn *sco = conn->link; | 224 | struct hci_conn *sco = conn->link; |
231 | if (sco) | 225 | if (sco) |
232 | sco->link = NULL; | 226 | sco->link = NULL; |
233 | 227 | ||
234 | /* Unacked frames */ | 228 | /* Unacked frames */ |
235 | hdev->acl_cnt += conn->sent; | 229 | hdev->acl_cnt += conn->sent; |
230 | } else { | ||
231 | struct hci_conn *acl = conn->link; | ||
232 | if (acl) { | ||
233 | acl->link = NULL; | ||
234 | hci_conn_put(acl); | ||
235 | } | ||
236 | } | 236 | } |
237 | 237 | ||
238 | tasklet_disable(&hdev->tx_task); | 238 | tasklet_disable(&hdev->tx_task); |
@@ -297,9 +297,10 @@ EXPORT_SYMBOL(hci_get_route); | |||
297 | 297 | ||
298 | /* Create SCO or ACL connection. | 298 | /* Create SCO or ACL connection. |
299 | * Device _must_ be locked */ | 299 | * Device _must_ be locked */ |
300 | struct hci_conn * hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) | 300 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) |
301 | { | 301 | { |
302 | struct hci_conn *acl; | 302 | struct hci_conn *acl; |
303 | struct hci_conn *sco; | ||
303 | 304 | ||
304 | BT_DBG("%s dst %s", hdev->name, batostr(dst)); | 305 | BT_DBG("%s dst %s", hdev->name, batostr(dst)); |
305 | 306 | ||
@@ -313,28 +314,26 @@ struct hci_conn * hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
313 | if (acl->state == BT_OPEN || acl->state == BT_CLOSED) | 314 | if (acl->state == BT_OPEN || acl->state == BT_CLOSED) |
314 | hci_acl_connect(acl); | 315 | hci_acl_connect(acl); |
315 | 316 | ||
316 | if (type == SCO_LINK) { | 317 | if (type == ACL_LINK) |
317 | struct hci_conn *sco; | 318 | return acl; |
318 | 319 | ||
319 | if (!(sco = hci_conn_hash_lookup_ba(hdev, SCO_LINK, dst))) { | 320 | if (!(sco = hci_conn_hash_lookup_ba(hdev, type, dst))) { |
320 | if (!(sco = hci_conn_add(hdev, SCO_LINK, dst))) { | 321 | if (!(sco = hci_conn_add(hdev, type, dst))) { |
321 | hci_conn_put(acl); | 322 | hci_conn_put(acl); |
322 | return NULL; | 323 | return NULL; |
323 | } | ||
324 | } | 324 | } |
325 | acl->link = sco; | 325 | } |
326 | sco->link = acl; | ||
327 | 326 | ||
328 | hci_conn_hold(sco); | 327 | acl->link = sco; |
328 | sco->link = acl; | ||
329 | 329 | ||
330 | if (acl->state == BT_CONNECTED && | 330 | hci_conn_hold(sco); |
331 | (sco->state == BT_OPEN || sco->state == BT_CLOSED)) | ||
332 | hci_add_sco(sco, acl->handle); | ||
333 | 331 | ||
334 | return sco; | 332 | if (acl->state == BT_CONNECTED && |
335 | } else { | 333 | (sco->state == BT_OPEN || sco->state == BT_CLOSED)) |
336 | return acl; | 334 | hci_add_sco(sco, acl->handle); |
337 | } | 335 | |
336 | return sco; | ||
338 | } | 337 | } |
339 | EXPORT_SYMBOL(hci_connect); | 338 | EXPORT_SYMBOL(hci_connect); |
340 | 339 | ||
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index aa4b56a8c3ea..f6d867e0179f 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -826,7 +826,7 @@ EXPORT_SYMBOL(hci_free_dev); | |||
826 | int hci_register_dev(struct hci_dev *hdev) | 826 | int hci_register_dev(struct hci_dev *hdev) |
827 | { | 827 | { |
828 | struct list_head *head = &hci_dev_list, *p; | 828 | struct list_head *head = &hci_dev_list, *p; |
829 | int id = 0; | 829 | int i, id = 0; |
830 | 830 | ||
831 | BT_DBG("%p name %s type %d owner %p", hdev, hdev->name, hdev->type, hdev->owner); | 831 | BT_DBG("%p name %s type %d owner %p", hdev, hdev->name, hdev->type, hdev->owner); |
832 | 832 | ||
@@ -851,6 +851,7 @@ int hci_register_dev(struct hci_dev *hdev) | |||
851 | 851 | ||
852 | hdev->flags = 0; | 852 | hdev->flags = 0; |
853 | hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1); | 853 | hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1); |
854 | hdev->esco_type = (ESCO_HV1); | ||
854 | hdev->link_mode = (HCI_LM_ACCEPT); | 855 | hdev->link_mode = (HCI_LM_ACCEPT); |
855 | 856 | ||
856 | hdev->idle_timeout = 0; | 857 | hdev->idle_timeout = 0; |
@@ -865,6 +866,9 @@ int hci_register_dev(struct hci_dev *hdev) | |||
865 | skb_queue_head_init(&hdev->cmd_q); | 866 | skb_queue_head_init(&hdev->cmd_q); |
866 | skb_queue_head_init(&hdev->raw_q); | 867 | skb_queue_head_init(&hdev->raw_q); |
867 | 868 | ||
869 | for (i = 0; i < 3; i++) | ||
870 | hdev->reassembly[i] = NULL; | ||
871 | |||
868 | init_waitqueue_head(&hdev->req_wait_q); | 872 | init_waitqueue_head(&hdev->req_wait_q); |
869 | init_MUTEX(&hdev->req_lock); | 873 | init_MUTEX(&hdev->req_lock); |
870 | 874 | ||
@@ -889,6 +893,8 @@ EXPORT_SYMBOL(hci_register_dev); | |||
889 | /* Unregister HCI device */ | 893 | /* Unregister HCI device */ |
890 | int hci_unregister_dev(struct hci_dev *hdev) | 894 | int hci_unregister_dev(struct hci_dev *hdev) |
891 | { | 895 | { |
896 | int i; | ||
897 | |||
892 | BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); | 898 | BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); |
893 | 899 | ||
894 | hci_unregister_sysfs(hdev); | 900 | hci_unregister_sysfs(hdev); |
@@ -899,9 +905,13 @@ int hci_unregister_dev(struct hci_dev *hdev) | |||
899 | 905 | ||
900 | hci_dev_do_close(hdev); | 906 | hci_dev_do_close(hdev); |
901 | 907 | ||
908 | for (i = 0; i < 3; i++) | ||
909 | kfree_skb(hdev->reassembly[i]); | ||
910 | |||
902 | hci_notify(hdev, HCI_DEV_UNREG); | 911 | hci_notify(hdev, HCI_DEV_UNREG); |
903 | 912 | ||
904 | __hci_dev_put(hdev); | 913 | __hci_dev_put(hdev); |
914 | |||
905 | return 0; | 915 | return 0; |
906 | } | 916 | } |
907 | EXPORT_SYMBOL(hci_unregister_dev); | 917 | EXPORT_SYMBOL(hci_unregister_dev); |
@@ -922,6 +932,90 @@ int hci_resume_dev(struct hci_dev *hdev) | |||
922 | } | 932 | } |
923 | EXPORT_SYMBOL(hci_resume_dev); | 933 | EXPORT_SYMBOL(hci_resume_dev); |
924 | 934 | ||
935 | /* Receive packet type fragment */ | ||
936 | #define __reassembly(hdev, type) ((hdev)->reassembly[(type) - 2]) | ||
937 | |||
938 | int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count) | ||
939 | { | ||
940 | if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) | ||
941 | return -EILSEQ; | ||
942 | |||
943 | while (count) { | ||
944 | struct sk_buff *skb = __reassembly(hdev, type); | ||
945 | struct { int expect; } *scb; | ||
946 | int len = 0; | ||
947 | |||
948 | if (!skb) { | ||
949 | /* Start of the frame */ | ||
950 | |||
951 | switch (type) { | ||
952 | case HCI_EVENT_PKT: | ||
953 | if (count >= HCI_EVENT_HDR_SIZE) { | ||
954 | struct hci_event_hdr *h = data; | ||
955 | len = HCI_EVENT_HDR_SIZE + h->plen; | ||
956 | } else | ||
957 | return -EILSEQ; | ||
958 | break; | ||
959 | |||
960 | case HCI_ACLDATA_PKT: | ||
961 | if (count >= HCI_ACL_HDR_SIZE) { | ||
962 | struct hci_acl_hdr *h = data; | ||
963 | len = HCI_ACL_HDR_SIZE + __le16_to_cpu(h->dlen); | ||
964 | } else | ||
965 | return -EILSEQ; | ||
966 | break; | ||
967 | |||
968 | case HCI_SCODATA_PKT: | ||
969 | if (count >= HCI_SCO_HDR_SIZE) { | ||
970 | struct hci_sco_hdr *h = data; | ||
971 | len = HCI_SCO_HDR_SIZE + h->dlen; | ||
972 | } else | ||
973 | return -EILSEQ; | ||
974 | break; | ||
975 | } | ||
976 | |||
977 | skb = bt_skb_alloc(len, GFP_ATOMIC); | ||
978 | if (!skb) { | ||
979 | BT_ERR("%s no memory for packet", hdev->name); | ||
980 | return -ENOMEM; | ||
981 | } | ||
982 | |||
983 | skb->dev = (void *) hdev; | ||
984 | bt_cb(skb)->pkt_type = type; | ||
985 | |||
986 | __reassembly(hdev, type) = skb; | ||
987 | |||
988 | scb = (void *) skb->cb; | ||
989 | scb->expect = len; | ||
990 | } else { | ||
991 | /* Continuation */ | ||
992 | |||
993 | scb = (void *) skb->cb; | ||
994 | len = scb->expect; | ||
995 | } | ||
996 | |||
997 | len = min(len, count); | ||
998 | |||
999 | memcpy(skb_put(skb, len), data, len); | ||
1000 | |||
1001 | scb->expect -= len; | ||
1002 | |||
1003 | if (scb->expect == 0) { | ||
1004 | /* Complete frame */ | ||
1005 | |||
1006 | __reassembly(hdev, type) = NULL; | ||
1007 | |||
1008 | bt_cb(skb)->pkt_type = type; | ||
1009 | hci_recv_frame(skb); | ||
1010 | } | ||
1011 | |||
1012 | count -= len; data += len; | ||
1013 | } | ||
1014 | |||
1015 | return 0; | ||
1016 | } | ||
1017 | EXPORT_SYMBOL(hci_recv_fragment); | ||
1018 | |||
925 | /* ---- Interface to upper protocols ---- */ | 1019 | /* ---- Interface to upper protocols ---- */ |
926 | 1020 | ||
927 | /* Register/Unregister protocols. | 1021 | /* Register/Unregister protocols. |
@@ -1029,7 +1123,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void *p | |||
1029 | 1123 | ||
1030 | skb = bt_skb_alloc(len, GFP_ATOMIC); | 1124 | skb = bt_skb_alloc(len, GFP_ATOMIC); |
1031 | if (!skb) { | 1125 | if (!skb) { |
1032 | BT_ERR("%s Can't allocate memory for HCI command", hdev->name); | 1126 | BT_ERR("%s no memory for command", hdev->name); |
1033 | return -ENOMEM; | 1127 | return -ENOMEM; |
1034 | } | 1128 | } |
1035 | 1129 | ||
@@ -1161,7 +1255,7 @@ EXPORT_SYMBOL(hci_send_sco); | |||
1161 | static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int *quote) | 1255 | static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int *quote) |
1162 | { | 1256 | { |
1163 | struct hci_conn_hash *h = &hdev->conn_hash; | 1257 | struct hci_conn_hash *h = &hdev->conn_hash; |
1164 | struct hci_conn *conn = NULL; | 1258 | struct hci_conn *conn = NULL; |
1165 | int num = 0, min = ~0; | 1259 | int num = 0, min = ~0; |
1166 | struct list_head *p; | 1260 | struct list_head *p; |
1167 | 1261 | ||
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 447ba7131220..4baea1e38652 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -350,11 +350,24 @@ static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *s | |||
350 | if (hdev->features[0] & LMP_5SLOT) | 350 | if (hdev->features[0] & LMP_5SLOT) |
351 | hdev->pkt_type |= (HCI_DM5 | HCI_DH5); | 351 | hdev->pkt_type |= (HCI_DM5 | HCI_DH5); |
352 | 352 | ||
353 | if (hdev->features[1] & LMP_HV2) | 353 | if (hdev->features[1] & LMP_HV2) { |
354 | hdev->pkt_type |= (HCI_HV2); | 354 | hdev->pkt_type |= (HCI_HV2); |
355 | hdev->esco_type |= (ESCO_HV2); | ||
356 | } | ||
357 | |||
358 | if (hdev->features[1] & LMP_HV3) { | ||
359 | hdev->pkt_type |= (HCI_HV3); | ||
360 | hdev->esco_type |= (ESCO_HV3); | ||
361 | } | ||
355 | 362 | ||
356 | if (hdev->features[1] & LMP_HV3) | 363 | if (hdev->features[3] & LMP_ESCO) |
357 | hdev->pkt_type |= (HCI_HV3); | 364 | hdev->esco_type |= (ESCO_EV3); |
365 | |||
366 | if (hdev->features[4] & LMP_EV4) | ||
367 | hdev->esco_type |= (ESCO_EV4); | ||
368 | |||
369 | if (hdev->features[4] & LMP_EV5) | ||
370 | hdev->esco_type |= (ESCO_EV5); | ||
358 | 371 | ||
359 | BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name, | 372 | BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name, |
360 | lf->features[0], lf->features[1], lf->features[2]); | 373 | lf->features[0], lf->features[1], lf->features[2]); |
@@ -881,12 +894,12 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s | |||
881 | if (conn) { | 894 | if (conn) { |
882 | conn->sent -= count; | 895 | conn->sent -= count; |
883 | 896 | ||
884 | if (conn->type == SCO_LINK) { | 897 | if (conn->type == ACL_LINK) { |
885 | if ((hdev->sco_cnt += count) > hdev->sco_pkts) | ||
886 | hdev->sco_cnt = hdev->sco_pkts; | ||
887 | } else { | ||
888 | if ((hdev->acl_cnt += count) > hdev->acl_pkts) | 898 | if ((hdev->acl_cnt += count) > hdev->acl_pkts) |
889 | hdev->acl_cnt = hdev->acl_pkts; | 899 | hdev->acl_cnt = hdev->acl_pkts; |
900 | } else { | ||
901 | if ((hdev->sco_cnt += count) > hdev->sco_pkts) | ||
902 | hdev->sco_cnt = hdev->sco_pkts; | ||
890 | } | 903 | } |
891 | } | 904 | } |
892 | } | 905 | } |
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index b2b1cceb102a..23ba61a13bdd 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
@@ -95,6 +95,10 @@ static void rfcomm_dev_destruct(struct rfcomm_dev *dev) | |||
95 | 95 | ||
96 | BT_DBG("dev %p dlc %p", dev, dlc); | 96 | BT_DBG("dev %p dlc %p", dev, dlc); |
97 | 97 | ||
98 | write_lock_bh(&rfcomm_dev_lock); | ||
99 | list_del_init(&dev->list); | ||
100 | write_unlock_bh(&rfcomm_dev_lock); | ||
101 | |||
98 | rfcomm_dlc_lock(dlc); | 102 | rfcomm_dlc_lock(dlc); |
99 | /* Detach DLC if it's owned by this dev */ | 103 | /* Detach DLC if it's owned by this dev */ |
100 | if (dlc->owner == dev) | 104 | if (dlc->owner == dev) |
@@ -156,8 +160,13 @@ static inline struct rfcomm_dev *rfcomm_dev_get(int id) | |||
156 | read_lock(&rfcomm_dev_lock); | 160 | read_lock(&rfcomm_dev_lock); |
157 | 161 | ||
158 | dev = __rfcomm_dev_get(id); | 162 | dev = __rfcomm_dev_get(id); |
159 | if (dev) | 163 | |
160 | rfcomm_dev_hold(dev); | 164 | if (dev) { |
165 | if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) | ||
166 | dev = NULL; | ||
167 | else | ||
168 | rfcomm_dev_hold(dev); | ||
169 | } | ||
161 | 170 | ||
162 | read_unlock(&rfcomm_dev_lock); | 171 | read_unlock(&rfcomm_dev_lock); |
163 | 172 | ||
@@ -265,6 +274,12 @@ out: | |||
265 | 274 | ||
266 | dev->tty_dev = tty_register_device(rfcomm_tty_driver, dev->id, NULL); | 275 | dev->tty_dev = tty_register_device(rfcomm_tty_driver, dev->id, NULL); |
267 | 276 | ||
277 | if (IS_ERR(dev->tty_dev)) { | ||
278 | list_del(&dev->list); | ||
279 | kfree(dev); | ||
280 | return PTR_ERR(dev->tty_dev); | ||
281 | } | ||
282 | |||
268 | return dev->id; | 283 | return dev->id; |
269 | } | 284 | } |
270 | 285 | ||
@@ -272,10 +287,7 @@ static void rfcomm_dev_del(struct rfcomm_dev *dev) | |||
272 | { | 287 | { |
273 | BT_DBG("dev %p", dev); | 288 | BT_DBG("dev %p", dev); |
274 | 289 | ||
275 | write_lock_bh(&rfcomm_dev_lock); | 290 | set_bit(RFCOMM_TTY_RELEASED, &dev->flags); |
276 | list_del_init(&dev->list); | ||
277 | write_unlock_bh(&rfcomm_dev_lock); | ||
278 | |||
279 | rfcomm_dev_put(dev); | 291 | rfcomm_dev_put(dev); |
280 | } | 292 | } |
281 | 293 | ||
@@ -329,7 +341,7 @@ static int rfcomm_create_dev(struct sock *sk, void __user *arg) | |||
329 | if (copy_from_user(&req, arg, sizeof(req))) | 341 | if (copy_from_user(&req, arg, sizeof(req))) |
330 | return -EFAULT; | 342 | return -EFAULT; |
331 | 343 | ||
332 | BT_DBG("sk %p dev_id %id flags 0x%x", sk, req.dev_id, req.flags); | 344 | BT_DBG("sk %p dev_id %d flags 0x%x", sk, req.dev_id, req.flags); |
333 | 345 | ||
334 | if (req.flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN)) | 346 | if (req.flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN)) |
335 | return -EPERM; | 347 | return -EPERM; |
@@ -370,7 +382,7 @@ static int rfcomm_release_dev(void __user *arg) | |||
370 | if (copy_from_user(&req, arg, sizeof(req))) | 382 | if (copy_from_user(&req, arg, sizeof(req))) |
371 | return -EFAULT; | 383 | return -EFAULT; |
372 | 384 | ||
373 | BT_DBG("dev_id %id flags 0x%x", req.dev_id, req.flags); | 385 | BT_DBG("dev_id %d flags 0x%x", req.dev_id, req.flags); |
374 | 386 | ||
375 | if (!(dev = rfcomm_dev_get(req.dev_id))) | 387 | if (!(dev = rfcomm_dev_get(req.dev_id))) |
376 | return -ENODEV; | 388 | return -ENODEV; |
@@ -383,6 +395,10 @@ static int rfcomm_release_dev(void __user *arg) | |||
383 | if (req.flags & (1 << RFCOMM_HANGUP_NOW)) | 395 | if (req.flags & (1 << RFCOMM_HANGUP_NOW)) |
384 | rfcomm_dlc_close(dev->dlc, 0); | 396 | rfcomm_dlc_close(dev->dlc, 0); |
385 | 397 | ||
398 | /* Shut down TTY synchronously before freeing rfcomm_dev */ | ||
399 | if (dev->tty) | ||
400 | tty_vhangup(dev->tty); | ||
401 | |||
386 | rfcomm_dev_del(dev); | 402 | rfcomm_dev_del(dev); |
387 | rfcomm_dev_put(dev); | 403 | rfcomm_dev_put(dev); |
388 | return 0; | 404 | return 0; |
@@ -415,6 +431,8 @@ static int rfcomm_get_dev_list(void __user *arg) | |||
415 | 431 | ||
416 | list_for_each(p, &rfcomm_dev_list) { | 432 | list_for_each(p, &rfcomm_dev_list) { |
417 | struct rfcomm_dev *dev = list_entry(p, struct rfcomm_dev, list); | 433 | struct rfcomm_dev *dev = list_entry(p, struct rfcomm_dev, list); |
434 | if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) | ||
435 | continue; | ||
418 | (di + n)->id = dev->id; | 436 | (di + n)->id = dev->id; |
419 | (di + n)->flags = dev->flags; | 437 | (di + n)->flags = dev->flags; |
420 | (di + n)->state = dev->dlc->state; | 438 | (di + n)->state = dev->dlc->state; |
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 849deaf14108..7b4ce9113be2 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -368,10 +368,18 @@ void br_features_recompute(struct net_bridge *br) | |||
368 | list_for_each_entry(p, &br->port_list, list) { | 368 | list_for_each_entry(p, &br->port_list, list) { |
369 | unsigned long feature = p->dev->features; | 369 | unsigned long feature = p->dev->features; |
370 | 370 | ||
371 | /* if device needs checksumming, downgrade to hw checksumming */ | ||
371 | if (checksum & NETIF_F_NO_CSUM && !(feature & NETIF_F_NO_CSUM)) | 372 | if (checksum & NETIF_F_NO_CSUM && !(feature & NETIF_F_NO_CSUM)) |
372 | checksum ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM; | 373 | checksum ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM; |
374 | |||
375 | /* if device can't do all checksum, downgrade to ipv4/ipv6 */ | ||
373 | if (checksum & NETIF_F_HW_CSUM && !(feature & NETIF_F_HW_CSUM)) | 376 | if (checksum & NETIF_F_HW_CSUM && !(feature & NETIF_F_HW_CSUM)) |
374 | checksum ^= NETIF_F_HW_CSUM | NETIF_F_IP_CSUM; | 377 | checksum ^= NETIF_F_HW_CSUM |
378 | | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; | ||
379 | |||
380 | if (checksum & NETIF_F_IPV6_CSUM && !(feature & NETIF_F_IPV6_CSUM)) | ||
381 | checksum &= ~NETIF_F_IPV6_CSUM; | ||
382 | |||
375 | if (!(feature & NETIF_F_IP_CSUM)) | 383 | if (!(feature & NETIF_F_IP_CSUM)) |
376 | checksum = 0; | 384 | checksum = 0; |
377 | 385 | ||
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 33c6c4a7c689..4f42263e0a8a 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c | |||
@@ -360,8 +360,9 @@ static struct attribute_group bridge_group = { | |||
360 | * | 360 | * |
361 | * Returns the number of bytes read. | 361 | * Returns the number of bytes read. |
362 | */ | 362 | */ |
363 | static ssize_t brforward_read(struct kobject *kobj, char *buf, | 363 | static ssize_t brforward_read(struct kobject *kobj, |
364 | loff_t off, size_t count) | 364 | struct bin_attribute *bin_attr, |
365 | char *buf, loff_t off, size_t count) | ||
365 | { | 366 | { |
366 | struct device *dev = to_dev(kobj); | 367 | struct device *dev = to_dev(kobj); |
367 | struct net_bridge *br = to_bridge(dev); | 368 | struct net_bridge *br = to_bridge(dev); |
@@ -383,8 +384,7 @@ static ssize_t brforward_read(struct kobject *kobj, char *buf, | |||
383 | 384 | ||
384 | static struct bin_attribute bridge_forward = { | 385 | static struct bin_attribute bridge_forward = { |
385 | .attr = { .name = SYSFS_BRIDGE_FDB, | 386 | .attr = { .name = SYSFS_BRIDGE_FDB, |
386 | .mode = S_IRUGO, | 387 | .mode = S_IRUGO, }, |
387 | .owner = THIS_MODULE, }, | ||
388 | .read = brforward_read, | 388 | .read = brforward_read, |
389 | }; | 389 | }; |
390 | 390 | ||
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index 2da22927d8dd..79db51fcb476 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c | |||
@@ -29,8 +29,7 @@ struct brport_attribute { | |||
29 | #define BRPORT_ATTR(_name,_mode,_show,_store) \ | 29 | #define BRPORT_ATTR(_name,_mode,_show,_store) \ |
30 | struct brport_attribute brport_attr_##_name = { \ | 30 | struct brport_attribute brport_attr_##_name = { \ |
31 | .attr = {.name = __stringify(_name), \ | 31 | .attr = {.name = __stringify(_name), \ |
32 | .mode = _mode, \ | 32 | .mode = _mode }, \ |
33 | .owner = THIS_MODULE, }, \ | ||
34 | .show = _show, \ | 33 | .show = _show, \ |
35 | .store = _store, \ | 34 | .store = _store, \ |
36 | }; | 35 | }; |
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index ac9984f98e59..4169a2a89a39 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
@@ -1525,14 +1525,14 @@ static int __init ebtables_init(void) | |||
1525 | if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0) | 1525 | if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0) |
1526 | return ret; | 1526 | return ret; |
1527 | 1527 | ||
1528 | printk(KERN_NOTICE "Ebtables v2.0 registered\n"); | 1528 | printk(KERN_INFO "Ebtables v2.0 registered\n"); |
1529 | return 0; | 1529 | return 0; |
1530 | } | 1530 | } |
1531 | 1531 | ||
1532 | static void __exit ebtables_fini(void) | 1532 | static void __exit ebtables_fini(void) |
1533 | { | 1533 | { |
1534 | nf_unregister_sockopt(&ebt_sockopts); | 1534 | nf_unregister_sockopt(&ebt_sockopts); |
1535 | printk(KERN_NOTICE "Ebtables v2.0 unregistered\n"); | 1535 | printk(KERN_INFO "Ebtables v2.0 unregistered\n"); |
1536 | } | 1536 | } |
1537 | 1537 | ||
1538 | EXPORT_SYMBOL(ebt_register_table); | 1538 | EXPORT_SYMBOL(ebt_register_table); |
diff --git a/net/compat.c b/net/compat.c index 9a0f5f2b90c8..d74d82155d78 100644 --- a/net/compat.c +++ b/net/compat.c | |||
@@ -276,7 +276,8 @@ void scm_detach_fds_compat(struct msghdr *kmsg, struct scm_cookie *scm) | |||
276 | err = security_file_receive(fp[i]); | 276 | err = security_file_receive(fp[i]); |
277 | if (err) | 277 | if (err) |
278 | break; | 278 | break; |
279 | err = get_unused_fd(); | 279 | err = get_unused_fd_flags(MSG_CMSG_CLOEXEC & kmsg->msg_flags |
280 | ? O_CLOEXEC : 0); | ||
280 | if (err < 0) | 281 | if (err < 0) |
281 | break; | 282 | break; |
282 | new_fd = err; | 283 | new_fd = err; |
diff --git a/net/core/dev.c b/net/core/dev.c index ee051bb398a0..13a0d9f6da54 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -98,6 +98,7 @@ | |||
98 | #include <linux/seq_file.h> | 98 | #include <linux/seq_file.h> |
99 | #include <linux/stat.h> | 99 | #include <linux/stat.h> |
100 | #include <linux/if_bridge.h> | 100 | #include <linux/if_bridge.h> |
101 | #include <linux/if_macvlan.h> | ||
101 | #include <net/dst.h> | 102 | #include <net/dst.h> |
102 | #include <net/pkt_sched.h> | 103 | #include <net/pkt_sched.h> |
103 | #include <net/checksum.h> | 104 | #include <net/checksum.h> |
@@ -151,9 +152,22 @@ static struct list_head ptype_base[16] __read_mostly; /* 16 way hashed list */ | |||
151 | static struct list_head ptype_all __read_mostly; /* Taps */ | 152 | static struct list_head ptype_all __read_mostly; /* Taps */ |
152 | 153 | ||
153 | #ifdef CONFIG_NET_DMA | 154 | #ifdef CONFIG_NET_DMA |
154 | static struct dma_client *net_dma_client; | 155 | struct net_dma { |
155 | static unsigned int net_dma_count; | 156 | struct dma_client client; |
156 | static spinlock_t net_dma_event_lock; | 157 | spinlock_t lock; |
158 | cpumask_t channel_mask; | ||
159 | struct dma_chan *channels[NR_CPUS]; | ||
160 | }; | ||
161 | |||
162 | static enum dma_state_client | ||
163 | netdev_dma_event(struct dma_client *client, struct dma_chan *chan, | ||
164 | enum dma_state state); | ||
165 | |||
166 | static struct net_dma net_dma = { | ||
167 | .client = { | ||
168 | .event_callback = netdev_dma_event, | ||
169 | }, | ||
170 | }; | ||
157 | #endif | 171 | #endif |
158 | 172 | ||
159 | /* | 173 | /* |
@@ -942,7 +956,7 @@ int dev_open(struct net_device *dev) | |||
942 | /* | 956 | /* |
943 | * Initialize multicasting status | 957 | * Initialize multicasting status |
944 | */ | 958 | */ |
945 | dev_mc_upload(dev); | 959 | dev_set_rx_mode(dev); |
946 | 960 | ||
947 | /* | 961 | /* |
948 | * Wakeup transmit queue engine | 962 | * Wakeup transmit queue engine |
@@ -1429,7 +1443,9 @@ gso: | |||
1429 | skb->next = nskb; | 1443 | skb->next = nskb; |
1430 | return rc; | 1444 | return rc; |
1431 | } | 1445 | } |
1432 | if (unlikely(netif_queue_stopped(dev) && skb->next)) | 1446 | if (unlikely((netif_queue_stopped(dev) || |
1447 | netif_subqueue_stopped(dev, skb->queue_mapping)) && | ||
1448 | skb->next)) | ||
1433 | return NETDEV_TX_BUSY; | 1449 | return NETDEV_TX_BUSY; |
1434 | } while (skb->next); | 1450 | } while (skb->next); |
1435 | 1451 | ||
@@ -1510,8 +1526,10 @@ int dev_queue_xmit(struct sk_buff *skb) | |||
1510 | skb_headroom(skb)); | 1526 | skb_headroom(skb)); |
1511 | 1527 | ||
1512 | if (!(dev->features & NETIF_F_GEN_CSUM) && | 1528 | if (!(dev->features & NETIF_F_GEN_CSUM) && |
1513 | (!(dev->features & NETIF_F_IP_CSUM) || | 1529 | !((dev->features & NETIF_F_IP_CSUM) && |
1514 | skb->protocol != htons(ETH_P_IP))) | 1530 | skb->protocol == htons(ETH_P_IP)) && |
1531 | !((dev->features & NETIF_F_IPV6_CSUM) && | ||
1532 | skb->protocol == htons(ETH_P_IPV6))) | ||
1515 | if (skb_checksum_help(skb)) | 1533 | if (skb_checksum_help(skb)) |
1516 | goto out_kfree_skb; | 1534 | goto out_kfree_skb; |
1517 | } | 1535 | } |
@@ -1545,6 +1563,8 @@ gso: | |||
1545 | spin_lock(&dev->queue_lock); | 1563 | spin_lock(&dev->queue_lock); |
1546 | q = dev->qdisc; | 1564 | q = dev->qdisc; |
1547 | if (q->enqueue) { | 1565 | if (q->enqueue) { |
1566 | /* reset queue_mapping to zero */ | ||
1567 | skb->queue_mapping = 0; | ||
1548 | rc = q->enqueue(skb, q); | 1568 | rc = q->enqueue(skb, q); |
1549 | qdisc_run(dev); | 1569 | qdisc_run(dev); |
1550 | spin_unlock(&dev->queue_lock); | 1570 | spin_unlock(&dev->queue_lock); |
@@ -1574,7 +1594,8 @@ gso: | |||
1574 | 1594 | ||
1575 | HARD_TX_LOCK(dev, cpu); | 1595 | HARD_TX_LOCK(dev, cpu); |
1576 | 1596 | ||
1577 | if (!netif_queue_stopped(dev)) { | 1597 | if (!netif_queue_stopped(dev) && |
1598 | !netif_subqueue_stopped(dev, skb->queue_mapping)) { | ||
1578 | rc = 0; | 1599 | rc = 0; |
1579 | if (!dev_hard_start_xmit(skb, dev)) { | 1600 | if (!dev_hard_start_xmit(skb, dev)) { |
1580 | HARD_TX_UNLOCK(dev); | 1601 | HARD_TX_UNLOCK(dev); |
@@ -1793,6 +1814,28 @@ static inline struct sk_buff *handle_bridge(struct sk_buff *skb, | |||
1793 | #define handle_bridge(skb, pt_prev, ret, orig_dev) (skb) | 1814 | #define handle_bridge(skb, pt_prev, ret, orig_dev) (skb) |
1794 | #endif | 1815 | #endif |
1795 | 1816 | ||
1817 | #if defined(CONFIG_MACVLAN) || defined(CONFIG_MACVLAN_MODULE) | ||
1818 | struct sk_buff *(*macvlan_handle_frame_hook)(struct sk_buff *skb) __read_mostly; | ||
1819 | EXPORT_SYMBOL_GPL(macvlan_handle_frame_hook); | ||
1820 | |||
1821 | static inline struct sk_buff *handle_macvlan(struct sk_buff *skb, | ||
1822 | struct packet_type **pt_prev, | ||
1823 | int *ret, | ||
1824 | struct net_device *orig_dev) | ||
1825 | { | ||
1826 | if (skb->dev->macvlan_port == NULL) | ||
1827 | return skb; | ||
1828 | |||
1829 | if (*pt_prev) { | ||
1830 | *ret = deliver_skb(skb, *pt_prev, orig_dev); | ||
1831 | *pt_prev = NULL; | ||
1832 | } | ||
1833 | return macvlan_handle_frame_hook(skb); | ||
1834 | } | ||
1835 | #else | ||
1836 | #define handle_macvlan(skb, pt_prev, ret, orig_dev) (skb) | ||
1837 | #endif | ||
1838 | |||
1796 | #ifdef CONFIG_NET_CLS_ACT | 1839 | #ifdef CONFIG_NET_CLS_ACT |
1797 | /* TODO: Maybe we should just force sch_ingress to be compiled in | 1840 | /* TODO: Maybe we should just force sch_ingress to be compiled in |
1798 | * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions | 1841 | * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions |
@@ -1900,6 +1943,9 @@ ncls: | |||
1900 | skb = handle_bridge(skb, &pt_prev, &ret, orig_dev); | 1943 | skb = handle_bridge(skb, &pt_prev, &ret, orig_dev); |
1901 | if (!skb) | 1944 | if (!skb) |
1902 | goto out; | 1945 | goto out; |
1946 | skb = handle_macvlan(skb, &pt_prev, &ret, orig_dev); | ||
1947 | if (!skb) | ||
1948 | goto out; | ||
1903 | 1949 | ||
1904 | type = skb->protocol; | 1950 | type = skb->protocol; |
1905 | list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) { | 1951 | list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) { |
@@ -2015,12 +2061,13 @@ out: | |||
2015 | * There may not be any more sk_buffs coming right now, so push | 2061 | * There may not be any more sk_buffs coming right now, so push |
2016 | * any pending DMA copies to hardware | 2062 | * any pending DMA copies to hardware |
2017 | */ | 2063 | */ |
2018 | if (net_dma_client) { | 2064 | if (!cpus_empty(net_dma.channel_mask)) { |
2019 | struct dma_chan *chan; | 2065 | int chan_idx; |
2020 | rcu_read_lock(); | 2066 | for_each_cpu_mask(chan_idx, net_dma.channel_mask) { |
2021 | list_for_each_entry_rcu(chan, &net_dma_client->channels, client_node) | 2067 | struct dma_chan *chan = net_dma.channels[chan_idx]; |
2022 | dma_async_memcpy_issue_pending(chan); | 2068 | if (chan) |
2023 | rcu_read_unlock(); | 2069 | dma_async_memcpy_issue_pending(chan); |
2070 | } | ||
2024 | } | 2071 | } |
2025 | #endif | 2072 | #endif |
2026 | return; | 2073 | return; |
@@ -2496,26 +2543,17 @@ int netdev_set_master(struct net_device *slave, struct net_device *master) | |||
2496 | return 0; | 2543 | return 0; |
2497 | } | 2544 | } |
2498 | 2545 | ||
2499 | /** | 2546 | static void __dev_set_promiscuity(struct net_device *dev, int inc) |
2500 | * dev_set_promiscuity - update promiscuity count on a device | ||
2501 | * @dev: device | ||
2502 | * @inc: modifier | ||
2503 | * | ||
2504 | * Add or remove promiscuity from a device. While the count in the device | ||
2505 | * remains above zero the interface remains promiscuous. Once it hits zero | ||
2506 | * the device reverts back to normal filtering operation. A negative inc | ||
2507 | * value is used to drop promiscuity on the device. | ||
2508 | */ | ||
2509 | void dev_set_promiscuity(struct net_device *dev, int inc) | ||
2510 | { | 2547 | { |
2511 | unsigned short old_flags = dev->flags; | 2548 | unsigned short old_flags = dev->flags; |
2512 | 2549 | ||
2550 | ASSERT_RTNL(); | ||
2551 | |||
2513 | if ((dev->promiscuity += inc) == 0) | 2552 | if ((dev->promiscuity += inc) == 0) |
2514 | dev->flags &= ~IFF_PROMISC; | 2553 | dev->flags &= ~IFF_PROMISC; |
2515 | else | 2554 | else |
2516 | dev->flags |= IFF_PROMISC; | 2555 | dev->flags |= IFF_PROMISC; |
2517 | if (dev->flags != old_flags) { | 2556 | if (dev->flags != old_flags) { |
2518 | dev_mc_upload(dev); | ||
2519 | printk(KERN_INFO "device %s %s promiscuous mode\n", | 2557 | printk(KERN_INFO "device %s %s promiscuous mode\n", |
2520 | dev->name, (dev->flags & IFF_PROMISC) ? "entered" : | 2558 | dev->name, (dev->flags & IFF_PROMISC) ? "entered" : |
2521 | "left"); | 2559 | "left"); |
@@ -2525,10 +2563,32 @@ void dev_set_promiscuity(struct net_device *dev, int inc) | |||
2525 | dev->name, (dev->flags & IFF_PROMISC), | 2563 | dev->name, (dev->flags & IFF_PROMISC), |
2526 | (old_flags & IFF_PROMISC), | 2564 | (old_flags & IFF_PROMISC), |
2527 | audit_get_loginuid(current->audit_context)); | 2565 | audit_get_loginuid(current->audit_context)); |
2566 | |||
2567 | if (dev->change_rx_flags) | ||
2568 | dev->change_rx_flags(dev, IFF_PROMISC); | ||
2528 | } | 2569 | } |
2529 | } | 2570 | } |
2530 | 2571 | ||
2531 | /** | 2572 | /** |
2573 | * dev_set_promiscuity - update promiscuity count on a device | ||
2574 | * @dev: device | ||
2575 | * @inc: modifier | ||
2576 | * | ||
2577 | * Add or remove promiscuity from a device. While the count in the device | ||
2578 | * remains above zero the interface remains promiscuous. Once it hits zero | ||
2579 | * the device reverts back to normal filtering operation. A negative inc | ||
2580 | * value is used to drop promiscuity on the device. | ||
2581 | */ | ||
2582 | void dev_set_promiscuity(struct net_device *dev, int inc) | ||
2583 | { | ||
2584 | unsigned short old_flags = dev->flags; | ||
2585 | |||
2586 | __dev_set_promiscuity(dev, inc); | ||
2587 | if (dev->flags != old_flags) | ||
2588 | dev_set_rx_mode(dev); | ||
2589 | } | ||
2590 | |||
2591 | /** | ||
2532 | * dev_set_allmulti - update allmulti count on a device | 2592 | * dev_set_allmulti - update allmulti count on a device |
2533 | * @dev: device | 2593 | * @dev: device |
2534 | * @inc: modifier | 2594 | * @inc: modifier |
@@ -2544,11 +2604,185 @@ void dev_set_allmulti(struct net_device *dev, int inc) | |||
2544 | { | 2604 | { |
2545 | unsigned short old_flags = dev->flags; | 2605 | unsigned short old_flags = dev->flags; |
2546 | 2606 | ||
2607 | ASSERT_RTNL(); | ||
2608 | |||
2547 | dev->flags |= IFF_ALLMULTI; | 2609 | dev->flags |= IFF_ALLMULTI; |
2548 | if ((dev->allmulti += inc) == 0) | 2610 | if ((dev->allmulti += inc) == 0) |
2549 | dev->flags &= ~IFF_ALLMULTI; | 2611 | dev->flags &= ~IFF_ALLMULTI; |
2550 | if (dev->flags ^ old_flags) | 2612 | if (dev->flags ^ old_flags) { |
2551 | dev_mc_upload(dev); | 2613 | if (dev->change_rx_flags) |
2614 | dev->change_rx_flags(dev, IFF_ALLMULTI); | ||
2615 | dev_set_rx_mode(dev); | ||
2616 | } | ||
2617 | } | ||
2618 | |||
2619 | /* | ||
2620 | * Upload unicast and multicast address lists to device and | ||
2621 | * configure RX filtering. When the device doesn't support unicast | ||
2622 | * filtering it is put in promiscous mode while unicast addresses | ||
2623 | * are present. | ||
2624 | */ | ||
2625 | void __dev_set_rx_mode(struct net_device *dev) | ||
2626 | { | ||
2627 | /* dev_open will call this function so the list will stay sane. */ | ||
2628 | if (!(dev->flags&IFF_UP)) | ||
2629 | return; | ||
2630 | |||
2631 | if (!netif_device_present(dev)) | ||
2632 | return; | ||
2633 | |||
2634 | if (dev->set_rx_mode) | ||
2635 | dev->set_rx_mode(dev); | ||
2636 | else { | ||
2637 | /* Unicast addresses changes may only happen under the rtnl, | ||
2638 | * therefore calling __dev_set_promiscuity here is safe. | ||
2639 | */ | ||
2640 | if (dev->uc_count > 0 && !dev->uc_promisc) { | ||
2641 | __dev_set_promiscuity(dev, 1); | ||
2642 | dev->uc_promisc = 1; | ||
2643 | } else if (dev->uc_count == 0 && dev->uc_promisc) { | ||
2644 | __dev_set_promiscuity(dev, -1); | ||
2645 | dev->uc_promisc = 0; | ||
2646 | } | ||
2647 | |||
2648 | if (dev->set_multicast_list) | ||
2649 | dev->set_multicast_list(dev); | ||
2650 | } | ||
2651 | } | ||
2652 | |||
2653 | void dev_set_rx_mode(struct net_device *dev) | ||
2654 | { | ||
2655 | netif_tx_lock_bh(dev); | ||
2656 | __dev_set_rx_mode(dev); | ||
2657 | netif_tx_unlock_bh(dev); | ||
2658 | } | ||
2659 | |||
2660 | int __dev_addr_delete(struct dev_addr_list **list, int *count, | ||
2661 | void *addr, int alen, int glbl) | ||
2662 | { | ||
2663 | struct dev_addr_list *da; | ||
2664 | |||
2665 | for (; (da = *list) != NULL; list = &da->next) { | ||
2666 | if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 && | ||
2667 | alen == da->da_addrlen) { | ||
2668 | if (glbl) { | ||
2669 | int old_glbl = da->da_gusers; | ||
2670 | da->da_gusers = 0; | ||
2671 | if (old_glbl == 0) | ||
2672 | break; | ||
2673 | } | ||
2674 | if (--da->da_users) | ||
2675 | return 0; | ||
2676 | |||
2677 | *list = da->next; | ||
2678 | kfree(da); | ||
2679 | (*count)--; | ||
2680 | return 0; | ||
2681 | } | ||
2682 | } | ||
2683 | return -ENOENT; | ||
2684 | } | ||
2685 | |||
2686 | int __dev_addr_add(struct dev_addr_list **list, int *count, | ||
2687 | void *addr, int alen, int glbl) | ||
2688 | { | ||
2689 | struct dev_addr_list *da; | ||
2690 | |||
2691 | for (da = *list; da != NULL; da = da->next) { | ||
2692 | if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 && | ||
2693 | da->da_addrlen == alen) { | ||
2694 | if (glbl) { | ||
2695 | int old_glbl = da->da_gusers; | ||
2696 | da->da_gusers = 1; | ||
2697 | if (old_glbl) | ||
2698 | return 0; | ||
2699 | } | ||
2700 | da->da_users++; | ||
2701 | return 0; | ||
2702 | } | ||
2703 | } | ||
2704 | |||
2705 | da = kmalloc(sizeof(*da), GFP_ATOMIC); | ||
2706 | if (da == NULL) | ||
2707 | return -ENOMEM; | ||
2708 | memcpy(da->da_addr, addr, alen); | ||
2709 | da->da_addrlen = alen; | ||
2710 | da->da_users = 1; | ||
2711 | da->da_gusers = glbl ? 1 : 0; | ||
2712 | da->next = *list; | ||
2713 | *list = da; | ||
2714 | (*count)++; | ||
2715 | return 0; | ||
2716 | } | ||
2717 | |||
2718 | void __dev_addr_discard(struct dev_addr_list **list) | ||
2719 | { | ||
2720 | struct dev_addr_list *tmp; | ||
2721 | |||
2722 | while (*list != NULL) { | ||
2723 | tmp = *list; | ||
2724 | *list = tmp->next; | ||
2725 | if (tmp->da_users > tmp->da_gusers) | ||
2726 | printk("__dev_addr_discard: address leakage! " | ||
2727 | "da_users=%d\n", tmp->da_users); | ||
2728 | kfree(tmp); | ||
2729 | } | ||
2730 | } | ||
2731 | |||
2732 | /** | ||
2733 | * dev_unicast_delete - Release secondary unicast address. | ||
2734 | * @dev: device | ||
2735 | * | ||
2736 | * Release reference to a secondary unicast address and remove it | ||
2737 | * from the device if the reference count drop to zero. | ||
2738 | * | ||
2739 | * The caller must hold the rtnl_mutex. | ||
2740 | */ | ||
2741 | int dev_unicast_delete(struct net_device *dev, void *addr, int alen) | ||
2742 | { | ||
2743 | int err; | ||
2744 | |||
2745 | ASSERT_RTNL(); | ||
2746 | |||
2747 | netif_tx_lock_bh(dev); | ||
2748 | err = __dev_addr_delete(&dev->uc_list, &dev->uc_count, addr, alen, 0); | ||
2749 | if (!err) | ||
2750 | __dev_set_rx_mode(dev); | ||
2751 | netif_tx_unlock_bh(dev); | ||
2752 | return err; | ||
2753 | } | ||
2754 | EXPORT_SYMBOL(dev_unicast_delete); | ||
2755 | |||
2756 | /** | ||
2757 | * dev_unicast_add - add a secondary unicast address | ||
2758 | * @dev: device | ||
2759 | * | ||
2760 | * Add a secondary unicast address to the device or increase | ||
2761 | * the reference count if it already exists. | ||
2762 | * | ||
2763 | * The caller must hold the rtnl_mutex. | ||
2764 | */ | ||
2765 | int dev_unicast_add(struct net_device *dev, void *addr, int alen) | ||
2766 | { | ||
2767 | int err; | ||
2768 | |||
2769 | ASSERT_RTNL(); | ||
2770 | |||
2771 | netif_tx_lock_bh(dev); | ||
2772 | err = __dev_addr_add(&dev->uc_list, &dev->uc_count, addr, alen, 0); | ||
2773 | if (!err) | ||
2774 | __dev_set_rx_mode(dev); | ||
2775 | netif_tx_unlock_bh(dev); | ||
2776 | return err; | ||
2777 | } | ||
2778 | EXPORT_SYMBOL(dev_unicast_add); | ||
2779 | |||
2780 | static void dev_unicast_discard(struct net_device *dev) | ||
2781 | { | ||
2782 | netif_tx_lock_bh(dev); | ||
2783 | __dev_addr_discard(&dev->uc_list); | ||
2784 | dev->uc_count = 0; | ||
2785 | netif_tx_unlock_bh(dev); | ||
2552 | } | 2786 | } |
2553 | 2787 | ||
2554 | unsigned dev_get_flags(const struct net_device *dev) | 2788 | unsigned dev_get_flags(const struct net_device *dev) |
@@ -2580,6 +2814,8 @@ int dev_change_flags(struct net_device *dev, unsigned flags) | |||
2580 | int ret, changes; | 2814 | int ret, changes; |
2581 | int old_flags = dev->flags; | 2815 | int old_flags = dev->flags; |
2582 | 2816 | ||
2817 | ASSERT_RTNL(); | ||
2818 | |||
2583 | /* | 2819 | /* |
2584 | * Set the flags on our device. | 2820 | * Set the flags on our device. |
2585 | */ | 2821 | */ |
@@ -2594,7 +2830,10 @@ int dev_change_flags(struct net_device *dev, unsigned flags) | |||
2594 | * Load in the correct multicast list now the flags have changed. | 2830 | * Load in the correct multicast list now the flags have changed. |
2595 | */ | 2831 | */ |
2596 | 2832 | ||
2597 | dev_mc_upload(dev); | 2833 | if (dev->change_rx_flags && (dev->flags ^ flags) & IFF_MULTICAST) |
2834 | dev->change_rx_flags(dev, IFF_MULTICAST); | ||
2835 | |||
2836 | dev_set_rx_mode(dev); | ||
2598 | 2837 | ||
2599 | /* | 2838 | /* |
2600 | * Have we downed the interface. We handle IFF_UP ourselves | 2839 | * Have we downed the interface. We handle IFF_UP ourselves |
@@ -2607,7 +2846,7 @@ int dev_change_flags(struct net_device *dev, unsigned flags) | |||
2607 | ret = ((old_flags & IFF_UP) ? dev_close : dev_open)(dev); | 2846 | ret = ((old_flags & IFF_UP) ? dev_close : dev_open)(dev); |
2608 | 2847 | ||
2609 | if (!ret) | 2848 | if (!ret) |
2610 | dev_mc_upload(dev); | 2849 | dev_set_rx_mode(dev); |
2611 | } | 2850 | } |
2612 | 2851 | ||
2613 | if (dev->flags & IFF_UP && | 2852 | if (dev->flags & IFF_UP && |
@@ -3107,6 +3346,22 @@ int register_netdevice(struct net_device *dev) | |||
3107 | } | 3346 | } |
3108 | } | 3347 | } |
3109 | 3348 | ||
3349 | /* Fix illegal checksum combinations */ | ||
3350 | if ((dev->features & NETIF_F_HW_CSUM) && | ||
3351 | (dev->features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) { | ||
3352 | printk(KERN_NOTICE "%s: mixed HW and IP checksum settings.\n", | ||
3353 | dev->name); | ||
3354 | dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM); | ||
3355 | } | ||
3356 | |||
3357 | if ((dev->features & NETIF_F_NO_CSUM) && | ||
3358 | (dev->features & (NETIF_F_HW_CSUM|NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) { | ||
3359 | printk(KERN_NOTICE "%s: mixed no checksumming and other settings.\n", | ||
3360 | dev->name); | ||
3361 | dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM|NETIF_F_HW_CSUM); | ||
3362 | } | ||
3363 | |||
3364 | |||
3110 | /* Fix illegal SG+CSUM combinations. */ | 3365 | /* Fix illegal SG+CSUM combinations. */ |
3111 | if ((dev->features & NETIF_F_SG) && | 3366 | if ((dev->features & NETIF_F_SG) && |
3112 | !(dev->features & NETIF_F_ALL_CSUM)) { | 3367 | !(dev->features & NETIF_F_ALL_CSUM)) { |
@@ -3343,16 +3598,18 @@ static struct net_device_stats *internal_stats(struct net_device *dev) | |||
3343 | } | 3598 | } |
3344 | 3599 | ||
3345 | /** | 3600 | /** |
3346 | * alloc_netdev - allocate network device | 3601 | * alloc_netdev_mq - allocate network device |
3347 | * @sizeof_priv: size of private data to allocate space for | 3602 | * @sizeof_priv: size of private data to allocate space for |
3348 | * @name: device name format string | 3603 | * @name: device name format string |
3349 | * @setup: callback to initialize device | 3604 | * @setup: callback to initialize device |
3605 | * @queue_count: the number of subqueues to allocate | ||
3350 | * | 3606 | * |
3351 | * Allocates a struct net_device with private data area for driver use | 3607 | * Allocates a struct net_device with private data area for driver use |
3352 | * and performs basic initialization. | 3608 | * and performs basic initialization. Also allocates subquue structs |
3609 | * for each queue on the device at the end of the netdevice. | ||
3353 | */ | 3610 | */ |
3354 | struct net_device *alloc_netdev(int sizeof_priv, const char *name, | 3611 | struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, |
3355 | void (*setup)(struct net_device *)) | 3612 | void (*setup)(struct net_device *), unsigned int queue_count) |
3356 | { | 3613 | { |
3357 | void *p; | 3614 | void *p; |
3358 | struct net_device *dev; | 3615 | struct net_device *dev; |
@@ -3361,7 +3618,9 @@ struct net_device *alloc_netdev(int sizeof_priv, const char *name, | |||
3361 | BUG_ON(strlen(name) >= sizeof(dev->name)); | 3618 | BUG_ON(strlen(name) >= sizeof(dev->name)); |
3362 | 3619 | ||
3363 | /* ensure 32-byte alignment of both the device and private area */ | 3620 | /* ensure 32-byte alignment of both the device and private area */ |
3364 | alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST; | 3621 | alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST + |
3622 | (sizeof(struct net_device_subqueue) * queue_count)) & | ||
3623 | ~NETDEV_ALIGN_CONST; | ||
3365 | alloc_size += sizeof_priv + NETDEV_ALIGN_CONST; | 3624 | alloc_size += sizeof_priv + NETDEV_ALIGN_CONST; |
3366 | 3625 | ||
3367 | p = kzalloc(alloc_size, GFP_KERNEL); | 3626 | p = kzalloc(alloc_size, GFP_KERNEL); |
@@ -3374,15 +3633,22 @@ struct net_device *alloc_netdev(int sizeof_priv, const char *name, | |||
3374 | (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); | 3633 | (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); |
3375 | dev->padded = (char *)dev - (char *)p; | 3634 | dev->padded = (char *)dev - (char *)p; |
3376 | 3635 | ||
3377 | if (sizeof_priv) | 3636 | if (sizeof_priv) { |
3378 | dev->priv = netdev_priv(dev); | 3637 | dev->priv = ((char *)dev + |
3638 | ((sizeof(struct net_device) + | ||
3639 | (sizeof(struct net_device_subqueue) * | ||
3640 | queue_count) + NETDEV_ALIGN_CONST) | ||
3641 | & ~NETDEV_ALIGN_CONST)); | ||
3642 | } | ||
3643 | |||
3644 | dev->egress_subqueue_count = queue_count; | ||
3379 | 3645 | ||
3380 | dev->get_stats = internal_stats; | 3646 | dev->get_stats = internal_stats; |
3381 | setup(dev); | 3647 | setup(dev); |
3382 | strcpy(dev->name, name); | 3648 | strcpy(dev->name, name); |
3383 | return dev; | 3649 | return dev; |
3384 | } | 3650 | } |
3385 | EXPORT_SYMBOL(alloc_netdev); | 3651 | EXPORT_SYMBOL(alloc_netdev_mq); |
3386 | 3652 | ||
3387 | /** | 3653 | /** |
3388 | * free_netdev - free network device | 3654 | * free_netdev - free network device |
@@ -3471,8 +3737,9 @@ void unregister_netdevice(struct net_device *dev) | |||
3471 | raw_notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev); | 3737 | raw_notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev); |
3472 | 3738 | ||
3473 | /* | 3739 | /* |
3474 | * Flush the multicast chain | 3740 | * Flush the unicast and multicast chains |
3475 | */ | 3741 | */ |
3742 | dev_unicast_discard(dev); | ||
3476 | dev_mc_discard(dev); | 3743 | dev_mc_discard(dev); |
3477 | 3744 | ||
3478 | if (dev->uninit) | 3745 | if (dev->uninit) |
@@ -3563,12 +3830,13 @@ static int dev_cpu_callback(struct notifier_block *nfb, | |||
3563 | * This is called when the number of channels allocated to the net_dma_client | 3830 | * This is called when the number of channels allocated to the net_dma_client |
3564 | * changes. The net_dma_client tries to have one DMA channel per CPU. | 3831 | * changes. The net_dma_client tries to have one DMA channel per CPU. |
3565 | */ | 3832 | */ |
3566 | static void net_dma_rebalance(void) | 3833 | |
3834 | static void net_dma_rebalance(struct net_dma *net_dma) | ||
3567 | { | 3835 | { |
3568 | unsigned int cpu, i, n; | 3836 | unsigned int cpu, i, n, chan_idx; |
3569 | struct dma_chan *chan; | 3837 | struct dma_chan *chan; |
3570 | 3838 | ||
3571 | if (net_dma_count == 0) { | 3839 | if (cpus_empty(net_dma->channel_mask)) { |
3572 | for_each_online_cpu(cpu) | 3840 | for_each_online_cpu(cpu) |
3573 | rcu_assign_pointer(per_cpu(softnet_data, cpu).net_dma, NULL); | 3841 | rcu_assign_pointer(per_cpu(softnet_data, cpu).net_dma, NULL); |
3574 | return; | 3842 | return; |
@@ -3577,10 +3845,12 @@ static void net_dma_rebalance(void) | |||
3577 | i = 0; | 3845 | i = 0; |
3578 | cpu = first_cpu(cpu_online_map); | 3846 | cpu = first_cpu(cpu_online_map); |
3579 | 3847 | ||
3580 | rcu_read_lock(); | 3848 | for_each_cpu_mask(chan_idx, net_dma->channel_mask) { |
3581 | list_for_each_entry(chan, &net_dma_client->channels, client_node) { | 3849 | chan = net_dma->channels[chan_idx]; |
3582 | n = ((num_online_cpus() / net_dma_count) | 3850 | |
3583 | + (i < (num_online_cpus() % net_dma_count) ? 1 : 0)); | 3851 | n = ((num_online_cpus() / cpus_weight(net_dma->channel_mask)) |
3852 | + (i < (num_online_cpus() % | ||
3853 | cpus_weight(net_dma->channel_mask)) ? 1 : 0)); | ||
3584 | 3854 | ||
3585 | while(n) { | 3855 | while(n) { |
3586 | per_cpu(softnet_data, cpu).net_dma = chan; | 3856 | per_cpu(softnet_data, cpu).net_dma = chan; |
@@ -3589,7 +3859,6 @@ static void net_dma_rebalance(void) | |||
3589 | } | 3859 | } |
3590 | i++; | 3860 | i++; |
3591 | } | 3861 | } |
3592 | rcu_read_unlock(); | ||
3593 | } | 3862 | } |
3594 | 3863 | ||
3595 | /** | 3864 | /** |
@@ -3598,23 +3867,53 @@ static void net_dma_rebalance(void) | |||
3598 | * @chan: DMA channel for the event | 3867 | * @chan: DMA channel for the event |
3599 | * @event: event type | 3868 | * @event: event type |
3600 | */ | 3869 | */ |
3601 | static void netdev_dma_event(struct dma_client *client, struct dma_chan *chan, | 3870 | static enum dma_state_client |
3602 | enum dma_event event) | 3871 | netdev_dma_event(struct dma_client *client, struct dma_chan *chan, |
3603 | { | 3872 | enum dma_state state) |
3604 | spin_lock(&net_dma_event_lock); | 3873 | { |
3605 | switch (event) { | 3874 | int i, found = 0, pos = -1; |
3606 | case DMA_RESOURCE_ADDED: | 3875 | struct net_dma *net_dma = |
3607 | net_dma_count++; | 3876 | container_of(client, struct net_dma, client); |
3608 | net_dma_rebalance(); | 3877 | enum dma_state_client ack = DMA_DUP; /* default: take no action */ |
3878 | |||
3879 | spin_lock(&net_dma->lock); | ||
3880 | switch (state) { | ||
3881 | case DMA_RESOURCE_AVAILABLE: | ||
3882 | for (i = 0; i < NR_CPUS; i++) | ||
3883 | if (net_dma->channels[i] == chan) { | ||
3884 | found = 1; | ||
3885 | break; | ||
3886 | } else if (net_dma->channels[i] == NULL && pos < 0) | ||
3887 | pos = i; | ||
3888 | |||
3889 | if (!found && pos >= 0) { | ||
3890 | ack = DMA_ACK; | ||
3891 | net_dma->channels[pos] = chan; | ||
3892 | cpu_set(pos, net_dma->channel_mask); | ||
3893 | net_dma_rebalance(net_dma); | ||
3894 | } | ||
3609 | break; | 3895 | break; |
3610 | case DMA_RESOURCE_REMOVED: | 3896 | case DMA_RESOURCE_REMOVED: |
3611 | net_dma_count--; | 3897 | for (i = 0; i < NR_CPUS; i++) |
3612 | net_dma_rebalance(); | 3898 | if (net_dma->channels[i] == chan) { |
3899 | found = 1; | ||
3900 | pos = i; | ||
3901 | break; | ||
3902 | } | ||
3903 | |||
3904 | if (found) { | ||
3905 | ack = DMA_ACK; | ||
3906 | cpu_clear(pos, net_dma->channel_mask); | ||
3907 | net_dma->channels[i] = NULL; | ||
3908 | net_dma_rebalance(net_dma); | ||
3909 | } | ||
3613 | break; | 3910 | break; |
3614 | default: | 3911 | default: |
3615 | break; | 3912 | break; |
3616 | } | 3913 | } |
3617 | spin_unlock(&net_dma_event_lock); | 3914 | spin_unlock(&net_dma->lock); |
3915 | |||
3916 | return ack; | ||
3618 | } | 3917 | } |
3619 | 3918 | ||
3620 | /** | 3919 | /** |
@@ -3622,12 +3921,10 @@ static void netdev_dma_event(struct dma_client *client, struct dma_chan *chan, | |||
3622 | */ | 3921 | */ |
3623 | static int __init netdev_dma_register(void) | 3922 | static int __init netdev_dma_register(void) |
3624 | { | 3923 | { |
3625 | spin_lock_init(&net_dma_event_lock); | 3924 | spin_lock_init(&net_dma.lock); |
3626 | net_dma_client = dma_async_client_register(netdev_dma_event); | 3925 | dma_cap_set(DMA_MEMCPY, net_dma.client.cap_mask); |
3627 | if (net_dma_client == NULL) | 3926 | dma_async_client_register(&net_dma.client); |
3628 | return -ENOMEM; | 3927 | dma_async_client_chan_request(&net_dma.client); |
3629 | |||
3630 | dma_async_client_chan_request(net_dma_client, num_online_cpus()); | ||
3631 | return 0; | 3928 | return 0; |
3632 | } | 3929 | } |
3633 | 3930 | ||
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c index 5a54053386c8..235a2a8a0d05 100644 --- a/net/core/dev_mcast.c +++ b/net/core/dev_mcast.c | |||
@@ -64,85 +64,24 @@ | |||
64 | */ | 64 | */ |
65 | 65 | ||
66 | /* | 66 | /* |
67 | * Update the multicast list into the physical NIC controller. | ||
68 | */ | ||
69 | |||
70 | static void __dev_mc_upload(struct net_device *dev) | ||
71 | { | ||
72 | /* Don't do anything till we up the interface | ||
73 | * [dev_open will call this function so the list will | ||
74 | * stay sane] | ||
75 | */ | ||
76 | |||
77 | if (!(dev->flags&IFF_UP)) | ||
78 | return; | ||
79 | |||
80 | /* | ||
81 | * Devices with no set multicast or which have been | ||
82 | * detached don't get set. | ||
83 | */ | ||
84 | |||
85 | if (dev->set_multicast_list == NULL || | ||
86 | !netif_device_present(dev)) | ||
87 | return; | ||
88 | |||
89 | dev->set_multicast_list(dev); | ||
90 | } | ||
91 | |||
92 | void dev_mc_upload(struct net_device *dev) | ||
93 | { | ||
94 | netif_tx_lock_bh(dev); | ||
95 | __dev_mc_upload(dev); | ||
96 | netif_tx_unlock_bh(dev); | ||
97 | } | ||
98 | |||
99 | /* | ||
100 | * Delete a device level multicast | 67 | * Delete a device level multicast |
101 | */ | 68 | */ |
102 | 69 | ||
103 | int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl) | 70 | int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl) |
104 | { | 71 | { |
105 | int err = 0; | 72 | int err; |
106 | struct dev_mc_list *dmi, **dmip; | ||
107 | 73 | ||
108 | netif_tx_lock_bh(dev); | 74 | netif_tx_lock_bh(dev); |
109 | 75 | err = __dev_addr_delete(&dev->mc_list, &dev->mc_count, | |
110 | for (dmip = &dev->mc_list; (dmi = *dmip) != NULL; dmip = &dmi->next) { | 76 | addr, alen, glbl); |
77 | if (!err) { | ||
111 | /* | 78 | /* |
112 | * Find the entry we want to delete. The device could | 79 | * We have altered the list, so the card |
113 | * have variable length entries so check these too. | 80 | * loaded filter is now wrong. Fix it |
114 | */ | 81 | */ |
115 | if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 && | 82 | |
116 | alen == dmi->dmi_addrlen) { | 83 | __dev_set_rx_mode(dev); |
117 | if (glbl) { | ||
118 | int old_glbl = dmi->dmi_gusers; | ||
119 | dmi->dmi_gusers = 0; | ||
120 | if (old_glbl == 0) | ||
121 | break; | ||
122 | } | ||
123 | if (--dmi->dmi_users) | ||
124 | goto done; | ||
125 | |||
126 | /* | ||
127 | * Last user. So delete the entry. | ||
128 | */ | ||
129 | *dmip = dmi->next; | ||
130 | dev->mc_count--; | ||
131 | |||
132 | kfree(dmi); | ||
133 | |||
134 | /* | ||
135 | * We have altered the list, so the card | ||
136 | * loaded filter is now wrong. Fix it | ||
137 | */ | ||
138 | __dev_mc_upload(dev); | ||
139 | |||
140 | netif_tx_unlock_bh(dev); | ||
141 | return 0; | ||
142 | } | ||
143 | } | 84 | } |
144 | err = -ENOENT; | ||
145 | done: | ||
146 | netif_tx_unlock_bh(dev); | 85 | netif_tx_unlock_bh(dev); |
147 | return err; | 86 | return err; |
148 | } | 87 | } |
@@ -153,48 +92,90 @@ done: | |||
153 | 92 | ||
154 | int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) | 93 | int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) |
155 | { | 94 | { |
156 | int err = 0; | 95 | int err; |
157 | struct dev_mc_list *dmi, *dmi1; | ||
158 | |||
159 | dmi1 = kmalloc(sizeof(*dmi), GFP_ATOMIC); | ||
160 | 96 | ||
161 | netif_tx_lock_bh(dev); | 97 | netif_tx_lock_bh(dev); |
162 | for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) { | 98 | err = __dev_addr_add(&dev->mc_list, &dev->mc_count, addr, alen, glbl); |
163 | if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 && | 99 | if (!err) |
164 | dmi->dmi_addrlen == alen) { | 100 | __dev_set_rx_mode(dev); |
165 | if (glbl) { | 101 | netif_tx_unlock_bh(dev); |
166 | int old_glbl = dmi->dmi_gusers; | 102 | return err; |
167 | dmi->dmi_gusers = 1; | 103 | } |
168 | if (old_glbl) | 104 | |
169 | goto done; | 105 | /** |
170 | } | 106 | * dev_mc_sync - Synchronize device's multicast list to another device |
171 | dmi->dmi_users++; | 107 | * @to: destination device |
172 | goto done; | 108 | * @from: source device |
109 | * | ||
110 | * Add newly added addresses to the destination device and release | ||
111 | * addresses that have no users left. The source device must be | ||
112 | * locked by netif_tx_lock_bh. | ||
113 | * | ||
114 | * This function is intended to be called from the dev->set_multicast_list | ||
115 | * function of layered software devices. | ||
116 | */ | ||
117 | int dev_mc_sync(struct net_device *to, struct net_device *from) | ||
118 | { | ||
119 | struct dev_addr_list *da; | ||
120 | int err = 0; | ||
121 | |||
122 | netif_tx_lock_bh(to); | ||
123 | for (da = from->mc_list; da != NULL; da = da->next) { | ||
124 | if (!da->da_synced) { | ||
125 | err = __dev_addr_add(&to->mc_list, &to->mc_count, | ||
126 | da->da_addr, da->da_addrlen, 0); | ||
127 | if (err < 0) | ||
128 | break; | ||
129 | da->da_synced = 1; | ||
130 | da->da_users++; | ||
131 | } else if (da->da_users == 1) { | ||
132 | __dev_addr_delete(&to->mc_list, &to->mc_count, | ||
133 | da->da_addr, da->da_addrlen, 0); | ||
134 | __dev_addr_delete(&from->mc_list, &from->mc_count, | ||
135 | da->da_addr, da->da_addrlen, 0); | ||
173 | } | 136 | } |
174 | } | 137 | } |
138 | if (!err) | ||
139 | __dev_set_rx_mode(to); | ||
140 | netif_tx_unlock_bh(to); | ||
175 | 141 | ||
176 | if ((dmi = dmi1) == NULL) { | 142 | return err; |
177 | netif_tx_unlock_bh(dev); | 143 | } |
178 | return -ENOMEM; | 144 | EXPORT_SYMBOL(dev_mc_sync); |
179 | } | ||
180 | memcpy(dmi->dmi_addr, addr, alen); | ||
181 | dmi->dmi_addrlen = alen; | ||
182 | dmi->next = dev->mc_list; | ||
183 | dmi->dmi_users = 1; | ||
184 | dmi->dmi_gusers = glbl ? 1 : 0; | ||
185 | dev->mc_list = dmi; | ||
186 | dev->mc_count++; | ||
187 | 145 | ||
188 | __dev_mc_upload(dev); | ||
189 | 146 | ||
190 | netif_tx_unlock_bh(dev); | 147 | /** |
191 | return 0; | 148 | * dev_mc_unsync - Remove synchronized addresses from the destination |
149 | * device | ||
150 | * @to: destination device | ||
151 | * @from: source device | ||
152 | * | ||
153 | * Remove all addresses that were added to the destination device by | ||
154 | * dev_mc_sync(). This function is intended to be called from the | ||
155 | * dev->stop function of layered software devices. | ||
156 | */ | ||
157 | void dev_mc_unsync(struct net_device *to, struct net_device *from) | ||
158 | { | ||
159 | struct dev_addr_list *da; | ||
160 | |||
161 | netif_tx_lock_bh(from); | ||
162 | netif_tx_lock_bh(to); | ||
163 | |||
164 | for (da = from->mc_list; da != NULL; da = da->next) { | ||
165 | if (!da->da_synced) | ||
166 | continue; | ||
167 | __dev_addr_delete(&to->mc_list, &to->mc_count, | ||
168 | da->da_addr, da->da_addrlen, 0); | ||
169 | da->da_synced = 0; | ||
170 | __dev_addr_delete(&from->mc_list, &from->mc_count, | ||
171 | da->da_addr, da->da_addrlen, 0); | ||
172 | } | ||
173 | __dev_set_rx_mode(to); | ||
192 | 174 | ||
193 | done: | 175 | netif_tx_unlock_bh(to); |
194 | netif_tx_unlock_bh(dev); | 176 | netif_tx_unlock_bh(from); |
195 | kfree(dmi1); | ||
196 | return err; | ||
197 | } | 177 | } |
178 | EXPORT_SYMBOL(dev_mc_unsync); | ||
198 | 179 | ||
199 | /* | 180 | /* |
200 | * Discard multicast list when a device is downed | 181 | * Discard multicast list when a device is downed |
@@ -203,16 +184,8 @@ done: | |||
203 | void dev_mc_discard(struct net_device *dev) | 184 | void dev_mc_discard(struct net_device *dev) |
204 | { | 185 | { |
205 | netif_tx_lock_bh(dev); | 186 | netif_tx_lock_bh(dev); |
206 | 187 | __dev_addr_discard(&dev->mc_list); | |
207 | while (dev->mc_list != NULL) { | ||
208 | struct dev_mc_list *tmp = dev->mc_list; | ||
209 | dev->mc_list = tmp->next; | ||
210 | if (tmp->dmi_users > tmp->dmi_gusers) | ||
211 | printk("dev_mc_discard: multicast leakage! dmi_users=%d\n", tmp->dmi_users); | ||
212 | kfree(tmp); | ||
213 | } | ||
214 | dev->mc_count = 0; | 188 | dev->mc_count = 0; |
215 | |||
216 | netif_tx_unlock_bh(dev); | 189 | netif_tx_unlock_bh(dev); |
217 | } | 190 | } |
218 | 191 | ||
@@ -244,7 +217,7 @@ static void dev_mc_seq_stop(struct seq_file *seq, void *v) | |||
244 | 217 | ||
245 | static int dev_mc_seq_show(struct seq_file *seq, void *v) | 218 | static int dev_mc_seq_show(struct seq_file *seq, void *v) |
246 | { | 219 | { |
247 | struct dev_mc_list *m; | 220 | struct dev_addr_list *m; |
248 | struct net_device *dev = v; | 221 | struct net_device *dev = v; |
249 | 222 | ||
250 | netif_tx_lock_bh(dev); | 223 | netif_tx_lock_bh(dev); |
@@ -292,4 +265,3 @@ void __init dev_mcast_init(void) | |||
292 | 265 | ||
293 | EXPORT_SYMBOL(dev_mc_add); | 266 | EXPORT_SYMBOL(dev_mc_add); |
294 | EXPORT_SYMBOL(dev_mc_delete); | 267 | EXPORT_SYMBOL(dev_mc_delete); |
295 | EXPORT_SYMBOL(dev_mc_upload); | ||
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 8d5e5a09b576..0b531e98ec33 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -52,6 +52,17 @@ int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data) | |||
52 | 52 | ||
53 | return 0; | 53 | return 0; |
54 | } | 54 | } |
55 | |||
56 | int ethtool_op_set_tx_ipv6_csum(struct net_device *dev, u32 data) | ||
57 | { | ||
58 | if (data) | ||
59 | dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; | ||
60 | else | ||
61 | dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); | ||
62 | |||
63 | return 0; | ||
64 | } | ||
65 | |||
55 | u32 ethtool_op_get_sg(struct net_device *dev) | 66 | u32 ethtool_op_get_sg(struct net_device *dev) |
56 | { | 67 | { |
57 | return (dev->features & NETIF_F_SG) != 0; | 68 | return (dev->features & NETIF_F_SG) != 0; |
@@ -980,5 +991,6 @@ EXPORT_SYMBOL(ethtool_op_set_sg); | |||
980 | EXPORT_SYMBOL(ethtool_op_set_tso); | 991 | EXPORT_SYMBOL(ethtool_op_set_tso); |
981 | EXPORT_SYMBOL(ethtool_op_set_tx_csum); | 992 | EXPORT_SYMBOL(ethtool_op_set_tx_csum); |
982 | EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum); | 993 | EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum); |
994 | EXPORT_SYMBOL(ethtool_op_set_tx_ipv6_csum); | ||
983 | EXPORT_SYMBOL(ethtool_op_set_ufo); | 995 | EXPORT_SYMBOL(ethtool_op_set_ufo); |
984 | EXPORT_SYMBOL(ethtool_op_get_ufo); | 996 | EXPORT_SYMBOL(ethtool_op_get_ufo); |
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index 17daf4c9f793..cc84d8d8a3c7 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c | |||
@@ -128,7 +128,8 @@ static void est_timer(unsigned long arg) | |||
128 | spin_unlock(e->stats_lock); | 128 | spin_unlock(e->stats_lock); |
129 | } | 129 | } |
130 | 130 | ||
131 | mod_timer(&elist[idx].timer, jiffies + ((HZ<<idx)/4)); | 131 | if (elist[idx].list != NULL) |
132 | mod_timer(&elist[idx].timer, jiffies + ((HZ<<idx)/4)); | ||
132 | read_unlock(&est_lock); | 133 | read_unlock(&est_lock); |
133 | } | 134 | } |
134 | 135 | ||
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index a0efdd7a6b37..de1b26aa5720 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
@@ -66,8 +66,9 @@ static void queue_process(struct work_struct *work) | |||
66 | 66 | ||
67 | local_irq_save(flags); | 67 | local_irq_save(flags); |
68 | netif_tx_lock(dev); | 68 | netif_tx_lock(dev); |
69 | if (netif_queue_stopped(dev) || | 69 | if ((netif_queue_stopped(dev) || |
70 | dev->hard_start_xmit(skb, dev) != NETDEV_TX_OK) { | 70 | netif_subqueue_stopped(dev, skb->queue_mapping)) || |
71 | dev->hard_start_xmit(skb, dev) != NETDEV_TX_OK) { | ||
71 | skb_queue_head(&npinfo->txq, skb); | 72 | skb_queue_head(&npinfo->txq, skb); |
72 | netif_tx_unlock(dev); | 73 | netif_tx_unlock(dev); |
73 | local_irq_restore(flags); | 74 | local_irq_restore(flags); |
@@ -254,7 +255,8 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) | |||
254 | for (tries = jiffies_to_usecs(1)/USEC_PER_POLL; | 255 | for (tries = jiffies_to_usecs(1)/USEC_PER_POLL; |
255 | tries > 0; --tries) { | 256 | tries > 0; --tries) { |
256 | if (netif_tx_trylock(dev)) { | 257 | if (netif_tx_trylock(dev)) { |
257 | if (!netif_queue_stopped(dev)) | 258 | if (!netif_queue_stopped(dev) && |
259 | !netif_subqueue_stopped(dev, skb->queue_mapping)) | ||
258 | status = dev->hard_start_xmit(skb, dev); | 260 | status = dev->hard_start_xmit(skb, dev); |
259 | netif_tx_unlock(dev); | 261 | netif_tx_unlock(dev); |
260 | 262 | ||
@@ -781,7 +783,6 @@ void netpoll_cleanup(struct netpoll *np) | |||
781 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); | 783 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); |
782 | } | 784 | } |
783 | 785 | ||
784 | np->dev->npinfo = NULL; | ||
785 | if (atomic_dec_and_test(&npinfo->refcnt)) { | 786 | if (atomic_dec_and_test(&npinfo->refcnt)) { |
786 | skb_queue_purge(&npinfo->arp_tx); | 787 | skb_queue_purge(&npinfo->arp_tx); |
787 | skb_queue_purge(&npinfo->txq); | 788 | skb_queue_purge(&npinfo->txq); |
@@ -794,6 +795,7 @@ void netpoll_cleanup(struct netpoll *np) | |||
794 | kfree_skb(skb); | 795 | kfree_skb(skb); |
795 | } | 796 | } |
796 | kfree(npinfo); | 797 | kfree(npinfo); |
798 | np->dev->npinfo = NULL; | ||
797 | } | 799 | } |
798 | } | 800 | } |
799 | 801 | ||
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 9cd3a1cb60ef..75215331b045 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
@@ -152,6 +152,9 @@ | |||
152 | #include <net/checksum.h> | 152 | #include <net/checksum.h> |
153 | #include <net/ipv6.h> | 153 | #include <net/ipv6.h> |
154 | #include <net/addrconf.h> | 154 | #include <net/addrconf.h> |
155 | #ifdef CONFIG_XFRM | ||
156 | #include <net/xfrm.h> | ||
157 | #endif | ||
155 | #include <asm/byteorder.h> | 158 | #include <asm/byteorder.h> |
156 | #include <linux/rcupdate.h> | 159 | #include <linux/rcupdate.h> |
157 | #include <asm/bitops.h> | 160 | #include <asm/bitops.h> |
@@ -181,6 +184,8 @@ | |||
181 | #define F_MPLS_RND (1<<8) /* Random MPLS labels */ | 184 | #define F_MPLS_RND (1<<8) /* Random MPLS labels */ |
182 | #define F_VID_RND (1<<9) /* Random VLAN ID */ | 185 | #define F_VID_RND (1<<9) /* Random VLAN ID */ |
183 | #define F_SVID_RND (1<<10) /* Random SVLAN ID */ | 186 | #define F_SVID_RND (1<<10) /* Random SVLAN ID */ |
187 | #define F_FLOW_SEQ (1<<11) /* Sequential flows */ | ||
188 | #define F_IPSEC_ON (1<<12) /* ipsec on for flows */ | ||
184 | 189 | ||
185 | /* Thread control flag bits */ | 190 | /* Thread control flag bits */ |
186 | #define T_TERMINATE (1<<0) | 191 | #define T_TERMINATE (1<<0) |
@@ -207,8 +212,15 @@ static struct proc_dir_entry *pg_proc_dir = NULL; | |||
207 | struct flow_state { | 212 | struct flow_state { |
208 | __be32 cur_daddr; | 213 | __be32 cur_daddr; |
209 | int count; | 214 | int count; |
215 | #ifdef CONFIG_XFRM | ||
216 | struct xfrm_state *x; | ||
217 | #endif | ||
218 | __u32 flags; | ||
210 | }; | 219 | }; |
211 | 220 | ||
221 | /* flow flag bits */ | ||
222 | #define F_INIT (1<<0) /* flow has been initialized */ | ||
223 | |||
212 | struct pktgen_dev { | 224 | struct pktgen_dev { |
213 | /* | 225 | /* |
214 | * Try to keep frequent/infrequent used vars. separated. | 226 | * Try to keep frequent/infrequent used vars. separated. |
@@ -228,6 +240,7 @@ struct pktgen_dev { | |||
228 | 240 | ||
229 | int min_pkt_size; /* = ETH_ZLEN; */ | 241 | int min_pkt_size; /* = ETH_ZLEN; */ |
230 | int max_pkt_size; /* = ETH_ZLEN; */ | 242 | int max_pkt_size; /* = ETH_ZLEN; */ |
243 | int pkt_overhead; /* overhead for MPLS, VLANs, IPSEC etc */ | ||
231 | int nfrags; | 244 | int nfrags; |
232 | __u32 delay_us; /* Default delay */ | 245 | __u32 delay_us; /* Default delay */ |
233 | __u32 delay_ns; | 246 | __u32 delay_ns; |
@@ -341,7 +354,11 @@ struct pktgen_dev { | |||
341 | unsigned cflows; /* Concurrent flows (config) */ | 354 | unsigned cflows; /* Concurrent flows (config) */ |
342 | unsigned lflow; /* Flow length (config) */ | 355 | unsigned lflow; /* Flow length (config) */ |
343 | unsigned nflows; /* accumulated flows (stats) */ | 356 | unsigned nflows; /* accumulated flows (stats) */ |
344 | 357 | unsigned curfl; /* current sequenced flow (state)*/ | |
358 | #ifdef CONFIG_XFRM | ||
359 | __u8 ipsmode; /* IPSEC mode (config) */ | ||
360 | __u8 ipsproto; /* IPSEC type (config) */ | ||
361 | #endif | ||
345 | char result[512]; | 362 | char result[512]; |
346 | }; | 363 | }; |
347 | 364 | ||
@@ -690,6 +707,18 @@ static int pktgen_if_show(struct seq_file *seq, void *v) | |||
690 | if (pkt_dev->flags & F_MPLS_RND) | 707 | if (pkt_dev->flags & F_MPLS_RND) |
691 | seq_printf(seq, "MPLS_RND "); | 708 | seq_printf(seq, "MPLS_RND "); |
692 | 709 | ||
710 | if (pkt_dev->cflows) { | ||
711 | if (pkt_dev->flags & F_FLOW_SEQ) | ||
712 | seq_printf(seq, "FLOW_SEQ "); /*in sequence flows*/ | ||
713 | else | ||
714 | seq_printf(seq, "FLOW_RND "); | ||
715 | } | ||
716 | |||
717 | #ifdef CONFIG_XFRM | ||
718 | if (pkt_dev->flags & F_IPSEC_ON) | ||
719 | seq_printf(seq, "IPSEC "); | ||
720 | #endif | ||
721 | |||
693 | if (pkt_dev->flags & F_MACSRC_RND) | 722 | if (pkt_dev->flags & F_MACSRC_RND) |
694 | seq_printf(seq, "MACSRC_RND "); | 723 | seq_printf(seq, "MACSRC_RND "); |
695 | 724 | ||
@@ -1181,6 +1210,14 @@ static ssize_t pktgen_if_write(struct file *file, | |||
1181 | else if (strcmp(f, "!SVID_RND") == 0) | 1210 | else if (strcmp(f, "!SVID_RND") == 0) |
1182 | pkt_dev->flags &= ~F_SVID_RND; | 1211 | pkt_dev->flags &= ~F_SVID_RND; |
1183 | 1212 | ||
1213 | else if (strcmp(f, "FLOW_SEQ") == 0) | ||
1214 | pkt_dev->flags |= F_FLOW_SEQ; | ||
1215 | |||
1216 | #ifdef CONFIG_XFRM | ||
1217 | else if (strcmp(f, "IPSEC") == 0) | ||
1218 | pkt_dev->flags |= F_IPSEC_ON; | ||
1219 | #endif | ||
1220 | |||
1184 | else if (strcmp(f, "!IPV6") == 0) | 1221 | else if (strcmp(f, "!IPV6") == 0) |
1185 | pkt_dev->flags &= ~F_IPV6; | 1222 | pkt_dev->flags &= ~F_IPV6; |
1186 | 1223 | ||
@@ -1189,7 +1226,7 @@ static ssize_t pktgen_if_write(struct file *file, | |||
1189 | "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s", | 1226 | "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s", |
1190 | f, | 1227 | f, |
1191 | "IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, " | 1228 | "IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, " |
1192 | "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND\n"); | 1229 | "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND, FLOW_SEQ, IPSEC\n"); |
1193 | return count; | 1230 | return count; |
1194 | } | 1231 | } |
1195 | sprintf(pg_result, "OK: flags=0x%x", pkt_dev->flags); | 1232 | sprintf(pg_result, "OK: flags=0x%x", pkt_dev->flags); |
@@ -2075,6 +2112,70 @@ static void spin(struct pktgen_dev *pkt_dev, __u64 spin_until_us) | |||
2075 | pkt_dev->idle_acc += now - start; | 2112 | pkt_dev->idle_acc += now - start; |
2076 | } | 2113 | } |
2077 | 2114 | ||
2115 | static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev) | ||
2116 | { | ||
2117 | pkt_dev->pkt_overhead = 0; | ||
2118 | pkt_dev->pkt_overhead += pkt_dev->nr_labels*sizeof(u32); | ||
2119 | pkt_dev->pkt_overhead += VLAN_TAG_SIZE(pkt_dev); | ||
2120 | pkt_dev->pkt_overhead += SVLAN_TAG_SIZE(pkt_dev); | ||
2121 | } | ||
2122 | |||
2123 | static inline int f_seen(struct pktgen_dev *pkt_dev, int flow) | ||
2124 | { | ||
2125 | |||
2126 | if (pkt_dev->flows[flow].flags & F_INIT) | ||
2127 | return 1; | ||
2128 | else | ||
2129 | return 0; | ||
2130 | } | ||
2131 | |||
2132 | static inline int f_pick(struct pktgen_dev *pkt_dev) | ||
2133 | { | ||
2134 | int flow = pkt_dev->curfl; | ||
2135 | |||
2136 | if (pkt_dev->flags & F_FLOW_SEQ) { | ||
2137 | if (pkt_dev->flows[flow].count >= pkt_dev->lflow) { | ||
2138 | /* reset time */ | ||
2139 | pkt_dev->flows[flow].count = 0; | ||
2140 | pkt_dev->curfl += 1; | ||
2141 | if (pkt_dev->curfl >= pkt_dev->cflows) | ||
2142 | pkt_dev->curfl = 0; /*reset */ | ||
2143 | } | ||
2144 | } else { | ||
2145 | flow = random32() % pkt_dev->cflows; | ||
2146 | |||
2147 | if (pkt_dev->flows[flow].count > pkt_dev->lflow) | ||
2148 | pkt_dev->flows[flow].count = 0; | ||
2149 | } | ||
2150 | |||
2151 | return pkt_dev->curfl; | ||
2152 | } | ||
2153 | |||
2154 | |||
2155 | #ifdef CONFIG_XFRM | ||
2156 | /* If there was already an IPSEC SA, we keep it as is, else | ||
2157 | * we go look for it ... | ||
2158 | */ | ||
2159 | inline | ||
2160 | void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow) | ||
2161 | { | ||
2162 | struct xfrm_state *x = pkt_dev->flows[flow].x; | ||
2163 | if (!x) { | ||
2164 | /*slow path: we dont already have xfrm_state*/ | ||
2165 | x = xfrm_stateonly_find((xfrm_address_t *)&pkt_dev->cur_daddr, | ||
2166 | (xfrm_address_t *)&pkt_dev->cur_saddr, | ||
2167 | AF_INET, | ||
2168 | pkt_dev->ipsmode, | ||
2169 | pkt_dev->ipsproto, 0); | ||
2170 | if (x) { | ||
2171 | pkt_dev->flows[flow].x = x; | ||
2172 | set_pkt_overhead(pkt_dev); | ||
2173 | pkt_dev->pkt_overhead+=x->props.header_len; | ||
2174 | } | ||
2175 | |||
2176 | } | ||
2177 | } | ||
2178 | #endif | ||
2078 | /* Increment/randomize headers according to flags and current values | 2179 | /* Increment/randomize headers according to flags and current values |
2079 | * for IP src/dest, UDP src/dst port, MAC-Addr src/dst | 2180 | * for IP src/dest, UDP src/dst port, MAC-Addr src/dst |
2080 | */ | 2181 | */ |
@@ -2084,12 +2185,8 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) | |||
2084 | __u32 imx; | 2185 | __u32 imx; |
2085 | int flow = 0; | 2186 | int flow = 0; |
2086 | 2187 | ||
2087 | if (pkt_dev->cflows) { | 2188 | if (pkt_dev->cflows) |
2088 | flow = random32() % pkt_dev->cflows; | 2189 | flow = f_pick(pkt_dev); |
2089 | |||
2090 | if (pkt_dev->flows[flow].count > pkt_dev->lflow) | ||
2091 | pkt_dev->flows[flow].count = 0; | ||
2092 | } | ||
2093 | 2190 | ||
2094 | /* Deal with source MAC */ | 2191 | /* Deal with source MAC */ |
2095 | if (pkt_dev->src_mac_count > 1) { | 2192 | if (pkt_dev->src_mac_count > 1) { |
@@ -2205,7 +2302,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) | |||
2205 | pkt_dev->cur_saddr = htonl(t); | 2302 | pkt_dev->cur_saddr = htonl(t); |
2206 | } | 2303 | } |
2207 | 2304 | ||
2208 | if (pkt_dev->cflows && pkt_dev->flows[flow].count != 0) { | 2305 | if (pkt_dev->cflows && f_seen(pkt_dev, flow)) { |
2209 | pkt_dev->cur_daddr = pkt_dev->flows[flow].cur_daddr; | 2306 | pkt_dev->cur_daddr = pkt_dev->flows[flow].cur_daddr; |
2210 | } else { | 2307 | } else { |
2211 | imn = ntohl(pkt_dev->daddr_min); | 2308 | imn = ntohl(pkt_dev->daddr_min); |
@@ -2235,8 +2332,13 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) | |||
2235 | } | 2332 | } |
2236 | } | 2333 | } |
2237 | if (pkt_dev->cflows) { | 2334 | if (pkt_dev->cflows) { |
2335 | pkt_dev->flows[flow].flags |= F_INIT; | ||
2238 | pkt_dev->flows[flow].cur_daddr = | 2336 | pkt_dev->flows[flow].cur_daddr = |
2239 | pkt_dev->cur_daddr; | 2337 | pkt_dev->cur_daddr; |
2338 | #ifdef CONFIG_XFRM | ||
2339 | if (pkt_dev->flags & F_IPSEC_ON) | ||
2340 | get_ipsec_sa(pkt_dev, flow); | ||
2341 | #endif | ||
2240 | pkt_dev->nflows++; | 2342 | pkt_dev->nflows++; |
2241 | } | 2343 | } |
2242 | } | 2344 | } |
@@ -2277,6 +2379,91 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) | |||
2277 | pkt_dev->flows[flow].count++; | 2379 | pkt_dev->flows[flow].count++; |
2278 | } | 2380 | } |
2279 | 2381 | ||
2382 | |||
2383 | #ifdef CONFIG_XFRM | ||
2384 | static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev) | ||
2385 | { | ||
2386 | struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x; | ||
2387 | int err = 0; | ||
2388 | struct iphdr *iph; | ||
2389 | |||
2390 | if (!x) | ||
2391 | return 0; | ||
2392 | /* XXX: we dont support tunnel mode for now until | ||
2393 | * we resolve the dst issue */ | ||
2394 | if (x->props.mode != XFRM_MODE_TRANSPORT) | ||
2395 | return 0; | ||
2396 | |||
2397 | spin_lock(&x->lock); | ||
2398 | iph = ip_hdr(skb); | ||
2399 | |||
2400 | err = x->mode->output(x, skb); | ||
2401 | if (err) | ||
2402 | goto error; | ||
2403 | err = x->type->output(x, skb); | ||
2404 | if (err) | ||
2405 | goto error; | ||
2406 | |||
2407 | x->curlft.bytes +=skb->len; | ||
2408 | x->curlft.packets++; | ||
2409 | spin_unlock(&x->lock); | ||
2410 | |||
2411 | error: | ||
2412 | spin_unlock(&x->lock); | ||
2413 | return err; | ||
2414 | } | ||
2415 | |||
2416 | static inline void free_SAs(struct pktgen_dev *pkt_dev) | ||
2417 | { | ||
2418 | if (pkt_dev->cflows) { | ||
2419 | /* let go of the SAs if we have them */ | ||
2420 | int i = 0; | ||
2421 | for (; i < pkt_dev->nflows; i++){ | ||
2422 | struct xfrm_state *x = pkt_dev->flows[i].x; | ||
2423 | if (x) { | ||
2424 | xfrm_state_put(x); | ||
2425 | pkt_dev->flows[i].x = NULL; | ||
2426 | } | ||
2427 | } | ||
2428 | } | ||
2429 | } | ||
2430 | |||
2431 | static inline int process_ipsec(struct pktgen_dev *pkt_dev, | ||
2432 | struct sk_buff *skb, __be16 protocol) | ||
2433 | { | ||
2434 | if (pkt_dev->flags & F_IPSEC_ON) { | ||
2435 | struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x; | ||
2436 | int nhead = 0; | ||
2437 | if (x) { | ||
2438 | int ret; | ||
2439 | __u8 *eth; | ||
2440 | nhead = x->props.header_len - skb_headroom(skb); | ||
2441 | if (nhead >0) { | ||
2442 | ret = pskb_expand_head(skb, nhead, 0, GFP_ATOMIC); | ||
2443 | if (ret < 0) { | ||
2444 | printk("Error expanding ipsec packet %d\n",ret); | ||
2445 | return 0; | ||
2446 | } | ||
2447 | } | ||
2448 | |||
2449 | /* ipsec is not expecting ll header */ | ||
2450 | skb_pull(skb, ETH_HLEN); | ||
2451 | ret = pktgen_output_ipsec(skb, pkt_dev); | ||
2452 | if (ret) { | ||
2453 | printk("Error creating ipsec packet %d\n",ret); | ||
2454 | kfree_skb(skb); | ||
2455 | return 0; | ||
2456 | } | ||
2457 | /* restore ll */ | ||
2458 | eth = (__u8 *) skb_push(skb, ETH_HLEN); | ||
2459 | memcpy(eth, pkt_dev->hh, 12); | ||
2460 | *(u16 *) & eth[12] = protocol; | ||
2461 | } | ||
2462 | } | ||
2463 | return 1; | ||
2464 | } | ||
2465 | #endif | ||
2466 | |||
2280 | static void mpls_push(__be32 *mpls, struct pktgen_dev *pkt_dev) | 2467 | static void mpls_push(__be32 *mpls, struct pktgen_dev *pkt_dev) |
2281 | { | 2468 | { |
2282 | unsigned i; | 2469 | unsigned i; |
@@ -2323,9 +2510,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, | |||
2323 | 2510 | ||
2324 | datalen = (odev->hard_header_len + 16) & ~0xf; | 2511 | datalen = (odev->hard_header_len + 16) & ~0xf; |
2325 | skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen + | 2512 | skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen + |
2326 | pkt_dev->nr_labels*sizeof(u32) + | 2513 | pkt_dev->pkt_overhead, GFP_ATOMIC); |
2327 | VLAN_TAG_SIZE(pkt_dev) + SVLAN_TAG_SIZE(pkt_dev), | ||
2328 | GFP_ATOMIC); | ||
2329 | if (!skb) { | 2514 | if (!skb) { |
2330 | sprintf(pkt_dev->result, "No memory"); | 2515 | sprintf(pkt_dev->result, "No memory"); |
2331 | return NULL; | 2516 | return NULL; |
@@ -2368,7 +2553,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, | |||
2368 | 2553 | ||
2369 | /* Eth + IPh + UDPh + mpls */ | 2554 | /* Eth + IPh + UDPh + mpls */ |
2370 | datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 - | 2555 | datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 - |
2371 | pkt_dev->nr_labels*sizeof(u32) - VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev); | 2556 | pkt_dev->pkt_overhead; |
2372 | if (datalen < sizeof(struct pktgen_hdr)) | 2557 | if (datalen < sizeof(struct pktgen_hdr)) |
2373 | datalen = sizeof(struct pktgen_hdr); | 2558 | datalen = sizeof(struct pktgen_hdr); |
2374 | 2559 | ||
@@ -2391,8 +2576,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, | |||
2391 | iph->check = ip_fast_csum((void *)iph, iph->ihl); | 2576 | iph->check = ip_fast_csum((void *)iph, iph->ihl); |
2392 | skb->protocol = protocol; | 2577 | skb->protocol = protocol; |
2393 | skb->mac_header = (skb->network_header - ETH_HLEN - | 2578 | skb->mac_header = (skb->network_header - ETH_HLEN - |
2394 | pkt_dev->nr_labels * sizeof(u32) - | 2579 | pkt_dev->pkt_overhead); |
2395 | VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev)); | ||
2396 | skb->dev = odev; | 2580 | skb->dev = odev; |
2397 | skb->pkt_type = PACKET_HOST; | 2581 | skb->pkt_type = PACKET_HOST; |
2398 | 2582 | ||
@@ -2463,6 +2647,11 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, | |||
2463 | pgh->tv_usec = htonl(timestamp.tv_usec); | 2647 | pgh->tv_usec = htonl(timestamp.tv_usec); |
2464 | } | 2648 | } |
2465 | 2649 | ||
2650 | #ifdef CONFIG_XFRM | ||
2651 | if (!process_ipsec(pkt_dev, skb, protocol)) | ||
2652 | return NULL; | ||
2653 | #endif | ||
2654 | |||
2466 | return skb; | 2655 | return skb; |
2467 | } | 2656 | } |
2468 | 2657 | ||
@@ -2662,9 +2851,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, | |||
2662 | mod_cur_headers(pkt_dev); | 2851 | mod_cur_headers(pkt_dev); |
2663 | 2852 | ||
2664 | skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16 + | 2853 | skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16 + |
2665 | pkt_dev->nr_labels*sizeof(u32) + | 2854 | pkt_dev->pkt_overhead, GFP_ATOMIC); |
2666 | VLAN_TAG_SIZE(pkt_dev) + SVLAN_TAG_SIZE(pkt_dev), | ||
2667 | GFP_ATOMIC); | ||
2668 | if (!skb) { | 2855 | if (!skb) { |
2669 | sprintf(pkt_dev->result, "No memory"); | 2856 | sprintf(pkt_dev->result, "No memory"); |
2670 | return NULL; | 2857 | return NULL; |
@@ -2708,7 +2895,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, | |||
2708 | /* Eth + IPh + UDPh + mpls */ | 2895 | /* Eth + IPh + UDPh + mpls */ |
2709 | datalen = pkt_dev->cur_pkt_size - 14 - | 2896 | datalen = pkt_dev->cur_pkt_size - 14 - |
2710 | sizeof(struct ipv6hdr) - sizeof(struct udphdr) - | 2897 | sizeof(struct ipv6hdr) - sizeof(struct udphdr) - |
2711 | pkt_dev->nr_labels*sizeof(u32) - VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev); | 2898 | pkt_dev->pkt_overhead; |
2712 | 2899 | ||
2713 | if (datalen < sizeof(struct pktgen_hdr)) { | 2900 | if (datalen < sizeof(struct pktgen_hdr)) { |
2714 | datalen = sizeof(struct pktgen_hdr); | 2901 | datalen = sizeof(struct pktgen_hdr); |
@@ -2738,8 +2925,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, | |||
2738 | ipv6_addr_copy(&iph->saddr, &pkt_dev->cur_in6_saddr); | 2925 | ipv6_addr_copy(&iph->saddr, &pkt_dev->cur_in6_saddr); |
2739 | 2926 | ||
2740 | skb->mac_header = (skb->network_header - ETH_HLEN - | 2927 | skb->mac_header = (skb->network_header - ETH_HLEN - |
2741 | pkt_dev->nr_labels * sizeof(u32) - | 2928 | pkt_dev->pkt_overhead); |
2742 | VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev)); | ||
2743 | skb->protocol = protocol; | 2929 | skb->protocol = protocol; |
2744 | skb->dev = odev; | 2930 | skb->dev = odev; |
2745 | skb->pkt_type = PACKET_HOST; | 2931 | skb->pkt_type = PACKET_HOST; |
@@ -2857,6 +3043,7 @@ static void pktgen_run(struct pktgen_thread *t) | |||
2857 | pkt_dev->started_at = getCurUs(); | 3043 | pkt_dev->started_at = getCurUs(); |
2858 | pkt_dev->next_tx_us = getCurUs(); /* Transmit immediately */ | 3044 | pkt_dev->next_tx_us = getCurUs(); /* Transmit immediately */ |
2859 | pkt_dev->next_tx_ns = 0; | 3045 | pkt_dev->next_tx_ns = 0; |
3046 | set_pkt_overhead(pkt_dev); | ||
2860 | 3047 | ||
2861 | strcpy(pkt_dev->result, "Starting"); | 3048 | strcpy(pkt_dev->result, "Starting"); |
2862 | started++; | 3049 | started++; |
@@ -3139,7 +3326,9 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev) | |||
3139 | } | 3326 | } |
3140 | } | 3327 | } |
3141 | 3328 | ||
3142 | if (netif_queue_stopped(odev) || need_resched()) { | 3329 | if ((netif_queue_stopped(odev) || |
3330 | netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping)) || | ||
3331 | need_resched()) { | ||
3143 | idle_start = getCurUs(); | 3332 | idle_start = getCurUs(); |
3144 | 3333 | ||
3145 | if (!netif_running(odev)) { | 3334 | if (!netif_running(odev)) { |
@@ -3154,7 +3343,8 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev) | |||
3154 | 3343 | ||
3155 | pkt_dev->idle_acc += getCurUs() - idle_start; | 3344 | pkt_dev->idle_acc += getCurUs() - idle_start; |
3156 | 3345 | ||
3157 | if (netif_queue_stopped(odev)) { | 3346 | if (netif_queue_stopped(odev) || |
3347 | netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping)) { | ||
3158 | pkt_dev->next_tx_us = getCurUs(); /* TODO */ | 3348 | pkt_dev->next_tx_us = getCurUs(); /* TODO */ |
3159 | pkt_dev->next_tx_ns = 0; | 3349 | pkt_dev->next_tx_ns = 0; |
3160 | goto out; /* Try the next interface */ | 3350 | goto out; /* Try the next interface */ |
@@ -3181,7 +3371,8 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev) | |||
3181 | } | 3371 | } |
3182 | 3372 | ||
3183 | netif_tx_lock_bh(odev); | 3373 | netif_tx_lock_bh(odev); |
3184 | if (!netif_queue_stopped(odev)) { | 3374 | if (!netif_queue_stopped(odev) && |
3375 | !netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping)) { | ||
3185 | 3376 | ||
3186 | atomic_inc(&(pkt_dev->skb->users)); | 3377 | atomic_inc(&(pkt_dev->skb->users)); |
3187 | retry_now: | 3378 | retry_now: |
@@ -3446,11 +3637,18 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname) | |||
3446 | } | 3637 | } |
3447 | pkt_dev->entry->proc_fops = &pktgen_if_fops; | 3638 | pkt_dev->entry->proc_fops = &pktgen_if_fops; |
3448 | pkt_dev->entry->data = pkt_dev; | 3639 | pkt_dev->entry->data = pkt_dev; |
3640 | #ifdef CONFIG_XFRM | ||
3641 | pkt_dev->ipsmode = XFRM_MODE_TRANSPORT; | ||
3642 | pkt_dev->ipsproto = IPPROTO_ESP; | ||
3643 | #endif | ||
3449 | 3644 | ||
3450 | return add_dev_to_thread(t, pkt_dev); | 3645 | return add_dev_to_thread(t, pkt_dev); |
3451 | out2: | 3646 | out2: |
3452 | dev_put(pkt_dev->odev); | 3647 | dev_put(pkt_dev->odev); |
3453 | out1: | 3648 | out1: |
3649 | #ifdef CONFIG_XFRM | ||
3650 | free_SAs(pkt_dev); | ||
3651 | #endif | ||
3454 | if (pkt_dev->flows) | 3652 | if (pkt_dev->flows) |
3455 | vfree(pkt_dev->flows); | 3653 | vfree(pkt_dev->flows); |
3456 | kfree(pkt_dev); | 3654 | kfree(pkt_dev); |
@@ -3545,6 +3743,9 @@ static int pktgen_remove_device(struct pktgen_thread *t, | |||
3545 | if (pkt_dev->entry) | 3743 | if (pkt_dev->entry) |
3546 | remove_proc_entry(pkt_dev->entry->name, pg_proc_dir); | 3744 | remove_proc_entry(pkt_dev->entry->name, pg_proc_dir); |
3547 | 3745 | ||
3746 | #ifdef CONFIG_XFRM | ||
3747 | free_SAs(pkt_dev); | ||
3748 | #endif | ||
3548 | if (pkt_dev->flows) | 3749 | if (pkt_dev->flows) |
3549 | vfree(pkt_dev->flows); | 3750 | vfree(pkt_dev->flows); |
3550 | kfree(pkt_dev); | 3751 | kfree(pkt_dev); |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 02e8bf084277..864cbdf31ed7 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -97,6 +97,19 @@ int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len) | |||
97 | return 0; | 97 | return 0; |
98 | } | 98 | } |
99 | 99 | ||
100 | int __rtattr_parse_nested_compat(struct rtattr *tb[], int maxattr, | ||
101 | struct rtattr *rta, int len) | ||
102 | { | ||
103 | if (RTA_PAYLOAD(rta) < len) | ||
104 | return -1; | ||
105 | if (RTA_PAYLOAD(rta) >= RTA_ALIGN(len) + sizeof(struct rtattr)) { | ||
106 | rta = RTA_DATA(rta) + RTA_ALIGN(len); | ||
107 | return rtattr_parse_nested(tb, maxattr, rta); | ||
108 | } | ||
109 | memset(tb, 0, sizeof(struct rtattr *) * maxattr); | ||
110 | return 0; | ||
111 | } | ||
112 | |||
100 | static struct rtnl_link *rtnl_msg_handlers[NPROTO]; | 113 | static struct rtnl_link *rtnl_msg_handlers[NPROTO]; |
101 | 114 | ||
102 | static inline int rtm_msgindex(int msgtype) | 115 | static inline int rtm_msgindex(int msgtype) |
@@ -243,6 +256,150 @@ void rtnl_unregister_all(int protocol) | |||
243 | 256 | ||
244 | EXPORT_SYMBOL_GPL(rtnl_unregister_all); | 257 | EXPORT_SYMBOL_GPL(rtnl_unregister_all); |
245 | 258 | ||
259 | static LIST_HEAD(link_ops); | ||
260 | |||
261 | /** | ||
262 | * __rtnl_link_register - Register rtnl_link_ops with rtnetlink. | ||
263 | * @ops: struct rtnl_link_ops * to register | ||
264 | * | ||
265 | * The caller must hold the rtnl_mutex. This function should be used | ||
266 | * by drivers that create devices during module initialization. It | ||
267 | * must be called before registering the devices. | ||
268 | * | ||
269 | * Returns 0 on success or a negative error code. | ||
270 | */ | ||
271 | int __rtnl_link_register(struct rtnl_link_ops *ops) | ||
272 | { | ||
273 | if (!ops->dellink) | ||
274 | ops->dellink = unregister_netdevice; | ||
275 | |||
276 | list_add_tail(&ops->list, &link_ops); | ||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | EXPORT_SYMBOL_GPL(__rtnl_link_register); | ||
281 | |||
282 | /** | ||
283 | * rtnl_link_register - Register rtnl_link_ops with rtnetlink. | ||
284 | * @ops: struct rtnl_link_ops * to register | ||
285 | * | ||
286 | * Returns 0 on success or a negative error code. | ||
287 | */ | ||
288 | int rtnl_link_register(struct rtnl_link_ops *ops) | ||
289 | { | ||
290 | int err; | ||
291 | |||
292 | rtnl_lock(); | ||
293 | err = __rtnl_link_register(ops); | ||
294 | rtnl_unlock(); | ||
295 | return err; | ||
296 | } | ||
297 | |||
298 | EXPORT_SYMBOL_GPL(rtnl_link_register); | ||
299 | |||
300 | /** | ||
301 | * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink. | ||
302 | * @ops: struct rtnl_link_ops * to unregister | ||
303 | * | ||
304 | * The caller must hold the rtnl_mutex. | ||
305 | */ | ||
306 | void __rtnl_link_unregister(struct rtnl_link_ops *ops) | ||
307 | { | ||
308 | struct net_device *dev, *n; | ||
309 | |||
310 | for_each_netdev_safe(dev, n) { | ||
311 | if (dev->rtnl_link_ops == ops) | ||
312 | ops->dellink(dev); | ||
313 | } | ||
314 | list_del(&ops->list); | ||
315 | } | ||
316 | |||
317 | EXPORT_SYMBOL_GPL(__rtnl_link_unregister); | ||
318 | |||
319 | /** | ||
320 | * rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink. | ||
321 | * @ops: struct rtnl_link_ops * to unregister | ||
322 | */ | ||
323 | void rtnl_link_unregister(struct rtnl_link_ops *ops) | ||
324 | { | ||
325 | rtnl_lock(); | ||
326 | __rtnl_link_unregister(ops); | ||
327 | rtnl_unlock(); | ||
328 | } | ||
329 | |||
330 | EXPORT_SYMBOL_GPL(rtnl_link_unregister); | ||
331 | |||
332 | static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind) | ||
333 | { | ||
334 | const struct rtnl_link_ops *ops; | ||
335 | |||
336 | list_for_each_entry(ops, &link_ops, list) { | ||
337 | if (!strcmp(ops->kind, kind)) | ||
338 | return ops; | ||
339 | } | ||
340 | return NULL; | ||
341 | } | ||
342 | |||
343 | static size_t rtnl_link_get_size(const struct net_device *dev) | ||
344 | { | ||
345 | const struct rtnl_link_ops *ops = dev->rtnl_link_ops; | ||
346 | size_t size; | ||
347 | |||
348 | if (!ops) | ||
349 | return 0; | ||
350 | |||
351 | size = nlmsg_total_size(sizeof(struct nlattr)) + /* IFLA_LINKINFO */ | ||
352 | nlmsg_total_size(strlen(ops->kind) + 1); /* IFLA_INFO_KIND */ | ||
353 | |||
354 | if (ops->get_size) | ||
355 | /* IFLA_INFO_DATA + nested data */ | ||
356 | size += nlmsg_total_size(sizeof(struct nlattr)) + | ||
357 | ops->get_size(dev); | ||
358 | |||
359 | if (ops->get_xstats_size) | ||
360 | size += ops->get_xstats_size(dev); /* IFLA_INFO_XSTATS */ | ||
361 | |||
362 | return size; | ||
363 | } | ||
364 | |||
365 | static int rtnl_link_fill(struct sk_buff *skb, const struct net_device *dev) | ||
366 | { | ||
367 | const struct rtnl_link_ops *ops = dev->rtnl_link_ops; | ||
368 | struct nlattr *linkinfo, *data; | ||
369 | int err = -EMSGSIZE; | ||
370 | |||
371 | linkinfo = nla_nest_start(skb, IFLA_LINKINFO); | ||
372 | if (linkinfo == NULL) | ||
373 | goto out; | ||
374 | |||
375 | if (nla_put_string(skb, IFLA_INFO_KIND, ops->kind) < 0) | ||
376 | goto err_cancel_link; | ||
377 | if (ops->fill_xstats) { | ||
378 | err = ops->fill_xstats(skb, dev); | ||
379 | if (err < 0) | ||
380 | goto err_cancel_link; | ||
381 | } | ||
382 | if (ops->fill_info) { | ||
383 | data = nla_nest_start(skb, IFLA_INFO_DATA); | ||
384 | if (data == NULL) | ||
385 | goto err_cancel_link; | ||
386 | err = ops->fill_info(skb, dev); | ||
387 | if (err < 0) | ||
388 | goto err_cancel_data; | ||
389 | nla_nest_end(skb, data); | ||
390 | } | ||
391 | |||
392 | nla_nest_end(skb, linkinfo); | ||
393 | return 0; | ||
394 | |||
395 | err_cancel_data: | ||
396 | nla_nest_cancel(skb, data); | ||
397 | err_cancel_link: | ||
398 | nla_nest_cancel(skb, linkinfo); | ||
399 | out: | ||
400 | return err; | ||
401 | } | ||
402 | |||
246 | static const int rtm_min[RTM_NR_FAMILIES] = | 403 | static const int rtm_min[RTM_NR_FAMILIES] = |
247 | { | 404 | { |
248 | [RTM_FAM(RTM_NEWLINK)] = NLMSG_LENGTH(sizeof(struct ifinfomsg)), | 405 | [RTM_FAM(RTM_NEWLINK)] = NLMSG_LENGTH(sizeof(struct ifinfomsg)), |
@@ -437,7 +594,7 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a, | |||
437 | a->tx_compressed = b->tx_compressed; | 594 | a->tx_compressed = b->tx_compressed; |
438 | }; | 595 | }; |
439 | 596 | ||
440 | static inline size_t if_nlmsg_size(void) | 597 | static inline size_t if_nlmsg_size(const struct net_device *dev) |
441 | { | 598 | { |
442 | return NLMSG_ALIGN(sizeof(struct ifinfomsg)) | 599 | return NLMSG_ALIGN(sizeof(struct ifinfomsg)) |
443 | + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */ | 600 | + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */ |
@@ -452,7 +609,8 @@ static inline size_t if_nlmsg_size(void) | |||
452 | + nla_total_size(4) /* IFLA_LINK */ | 609 | + nla_total_size(4) /* IFLA_LINK */ |
453 | + nla_total_size(4) /* IFLA_MASTER */ | 610 | + nla_total_size(4) /* IFLA_MASTER */ |
454 | + nla_total_size(1) /* IFLA_OPERSTATE */ | 611 | + nla_total_size(1) /* IFLA_OPERSTATE */ |
455 | + nla_total_size(1); /* IFLA_LINKMODE */ | 612 | + nla_total_size(1) /* IFLA_LINKMODE */ |
613 | + rtnl_link_get_size(dev); /* IFLA_LINKINFO */ | ||
456 | } | 614 | } |
457 | 615 | ||
458 | static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | 616 | static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, |
@@ -522,6 +680,11 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |||
522 | } | 680 | } |
523 | } | 681 | } |
524 | 682 | ||
683 | if (dev->rtnl_link_ops) { | ||
684 | if (rtnl_link_fill(skb, dev) < 0) | ||
685 | goto nla_put_failure; | ||
686 | } | ||
687 | |||
525 | return nlmsg_end(skb, nlh); | 688 | return nlmsg_end(skb, nlh); |
526 | 689 | ||
527 | nla_put_failure: | 690 | nla_put_failure: |
@@ -553,6 +716,8 @@ cont: | |||
553 | 716 | ||
554 | static const struct nla_policy ifla_policy[IFLA_MAX+1] = { | 717 | static const struct nla_policy ifla_policy[IFLA_MAX+1] = { |
555 | [IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 }, | 718 | [IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 }, |
719 | [IFLA_ADDRESS] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, | ||
720 | [IFLA_BROADCAST] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, | ||
556 | [IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) }, | 721 | [IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) }, |
557 | [IFLA_MTU] = { .type = NLA_U32 }, | 722 | [IFLA_MTU] = { .type = NLA_U32 }, |
558 | [IFLA_TXQLEN] = { .type = NLA_U32 }, | 723 | [IFLA_TXQLEN] = { .type = NLA_U32 }, |
@@ -561,44 +726,16 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = { | |||
561 | [IFLA_LINKMODE] = { .type = NLA_U8 }, | 726 | [IFLA_LINKMODE] = { .type = NLA_U8 }, |
562 | }; | 727 | }; |
563 | 728 | ||
564 | static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 729 | static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { |
565 | { | 730 | [IFLA_INFO_KIND] = { .type = NLA_STRING }, |
566 | struct ifinfomsg *ifm; | 731 | [IFLA_INFO_DATA] = { .type = NLA_NESTED }, |
567 | struct net_device *dev; | 732 | }; |
568 | int err, send_addr_notify = 0, modified = 0; | ||
569 | struct nlattr *tb[IFLA_MAX+1]; | ||
570 | char ifname[IFNAMSIZ]; | ||
571 | |||
572 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); | ||
573 | if (err < 0) | ||
574 | goto errout; | ||
575 | |||
576 | if (tb[IFLA_IFNAME]) | ||
577 | nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); | ||
578 | else | ||
579 | ifname[0] = '\0'; | ||
580 | |||
581 | err = -EINVAL; | ||
582 | ifm = nlmsg_data(nlh); | ||
583 | if (ifm->ifi_index > 0) | ||
584 | dev = dev_get_by_index(ifm->ifi_index); | ||
585 | else if (tb[IFLA_IFNAME]) | ||
586 | dev = dev_get_by_name(ifname); | ||
587 | else | ||
588 | goto errout; | ||
589 | |||
590 | if (dev == NULL) { | ||
591 | err = -ENODEV; | ||
592 | goto errout; | ||
593 | } | ||
594 | |||
595 | if (tb[IFLA_ADDRESS] && | ||
596 | nla_len(tb[IFLA_ADDRESS]) < dev->addr_len) | ||
597 | goto errout_dev; | ||
598 | 733 | ||
599 | if (tb[IFLA_BROADCAST] && | 734 | static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, |
600 | nla_len(tb[IFLA_BROADCAST]) < dev->addr_len) | 735 | struct nlattr **tb, char *ifname, int modified) |
601 | goto errout_dev; | 736 | { |
737 | int send_addr_notify = 0; | ||
738 | int err; | ||
602 | 739 | ||
603 | if (tb[IFLA_MAP]) { | 740 | if (tb[IFLA_MAP]) { |
604 | struct rtnl_link_ifmap *u_map; | 741 | struct rtnl_link_ifmap *u_map; |
@@ -606,12 +743,12 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
606 | 743 | ||
607 | if (!dev->set_config) { | 744 | if (!dev->set_config) { |
608 | err = -EOPNOTSUPP; | 745 | err = -EOPNOTSUPP; |
609 | goto errout_dev; | 746 | goto errout; |
610 | } | 747 | } |
611 | 748 | ||
612 | if (!netif_device_present(dev)) { | 749 | if (!netif_device_present(dev)) { |
613 | err = -ENODEV; | 750 | err = -ENODEV; |
614 | goto errout_dev; | 751 | goto errout; |
615 | } | 752 | } |
616 | 753 | ||
617 | u_map = nla_data(tb[IFLA_MAP]); | 754 | u_map = nla_data(tb[IFLA_MAP]); |
@@ -624,7 +761,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
624 | 761 | ||
625 | err = dev->set_config(dev, &k_map); | 762 | err = dev->set_config(dev, &k_map); |
626 | if (err < 0) | 763 | if (err < 0) |
627 | goto errout_dev; | 764 | goto errout; |
628 | 765 | ||
629 | modified = 1; | 766 | modified = 1; |
630 | } | 767 | } |
@@ -635,19 +772,19 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
635 | 772 | ||
636 | if (!dev->set_mac_address) { | 773 | if (!dev->set_mac_address) { |
637 | err = -EOPNOTSUPP; | 774 | err = -EOPNOTSUPP; |
638 | goto errout_dev; | 775 | goto errout; |
639 | } | 776 | } |
640 | 777 | ||
641 | if (!netif_device_present(dev)) { | 778 | if (!netif_device_present(dev)) { |
642 | err = -ENODEV; | 779 | err = -ENODEV; |
643 | goto errout_dev; | 780 | goto errout; |
644 | } | 781 | } |
645 | 782 | ||
646 | len = sizeof(sa_family_t) + dev->addr_len; | 783 | len = sizeof(sa_family_t) + dev->addr_len; |
647 | sa = kmalloc(len, GFP_KERNEL); | 784 | sa = kmalloc(len, GFP_KERNEL); |
648 | if (!sa) { | 785 | if (!sa) { |
649 | err = -ENOMEM; | 786 | err = -ENOMEM; |
650 | goto errout_dev; | 787 | goto errout; |
651 | } | 788 | } |
652 | sa->sa_family = dev->type; | 789 | sa->sa_family = dev->type; |
653 | memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]), | 790 | memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]), |
@@ -655,7 +792,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
655 | err = dev->set_mac_address(dev, sa); | 792 | err = dev->set_mac_address(dev, sa); |
656 | kfree(sa); | 793 | kfree(sa); |
657 | if (err) | 794 | if (err) |
658 | goto errout_dev; | 795 | goto errout; |
659 | send_addr_notify = 1; | 796 | send_addr_notify = 1; |
660 | modified = 1; | 797 | modified = 1; |
661 | } | 798 | } |
@@ -663,7 +800,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
663 | if (tb[IFLA_MTU]) { | 800 | if (tb[IFLA_MTU]) { |
664 | err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU])); | 801 | err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU])); |
665 | if (err < 0) | 802 | if (err < 0) |
666 | goto errout_dev; | 803 | goto errout; |
667 | modified = 1; | 804 | modified = 1; |
668 | } | 805 | } |
669 | 806 | ||
@@ -675,7 +812,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
675 | if (ifm->ifi_index > 0 && ifname[0]) { | 812 | if (ifm->ifi_index > 0 && ifname[0]) { |
676 | err = dev_change_name(dev, ifname); | 813 | err = dev_change_name(dev, ifname); |
677 | if (err < 0) | 814 | if (err < 0) |
678 | goto errout_dev; | 815 | goto errout; |
679 | modified = 1; | 816 | modified = 1; |
680 | } | 817 | } |
681 | 818 | ||
@@ -684,7 +821,6 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
684 | send_addr_notify = 1; | 821 | send_addr_notify = 1; |
685 | } | 822 | } |
686 | 823 | ||
687 | |||
688 | if (ifm->ifi_flags || ifm->ifi_change) { | 824 | if (ifm->ifi_flags || ifm->ifi_change) { |
689 | unsigned int flags = ifm->ifi_flags; | 825 | unsigned int flags = ifm->ifi_flags; |
690 | 826 | ||
@@ -712,7 +848,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
712 | 848 | ||
713 | err = 0; | 849 | err = 0; |
714 | 850 | ||
715 | errout_dev: | 851 | errout: |
716 | if (err < 0 && modified && net_ratelimit()) | 852 | if (err < 0 && modified && net_ratelimit()) |
717 | printk(KERN_WARNING "A link change request failed with " | 853 | printk(KERN_WARNING "A link change request failed with " |
718 | "some changes comitted already. Interface %s may " | 854 | "some changes comitted already. Interface %s may " |
@@ -721,12 +857,239 @@ errout_dev: | |||
721 | 857 | ||
722 | if (send_addr_notify) | 858 | if (send_addr_notify) |
723 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); | 859 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); |
860 | return err; | ||
861 | } | ||
862 | |||
863 | static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | ||
864 | { | ||
865 | struct ifinfomsg *ifm; | ||
866 | struct net_device *dev; | ||
867 | int err; | ||
868 | struct nlattr *tb[IFLA_MAX+1]; | ||
869 | char ifname[IFNAMSIZ]; | ||
870 | |||
871 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); | ||
872 | if (err < 0) | ||
873 | goto errout; | ||
874 | |||
875 | if (tb[IFLA_IFNAME]) | ||
876 | nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); | ||
877 | else | ||
878 | ifname[0] = '\0'; | ||
879 | |||
880 | err = -EINVAL; | ||
881 | ifm = nlmsg_data(nlh); | ||
882 | if (ifm->ifi_index > 0) | ||
883 | dev = dev_get_by_index(ifm->ifi_index); | ||
884 | else if (tb[IFLA_IFNAME]) | ||
885 | dev = dev_get_by_name(ifname); | ||
886 | else | ||
887 | goto errout; | ||
888 | |||
889 | if (dev == NULL) { | ||
890 | err = -ENODEV; | ||
891 | goto errout; | ||
892 | } | ||
724 | 893 | ||
894 | if (tb[IFLA_ADDRESS] && | ||
895 | nla_len(tb[IFLA_ADDRESS]) < dev->addr_len) | ||
896 | goto errout_dev; | ||
897 | |||
898 | if (tb[IFLA_BROADCAST] && | ||
899 | nla_len(tb[IFLA_BROADCAST]) < dev->addr_len) | ||
900 | goto errout_dev; | ||
901 | |||
902 | err = do_setlink(dev, ifm, tb, ifname, 0); | ||
903 | errout_dev: | ||
725 | dev_put(dev); | 904 | dev_put(dev); |
726 | errout: | 905 | errout: |
727 | return err; | 906 | return err; |
728 | } | 907 | } |
729 | 908 | ||
909 | static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | ||
910 | { | ||
911 | const struct rtnl_link_ops *ops; | ||
912 | struct net_device *dev; | ||
913 | struct ifinfomsg *ifm; | ||
914 | char ifname[IFNAMSIZ]; | ||
915 | struct nlattr *tb[IFLA_MAX+1]; | ||
916 | int err; | ||
917 | |||
918 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); | ||
919 | if (err < 0) | ||
920 | return err; | ||
921 | |||
922 | if (tb[IFLA_IFNAME]) | ||
923 | nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); | ||
924 | |||
925 | ifm = nlmsg_data(nlh); | ||
926 | if (ifm->ifi_index > 0) | ||
927 | dev = __dev_get_by_index(ifm->ifi_index); | ||
928 | else if (tb[IFLA_IFNAME]) | ||
929 | dev = __dev_get_by_name(ifname); | ||
930 | else | ||
931 | return -EINVAL; | ||
932 | |||
933 | if (!dev) | ||
934 | return -ENODEV; | ||
935 | |||
936 | ops = dev->rtnl_link_ops; | ||
937 | if (!ops) | ||
938 | return -EOPNOTSUPP; | ||
939 | |||
940 | ops->dellink(dev); | ||
941 | return 0; | ||
942 | } | ||
943 | |||
944 | static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | ||
945 | { | ||
946 | const struct rtnl_link_ops *ops; | ||
947 | struct net_device *dev; | ||
948 | struct ifinfomsg *ifm; | ||
949 | char kind[MODULE_NAME_LEN]; | ||
950 | char ifname[IFNAMSIZ]; | ||
951 | struct nlattr *tb[IFLA_MAX+1]; | ||
952 | struct nlattr *linkinfo[IFLA_INFO_MAX+1]; | ||
953 | int err; | ||
954 | |||
955 | replay: | ||
956 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); | ||
957 | if (err < 0) | ||
958 | return err; | ||
959 | |||
960 | if (tb[IFLA_IFNAME]) | ||
961 | nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); | ||
962 | else | ||
963 | ifname[0] = '\0'; | ||
964 | |||
965 | ifm = nlmsg_data(nlh); | ||
966 | if (ifm->ifi_index > 0) | ||
967 | dev = __dev_get_by_index(ifm->ifi_index); | ||
968 | else if (ifname[0]) | ||
969 | dev = __dev_get_by_name(ifname); | ||
970 | else | ||
971 | dev = NULL; | ||
972 | |||
973 | if (tb[IFLA_LINKINFO]) { | ||
974 | err = nla_parse_nested(linkinfo, IFLA_INFO_MAX, | ||
975 | tb[IFLA_LINKINFO], ifla_info_policy); | ||
976 | if (err < 0) | ||
977 | return err; | ||
978 | } else | ||
979 | memset(linkinfo, 0, sizeof(linkinfo)); | ||
980 | |||
981 | if (linkinfo[IFLA_INFO_KIND]) { | ||
982 | nla_strlcpy(kind, linkinfo[IFLA_INFO_KIND], sizeof(kind)); | ||
983 | ops = rtnl_link_ops_get(kind); | ||
984 | } else { | ||
985 | kind[0] = '\0'; | ||
986 | ops = NULL; | ||
987 | } | ||
988 | |||
989 | if (1) { | ||
990 | struct nlattr *attr[ops ? ops->maxtype + 1 : 0], **data = NULL; | ||
991 | |||
992 | if (ops) { | ||
993 | if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) { | ||
994 | err = nla_parse_nested(attr, ops->maxtype, | ||
995 | linkinfo[IFLA_INFO_DATA], | ||
996 | ops->policy); | ||
997 | if (err < 0) | ||
998 | return err; | ||
999 | data = attr; | ||
1000 | } | ||
1001 | if (ops->validate) { | ||
1002 | err = ops->validate(tb, data); | ||
1003 | if (err < 0) | ||
1004 | return err; | ||
1005 | } | ||
1006 | } | ||
1007 | |||
1008 | if (dev) { | ||
1009 | int modified = 0; | ||
1010 | |||
1011 | if (nlh->nlmsg_flags & NLM_F_EXCL) | ||
1012 | return -EEXIST; | ||
1013 | if (nlh->nlmsg_flags & NLM_F_REPLACE) | ||
1014 | return -EOPNOTSUPP; | ||
1015 | |||
1016 | if (linkinfo[IFLA_INFO_DATA]) { | ||
1017 | if (!ops || ops != dev->rtnl_link_ops || | ||
1018 | !ops->changelink) | ||
1019 | return -EOPNOTSUPP; | ||
1020 | |||
1021 | err = ops->changelink(dev, tb, data); | ||
1022 | if (err < 0) | ||
1023 | return err; | ||
1024 | modified = 1; | ||
1025 | } | ||
1026 | |||
1027 | return do_setlink(dev, ifm, tb, ifname, modified); | ||
1028 | } | ||
1029 | |||
1030 | if (!(nlh->nlmsg_flags & NLM_F_CREATE)) | ||
1031 | return -ENODEV; | ||
1032 | |||
1033 | if (ifm->ifi_index || ifm->ifi_flags || ifm->ifi_change) | ||
1034 | return -EOPNOTSUPP; | ||
1035 | if (tb[IFLA_MAP] || tb[IFLA_MASTER] || tb[IFLA_PROTINFO]) | ||
1036 | return -EOPNOTSUPP; | ||
1037 | |||
1038 | if (!ops) { | ||
1039 | #ifdef CONFIG_KMOD | ||
1040 | if (kind[0]) { | ||
1041 | __rtnl_unlock(); | ||
1042 | request_module("rtnl-link-%s", kind); | ||
1043 | rtnl_lock(); | ||
1044 | ops = rtnl_link_ops_get(kind); | ||
1045 | if (ops) | ||
1046 | goto replay; | ||
1047 | } | ||
1048 | #endif | ||
1049 | return -EOPNOTSUPP; | ||
1050 | } | ||
1051 | |||
1052 | if (!ifname[0]) | ||
1053 | snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind); | ||
1054 | dev = alloc_netdev(ops->priv_size, ifname, ops->setup); | ||
1055 | if (!dev) | ||
1056 | return -ENOMEM; | ||
1057 | |||
1058 | if (strchr(dev->name, '%')) { | ||
1059 | err = dev_alloc_name(dev, dev->name); | ||
1060 | if (err < 0) | ||
1061 | goto err_free; | ||
1062 | } | ||
1063 | dev->rtnl_link_ops = ops; | ||
1064 | |||
1065 | if (tb[IFLA_MTU]) | ||
1066 | dev->mtu = nla_get_u32(tb[IFLA_MTU]); | ||
1067 | if (tb[IFLA_ADDRESS]) | ||
1068 | memcpy(dev->dev_addr, nla_data(tb[IFLA_ADDRESS]), | ||
1069 | nla_len(tb[IFLA_ADDRESS])); | ||
1070 | if (tb[IFLA_BROADCAST]) | ||
1071 | memcpy(dev->broadcast, nla_data(tb[IFLA_BROADCAST]), | ||
1072 | nla_len(tb[IFLA_BROADCAST])); | ||
1073 | if (tb[IFLA_TXQLEN]) | ||
1074 | dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]); | ||
1075 | if (tb[IFLA_WEIGHT]) | ||
1076 | dev->weight = nla_get_u32(tb[IFLA_WEIGHT]); | ||
1077 | if (tb[IFLA_OPERSTATE]) | ||
1078 | set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE])); | ||
1079 | if (tb[IFLA_LINKMODE]) | ||
1080 | dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]); | ||
1081 | |||
1082 | if (ops->newlink) | ||
1083 | err = ops->newlink(dev, tb, data); | ||
1084 | else | ||
1085 | err = register_netdevice(dev); | ||
1086 | err_free: | ||
1087 | if (err < 0) | ||
1088 | free_netdev(dev); | ||
1089 | return err; | ||
1090 | } | ||
1091 | } | ||
1092 | |||
730 | static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | 1093 | static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) |
731 | { | 1094 | { |
732 | struct ifinfomsg *ifm; | 1095 | struct ifinfomsg *ifm; |
@@ -747,7 +1110,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
747 | } else | 1110 | } else |
748 | return -EINVAL; | 1111 | return -EINVAL; |
749 | 1112 | ||
750 | nskb = nlmsg_new(if_nlmsg_size(), GFP_KERNEL); | 1113 | nskb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL); |
751 | if (nskb == NULL) { | 1114 | if (nskb == NULL) { |
752 | err = -ENOBUFS; | 1115 | err = -ENOBUFS; |
753 | goto errout; | 1116 | goto errout; |
@@ -797,7 +1160,7 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change) | |||
797 | struct sk_buff *skb; | 1160 | struct sk_buff *skb; |
798 | int err = -ENOBUFS; | 1161 | int err = -ENOBUFS; |
799 | 1162 | ||
800 | skb = nlmsg_new(if_nlmsg_size(), GFP_KERNEL); | 1163 | skb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL); |
801 | if (skb == NULL) | 1164 | if (skb == NULL) |
802 | goto errout; | 1165 | goto errout; |
803 | 1166 | ||
@@ -952,6 +1315,8 @@ void __init rtnetlink_init(void) | |||
952 | 1315 | ||
953 | rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink, rtnl_dump_ifinfo); | 1316 | rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink, rtnl_dump_ifinfo); |
954 | rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL); | 1317 | rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL); |
1318 | rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL); | ||
1319 | rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL); | ||
955 | 1320 | ||
956 | rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all); | 1321 | rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all); |
957 | rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all); | 1322 | rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all); |
@@ -960,6 +1325,7 @@ void __init rtnetlink_init(void) | |||
960 | EXPORT_SYMBOL(__rta_fill); | 1325 | EXPORT_SYMBOL(__rta_fill); |
961 | EXPORT_SYMBOL(rtattr_strlcpy); | 1326 | EXPORT_SYMBOL(rtattr_strlcpy); |
962 | EXPORT_SYMBOL(rtattr_parse); | 1327 | EXPORT_SYMBOL(rtattr_parse); |
1328 | EXPORT_SYMBOL(__rtattr_parse_nested_compat); | ||
963 | EXPORT_SYMBOL(rtnetlink_put_metrics); | 1329 | EXPORT_SYMBOL(rtnetlink_put_metrics); |
964 | EXPORT_SYMBOL(rtnl_lock); | 1330 | EXPORT_SYMBOL(rtnl_lock); |
965 | EXPORT_SYMBOL(rtnl_trylock); | 1331 | EXPORT_SYMBOL(rtnl_trylock); |
diff --git a/net/core/scm.c b/net/core/scm.c index 292ad8d5ad76..44c4ec2c8769 100644 --- a/net/core/scm.c +++ b/net/core/scm.c | |||
@@ -228,7 +228,8 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) | |||
228 | err = security_file_receive(fp[i]); | 228 | err = security_file_receive(fp[i]); |
229 | if (err) | 229 | if (err) |
230 | break; | 230 | break; |
231 | err = get_unused_fd(); | 231 | err = get_unused_fd_flags(MSG_CMSG_CLOEXEC & msg->msg_flags |
232 | ? O_CLOEXEC : 0); | ||
232 | if (err < 0) | 233 | if (err < 0) |
233 | break; | 234 | break; |
234 | new_fd = err; | 235 | new_fd = err; |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 3943c3ad9145..0583e8498f13 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -415,9 +415,11 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) | |||
415 | C(csum); | 415 | C(csum); |
416 | C(local_df); | 416 | C(local_df); |
417 | n->cloned = 1; | 417 | n->cloned = 1; |
418 | n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len; | ||
418 | n->nohdr = 0; | 419 | n->nohdr = 0; |
419 | C(pkt_type); | 420 | C(pkt_type); |
420 | C(ip_summed); | 421 | C(ip_summed); |
422 | skb_copy_queue_mapping(n, skb); | ||
421 | C(priority); | 423 | C(priority); |
422 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) | 424 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) |
423 | C(ipvs_property); | 425 | C(ipvs_property); |
@@ -426,6 +428,10 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) | |||
426 | n->destructor = NULL; | 428 | n->destructor = NULL; |
427 | C(mark); | 429 | C(mark); |
428 | __nf_copy(n, skb); | 430 | __nf_copy(n, skb); |
431 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||
432 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | ||
433 | C(nf_trace); | ||
434 | #endif | ||
429 | #ifdef CONFIG_NET_SCHED | 435 | #ifdef CONFIG_NET_SCHED |
430 | C(tc_index); | 436 | C(tc_index); |
431 | #ifdef CONFIG_NET_CLS_ACT | 437 | #ifdef CONFIG_NET_CLS_ACT |
@@ -459,6 +465,7 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | |||
459 | #endif | 465 | #endif |
460 | new->sk = NULL; | 466 | new->sk = NULL; |
461 | new->dev = old->dev; | 467 | new->dev = old->dev; |
468 | skb_copy_queue_mapping(new, old); | ||
462 | new->priority = old->priority; | 469 | new->priority = old->priority; |
463 | new->protocol = old->protocol; | 470 | new->protocol = old->protocol; |
464 | new->dst = dst_clone(old->dst); | 471 | new->dst = dst_clone(old->dst); |
@@ -482,6 +489,10 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | |||
482 | new->destructor = NULL; | 489 | new->destructor = NULL; |
483 | new->mark = old->mark; | 490 | new->mark = old->mark; |
484 | __nf_copy(new, old); | 491 | __nf_copy(new, old); |
492 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||
493 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | ||
494 | new->nf_trace = old->nf_trace; | ||
495 | #endif | ||
485 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) | 496 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) |
486 | new->ipvs_property = old->ipvs_property; | 497 | new->ipvs_property = old->ipvs_property; |
487 | #endif | 498 | #endif |
@@ -676,6 +687,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, | |||
676 | skb->network_header += off; | 687 | skb->network_header += off; |
677 | skb->mac_header += off; | 688 | skb->mac_header += off; |
678 | skb->cloned = 0; | 689 | skb->cloned = 0; |
690 | skb->hdr_len = 0; | ||
679 | skb->nohdr = 0; | 691 | skb->nohdr = 0; |
680 | atomic_set(&skb_shinfo(skb)->dataref, 1); | 692 | atomic_set(&skb_shinfo(skb)->dataref, 1); |
681 | return 0; | 693 | return 0; |
@@ -1930,6 +1942,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) | |||
1930 | tail = nskb; | 1942 | tail = nskb; |
1931 | 1943 | ||
1932 | nskb->dev = skb->dev; | 1944 | nskb->dev = skb->dev; |
1945 | skb_copy_queue_mapping(nskb, skb); | ||
1933 | nskb->priority = skb->priority; | 1946 | nskb->priority = skb->priority; |
1934 | nskb->protocol = skb->protocol; | 1947 | nskb->protocol = skb->protocol; |
1935 | nskb->dst = dst_clone(skb->dst); | 1948 | nskb->dst = dst_clone(skb->dst); |
diff --git a/net/core/sock.c b/net/core/sock.c index c14ce0198d25..091032a250c7 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -210,7 +210,8 @@ static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen) | |||
210 | return -EDOM; | 210 | return -EDOM; |
211 | 211 | ||
212 | if (tv.tv_sec < 0) { | 212 | if (tv.tv_sec < 0) { |
213 | static int warned = 0; | 213 | static int warned __read_mostly; |
214 | |||
214 | *timeo_p = 0; | 215 | *timeo_p = 0; |
215 | if (warned < 10 && net_ratelimit()) | 216 | if (warned < 10 && net_ratelimit()) |
216 | warned++; | 217 | warned++; |
@@ -1851,46 +1852,15 @@ void proto_unregister(struct proto *prot) | |||
1851 | EXPORT_SYMBOL(proto_unregister); | 1852 | EXPORT_SYMBOL(proto_unregister); |
1852 | 1853 | ||
1853 | #ifdef CONFIG_PROC_FS | 1854 | #ifdef CONFIG_PROC_FS |
1854 | static inline struct proto *__proto_head(void) | ||
1855 | { | ||
1856 | return list_entry(proto_list.next, struct proto, node); | ||
1857 | } | ||
1858 | |||
1859 | static inline struct proto *proto_head(void) | ||
1860 | { | ||
1861 | return list_empty(&proto_list) ? NULL : __proto_head(); | ||
1862 | } | ||
1863 | |||
1864 | static inline struct proto *proto_next(struct proto *proto) | ||
1865 | { | ||
1866 | return proto->node.next == &proto_list ? NULL : | ||
1867 | list_entry(proto->node.next, struct proto, node); | ||
1868 | } | ||
1869 | |||
1870 | static inline struct proto *proto_get_idx(loff_t pos) | ||
1871 | { | ||
1872 | struct proto *proto; | ||
1873 | loff_t i = 0; | ||
1874 | |||
1875 | list_for_each_entry(proto, &proto_list, node) | ||
1876 | if (i++ == pos) | ||
1877 | goto out; | ||
1878 | |||
1879 | proto = NULL; | ||
1880 | out: | ||
1881 | return proto; | ||
1882 | } | ||
1883 | |||
1884 | static void *proto_seq_start(struct seq_file *seq, loff_t *pos) | 1855 | static void *proto_seq_start(struct seq_file *seq, loff_t *pos) |
1885 | { | 1856 | { |
1886 | read_lock(&proto_list_lock); | 1857 | read_lock(&proto_list_lock); |
1887 | return *pos ? proto_get_idx(*pos - 1) : SEQ_START_TOKEN; | 1858 | return seq_list_start_head(&proto_list, *pos); |
1888 | } | 1859 | } |
1889 | 1860 | ||
1890 | static void *proto_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 1861 | static void *proto_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
1891 | { | 1862 | { |
1892 | ++*pos; | 1863 | return seq_list_next(v, &proto_list, pos); |
1893 | return v == SEQ_START_TOKEN ? proto_head() : proto_next(v); | ||
1894 | } | 1864 | } |
1895 | 1865 | ||
1896 | static void proto_seq_stop(struct seq_file *seq, void *v) | 1866 | static void proto_seq_stop(struct seq_file *seq, void *v) |
@@ -1938,7 +1908,7 @@ static void proto_seq_printf(struct seq_file *seq, struct proto *proto) | |||
1938 | 1908 | ||
1939 | static int proto_seq_show(struct seq_file *seq, void *v) | 1909 | static int proto_seq_show(struct seq_file *seq, void *v) |
1940 | { | 1910 | { |
1941 | if (v == SEQ_START_TOKEN) | 1911 | if (v == &proto_list) |
1942 | seq_printf(seq, "%-9s %-4s %-8s %-6s %-5s %-7s %-4s %-10s %s", | 1912 | seq_printf(seq, "%-9s %-4s %-8s %-6s %-5s %-7s %-4s %-10s %s", |
1943 | "protocol", | 1913 | "protocol", |
1944 | "size", | 1914 | "size", |
@@ -1950,7 +1920,7 @@ static int proto_seq_show(struct seq_file *seq, void *v) | |||
1950 | "module", | 1920 | "module", |
1951 | "cl co di ac io in de sh ss gs se re sp bi br ha uh gp em\n"); | 1921 | "cl co di ac io in de sh ss gs se re sp bi br ha uh gp em\n"); |
1952 | else | 1922 | else |
1953 | proto_seq_printf(seq, v); | 1923 | proto_seq_printf(seq, list_entry(v, struct proto, node)); |
1954 | return 0; | 1924 | return 0; |
1955 | } | 1925 | } |
1956 | 1926 | ||
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index ec7fa4d67f08..e91c2b9dc27b 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * net/dccp/ccids/ccid3.c | 2 | * net/dccp/ccids/ccid3.c |
3 | * | 3 | * |
4 | * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. | 4 | * Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand. |
5 | * Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz> | 5 | * Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz> |
6 | * | 6 | * |
7 | * An implementation of the DCCP protocol | 7 | * An implementation of the DCCP protocol |
8 | * | 8 | * |
@@ -49,7 +49,6 @@ static int ccid3_debug; | |||
49 | 49 | ||
50 | static struct dccp_tx_hist *ccid3_tx_hist; | 50 | static struct dccp_tx_hist *ccid3_tx_hist; |
51 | static struct dccp_rx_hist *ccid3_rx_hist; | 51 | static struct dccp_rx_hist *ccid3_rx_hist; |
52 | static struct dccp_li_hist *ccid3_li_hist; | ||
53 | 52 | ||
54 | /* | 53 | /* |
55 | * Transmitter Half-Connection Routines | 54 | * Transmitter Half-Connection Routines |
@@ -194,25 +193,20 @@ static inline void ccid3_hc_tx_update_s(struct ccid3_hc_tx_sock *hctx, int len) | |||
194 | * The algorithm is not applicable if RTT < 4 microseconds. | 193 | * The algorithm is not applicable if RTT < 4 microseconds. |
195 | */ | 194 | */ |
196 | static inline void ccid3_hc_tx_update_win_count(struct ccid3_hc_tx_sock *hctx, | 195 | static inline void ccid3_hc_tx_update_win_count(struct ccid3_hc_tx_sock *hctx, |
197 | struct timeval *now) | 196 | ktime_t now) |
198 | { | 197 | { |
199 | suseconds_t delta; | ||
200 | u32 quarter_rtts; | 198 | u32 quarter_rtts; |
201 | 199 | ||
202 | if (unlikely(hctx->ccid3hctx_rtt < 4)) /* avoid divide-by-zero */ | 200 | if (unlikely(hctx->ccid3hctx_rtt < 4)) /* avoid divide-by-zero */ |
203 | return; | 201 | return; |
204 | 202 | ||
205 | delta = timeval_delta(now, &hctx->ccid3hctx_t_last_win_count); | 203 | quarter_rtts = ktime_us_delta(now, hctx->ccid3hctx_t_last_win_count); |
206 | DCCP_BUG_ON(delta < 0); | 204 | quarter_rtts /= hctx->ccid3hctx_rtt / 4; |
207 | |||
208 | quarter_rtts = (u32)delta / (hctx->ccid3hctx_rtt / 4); | ||
209 | 205 | ||
210 | if (quarter_rtts > 0) { | 206 | if (quarter_rtts > 0) { |
211 | hctx->ccid3hctx_t_last_win_count = *now; | 207 | hctx->ccid3hctx_t_last_win_count = now; |
212 | hctx->ccid3hctx_last_win_count += min_t(u32, quarter_rtts, 5); | 208 | hctx->ccid3hctx_last_win_count += min_t(u32, quarter_rtts, 5); |
213 | hctx->ccid3hctx_last_win_count &= 0xF; /* mod 16 */ | 209 | hctx->ccid3hctx_last_win_count &= 0xF; /* mod 16 */ |
214 | |||
215 | ccid3_pr_debug("now at %#X\n", hctx->ccid3hctx_last_win_count); | ||
216 | } | 210 | } |
217 | } | 211 | } |
218 | 212 | ||
@@ -312,8 +306,8 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) | |||
312 | { | 306 | { |
313 | struct dccp_sock *dp = dccp_sk(sk); | 307 | struct dccp_sock *dp = dccp_sk(sk); |
314 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); | 308 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); |
315 | struct timeval now; | 309 | ktime_t now = ktime_get_real(); |
316 | suseconds_t delay; | 310 | s64 delay; |
317 | 311 | ||
318 | BUG_ON(hctx == NULL); | 312 | BUG_ON(hctx == NULL); |
319 | 313 | ||
@@ -325,8 +319,6 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) | |||
325 | if (unlikely(skb->len == 0)) | 319 | if (unlikely(skb->len == 0)) |
326 | return -EBADMSG; | 320 | return -EBADMSG; |
327 | 321 | ||
328 | dccp_timestamp(sk, &now); | ||
329 | |||
330 | switch (hctx->ccid3hctx_state) { | 322 | switch (hctx->ccid3hctx_state) { |
331 | case TFRC_SSTATE_NO_SENT: | 323 | case TFRC_SSTATE_NO_SENT: |
332 | sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, | 324 | sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, |
@@ -349,7 +341,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) | |||
349 | ccid3_pr_debug("SYN RTT = %uus\n", dp->dccps_syn_rtt); | 341 | ccid3_pr_debug("SYN RTT = %uus\n", dp->dccps_syn_rtt); |
350 | hctx->ccid3hctx_rtt = dp->dccps_syn_rtt; | 342 | hctx->ccid3hctx_rtt = dp->dccps_syn_rtt; |
351 | hctx->ccid3hctx_x = rfc3390_initial_rate(sk); | 343 | hctx->ccid3hctx_x = rfc3390_initial_rate(sk); |
352 | hctx->ccid3hctx_t_ld = now; | 344 | hctx->ccid3hctx_t_ld = ktime_to_timeval(now); |
353 | } else { | 345 | } else { |
354 | /* Sender does not have RTT sample: X = MSS/second */ | 346 | /* Sender does not have RTT sample: X = MSS/second */ |
355 | hctx->ccid3hctx_x = dp->dccps_mss_cache; | 347 | hctx->ccid3hctx_x = dp->dccps_mss_cache; |
@@ -361,7 +353,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) | |||
361 | break; | 353 | break; |
362 | case TFRC_SSTATE_NO_FBACK: | 354 | case TFRC_SSTATE_NO_FBACK: |
363 | case TFRC_SSTATE_FBACK: | 355 | case TFRC_SSTATE_FBACK: |
364 | delay = timeval_delta(&hctx->ccid3hctx_t_nom, &now); | 356 | delay = ktime_us_delta(hctx->ccid3hctx_t_nom, now); |
365 | ccid3_pr_debug("delay=%ld\n", (long)delay); | 357 | ccid3_pr_debug("delay=%ld\n", (long)delay); |
366 | /* | 358 | /* |
367 | * Scheduling of packet transmissions [RFC 3448, 4.6] | 359 | * Scheduling of packet transmissions [RFC 3448, 4.6] |
@@ -371,10 +363,10 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) | |||
371 | * else | 363 | * else |
372 | * // send the packet in (t_nom - t_now) milliseconds. | 364 | * // send the packet in (t_nom - t_now) milliseconds. |
373 | */ | 365 | */ |
374 | if (delay - (suseconds_t)hctx->ccid3hctx_delta >= 0) | 366 | if (delay - (s64)hctx->ccid3hctx_delta >= 1000) |
375 | return delay / 1000L; | 367 | return (u32)delay / 1000L; |
376 | 368 | ||
377 | ccid3_hc_tx_update_win_count(hctx, &now); | 369 | ccid3_hc_tx_update_win_count(hctx, now); |
378 | break; | 370 | break; |
379 | case TFRC_SSTATE_TERM: | 371 | case TFRC_SSTATE_TERM: |
380 | DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk); | 372 | DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk); |
@@ -387,8 +379,8 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) | |||
387 | hctx->ccid3hctx_idle = 0; | 379 | hctx->ccid3hctx_idle = 0; |
388 | 380 | ||
389 | /* set the nominal send time for the next following packet */ | 381 | /* set the nominal send time for the next following packet */ |
390 | timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi); | 382 | hctx->ccid3hctx_t_nom = ktime_add_us(hctx->ccid3hctx_t_nom, |
391 | 383 | hctx->ccid3hctx_t_ipi); | |
392 | return 0; | 384 | return 0; |
393 | } | 385 | } |
394 | 386 | ||
@@ -819,154 +811,6 @@ static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb) | |||
819 | return 0; | 811 | return 0; |
820 | } | 812 | } |
821 | 813 | ||
822 | /* calculate first loss interval | ||
823 | * | ||
824 | * returns estimated loss interval in usecs */ | ||
825 | |||
826 | static u32 ccid3_hc_rx_calc_first_li(struct sock *sk) | ||
827 | { | ||
828 | struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); | ||
829 | struct dccp_rx_hist_entry *entry, *next, *tail = NULL; | ||
830 | u32 x_recv, p; | ||
831 | suseconds_t rtt, delta; | ||
832 | struct timeval tstamp = { 0, }; | ||
833 | int interval = 0; | ||
834 | int win_count = 0; | ||
835 | int step = 0; | ||
836 | u64 fval; | ||
837 | |||
838 | list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist, | ||
839 | dccphrx_node) { | ||
840 | if (dccp_rx_hist_entry_data_packet(entry)) { | ||
841 | tail = entry; | ||
842 | |||
843 | switch (step) { | ||
844 | case 0: | ||
845 | tstamp = entry->dccphrx_tstamp; | ||
846 | win_count = entry->dccphrx_ccval; | ||
847 | step = 1; | ||
848 | break; | ||
849 | case 1: | ||
850 | interval = win_count - entry->dccphrx_ccval; | ||
851 | if (interval < 0) | ||
852 | interval += TFRC_WIN_COUNT_LIMIT; | ||
853 | if (interval > 4) | ||
854 | goto found; | ||
855 | break; | ||
856 | } | ||
857 | } | ||
858 | } | ||
859 | |||
860 | if (unlikely(step == 0)) { | ||
861 | DCCP_WARN("%s(%p), packet history has no data packets!\n", | ||
862 | dccp_role(sk), sk); | ||
863 | return ~0; | ||
864 | } | ||
865 | |||
866 | if (unlikely(interval == 0)) { | ||
867 | DCCP_WARN("%s(%p), Could not find a win_count interval > 0." | ||
868 | "Defaulting to 1\n", dccp_role(sk), sk); | ||
869 | interval = 1; | ||
870 | } | ||
871 | found: | ||
872 | if (!tail) { | ||
873 | DCCP_CRIT("tail is null\n"); | ||
874 | return ~0; | ||
875 | } | ||
876 | |||
877 | delta = timeval_delta(&tstamp, &tail->dccphrx_tstamp); | ||
878 | DCCP_BUG_ON(delta < 0); | ||
879 | |||
880 | rtt = delta * 4 / interval; | ||
881 | ccid3_pr_debug("%s(%p), approximated RTT to %dus\n", | ||
882 | dccp_role(sk), sk, (int)rtt); | ||
883 | |||
884 | /* | ||
885 | * Determine the length of the first loss interval via inverse lookup. | ||
886 | * Assume that X_recv can be computed by the throughput equation | ||
887 | * s | ||
888 | * X_recv = -------- | ||
889 | * R * fval | ||
890 | * Find some p such that f(p) = fval; return 1/p [RFC 3448, 6.3.1]. | ||
891 | */ | ||
892 | if (rtt == 0) { /* would result in divide-by-zero */ | ||
893 | DCCP_WARN("RTT==0\n"); | ||
894 | return ~0; | ||
895 | } | ||
896 | |||
897 | dccp_timestamp(sk, &tstamp); | ||
898 | delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback); | ||
899 | DCCP_BUG_ON(delta <= 0); | ||
900 | |||
901 | x_recv = scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta); | ||
902 | if (x_recv == 0) { /* would also trigger divide-by-zero */ | ||
903 | DCCP_WARN("X_recv==0\n"); | ||
904 | if ((x_recv = hcrx->ccid3hcrx_x_recv) == 0) { | ||
905 | DCCP_BUG("stored value of X_recv is zero"); | ||
906 | return ~0; | ||
907 | } | ||
908 | } | ||
909 | |||
910 | fval = scaled_div(hcrx->ccid3hcrx_s, rtt); | ||
911 | fval = scaled_div32(fval, x_recv); | ||
912 | p = tfrc_calc_x_reverse_lookup(fval); | ||
913 | |||
914 | ccid3_pr_debug("%s(%p), receive rate=%u bytes/s, implied " | ||
915 | "loss rate=%u\n", dccp_role(sk), sk, x_recv, p); | ||
916 | |||
917 | if (p == 0) | ||
918 | return ~0; | ||
919 | else | ||
920 | return 1000000 / p; | ||
921 | } | ||
922 | |||
923 | static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss) | ||
924 | { | ||
925 | struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); | ||
926 | struct dccp_li_hist_entry *head; | ||
927 | u64 seq_temp; | ||
928 | |||
929 | if (list_empty(&hcrx->ccid3hcrx_li_hist)) { | ||
930 | if (!dccp_li_hist_interval_new(ccid3_li_hist, | ||
931 | &hcrx->ccid3hcrx_li_hist, seq_loss, win_loss)) | ||
932 | return; | ||
933 | |||
934 | head = list_entry(hcrx->ccid3hcrx_li_hist.next, | ||
935 | struct dccp_li_hist_entry, dccplih_node); | ||
936 | head->dccplih_interval = ccid3_hc_rx_calc_first_li(sk); | ||
937 | } else { | ||
938 | struct dccp_li_hist_entry *entry; | ||
939 | struct list_head *tail; | ||
940 | |||
941 | head = list_entry(hcrx->ccid3hcrx_li_hist.next, | ||
942 | struct dccp_li_hist_entry, dccplih_node); | ||
943 | /* FIXME win count check removed as was wrong */ | ||
944 | /* should make this check with receive history */ | ||
945 | /* and compare there as per section 10.2 of RFC4342 */ | ||
946 | |||
947 | /* new loss event detected */ | ||
948 | /* calculate last interval length */ | ||
949 | seq_temp = dccp_delta_seqno(head->dccplih_seqno, seq_loss); | ||
950 | entry = dccp_li_hist_entry_new(ccid3_li_hist, GFP_ATOMIC); | ||
951 | |||
952 | if (entry == NULL) { | ||
953 | DCCP_BUG("out of memory - can not allocate entry"); | ||
954 | return; | ||
955 | } | ||
956 | |||
957 | list_add(&entry->dccplih_node, &hcrx->ccid3hcrx_li_hist); | ||
958 | |||
959 | tail = hcrx->ccid3hcrx_li_hist.prev; | ||
960 | list_del(tail); | ||
961 | kmem_cache_free(ccid3_li_hist->dccplih_slab, tail); | ||
962 | |||
963 | /* Create the newest interval */ | ||
964 | entry->dccplih_seqno = seq_loss; | ||
965 | entry->dccplih_interval = seq_temp; | ||
966 | entry->dccplih_win_count = win_loss; | ||
967 | } | ||
968 | } | ||
969 | |||
970 | static int ccid3_hc_rx_detect_loss(struct sock *sk, | 814 | static int ccid3_hc_rx_detect_loss(struct sock *sk, |
971 | struct dccp_rx_hist_entry *packet) | 815 | struct dccp_rx_hist_entry *packet) |
972 | { | 816 | { |
@@ -992,8 +836,15 @@ static int ccid3_hc_rx_detect_loss(struct sock *sk, | |||
992 | while (dccp_delta_seqno(hcrx->ccid3hcrx_seqno_nonloss, seqno) | 836 | while (dccp_delta_seqno(hcrx->ccid3hcrx_seqno_nonloss, seqno) |
993 | > TFRC_RECV_NUM_LATE_LOSS) { | 837 | > TFRC_RECV_NUM_LATE_LOSS) { |
994 | loss = 1; | 838 | loss = 1; |
995 | ccid3_hc_rx_update_li(sk, hcrx->ccid3hcrx_seqno_nonloss, | 839 | dccp_li_update_li(sk, |
996 | hcrx->ccid3hcrx_ccval_nonloss); | 840 | &hcrx->ccid3hcrx_li_hist, |
841 | &hcrx->ccid3hcrx_hist, | ||
842 | &hcrx->ccid3hcrx_tstamp_last_feedback, | ||
843 | hcrx->ccid3hcrx_s, | ||
844 | hcrx->ccid3hcrx_bytes_recv, | ||
845 | hcrx->ccid3hcrx_x_recv, | ||
846 | hcrx->ccid3hcrx_seqno_nonloss, | ||
847 | hcrx->ccid3hcrx_ccval_nonloss); | ||
997 | tmp_seqno = hcrx->ccid3hcrx_seqno_nonloss; | 848 | tmp_seqno = hcrx->ccid3hcrx_seqno_nonloss; |
998 | dccp_inc_seqno(&tmp_seqno); | 849 | dccp_inc_seqno(&tmp_seqno); |
999 | hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno; | 850 | hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno; |
@@ -1152,7 +1003,7 @@ static void ccid3_hc_rx_exit(struct sock *sk) | |||
1152 | dccp_rx_hist_purge(ccid3_rx_hist, &hcrx->ccid3hcrx_hist); | 1003 | dccp_rx_hist_purge(ccid3_rx_hist, &hcrx->ccid3hcrx_hist); |
1153 | 1004 | ||
1154 | /* Empty loss interval history */ | 1005 | /* Empty loss interval history */ |
1155 | dccp_li_hist_purge(ccid3_li_hist, &hcrx->ccid3hcrx_li_hist); | 1006 | dccp_li_hist_purge(&hcrx->ccid3hcrx_li_hist); |
1156 | } | 1007 | } |
1157 | 1008 | ||
1158 | static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info) | 1009 | static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info) |
@@ -1236,19 +1087,12 @@ static __init int ccid3_module_init(void) | |||
1236 | if (ccid3_tx_hist == NULL) | 1087 | if (ccid3_tx_hist == NULL) |
1237 | goto out_free_rx; | 1088 | goto out_free_rx; |
1238 | 1089 | ||
1239 | ccid3_li_hist = dccp_li_hist_new("ccid3"); | ||
1240 | if (ccid3_li_hist == NULL) | ||
1241 | goto out_free_tx; | ||
1242 | |||
1243 | rc = ccid_register(&ccid3); | 1090 | rc = ccid_register(&ccid3); |
1244 | if (rc != 0) | 1091 | if (rc != 0) |
1245 | goto out_free_loss_interval_history; | 1092 | goto out_free_tx; |
1246 | out: | 1093 | out: |
1247 | return rc; | 1094 | return rc; |
1248 | 1095 | ||
1249 | out_free_loss_interval_history: | ||
1250 | dccp_li_hist_delete(ccid3_li_hist); | ||
1251 | ccid3_li_hist = NULL; | ||
1252 | out_free_tx: | 1096 | out_free_tx: |
1253 | dccp_tx_hist_delete(ccid3_tx_hist); | 1097 | dccp_tx_hist_delete(ccid3_tx_hist); |
1254 | ccid3_tx_hist = NULL; | 1098 | ccid3_tx_hist = NULL; |
@@ -1271,10 +1115,6 @@ static __exit void ccid3_module_exit(void) | |||
1271 | dccp_rx_hist_delete(ccid3_rx_hist); | 1115 | dccp_rx_hist_delete(ccid3_rx_hist); |
1272 | ccid3_rx_hist = NULL; | 1116 | ccid3_rx_hist = NULL; |
1273 | } | 1117 | } |
1274 | if (ccid3_li_hist != NULL) { | ||
1275 | dccp_li_hist_delete(ccid3_li_hist); | ||
1276 | ccid3_li_hist = NULL; | ||
1277 | } | ||
1278 | } | 1118 | } |
1279 | module_exit(ccid3_module_exit); | 1119 | module_exit(ccid3_module_exit); |
1280 | 1120 | ||
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index 8d31b389c19c..51d4b804e334 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h | |||
@@ -36,6 +36,7 @@ | |||
36 | #ifndef _DCCP_CCID3_H_ | 36 | #ifndef _DCCP_CCID3_H_ |
37 | #define _DCCP_CCID3_H_ | 37 | #define _DCCP_CCID3_H_ |
38 | 38 | ||
39 | #include <linux/ktime.h> | ||
39 | #include <linux/list.h> | 40 | #include <linux/list.h> |
40 | #include <linux/time.h> | 41 | #include <linux/time.h> |
41 | #include <linux/types.h> | 42 | #include <linux/types.h> |
@@ -108,10 +109,10 @@ struct ccid3_hc_tx_sock { | |||
108 | enum ccid3_hc_tx_states ccid3hctx_state:8; | 109 | enum ccid3_hc_tx_states ccid3hctx_state:8; |
109 | u8 ccid3hctx_last_win_count; | 110 | u8 ccid3hctx_last_win_count; |
110 | u8 ccid3hctx_idle; | 111 | u8 ccid3hctx_idle; |
111 | struct timeval ccid3hctx_t_last_win_count; | 112 | ktime_t ccid3hctx_t_last_win_count; |
112 | struct timer_list ccid3hctx_no_feedback_timer; | 113 | struct timer_list ccid3hctx_no_feedback_timer; |
113 | struct timeval ccid3hctx_t_ld; | 114 | struct timeval ccid3hctx_t_ld; |
114 | struct timeval ccid3hctx_t_nom; | 115 | ktime_t ccid3hctx_t_nom; |
115 | u32 ccid3hctx_delta; | 116 | u32 ccid3hctx_delta; |
116 | struct list_head ccid3hctx_hist; | 117 | struct list_head ccid3hctx_hist; |
117 | struct ccid3_options_received ccid3hctx_options_received; | 118 | struct ccid3_options_received ccid3hctx_options_received; |
diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c index 372d7e75cdd8..515225f3a464 100644 --- a/net/dccp/ccids/lib/loss_interval.c +++ b/net/dccp/ccids/lib/loss_interval.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * net/dccp/ccids/lib/loss_interval.c | 2 | * net/dccp/ccids/lib/loss_interval.c |
3 | * | 3 | * |
4 | * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. | 4 | * Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand. |
5 | * Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz> | 5 | * Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz> |
6 | * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> | 6 | * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
@@ -15,58 +15,38 @@ | |||
15 | #include <net/sock.h> | 15 | #include <net/sock.h> |
16 | #include "../../dccp.h" | 16 | #include "../../dccp.h" |
17 | #include "loss_interval.h" | 17 | #include "loss_interval.h" |
18 | #include "packet_history.h" | ||
19 | #include "tfrc.h" | ||
18 | 20 | ||
19 | struct dccp_li_hist *dccp_li_hist_new(const char *name) | 21 | #define DCCP_LI_HIST_IVAL_F_LENGTH 8 |
20 | { | ||
21 | struct dccp_li_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC); | ||
22 | static const char dccp_li_hist_mask[] = "li_hist_%s"; | ||
23 | char *slab_name; | ||
24 | |||
25 | if (hist == NULL) | ||
26 | goto out; | ||
27 | |||
28 | slab_name = kmalloc(strlen(name) + sizeof(dccp_li_hist_mask) - 1, | ||
29 | GFP_ATOMIC); | ||
30 | if (slab_name == NULL) | ||
31 | goto out_free_hist; | ||
32 | |||
33 | sprintf(slab_name, dccp_li_hist_mask, name); | ||
34 | hist->dccplih_slab = kmem_cache_create(slab_name, | ||
35 | sizeof(struct dccp_li_hist_entry), | ||
36 | 0, SLAB_HWCACHE_ALIGN, | ||
37 | NULL, NULL); | ||
38 | if (hist->dccplih_slab == NULL) | ||
39 | goto out_free_slab_name; | ||
40 | out: | ||
41 | return hist; | ||
42 | out_free_slab_name: | ||
43 | kfree(slab_name); | ||
44 | out_free_hist: | ||
45 | kfree(hist); | ||
46 | hist = NULL; | ||
47 | goto out; | ||
48 | } | ||
49 | 22 | ||
50 | EXPORT_SYMBOL_GPL(dccp_li_hist_new); | 23 | struct dccp_li_hist_entry { |
24 | struct list_head dccplih_node; | ||
25 | u64 dccplih_seqno:48, | ||
26 | dccplih_win_count:4; | ||
27 | u32 dccplih_interval; | ||
28 | }; | ||
51 | 29 | ||
52 | void dccp_li_hist_delete(struct dccp_li_hist *hist) | 30 | static struct kmem_cache *dccp_li_cachep __read_mostly; |
53 | { | ||
54 | const char* name = kmem_cache_name(hist->dccplih_slab); | ||
55 | 31 | ||
56 | kmem_cache_destroy(hist->dccplih_slab); | 32 | static inline struct dccp_li_hist_entry *dccp_li_hist_entry_new(const gfp_t prio) |
57 | kfree(name); | 33 | { |
58 | kfree(hist); | 34 | return kmem_cache_alloc(dccp_li_cachep, prio); |
59 | } | 35 | } |
60 | 36 | ||
61 | EXPORT_SYMBOL_GPL(dccp_li_hist_delete); | 37 | static inline void dccp_li_hist_entry_delete(struct dccp_li_hist_entry *entry) |
38 | { | ||
39 | if (entry != NULL) | ||
40 | kmem_cache_free(dccp_li_cachep, entry); | ||
41 | } | ||
62 | 42 | ||
63 | void dccp_li_hist_purge(struct dccp_li_hist *hist, struct list_head *list) | 43 | void dccp_li_hist_purge(struct list_head *list) |
64 | { | 44 | { |
65 | struct dccp_li_hist_entry *entry, *next; | 45 | struct dccp_li_hist_entry *entry, *next; |
66 | 46 | ||
67 | list_for_each_entry_safe(entry, next, list, dccplih_node) { | 47 | list_for_each_entry_safe(entry, next, list, dccplih_node) { |
68 | list_del_init(&entry->dccplih_node); | 48 | list_del_init(&entry->dccplih_node); |
69 | kmem_cache_free(hist->dccplih_slab, entry); | 49 | kmem_cache_free(dccp_li_cachep, entry); |
70 | } | 50 | } |
71 | } | 51 | } |
72 | 52 | ||
@@ -118,16 +98,16 @@ u32 dccp_li_hist_calc_i_mean(struct list_head *list) | |||
118 | 98 | ||
119 | EXPORT_SYMBOL_GPL(dccp_li_hist_calc_i_mean); | 99 | EXPORT_SYMBOL_GPL(dccp_li_hist_calc_i_mean); |
120 | 100 | ||
121 | int dccp_li_hist_interval_new(struct dccp_li_hist *hist, | 101 | static int dccp_li_hist_interval_new(struct list_head *list, |
122 | struct list_head *list, const u64 seq_loss, const u8 win_loss) | 102 | const u64 seq_loss, const u8 win_loss) |
123 | { | 103 | { |
124 | struct dccp_li_hist_entry *entry; | 104 | struct dccp_li_hist_entry *entry; |
125 | int i; | 105 | int i; |
126 | 106 | ||
127 | for (i = 0; i < DCCP_LI_HIST_IVAL_F_LENGTH; i++) { | 107 | for (i = 0; i < DCCP_LI_HIST_IVAL_F_LENGTH; i++) { |
128 | entry = dccp_li_hist_entry_new(hist, GFP_ATOMIC); | 108 | entry = dccp_li_hist_entry_new(GFP_ATOMIC); |
129 | if (entry == NULL) { | 109 | if (entry == NULL) { |
130 | dccp_li_hist_purge(hist, list); | 110 | dccp_li_hist_purge(list); |
131 | DCCP_BUG("loss interval list entry is NULL"); | 111 | DCCP_BUG("loss interval list entry is NULL"); |
132 | return 0; | 112 | return 0; |
133 | } | 113 | } |
@@ -140,4 +120,176 @@ int dccp_li_hist_interval_new(struct dccp_li_hist *hist, | |||
140 | return 1; | 120 | return 1; |
141 | } | 121 | } |
142 | 122 | ||
143 | EXPORT_SYMBOL_GPL(dccp_li_hist_interval_new); | 123 | /* calculate first loss interval |
124 | * | ||
125 | * returns estimated loss interval in usecs */ | ||
126 | static u32 dccp_li_calc_first_li(struct sock *sk, | ||
127 | struct list_head *hist_list, | ||
128 | struct timeval *last_feedback, | ||
129 | u16 s, u32 bytes_recv, | ||
130 | u32 previous_x_recv) | ||
131 | { | ||
132 | struct dccp_rx_hist_entry *entry, *next, *tail = NULL; | ||
133 | u32 x_recv, p; | ||
134 | suseconds_t rtt, delta; | ||
135 | struct timeval tstamp = { 0, 0 }; | ||
136 | int interval = 0; | ||
137 | int win_count = 0; | ||
138 | int step = 0; | ||
139 | u64 fval; | ||
140 | |||
141 | list_for_each_entry_safe(entry, next, hist_list, dccphrx_node) { | ||
142 | if (dccp_rx_hist_entry_data_packet(entry)) { | ||
143 | tail = entry; | ||
144 | |||
145 | switch (step) { | ||
146 | case 0: | ||
147 | tstamp = entry->dccphrx_tstamp; | ||
148 | win_count = entry->dccphrx_ccval; | ||
149 | step = 1; | ||
150 | break; | ||
151 | case 1: | ||
152 | interval = win_count - entry->dccphrx_ccval; | ||
153 | if (interval < 0) | ||
154 | interval += TFRC_WIN_COUNT_LIMIT; | ||
155 | if (interval > 4) | ||
156 | goto found; | ||
157 | break; | ||
158 | } | ||
159 | } | ||
160 | } | ||
161 | |||
162 | if (unlikely(step == 0)) { | ||
163 | DCCP_WARN("%s(%p), packet history has no data packets!\n", | ||
164 | dccp_role(sk), sk); | ||
165 | return ~0; | ||
166 | } | ||
167 | |||
168 | if (unlikely(interval == 0)) { | ||
169 | DCCP_WARN("%s(%p), Could not find a win_count interval > 0." | ||
170 | "Defaulting to 1\n", dccp_role(sk), sk); | ||
171 | interval = 1; | ||
172 | } | ||
173 | found: | ||
174 | if (!tail) { | ||
175 | DCCP_CRIT("tail is null\n"); | ||
176 | return ~0; | ||
177 | } | ||
178 | |||
179 | delta = timeval_delta(&tstamp, &tail->dccphrx_tstamp); | ||
180 | DCCP_BUG_ON(delta < 0); | ||
181 | |||
182 | rtt = delta * 4 / interval; | ||
183 | dccp_pr_debug("%s(%p), approximated RTT to %dus\n", | ||
184 | dccp_role(sk), sk, (int)rtt); | ||
185 | |||
186 | /* | ||
187 | * Determine the length of the first loss interval via inverse lookup. | ||
188 | * Assume that X_recv can be computed by the throughput equation | ||
189 | * s | ||
190 | * X_recv = -------- | ||
191 | * R * fval | ||
192 | * Find some p such that f(p) = fval; return 1/p [RFC 3448, 6.3.1]. | ||
193 | */ | ||
194 | if (rtt == 0) { /* would result in divide-by-zero */ | ||
195 | DCCP_WARN("RTT==0\n"); | ||
196 | return ~0; | ||
197 | } | ||
198 | |||
199 | dccp_timestamp(sk, &tstamp); | ||
200 | delta = timeval_delta(&tstamp, last_feedback); | ||
201 | DCCP_BUG_ON(delta <= 0); | ||
202 | |||
203 | x_recv = scaled_div32(bytes_recv, delta); | ||
204 | if (x_recv == 0) { /* would also trigger divide-by-zero */ | ||
205 | DCCP_WARN("X_recv==0\n"); | ||
206 | if (previous_x_recv == 0) { | ||
207 | DCCP_BUG("stored value of X_recv is zero"); | ||
208 | return ~0; | ||
209 | } | ||
210 | x_recv = previous_x_recv; | ||
211 | } | ||
212 | |||
213 | fval = scaled_div(s, rtt); | ||
214 | fval = scaled_div32(fval, x_recv); | ||
215 | p = tfrc_calc_x_reverse_lookup(fval); | ||
216 | |||
217 | dccp_pr_debug("%s(%p), receive rate=%u bytes/s, implied " | ||
218 | "loss rate=%u\n", dccp_role(sk), sk, x_recv, p); | ||
219 | |||
220 | if (p == 0) | ||
221 | return ~0; | ||
222 | else | ||
223 | return 1000000 / p; | ||
224 | } | ||
225 | |||
226 | void dccp_li_update_li(struct sock *sk, | ||
227 | struct list_head *li_hist_list, | ||
228 | struct list_head *hist_list, | ||
229 | struct timeval *last_feedback, u16 s, u32 bytes_recv, | ||
230 | u32 previous_x_recv, u64 seq_loss, u8 win_loss) | ||
231 | { | ||
232 | struct dccp_li_hist_entry *head; | ||
233 | u64 seq_temp; | ||
234 | |||
235 | if (list_empty(li_hist_list)) { | ||
236 | if (!dccp_li_hist_interval_new(li_hist_list, seq_loss, | ||
237 | win_loss)) | ||
238 | return; | ||
239 | |||
240 | head = list_entry(li_hist_list->next, struct dccp_li_hist_entry, | ||
241 | dccplih_node); | ||
242 | head->dccplih_interval = dccp_li_calc_first_li(sk, hist_list, | ||
243 | last_feedback, | ||
244 | s, bytes_recv, | ||
245 | previous_x_recv); | ||
246 | } else { | ||
247 | struct dccp_li_hist_entry *entry; | ||
248 | struct list_head *tail; | ||
249 | |||
250 | head = list_entry(li_hist_list->next, struct dccp_li_hist_entry, | ||
251 | dccplih_node); | ||
252 | /* FIXME win count check removed as was wrong */ | ||
253 | /* should make this check with receive history */ | ||
254 | /* and compare there as per section 10.2 of RFC4342 */ | ||
255 | |||
256 | /* new loss event detected */ | ||
257 | /* calculate last interval length */ | ||
258 | seq_temp = dccp_delta_seqno(head->dccplih_seqno, seq_loss); | ||
259 | entry = dccp_li_hist_entry_new(GFP_ATOMIC); | ||
260 | |||
261 | if (entry == NULL) { | ||
262 | DCCP_BUG("out of memory - can not allocate entry"); | ||
263 | return; | ||
264 | } | ||
265 | |||
266 | list_add(&entry->dccplih_node, li_hist_list); | ||
267 | |||
268 | tail = li_hist_list->prev; | ||
269 | list_del(tail); | ||
270 | kmem_cache_free(dccp_li_cachep, tail); | ||
271 | |||
272 | /* Create the newest interval */ | ||
273 | entry->dccplih_seqno = seq_loss; | ||
274 | entry->dccplih_interval = seq_temp; | ||
275 | entry->dccplih_win_count = win_loss; | ||
276 | } | ||
277 | } | ||
278 | |||
279 | EXPORT_SYMBOL_GPL(dccp_li_update_li); | ||
280 | |||
281 | static __init int dccp_li_init(void) | ||
282 | { | ||
283 | dccp_li_cachep = kmem_cache_create("dccp_li_hist", | ||
284 | sizeof(struct dccp_li_hist_entry), | ||
285 | 0, SLAB_HWCACHE_ALIGN, NULL, NULL); | ||
286 | return dccp_li_cachep == NULL ? -ENOBUFS : 0; | ||
287 | } | ||
288 | |||
289 | static __exit void dccp_li_exit(void) | ||
290 | { | ||
291 | kmem_cache_destroy(dccp_li_cachep); | ||
292 | } | ||
293 | |||
294 | module_init(dccp_li_init); | ||
295 | module_exit(dccp_li_exit); | ||
diff --git a/net/dccp/ccids/lib/loss_interval.h b/net/dccp/ccids/lib/loss_interval.h index eb257014dd74..906c806d6d9d 100644 --- a/net/dccp/ccids/lib/loss_interval.h +++ b/net/dccp/ccids/lib/loss_interval.h | |||
@@ -3,8 +3,8 @@ | |||
3 | /* | 3 | /* |
4 | * net/dccp/ccids/lib/loss_interval.h | 4 | * net/dccp/ccids/lib/loss_interval.h |
5 | * | 5 | * |
6 | * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. | 6 | * Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand. |
7 | * Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz> | 7 | * Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz> |
8 | * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> | 8 | * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify it | 10 | * This program is free software; you can redistribute it and/or modify it |
@@ -14,44 +14,16 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/list.h> | 16 | #include <linux/list.h> |
17 | #include <linux/slab.h> | ||
18 | #include <linux/time.h> | 17 | #include <linux/time.h> |
19 | 18 | ||
20 | #define DCCP_LI_HIST_IVAL_F_LENGTH 8 | 19 | extern void dccp_li_hist_purge(struct list_head *list); |
21 | |||
22 | struct dccp_li_hist { | ||
23 | struct kmem_cache *dccplih_slab; | ||
24 | }; | ||
25 | |||
26 | extern struct dccp_li_hist *dccp_li_hist_new(const char *name); | ||
27 | extern void dccp_li_hist_delete(struct dccp_li_hist *hist); | ||
28 | |||
29 | struct dccp_li_hist_entry { | ||
30 | struct list_head dccplih_node; | ||
31 | u64 dccplih_seqno:48, | ||
32 | dccplih_win_count:4; | ||
33 | u32 dccplih_interval; | ||
34 | }; | ||
35 | |||
36 | static inline struct dccp_li_hist_entry * | ||
37 | dccp_li_hist_entry_new(struct dccp_li_hist *hist, | ||
38 | const gfp_t prio) | ||
39 | { | ||
40 | return kmem_cache_alloc(hist->dccplih_slab, prio); | ||
41 | } | ||
42 | |||
43 | static inline void dccp_li_hist_entry_delete(struct dccp_li_hist *hist, | ||
44 | struct dccp_li_hist_entry *entry) | ||
45 | { | ||
46 | if (entry != NULL) | ||
47 | kmem_cache_free(hist->dccplih_slab, entry); | ||
48 | } | ||
49 | |||
50 | extern void dccp_li_hist_purge(struct dccp_li_hist *hist, | ||
51 | struct list_head *list); | ||
52 | 20 | ||
53 | extern u32 dccp_li_hist_calc_i_mean(struct list_head *list); | 21 | extern u32 dccp_li_hist_calc_i_mean(struct list_head *list); |
54 | 22 | ||
55 | extern int dccp_li_hist_interval_new(struct dccp_li_hist *hist, | 23 | extern void dccp_li_update_li(struct sock *sk, |
56 | struct list_head *list, const u64 seq_loss, const u8 win_loss); | 24 | struct list_head *li_hist_list, |
25 | struct list_head *hist_list, | ||
26 | struct timeval *last_feedback, u16 s, | ||
27 | u32 bytes_recv, u32 previous_x_recv, | ||
28 | u64 seq_loss, u8 win_loss); | ||
57 | #endif /* _DCCP_LI_HIST_ */ | 29 | #endif /* _DCCP_LI_HIST_ */ |
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index d8ad27bfe01a..e2d74cd7eeeb 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h | |||
@@ -184,7 +184,7 @@ DECLARE_SNMP_STAT(struct dccp_mib, dccp_statistics); | |||
184 | /* | 184 | /* |
185 | * Checksumming routines | 185 | * Checksumming routines |
186 | */ | 186 | */ |
187 | static inline int dccp_csum_coverage(const struct sk_buff *skb) | 187 | static inline unsigned int dccp_csum_coverage(const struct sk_buff *skb) |
188 | { | 188 | { |
189 | const struct dccp_hdr* dh = dccp_hdr(skb); | 189 | const struct dccp_hdr* dh = dccp_hdr(skb); |
190 | 190 | ||
@@ -195,7 +195,7 @@ static inline int dccp_csum_coverage(const struct sk_buff *skb) | |||
195 | 195 | ||
196 | static inline void dccp_csum_outgoing(struct sk_buff *skb) | 196 | static inline void dccp_csum_outgoing(struct sk_buff *skb) |
197 | { | 197 | { |
198 | int cov = dccp_csum_coverage(skb); | 198 | unsigned int cov = dccp_csum_coverage(skb); |
199 | 199 | ||
200 | if (cov >= skb->len) | 200 | if (cov >= skb->len) |
201 | dccp_hdr(skb)->dccph_cscov = 0; | 201 | dccp_hdr(skb)->dccph_cscov = 0; |
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 31737cdf156a..b158c661867b 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
@@ -253,17 +253,6 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, | |||
253 | 253 | ||
254 | if (dst == NULL) { | 254 | if (dst == NULL) { |
255 | opt = np->opt; | 255 | opt = np->opt; |
256 | if (opt == NULL && | ||
257 | np->rxopt.bits.osrcrt == 2 && | ||
258 | ireq6->pktopts) { | ||
259 | struct sk_buff *pktopts = ireq6->pktopts; | ||
260 | struct inet6_skb_parm *rxopt = IP6CB(pktopts); | ||
261 | |||
262 | if (rxopt->srcrt) | ||
263 | opt = ipv6_invert_rthdr(sk, | ||
264 | (struct ipv6_rt_hdr *)(skb_network_header(pktopts) + | ||
265 | rxopt->srcrt)); | ||
266 | } | ||
267 | 256 | ||
268 | if (opt != NULL && opt->srcrt != NULL) { | 257 | if (opt != NULL && opt->srcrt != NULL) { |
269 | const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt; | 258 | const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt; |
@@ -570,15 +559,6 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, | |||
570 | if (sk_acceptq_is_full(sk)) | 559 | if (sk_acceptq_is_full(sk)) |
571 | goto out_overflow; | 560 | goto out_overflow; |
572 | 561 | ||
573 | if (np->rxopt.bits.osrcrt == 2 && opt == NULL && ireq6->pktopts) { | ||
574 | const struct inet6_skb_parm *rxopt = IP6CB(ireq6->pktopts); | ||
575 | |||
576 | if (rxopt->srcrt) | ||
577 | opt = ipv6_invert_rthdr(sk, | ||
578 | (struct ipv6_rt_hdr *)(skb_network_header(ireq6->pktopts) + | ||
579 | rxopt->srcrt)); | ||
580 | } | ||
581 | |||
582 | if (dst == NULL) { | 562 | if (dst == NULL) { |
583 | struct in6_addr *final_p = NULL, final; | 563 | struct in6_addr *final_p = NULL, final; |
584 | struct flowi fl; | 564 | struct flowi fl; |
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index bfa910b6ad25..ed76d4aab4a9 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c | |||
@@ -2304,7 +2304,7 @@ static int dn_socket_seq_show(struct seq_file *seq, void *v) | |||
2304 | return 0; | 2304 | return 0; |
2305 | } | 2305 | } |
2306 | 2306 | ||
2307 | static struct seq_operations dn_socket_seq_ops = { | 2307 | static const struct seq_operations dn_socket_seq_ops = { |
2308 | .start = dn_socket_seq_start, | 2308 | .start = dn_socket_seq_start, |
2309 | .next = dn_socket_seq_next, | 2309 | .next = dn_socket_seq_next, |
2310 | .stop = dn_socket_seq_stop, | 2310 | .stop = dn_socket_seq_stop, |
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index ab41c1879fd4..fa6604fcf0e7 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c | |||
@@ -461,7 +461,6 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa) | |||
461 | if (ifa->ifa_local != dn_eth2dn(dev->dev_addr)) { | 461 | if (ifa->ifa_local != dn_eth2dn(dev->dev_addr)) { |
462 | dn_dn2eth(mac_addr, ifa->ifa_local); | 462 | dn_dn2eth(mac_addr, ifa->ifa_local); |
463 | dev_mc_add(dev, mac_addr, ETH_ALEN, 0); | 463 | dev_mc_add(dev, mac_addr, ETH_ALEN, 0); |
464 | dev_mc_upload(dev); | ||
465 | } | 464 | } |
466 | } | 465 | } |
467 | 466 | ||
@@ -1064,8 +1063,6 @@ static int dn_eth_up(struct net_device *dev) | |||
1064 | else | 1063 | else |
1065 | dev_mc_add(dev, dn_rt_all_rt_mcast, ETH_ALEN, 0); | 1064 | dev_mc_add(dev, dn_rt_all_rt_mcast, ETH_ALEN, 0); |
1066 | 1065 | ||
1067 | dev_mc_upload(dev); | ||
1068 | |||
1069 | dn_db->use_long = 1; | 1066 | dn_db->use_long = 1; |
1070 | 1067 | ||
1071 | return 0; | 1068 | return 0; |
@@ -1419,7 +1416,7 @@ static int dn_dev_seq_show(struct seq_file *seq, void *v) | |||
1419 | return 0; | 1416 | return 0; |
1420 | } | 1417 | } |
1421 | 1418 | ||
1422 | static struct seq_operations dn_dev_seq_ops = { | 1419 | static const struct seq_operations dn_dev_seq_ops = { |
1423 | .start = dn_dev_seq_start, | 1420 | .start = dn_dev_seq_start, |
1424 | .next = dn_dev_seq_next, | 1421 | .next = dn_dev_seq_next, |
1425 | .stop = dn_dev_seq_stop, | 1422 | .stop = dn_dev_seq_stop, |
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c index 4bf066c416e2..174d8a7a6dac 100644 --- a/net/decnet/dn_neigh.c +++ b/net/decnet/dn_neigh.c | |||
@@ -569,7 +569,7 @@ static void *dn_neigh_seq_start(struct seq_file *seq, loff_t *pos) | |||
569 | NEIGH_SEQ_NEIGH_ONLY); | 569 | NEIGH_SEQ_NEIGH_ONLY); |
570 | } | 570 | } |
571 | 571 | ||
572 | static struct seq_operations dn_neigh_seq_ops = { | 572 | static const struct seq_operations dn_neigh_seq_ops = { |
573 | .start = dn_neigh_seq_start, | 573 | .start = dn_neigh_seq_start, |
574 | .next = neigh_seq_next, | 574 | .next = neigh_seq_next, |
575 | .stop = neigh_seq_stop, | 575 | .stop = neigh_seq_stop, |
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index a8bf106b7a61..82622fb6f68f 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c | |||
@@ -1726,7 +1726,7 @@ static int dn_rt_cache_seq_show(struct seq_file *seq, void *v) | |||
1726 | return 0; | 1726 | return 0; |
1727 | } | 1727 | } |
1728 | 1728 | ||
1729 | static struct seq_operations dn_rt_cache_seq_ops = { | 1729 | static const struct seq_operations dn_rt_cache_seq_ops = { |
1730 | .start = dn_rt_cache_seq_start, | 1730 | .start = dn_rt_cache_seq_start, |
1731 | .next = dn_rt_cache_seq_next, | 1731 | .next = dn_rt_cache_seq_next, |
1732 | .stop = dn_rt_cache_seq_stop, | 1732 | .stop = dn_rt_cache_seq_stop, |
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 0ac2524f3b68..12c765715acf 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c | |||
@@ -266,8 +266,11 @@ void eth_header_cache_update(struct hh_cache *hh, struct net_device *dev, | |||
266 | static int eth_mac_addr(struct net_device *dev, void *p) | 266 | static int eth_mac_addr(struct net_device *dev, void *p) |
267 | { | 267 | { |
268 | struct sockaddr *addr = p; | 268 | struct sockaddr *addr = p; |
269 | |||
269 | if (netif_running(dev)) | 270 | if (netif_running(dev)) |
270 | return -EBUSY; | 271 | return -EBUSY; |
272 | if (!is_valid_ether_addr(addr->sa_data)) | ||
273 | return -EADDRNOTAVAIL; | ||
271 | memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); | 274 | memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); |
272 | return 0; | 275 | return 0; |
273 | } | 276 | } |
@@ -316,9 +319,10 @@ void ether_setup(struct net_device *dev) | |||
316 | EXPORT_SYMBOL(ether_setup); | 319 | EXPORT_SYMBOL(ether_setup); |
317 | 320 | ||
318 | /** | 321 | /** |
319 | * alloc_etherdev - Allocates and sets up an Ethernet device | 322 | * alloc_etherdev_mq - Allocates and sets up an Ethernet device |
320 | * @sizeof_priv: Size of additional driver-private structure to be allocated | 323 | * @sizeof_priv: Size of additional driver-private structure to be allocated |
321 | * for this Ethernet device | 324 | * for this Ethernet device |
325 | * @queue_count: The number of queues this device has. | ||
322 | * | 326 | * |
323 | * Fill in the fields of the device structure with Ethernet-generic | 327 | * Fill in the fields of the device structure with Ethernet-generic |
324 | * values. Basically does everything except registering the device. | 328 | * values. Basically does everything except registering the device. |
@@ -328,8 +332,8 @@ EXPORT_SYMBOL(ether_setup); | |||
328 | * this private data area. | 332 | * this private data area. |
329 | */ | 333 | */ |
330 | 334 | ||
331 | struct net_device *alloc_etherdev(int sizeof_priv) | 335 | struct net_device *alloc_etherdev_mq(int sizeof_priv, unsigned int queue_count) |
332 | { | 336 | { |
333 | return alloc_netdev(sizeof_priv, "eth%d", ether_setup); | 337 | return alloc_netdev_mq(sizeof_priv, "eth%d", ether_setup, queue_count); |
334 | } | 338 | } |
335 | EXPORT_SYMBOL(alloc_etherdev); | 339 | EXPORT_SYMBOL(alloc_etherdev_mq); |
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 010fbb2d45e9..fb7909774254 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig | |||
@@ -116,48 +116,6 @@ config IP_ROUTE_MULTIPATH | |||
116 | equal "cost" and chooses one of them in a non-deterministic fashion | 116 | equal "cost" and chooses one of them in a non-deterministic fashion |
117 | if a matching packet arrives. | 117 | if a matching packet arrives. |
118 | 118 | ||
119 | config IP_ROUTE_MULTIPATH_CACHED | ||
120 | bool "IP: equal cost multipath with caching support (EXPERIMENTAL)" | ||
121 | depends on IP_ROUTE_MULTIPATH | ||
122 | help | ||
123 | Normally, equal cost multipath routing is not supported by the | ||
124 | routing cache. If you say Y here, alternative routes are cached | ||
125 | and on cache lookup a route is chosen in a configurable fashion. | ||
126 | |||
127 | If unsure, say N. | ||
128 | |||
129 | config IP_ROUTE_MULTIPATH_RR | ||
130 | tristate "MULTIPATH: round robin algorithm" | ||
131 | depends on IP_ROUTE_MULTIPATH_CACHED | ||
132 | help | ||
133 | Multipath routes are chosen according to Round Robin | ||
134 | |||
135 | config IP_ROUTE_MULTIPATH_RANDOM | ||
136 | tristate "MULTIPATH: random algorithm" | ||
137 | depends on IP_ROUTE_MULTIPATH_CACHED | ||
138 | help | ||
139 | Multipath routes are chosen in a random fashion. Actually, | ||
140 | there is no weight for a route. The advantage of this policy | ||
141 | is that it is implemented stateless and therefore introduces only | ||
142 | a very small delay. | ||
143 | |||
144 | config IP_ROUTE_MULTIPATH_WRANDOM | ||
145 | tristate "MULTIPATH: weighted random algorithm" | ||
146 | depends on IP_ROUTE_MULTIPATH_CACHED | ||
147 | help | ||
148 | Multipath routes are chosen in a weighted random fashion. | ||
149 | The per route weights are the weights visible via ip route 2. As the | ||
150 | corresponding state management introduces some overhead routing delay | ||
151 | is increased. | ||
152 | |||
153 | config IP_ROUTE_MULTIPATH_DRR | ||
154 | tristate "MULTIPATH: interface round robin algorithm" | ||
155 | depends on IP_ROUTE_MULTIPATH_CACHED | ||
156 | help | ||
157 | Connections are distributed in a round robin fashion over the | ||
158 | available interfaces. This policy makes sense if the connections | ||
159 | should be primarily distributed on interfaces and not on routes. | ||
160 | |||
161 | config IP_ROUTE_VERBOSE | 119 | config IP_ROUTE_VERBOSE |
162 | bool "IP: verbose route monitoring" | 120 | bool "IP: verbose route monitoring" |
163 | depends on IP_ADVANCED_ROUTER | 121 | depends on IP_ADVANCED_ROUTER |
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index 4ff6c151d7f3..fbf1674e0c2a 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile | |||
@@ -29,14 +29,9 @@ obj-$(CONFIG_INET_TUNNEL) += tunnel4.o | |||
29 | obj-$(CONFIG_INET_XFRM_MODE_TRANSPORT) += xfrm4_mode_transport.o | 29 | obj-$(CONFIG_INET_XFRM_MODE_TRANSPORT) += xfrm4_mode_transport.o |
30 | obj-$(CONFIG_INET_XFRM_MODE_TUNNEL) += xfrm4_mode_tunnel.o | 30 | obj-$(CONFIG_INET_XFRM_MODE_TUNNEL) += xfrm4_mode_tunnel.o |
31 | obj-$(CONFIG_IP_PNP) += ipconfig.o | 31 | obj-$(CONFIG_IP_PNP) += ipconfig.o |
32 | obj-$(CONFIG_IP_ROUTE_MULTIPATH_RR) += multipath_rr.o | ||
33 | obj-$(CONFIG_IP_ROUTE_MULTIPATH_RANDOM) += multipath_random.o | ||
34 | obj-$(CONFIG_IP_ROUTE_MULTIPATH_WRANDOM) += multipath_wrandom.o | ||
35 | obj-$(CONFIG_IP_ROUTE_MULTIPATH_DRR) += multipath_drr.o | ||
36 | obj-$(CONFIG_NETFILTER) += netfilter.o netfilter/ | 32 | obj-$(CONFIG_NETFILTER) += netfilter.o netfilter/ |
37 | obj-$(CONFIG_IP_VS) += ipvs/ | 33 | obj-$(CONFIG_IP_VS) += ipvs/ |
38 | obj-$(CONFIG_INET_DIAG) += inet_diag.o | 34 | obj-$(CONFIG_INET_DIAG) += inet_diag.o |
39 | obj-$(CONFIG_IP_ROUTE_MULTIPATH_CACHED) += multipath.o | ||
40 | obj-$(CONFIG_INET_TCP_DIAG) += tcp_diag.o | 35 | obj-$(CONFIG_INET_TCP_DIAG) += tcp_diag.o |
41 | obj-$(CONFIG_NET_TCPPROBE) += tcp_probe.o | 36 | obj-$(CONFIG_NET_TCPPROBE) += tcp_probe.o |
42 | obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o | 37 | obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o |
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 041fba3fa0aa..06c08e5740fb 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -1170,6 +1170,9 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features) | |||
1170 | int ihl; | 1170 | int ihl; |
1171 | int id; | 1171 | int id; |
1172 | 1172 | ||
1173 | if (!(features & NETIF_F_V4_CSUM)) | ||
1174 | features &= ~NETIF_F_SG; | ||
1175 | |||
1173 | if (unlikely(skb_shinfo(skb)->gso_type & | 1176 | if (unlikely(skb_shinfo(skb)->gso_type & |
1174 | ~(SKB_GSO_TCPV4 | | 1177 | ~(SKB_GSO_TCPV4 | |
1175 | SKB_GSO_UDP | | 1178 | SKB_GSO_UDP | |
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index 6da8ff597ad3..7a23e59c374a 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c | |||
@@ -339,3 +339,4 @@ static void __exit ah4_fini(void) | |||
339 | module_init(ah4_init); | 339 | module_init(ah4_init); |
340 | module_exit(ah4_fini); | 340 | module_exit(ah4_fini); |
341 | MODULE_LICENSE("GPL"); | 341 | MODULE_LICENSE("GPL"); |
342 | MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_AH); | ||
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index e00767e8ebd9..9ab9d534fbac 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c | |||
@@ -885,7 +885,7 @@ static int arp_process(struct sk_buff *skb) | |||
885 | if (n == NULL && | 885 | if (n == NULL && |
886 | arp->ar_op == htons(ARPOP_REPLY) && | 886 | arp->ar_op == htons(ARPOP_REPLY) && |
887 | inet_addr_type(sip) == RTN_UNICAST) | 887 | inet_addr_type(sip) == RTN_UNICAST) |
888 | n = __neigh_lookup(&arp_tbl, &sip, dev, -1); | 888 | n = __neigh_lookup(&arp_tbl, &sip, dev, 1); |
889 | } | 889 | } |
890 | 890 | ||
891 | if (n) { | 891 | if (n) { |
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 47c95e8ef045..98767a4f1185 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c | |||
@@ -481,3 +481,4 @@ static void __exit esp4_fini(void) | |||
481 | module_init(esp4_init); | 481 | module_init(esp4_init); |
482 | module_exit(esp4_fini); | 482 | module_exit(esp4_fini); |
483 | MODULE_LICENSE("GPL"); | 483 | MODULE_LICENSE("GPL"); |
484 | MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_ESP); | ||
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 311d633f7f39..2eb909be8041 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -453,7 +453,6 @@ const struct nla_policy rtm_ipv4_policy[RTA_MAX+1] = { | |||
453 | [RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) }, | 453 | [RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) }, |
454 | [RTA_PROTOINFO] = { .type = NLA_U32 }, | 454 | [RTA_PROTOINFO] = { .type = NLA_U32 }, |
455 | [RTA_FLOW] = { .type = NLA_U32 }, | 455 | [RTA_FLOW] = { .type = NLA_U32 }, |
456 | [RTA_MP_ALGO] = { .type = NLA_U32 }, | ||
457 | }; | 456 | }; |
458 | 457 | ||
459 | static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh, | 458 | static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh, |
@@ -515,9 +514,6 @@ static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
515 | case RTA_FLOW: | 514 | case RTA_FLOW: |
516 | cfg->fc_flow = nla_get_u32(attr); | 515 | cfg->fc_flow = nla_get_u32(attr); |
517 | break; | 516 | break; |
518 | case RTA_MP_ALGO: | ||
519 | cfg->fc_mp_alg = nla_get_u32(attr); | ||
520 | break; | ||
521 | case RTA_TABLE: | 517 | case RTA_TABLE: |
522 | cfg->fc_table = nla_get_u32(attr); | 518 | cfg->fc_table = nla_get_u32(attr); |
523 | break; | 519 | break; |
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index bb94550d95c3..c434119deb52 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c | |||
@@ -42,7 +42,6 @@ | |||
42 | #include <net/tcp.h> | 42 | #include <net/tcp.h> |
43 | #include <net/sock.h> | 43 | #include <net/sock.h> |
44 | #include <net/ip_fib.h> | 44 | #include <net/ip_fib.h> |
45 | #include <net/ip_mp_alg.h> | ||
46 | #include <net/netlink.h> | 45 | #include <net/netlink.h> |
47 | #include <net/nexthop.h> | 46 | #include <net/nexthop.h> |
48 | 47 | ||
@@ -697,13 +696,6 @@ struct fib_info *fib_create_info(struct fib_config *cfg) | |||
697 | goto err_inval; | 696 | goto err_inval; |
698 | } | 697 | } |
699 | #endif | 698 | #endif |
700 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | ||
701 | if (cfg->fc_mp_alg) { | ||
702 | if (cfg->fc_mp_alg < IP_MP_ALG_NONE || | ||
703 | cfg->fc_mp_alg > IP_MP_ALG_MAX) | ||
704 | goto err_inval; | ||
705 | } | ||
706 | #endif | ||
707 | 699 | ||
708 | err = -ENOBUFS; | 700 | err = -ENOBUFS; |
709 | if (fib_info_cnt >= fib_hash_size) { | 701 | if (fib_info_cnt >= fib_hash_size) { |
@@ -791,10 +783,6 @@ struct fib_info *fib_create_info(struct fib_config *cfg) | |||
791 | #endif | 783 | #endif |
792 | } | 784 | } |
793 | 785 | ||
794 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | ||
795 | fi->fib_mp_alg = cfg->fc_mp_alg; | ||
796 | #endif | ||
797 | |||
798 | if (fib_props[cfg->fc_type].error) { | 786 | if (fib_props[cfg->fc_type].error) { |
799 | if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp) | 787 | if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp) |
800 | goto err_inval; | 788 | goto err_inval; |
@@ -940,10 +928,6 @@ out_fill_res: | |||
940 | res->type = fa->fa_type; | 928 | res->type = fa->fa_type; |
941 | res->scope = fa->fa_scope; | 929 | res->scope = fa->fa_scope; |
942 | res->fi = fa->fa_info; | 930 | res->fi = fa->fa_info; |
943 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | ||
944 | res->netmask = mask; | ||
945 | res->network = zone & inet_make_mask(prefixlen); | ||
946 | #endif | ||
947 | atomic_inc(&res->fi->fib_clntref); | 931 | atomic_inc(&res->fi->fib_clntref); |
948 | return 0; | 932 | return 0; |
949 | } | 933 | } |
diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c index a73cf93cee36..2586df09b9b6 100644 --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c | |||
@@ -14,7 +14,8 @@ | |||
14 | #include <net/ip.h> | 14 | #include <net/ip.h> |
15 | 15 | ||
16 | /* Must be called with locally disabled BHs. */ | 16 | /* Must be called with locally disabled BHs. */ |
17 | void __inet_twsk_kill(struct inet_timewait_sock *tw, struct inet_hashinfo *hashinfo) | 17 | static void __inet_twsk_kill(struct inet_timewait_sock *tw, |
18 | struct inet_hashinfo *hashinfo) | ||
18 | { | 19 | { |
19 | struct inet_bind_hashbucket *bhead; | 20 | struct inet_bind_hashbucket *bhead; |
20 | struct inet_bind_bucket *tb; | 21 | struct inet_bind_bucket *tb; |
@@ -47,8 +48,6 @@ void __inet_twsk_kill(struct inet_timewait_sock *tw, struct inet_hashinfo *hashi | |||
47 | inet_twsk_put(tw); | 48 | inet_twsk_put(tw); |
48 | } | 49 | } |
49 | 50 | ||
50 | EXPORT_SYMBOL_GPL(__inet_twsk_kill); | ||
51 | |||
52 | /* | 51 | /* |
53 | * Enter the time wait state. This is called with locally disabled BH. | 52 | * Enter the time wait state. This is called with locally disabled BH. |
54 | * Essentially we whip up a timewait bucket, copy the relevant info into it | 53 | * Essentially we whip up a timewait bucket, copy the relevant info into it |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 63282934725e..5c14ed63e56c 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -809,7 +809,8 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
809 | 809 | ||
810 | max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen; | 810 | max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen; |
811 | 811 | ||
812 | if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) { | 812 | if (skb_headroom(skb) < max_headroom || skb_shared(skb)|| |
813 | (skb_cloned(skb) && !skb_clone_writable(skb, 0))) { | ||
813 | struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); | 814 | struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); |
814 | if (!new_skb) { | 815 | if (!new_skb) { |
815 | ip_rt_put(rt); | 816 | ip_rt_put(rt); |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 34ea4547ebbe..c9e2b5e6305e 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -399,6 +399,10 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from) | |||
399 | to->tc_index = from->tc_index; | 399 | to->tc_index = from->tc_index; |
400 | #endif | 400 | #endif |
401 | nf_copy(to, from); | 401 | nf_copy(to, from); |
402 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||
403 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | ||
404 | to->nf_trace = from->nf_trace; | ||
405 | #endif | ||
402 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) | 406 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) |
403 | to->ipvs_property = from->ipvs_property; | 407 | to->ipvs_property = from->ipvs_property; |
404 | #endif | 408 | #endif |
@@ -837,7 +841,7 @@ int ip_append_data(struct sock *sk, | |||
837 | */ | 841 | */ |
838 | if (transhdrlen && | 842 | if (transhdrlen && |
839 | length + fragheaderlen <= mtu && | 843 | length + fragheaderlen <= mtu && |
840 | rt->u.dst.dev->features & NETIF_F_ALL_CSUM && | 844 | rt->u.dst.dev->features & NETIF_F_V4_CSUM && |
841 | !exthdrlen) | 845 | !exthdrlen) |
842 | csummode = CHECKSUM_PARTIAL; | 846 | csummode = CHECKSUM_PARTIAL; |
843 | 847 | ||
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index ab86137c71d2..e787044a8514 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c | |||
@@ -485,3 +485,4 @@ MODULE_LICENSE("GPL"); | |||
485 | MODULE_DESCRIPTION("IP Payload Compression Protocol (IPComp) - RFC3173"); | 485 | MODULE_DESCRIPTION("IP Payload Compression Protocol (IPComp) - RFC3173"); |
486 | MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>"); | 486 | MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>"); |
487 | 487 | ||
488 | MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_COMP); | ||
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index ebd2f2d532f6..396437242a1b 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
@@ -595,7 +595,8 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
595 | */ | 595 | */ |
596 | max_headroom = (LL_RESERVED_SPACE(tdev)+sizeof(struct iphdr)); | 596 | max_headroom = (LL_RESERVED_SPACE(tdev)+sizeof(struct iphdr)); |
597 | 597 | ||
598 | if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) { | 598 | if (skb_headroom(skb) < max_headroom || skb_shared(skb) || |
599 | (skb_cloned(skb) && !skb_clone_writable(skb, 0))) { | ||
599 | struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); | 600 | struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); |
600 | if (!new_skb) { | 601 | if (!new_skb) { |
601 | ip_rt_put(rt); | 602 | ip_rt_put(rt); |
diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c index 15ad5dd2d984..8d6901d4e94f 100644 --- a/net/ipv4/ipvs/ip_vs_app.c +++ b/net/ipv4/ipvs/ip_vs_app.c | |||
@@ -549,7 +549,7 @@ static int ip_vs_app_seq_show(struct seq_file *seq, void *v) | |||
549 | return 0; | 549 | return 0; |
550 | } | 550 | } |
551 | 551 | ||
552 | static struct seq_operations ip_vs_app_seq_ops = { | 552 | static const struct seq_operations ip_vs_app_seq_ops = { |
553 | .start = ip_vs_app_seq_start, | 553 | .start = ip_vs_app_seq_start, |
554 | .next = ip_vs_app_seq_next, | 554 | .next = ip_vs_app_seq_next, |
555 | .stop = ip_vs_app_seq_stop, | 555 | .stop = ip_vs_app_seq_stop, |
diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c index 7018f97c75dc..3b446b1a6b9c 100644 --- a/net/ipv4/ipvs/ip_vs_conn.c +++ b/net/ipv4/ipvs/ip_vs_conn.c | |||
@@ -745,7 +745,7 @@ static int ip_vs_conn_seq_show(struct seq_file *seq, void *v) | |||
745 | return 0; | 745 | return 0; |
746 | } | 746 | } |
747 | 747 | ||
748 | static struct seq_operations ip_vs_conn_seq_ops = { | 748 | static const struct seq_operations ip_vs_conn_seq_ops = { |
749 | .start = ip_vs_conn_seq_start, | 749 | .start = ip_vs_conn_seq_start, |
750 | .next = ip_vs_conn_seq_next, | 750 | .next = ip_vs_conn_seq_next, |
751 | .stop = ip_vs_conn_seq_stop, | 751 | .stop = ip_vs_conn_seq_stop, |
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c index 68fe1d4d0210..e1052bcf4ed1 100644 --- a/net/ipv4/ipvs/ip_vs_ctl.c +++ b/net/ipv4/ipvs/ip_vs_ctl.c | |||
@@ -1783,7 +1783,7 @@ static int ip_vs_info_seq_show(struct seq_file *seq, void *v) | |||
1783 | return 0; | 1783 | return 0; |
1784 | } | 1784 | } |
1785 | 1785 | ||
1786 | static struct seq_operations ip_vs_info_seq_ops = { | 1786 | static const struct seq_operations ip_vs_info_seq_ops = { |
1787 | .start = ip_vs_info_seq_start, | 1787 | .start = ip_vs_info_seq_start, |
1788 | .next = ip_vs_info_seq_next, | 1788 | .next = ip_vs_info_seq_next, |
1789 | .stop = ip_vs_info_seq_stop, | 1789 | .stop = ip_vs_info_seq_stop, |
diff --git a/net/ipv4/multipath.c b/net/ipv4/multipath.c deleted file mode 100644 index 4e9ca7c76407..000000000000 --- a/net/ipv4/multipath.c +++ /dev/null | |||
@@ -1,55 +0,0 @@ | |||
1 | /* multipath.c: IPV4 multipath algorithm support. | ||
2 | * | ||
3 | * Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com> | ||
4 | * Copyright (C) 2005 David S. Miller <davem@davemloft.net> | ||
5 | */ | ||
6 | |||
7 | #include <linux/module.h> | ||
8 | #include <linux/errno.h> | ||
9 | #include <linux/netdevice.h> | ||
10 | #include <linux/spinlock.h> | ||
11 | |||
12 | #include <net/ip_mp_alg.h> | ||
13 | |||
14 | static DEFINE_SPINLOCK(alg_table_lock); | ||
15 | struct ip_mp_alg_ops *ip_mp_alg_table[IP_MP_ALG_MAX + 1]; | ||
16 | |||
17 | int multipath_alg_register(struct ip_mp_alg_ops *ops, enum ip_mp_alg n) | ||
18 | { | ||
19 | struct ip_mp_alg_ops **slot; | ||
20 | int err; | ||
21 | |||
22 | if (n < IP_MP_ALG_NONE || n > IP_MP_ALG_MAX || | ||
23 | !ops->mp_alg_select_route) | ||
24 | return -EINVAL; | ||
25 | |||
26 | spin_lock(&alg_table_lock); | ||
27 | slot = &ip_mp_alg_table[n]; | ||
28 | if (*slot != NULL) { | ||
29 | err = -EBUSY; | ||
30 | } else { | ||
31 | *slot = ops; | ||
32 | err = 0; | ||
33 | } | ||
34 | spin_unlock(&alg_table_lock); | ||
35 | |||
36 | return err; | ||
37 | } | ||
38 | EXPORT_SYMBOL(multipath_alg_register); | ||
39 | |||
40 | void multipath_alg_unregister(struct ip_mp_alg_ops *ops, enum ip_mp_alg n) | ||
41 | { | ||
42 | struct ip_mp_alg_ops **slot; | ||
43 | |||
44 | if (n < IP_MP_ALG_NONE || n > IP_MP_ALG_MAX) | ||
45 | return; | ||
46 | |||
47 | spin_lock(&alg_table_lock); | ||
48 | slot = &ip_mp_alg_table[n]; | ||
49 | if (*slot == ops) | ||
50 | *slot = NULL; | ||
51 | spin_unlock(&alg_table_lock); | ||
52 | |||
53 | synchronize_net(); | ||
54 | } | ||
55 | EXPORT_SYMBOL(multipath_alg_unregister); | ||
diff --git a/net/ipv4/multipath_drr.c b/net/ipv4/multipath_drr.c deleted file mode 100644 index b03c5ca2c823..000000000000 --- a/net/ipv4/multipath_drr.c +++ /dev/null | |||
@@ -1,249 +0,0 @@ | |||
1 | /* | ||
2 | * Device round robin policy for multipath. | ||
3 | * | ||
4 | * | ||
5 | * Version: $Id: multipath_drr.c,v 1.1.2.1 2004/09/16 07:42:34 elueck Exp $ | ||
6 | * | ||
7 | * Authors: Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * as published by the Free Software Foundation; either version | ||
12 | * 2 of the License, or (at your option) any later version. | ||
13 | */ | ||
14 | |||
15 | #include <asm/system.h> | ||
16 | #include <asm/uaccess.h> | ||
17 | #include <linux/types.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/timer.h> | ||
20 | #include <linux/mm.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/fcntl.h> | ||
23 | #include <linux/stat.h> | ||
24 | #include <linux/socket.h> | ||
25 | #include <linux/in.h> | ||
26 | #include <linux/inet.h> | ||
27 | #include <linux/netdevice.h> | ||
28 | #include <linux/inetdevice.h> | ||
29 | #include <linux/igmp.h> | ||
30 | #include <linux/proc_fs.h> | ||
31 | #include <linux/seq_file.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/mroute.h> | ||
34 | #include <linux/init.h> | ||
35 | #include <net/ip.h> | ||
36 | #include <net/protocol.h> | ||
37 | #include <linux/skbuff.h> | ||
38 | #include <net/sock.h> | ||
39 | #include <net/icmp.h> | ||
40 | #include <net/udp.h> | ||
41 | #include <net/raw.h> | ||
42 | #include <linux/notifier.h> | ||
43 | #include <linux/if_arp.h> | ||
44 | #include <linux/netfilter_ipv4.h> | ||
45 | #include <net/ipip.h> | ||
46 | #include <net/checksum.h> | ||
47 | #include <net/ip_mp_alg.h> | ||
48 | |||
49 | struct multipath_device { | ||
50 | int ifi; /* interface index of device */ | ||
51 | atomic_t usecount; | ||
52 | int allocated; | ||
53 | }; | ||
54 | |||
55 | #define MULTIPATH_MAX_DEVICECANDIDATES 10 | ||
56 | |||
57 | static struct multipath_device state[MULTIPATH_MAX_DEVICECANDIDATES]; | ||
58 | static DEFINE_SPINLOCK(state_lock); | ||
59 | |||
60 | static int inline __multipath_findslot(void) | ||
61 | { | ||
62 | int i; | ||
63 | |||
64 | for (i = 0; i < MULTIPATH_MAX_DEVICECANDIDATES; i++) { | ||
65 | if (state[i].allocated == 0) | ||
66 | return i; | ||
67 | } | ||
68 | return -1; | ||
69 | } | ||
70 | |||
71 | static int inline __multipath_finddev(int ifindex) | ||
72 | { | ||
73 | int i; | ||
74 | |||
75 | for (i = 0; i < MULTIPATH_MAX_DEVICECANDIDATES; i++) { | ||
76 | if (state[i].allocated != 0 && | ||
77 | state[i].ifi == ifindex) | ||
78 | return i; | ||
79 | } | ||
80 | return -1; | ||
81 | } | ||
82 | |||
83 | static int drr_dev_event(struct notifier_block *this, | ||
84 | unsigned long event, void *ptr) | ||
85 | { | ||
86 | struct net_device *dev = ptr; | ||
87 | int devidx; | ||
88 | |||
89 | switch (event) { | ||
90 | case NETDEV_UNREGISTER: | ||
91 | case NETDEV_DOWN: | ||
92 | spin_lock_bh(&state_lock); | ||
93 | |||
94 | devidx = __multipath_finddev(dev->ifindex); | ||
95 | if (devidx != -1) { | ||
96 | state[devidx].allocated = 0; | ||
97 | state[devidx].ifi = 0; | ||
98 | atomic_set(&state[devidx].usecount, 0); | ||
99 | } | ||
100 | |||
101 | spin_unlock_bh(&state_lock); | ||
102 | break; | ||
103 | } | ||
104 | |||
105 | return NOTIFY_DONE; | ||
106 | } | ||
107 | |||
108 | static struct notifier_block drr_dev_notifier = { | ||
109 | .notifier_call = drr_dev_event, | ||
110 | }; | ||
111 | |||
112 | |||
113 | static void drr_safe_inc(atomic_t *usecount) | ||
114 | { | ||
115 | int n; | ||
116 | |||
117 | atomic_inc(usecount); | ||
118 | |||
119 | n = atomic_read(usecount); | ||
120 | if (n <= 0) { | ||
121 | int i; | ||
122 | |||
123 | spin_lock_bh(&state_lock); | ||
124 | |||
125 | for (i = 0; i < MULTIPATH_MAX_DEVICECANDIDATES; i++) | ||
126 | atomic_set(&state[i].usecount, 0); | ||
127 | |||
128 | spin_unlock_bh(&state_lock); | ||
129 | } | ||
130 | } | ||
131 | |||
132 | static void drr_select_route(const struct flowi *flp, | ||
133 | struct rtable *first, struct rtable **rp) | ||
134 | { | ||
135 | struct rtable *nh, *result, *cur_min; | ||
136 | int min_usecount = -1; | ||
137 | int devidx = -1; | ||
138 | int cur_min_devidx = -1; | ||
139 | |||
140 | /* 1. make sure all alt. nexthops have the same GC related data */ | ||
141 | /* 2. determine the new candidate to be returned */ | ||
142 | result = NULL; | ||
143 | cur_min = NULL; | ||
144 | for (nh = rcu_dereference(first); nh; | ||
145 | nh = rcu_dereference(nh->u.dst.rt_next)) { | ||
146 | if ((nh->u.dst.flags & DST_BALANCED) != 0 && | ||
147 | multipath_comparekeys(&nh->fl, flp)) { | ||
148 | int nh_ifidx = nh->u.dst.dev->ifindex; | ||
149 | |||
150 | nh->u.dst.lastuse = jiffies; | ||
151 | nh->u.dst.__use++; | ||
152 | if (result != NULL) | ||
153 | continue; | ||
154 | |||
155 | /* search for the output interface */ | ||
156 | |||
157 | /* this is not SMP safe, only add/remove are | ||
158 | * SMP safe as wrong usecount updates have no big | ||
159 | * impact | ||
160 | */ | ||
161 | devidx = __multipath_finddev(nh_ifidx); | ||
162 | if (devidx == -1) { | ||
163 | /* add the interface to the array | ||
164 | * SMP safe | ||
165 | */ | ||
166 | spin_lock_bh(&state_lock); | ||
167 | |||
168 | /* due to SMP: search again */ | ||
169 | devidx = __multipath_finddev(nh_ifidx); | ||
170 | if (devidx == -1) { | ||
171 | /* add entry for device */ | ||
172 | devidx = __multipath_findslot(); | ||
173 | if (devidx == -1) { | ||
174 | /* unlikely but possible */ | ||
175 | continue; | ||
176 | } | ||
177 | |||
178 | state[devidx].allocated = 1; | ||
179 | state[devidx].ifi = nh_ifidx; | ||
180 | atomic_set(&state[devidx].usecount, 0); | ||
181 | min_usecount = 0; | ||
182 | } | ||
183 | |||
184 | spin_unlock_bh(&state_lock); | ||
185 | } | ||
186 | |||
187 | if (min_usecount == 0) { | ||
188 | /* if the device has not been used it is | ||
189 | * the primary target | ||
190 | */ | ||
191 | drr_safe_inc(&state[devidx].usecount); | ||
192 | result = nh; | ||
193 | } else { | ||
194 | int count = | ||
195 | atomic_read(&state[devidx].usecount); | ||
196 | |||
197 | if (min_usecount == -1 || | ||
198 | count < min_usecount) { | ||
199 | cur_min = nh; | ||
200 | cur_min_devidx = devidx; | ||
201 | min_usecount = count; | ||
202 | } | ||
203 | } | ||
204 | } | ||
205 | } | ||
206 | |||
207 | if (!result) { | ||
208 | if (cur_min) { | ||
209 | drr_safe_inc(&state[cur_min_devidx].usecount); | ||
210 | result = cur_min; | ||
211 | } else { | ||
212 | result = first; | ||
213 | } | ||
214 | } | ||
215 | |||
216 | *rp = result; | ||
217 | } | ||
218 | |||
219 | static struct ip_mp_alg_ops drr_ops = { | ||
220 | .mp_alg_select_route = drr_select_route, | ||
221 | }; | ||
222 | |||
223 | static int __init drr_init(void) | ||
224 | { | ||
225 | int err = register_netdevice_notifier(&drr_dev_notifier); | ||
226 | |||
227 | if (err) | ||
228 | return err; | ||
229 | |||
230 | err = multipath_alg_register(&drr_ops, IP_MP_ALG_DRR); | ||
231 | if (err) | ||
232 | goto fail; | ||
233 | |||
234 | return 0; | ||
235 | |||
236 | fail: | ||
237 | unregister_netdevice_notifier(&drr_dev_notifier); | ||
238 | return err; | ||
239 | } | ||
240 | |||
241 | static void __exit drr_exit(void) | ||
242 | { | ||
243 | unregister_netdevice_notifier(&drr_dev_notifier); | ||
244 | multipath_alg_unregister(&drr_ops, IP_MP_ALG_DRR); | ||
245 | } | ||
246 | |||
247 | module_init(drr_init); | ||
248 | module_exit(drr_exit); | ||
249 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/ipv4/multipath_random.c b/net/ipv4/multipath_random.c deleted file mode 100644 index c312785d14d0..000000000000 --- a/net/ipv4/multipath_random.c +++ /dev/null | |||
@@ -1,114 +0,0 @@ | |||
1 | /* | ||
2 | * Random policy for multipath. | ||
3 | * | ||
4 | * | ||
5 | * Version: $Id: multipath_random.c,v 1.1.2.3 2004/09/21 08:42:11 elueck Exp $ | ||
6 | * | ||
7 | * Authors: Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * as published by the Free Software Foundation; either version | ||
12 | * 2 of the License, or (at your option) any later version. | ||
13 | */ | ||
14 | |||
15 | #include <asm/system.h> | ||
16 | #include <asm/uaccess.h> | ||
17 | #include <linux/types.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/timer.h> | ||
20 | #include <linux/mm.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/fcntl.h> | ||
23 | #include <linux/stat.h> | ||
24 | #include <linux/socket.h> | ||
25 | #include <linux/in.h> | ||
26 | #include <linux/inet.h> | ||
27 | #include <linux/netdevice.h> | ||
28 | #include <linux/inetdevice.h> | ||
29 | #include <linux/igmp.h> | ||
30 | #include <linux/proc_fs.h> | ||
31 | #include <linux/seq_file.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/mroute.h> | ||
34 | #include <linux/init.h> | ||
35 | #include <linux/random.h> | ||
36 | #include <net/ip.h> | ||
37 | #include <net/protocol.h> | ||
38 | #include <linux/skbuff.h> | ||
39 | #include <net/sock.h> | ||
40 | #include <net/icmp.h> | ||
41 | #include <net/udp.h> | ||
42 | #include <net/raw.h> | ||
43 | #include <linux/notifier.h> | ||
44 | #include <linux/if_arp.h> | ||
45 | #include <linux/netfilter_ipv4.h> | ||
46 | #include <net/ipip.h> | ||
47 | #include <net/checksum.h> | ||
48 | #include <net/ip_mp_alg.h> | ||
49 | |||
50 | #define MULTIPATH_MAX_CANDIDATES 40 | ||
51 | |||
52 | static void random_select_route(const struct flowi *flp, | ||
53 | struct rtable *first, | ||
54 | struct rtable **rp) | ||
55 | { | ||
56 | struct rtable *rt; | ||
57 | struct rtable *decision; | ||
58 | unsigned char candidate_count = 0; | ||
59 | |||
60 | /* count all candidate */ | ||
61 | for (rt = rcu_dereference(first); rt; | ||
62 | rt = rcu_dereference(rt->u.dst.rt_next)) { | ||
63 | if ((rt->u.dst.flags & DST_BALANCED) != 0 && | ||
64 | multipath_comparekeys(&rt->fl, flp)) | ||
65 | ++candidate_count; | ||
66 | } | ||
67 | |||
68 | /* choose a random candidate */ | ||
69 | decision = first; | ||
70 | if (candidate_count > 1) { | ||
71 | unsigned char i = 0; | ||
72 | unsigned char candidate_no = (unsigned char) | ||
73 | (random32() % candidate_count); | ||
74 | |||
75 | /* find chosen candidate and adjust GC data for all candidates | ||
76 | * to ensure they stay in cache | ||
77 | */ | ||
78 | for (rt = first; rt; rt = rt->u.dst.rt_next) { | ||
79 | if ((rt->u.dst.flags & DST_BALANCED) != 0 && | ||
80 | multipath_comparekeys(&rt->fl, flp)) { | ||
81 | rt->u.dst.lastuse = jiffies; | ||
82 | |||
83 | if (i == candidate_no) | ||
84 | decision = rt; | ||
85 | |||
86 | if (i >= candidate_count) | ||
87 | break; | ||
88 | |||
89 | i++; | ||
90 | } | ||
91 | } | ||
92 | } | ||
93 | |||
94 | decision->u.dst.__use++; | ||
95 | *rp = decision; | ||
96 | } | ||
97 | |||
98 | static struct ip_mp_alg_ops random_ops = { | ||
99 | .mp_alg_select_route = random_select_route, | ||
100 | }; | ||
101 | |||
102 | static int __init random_init(void) | ||
103 | { | ||
104 | return multipath_alg_register(&random_ops, IP_MP_ALG_RANDOM); | ||
105 | } | ||
106 | |||
107 | static void __exit random_exit(void) | ||
108 | { | ||
109 | multipath_alg_unregister(&random_ops, IP_MP_ALG_RANDOM); | ||
110 | } | ||
111 | |||
112 | module_init(random_init); | ||
113 | module_exit(random_exit); | ||
114 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/ipv4/multipath_rr.c b/net/ipv4/multipath_rr.c deleted file mode 100644 index 0ad22524f450..000000000000 --- a/net/ipv4/multipath_rr.c +++ /dev/null | |||
@@ -1,95 +0,0 @@ | |||
1 | /* | ||
2 | * Round robin policy for multipath. | ||
3 | * | ||
4 | * | ||
5 | * Version: $Id: multipath_rr.c,v 1.1.2.2 2004/09/16 07:42:34 elueck Exp $ | ||
6 | * | ||
7 | * Authors: Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * as published by the Free Software Foundation; either version | ||
12 | * 2 of the License, or (at your option) any later version. | ||
13 | */ | ||
14 | |||
15 | #include <asm/system.h> | ||
16 | #include <asm/uaccess.h> | ||
17 | #include <linux/types.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/timer.h> | ||
20 | #include <linux/mm.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/fcntl.h> | ||
23 | #include <linux/stat.h> | ||
24 | #include <linux/socket.h> | ||
25 | #include <linux/in.h> | ||
26 | #include <linux/inet.h> | ||
27 | #include <linux/netdevice.h> | ||
28 | #include <linux/inetdevice.h> | ||
29 | #include <linux/igmp.h> | ||
30 | #include <linux/proc_fs.h> | ||
31 | #include <linux/seq_file.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/mroute.h> | ||
34 | #include <linux/init.h> | ||
35 | #include <net/ip.h> | ||
36 | #include <net/protocol.h> | ||
37 | #include <linux/skbuff.h> | ||
38 | #include <net/sock.h> | ||
39 | #include <net/icmp.h> | ||
40 | #include <net/udp.h> | ||
41 | #include <net/raw.h> | ||
42 | #include <linux/notifier.h> | ||
43 | #include <linux/if_arp.h> | ||
44 | #include <linux/netfilter_ipv4.h> | ||
45 | #include <net/ipip.h> | ||
46 | #include <net/checksum.h> | ||
47 | #include <net/ip_mp_alg.h> | ||
48 | |||
49 | static void rr_select_route(const struct flowi *flp, | ||
50 | struct rtable *first, struct rtable **rp) | ||
51 | { | ||
52 | struct rtable *nh, *result, *min_use_cand = NULL; | ||
53 | int min_use = -1; | ||
54 | |||
55 | /* 1. make sure all alt. nexthops have the same GC related data | ||
56 | * 2. determine the new candidate to be returned | ||
57 | */ | ||
58 | result = NULL; | ||
59 | for (nh = rcu_dereference(first); nh; | ||
60 | nh = rcu_dereference(nh->u.dst.rt_next)) { | ||
61 | if ((nh->u.dst.flags & DST_BALANCED) != 0 && | ||
62 | multipath_comparekeys(&nh->fl, flp)) { | ||
63 | nh->u.dst.lastuse = jiffies; | ||
64 | |||
65 | if (min_use == -1 || nh->u.dst.__use < min_use) { | ||
66 | min_use = nh->u.dst.__use; | ||
67 | min_use_cand = nh; | ||
68 | } | ||
69 | } | ||
70 | } | ||
71 | result = min_use_cand; | ||
72 | if (!result) | ||
73 | result = first; | ||
74 | |||
75 | result->u.dst.__use++; | ||
76 | *rp = result; | ||
77 | } | ||
78 | |||
79 | static struct ip_mp_alg_ops rr_ops = { | ||
80 | .mp_alg_select_route = rr_select_route, | ||
81 | }; | ||
82 | |||
83 | static int __init rr_init(void) | ||
84 | { | ||
85 | return multipath_alg_register(&rr_ops, IP_MP_ALG_RR); | ||
86 | } | ||
87 | |||
88 | static void __exit rr_exit(void) | ||
89 | { | ||
90 | multipath_alg_unregister(&rr_ops, IP_MP_ALG_RR); | ||
91 | } | ||
92 | |||
93 | module_init(rr_init); | ||
94 | module_exit(rr_exit); | ||
95 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/ipv4/multipath_wrandom.c b/net/ipv4/multipath_wrandom.c deleted file mode 100644 index 57c503694539..000000000000 --- a/net/ipv4/multipath_wrandom.c +++ /dev/null | |||
@@ -1,329 +0,0 @@ | |||
1 | /* | ||
2 | * Weighted random policy for multipath. | ||
3 | * | ||
4 | * | ||
5 | * Version: $Id: multipath_wrandom.c,v 1.1.2.3 2004/09/22 07:51:40 elueck Exp $ | ||
6 | * | ||
7 | * Authors: Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * as published by the Free Software Foundation; either version | ||
12 | * 2 of the License, or (at your option) any later version. | ||
13 | */ | ||
14 | |||
15 | #include <asm/system.h> | ||
16 | #include <asm/uaccess.h> | ||
17 | #include <linux/types.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/timer.h> | ||
20 | #include <linux/mm.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/fcntl.h> | ||
23 | #include <linux/stat.h> | ||
24 | #include <linux/socket.h> | ||
25 | #include <linux/in.h> | ||
26 | #include <linux/inet.h> | ||
27 | #include <linux/netdevice.h> | ||
28 | #include <linux/inetdevice.h> | ||
29 | #include <linux/igmp.h> | ||
30 | #include <linux/proc_fs.h> | ||
31 | #include <linux/seq_file.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/mroute.h> | ||
34 | #include <linux/init.h> | ||
35 | #include <linux/random.h> | ||
36 | #include <net/ip.h> | ||
37 | #include <net/protocol.h> | ||
38 | #include <linux/skbuff.h> | ||
39 | #include <net/sock.h> | ||
40 | #include <net/icmp.h> | ||
41 | #include <net/udp.h> | ||
42 | #include <net/raw.h> | ||
43 | #include <linux/notifier.h> | ||
44 | #include <linux/if_arp.h> | ||
45 | #include <linux/netfilter_ipv4.h> | ||
46 | #include <net/ipip.h> | ||
47 | #include <net/checksum.h> | ||
48 | #include <net/ip_fib.h> | ||
49 | #include <net/ip_mp_alg.h> | ||
50 | |||
51 | #define MULTIPATH_STATE_SIZE 15 | ||
52 | |||
53 | struct multipath_candidate { | ||
54 | struct multipath_candidate *next; | ||
55 | int power; | ||
56 | struct rtable *rt; | ||
57 | }; | ||
58 | |||
59 | struct multipath_dest { | ||
60 | struct list_head list; | ||
61 | |||
62 | const struct fib_nh *nh_info; | ||
63 | __be32 netmask; | ||
64 | __be32 network; | ||
65 | unsigned char prefixlen; | ||
66 | |||
67 | struct rcu_head rcu; | ||
68 | }; | ||
69 | |||
70 | struct multipath_bucket { | ||
71 | struct list_head head; | ||
72 | spinlock_t lock; | ||
73 | }; | ||
74 | |||
75 | struct multipath_route { | ||
76 | struct list_head list; | ||
77 | |||
78 | int oif; | ||
79 | __be32 gw; | ||
80 | struct list_head dests; | ||
81 | |||
82 | struct rcu_head rcu; | ||
83 | }; | ||
84 | |||
85 | /* state: primarily weight per route information */ | ||
86 | static struct multipath_bucket state[MULTIPATH_STATE_SIZE]; | ||
87 | |||
88 | static unsigned char __multipath_lookup_weight(const struct flowi *fl, | ||
89 | const struct rtable *rt) | ||
90 | { | ||
91 | const int state_idx = rt->idev->dev->ifindex % MULTIPATH_STATE_SIZE; | ||
92 | struct multipath_route *r; | ||
93 | struct multipath_route *target_route = NULL; | ||
94 | struct multipath_dest *d; | ||
95 | int weight = 1; | ||
96 | |||
97 | /* lookup the weight information for a certain route */ | ||
98 | rcu_read_lock(); | ||
99 | |||
100 | /* find state entry for gateway or add one if necessary */ | ||
101 | list_for_each_entry_rcu(r, &state[state_idx].head, list) { | ||
102 | if (r->gw == rt->rt_gateway && | ||
103 | r->oif == rt->idev->dev->ifindex) { | ||
104 | target_route = r; | ||
105 | break; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | if (!target_route) { | ||
110 | /* this should not happen... but we are prepared */ | ||
111 | printk( KERN_CRIT"%s: missing state for gateway: %u and " \ | ||
112 | "device %d\n", __FUNCTION__, rt->rt_gateway, | ||
113 | rt->idev->dev->ifindex); | ||
114 | goto out; | ||
115 | } | ||
116 | |||
117 | /* find state entry for destination */ | ||
118 | list_for_each_entry_rcu(d, &target_route->dests, list) { | ||
119 | __be32 targetnetwork = fl->fl4_dst & | ||
120 | inet_make_mask(d->prefixlen); | ||
121 | |||
122 | if ((targetnetwork & d->netmask) == d->network) { | ||
123 | weight = d->nh_info->nh_weight; | ||
124 | goto out; | ||
125 | } | ||
126 | } | ||
127 | |||
128 | out: | ||
129 | rcu_read_unlock(); | ||
130 | return weight; | ||
131 | } | ||
132 | |||
133 | static void wrandom_init_state(void) | ||
134 | { | ||
135 | int i; | ||
136 | |||
137 | for (i = 0; i < MULTIPATH_STATE_SIZE; ++i) { | ||
138 | INIT_LIST_HEAD(&state[i].head); | ||
139 | spin_lock_init(&state[i].lock); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | static void wrandom_select_route(const struct flowi *flp, | ||
144 | struct rtable *first, | ||
145 | struct rtable **rp) | ||
146 | { | ||
147 | struct rtable *rt; | ||
148 | struct rtable *decision; | ||
149 | struct multipath_candidate *first_mpc = NULL; | ||
150 | struct multipath_candidate *mpc, *last_mpc = NULL; | ||
151 | int power = 0; | ||
152 | int last_power; | ||
153 | int selector; | ||
154 | const size_t size_mpc = sizeof(struct multipath_candidate); | ||
155 | |||
156 | /* collect all candidates and identify their weights */ | ||
157 | for (rt = rcu_dereference(first); rt; | ||
158 | rt = rcu_dereference(rt->u.dst.rt_next)) { | ||
159 | if ((rt->u.dst.flags & DST_BALANCED) != 0 && | ||
160 | multipath_comparekeys(&rt->fl, flp)) { | ||
161 | struct multipath_candidate* mpc = | ||
162 | (struct multipath_candidate*) | ||
163 | kmalloc(size_mpc, GFP_ATOMIC); | ||
164 | |||
165 | if (!mpc) | ||
166 | return; | ||
167 | |||
168 | power += __multipath_lookup_weight(flp, rt) * 10000; | ||
169 | |||
170 | mpc->power = power; | ||
171 | mpc->rt = rt; | ||
172 | mpc->next = NULL; | ||
173 | |||
174 | if (!first_mpc) | ||
175 | first_mpc = mpc; | ||
176 | else | ||
177 | last_mpc->next = mpc; | ||
178 | |||
179 | last_mpc = mpc; | ||
180 | } | ||
181 | } | ||
182 | |||
183 | /* choose a weighted random candidate */ | ||
184 | decision = first; | ||
185 | selector = random32() % power; | ||
186 | last_power = 0; | ||
187 | |||
188 | /* select candidate, adjust GC data and cleanup local state */ | ||
189 | decision = first; | ||
190 | last_mpc = NULL; | ||
191 | for (mpc = first_mpc; mpc; mpc = mpc->next) { | ||
192 | mpc->rt->u.dst.lastuse = jiffies; | ||
193 | if (last_power <= selector && selector < mpc->power) | ||
194 | decision = mpc->rt; | ||
195 | |||
196 | last_power = mpc->power; | ||
197 | kfree(last_mpc); | ||
198 | last_mpc = mpc; | ||
199 | } | ||
200 | |||
201 | /* concurrent __multipath_flush may lead to !last_mpc */ | ||
202 | kfree(last_mpc); | ||
203 | |||
204 | decision->u.dst.__use++; | ||
205 | *rp = decision; | ||
206 | } | ||
207 | |||
208 | static void wrandom_set_nhinfo(__be32 network, | ||
209 | __be32 netmask, | ||
210 | unsigned char prefixlen, | ||
211 | const struct fib_nh *nh) | ||
212 | { | ||
213 | const int state_idx = nh->nh_oif % MULTIPATH_STATE_SIZE; | ||
214 | struct multipath_route *r, *target_route = NULL; | ||
215 | struct multipath_dest *d, *target_dest = NULL; | ||
216 | |||
217 | /* store the weight information for a certain route */ | ||
218 | spin_lock_bh(&state[state_idx].lock); | ||
219 | |||
220 | /* find state entry for gateway or add one if necessary */ | ||
221 | list_for_each_entry_rcu(r, &state[state_idx].head, list) { | ||
222 | if (r->gw == nh->nh_gw && r->oif == nh->nh_oif) { | ||
223 | target_route = r; | ||
224 | break; | ||
225 | } | ||
226 | } | ||
227 | |||
228 | if (!target_route) { | ||
229 | const size_t size_rt = sizeof(struct multipath_route); | ||
230 | target_route = (struct multipath_route *) | ||
231 | kmalloc(size_rt, GFP_ATOMIC); | ||
232 | |||
233 | target_route->gw = nh->nh_gw; | ||
234 | target_route->oif = nh->nh_oif; | ||
235 | memset(&target_route->rcu, 0, sizeof(struct rcu_head)); | ||
236 | INIT_LIST_HEAD(&target_route->dests); | ||
237 | |||
238 | list_add_rcu(&target_route->list, &state[state_idx].head); | ||
239 | } | ||
240 | |||
241 | /* find state entry for destination or add one if necessary */ | ||
242 | list_for_each_entry_rcu(d, &target_route->dests, list) { | ||
243 | if (d->nh_info == nh) { | ||
244 | target_dest = d; | ||
245 | break; | ||
246 | } | ||
247 | } | ||
248 | |||
249 | if (!target_dest) { | ||
250 | const size_t size_dst = sizeof(struct multipath_dest); | ||
251 | target_dest = (struct multipath_dest*) | ||
252 | kmalloc(size_dst, GFP_ATOMIC); | ||
253 | |||
254 | target_dest->nh_info = nh; | ||
255 | target_dest->network = network; | ||
256 | target_dest->netmask = netmask; | ||
257 | target_dest->prefixlen = prefixlen; | ||
258 | memset(&target_dest->rcu, 0, sizeof(struct rcu_head)); | ||
259 | |||
260 | list_add_rcu(&target_dest->list, &target_route->dests); | ||
261 | } | ||
262 | /* else: we already stored this info for another destination => | ||
263 | * we are finished | ||
264 | */ | ||
265 | |||
266 | spin_unlock_bh(&state[state_idx].lock); | ||
267 | } | ||
268 | |||
269 | static void __multipath_free(struct rcu_head *head) | ||
270 | { | ||
271 | struct multipath_route *rt = container_of(head, struct multipath_route, | ||
272 | rcu); | ||
273 | kfree(rt); | ||
274 | } | ||
275 | |||
276 | static void __multipath_free_dst(struct rcu_head *head) | ||
277 | { | ||
278 | struct multipath_dest *dst = container_of(head, | ||
279 | struct multipath_dest, | ||
280 | rcu); | ||
281 | kfree(dst); | ||
282 | } | ||
283 | |||
284 | static void wrandom_flush(void) | ||
285 | { | ||
286 | int i; | ||
287 | |||
288 | /* defere delete to all entries */ | ||
289 | for (i = 0; i < MULTIPATH_STATE_SIZE; ++i) { | ||
290 | struct multipath_route *r; | ||
291 | |||
292 | spin_lock_bh(&state[i].lock); | ||
293 | list_for_each_entry_rcu(r, &state[i].head, list) { | ||
294 | struct multipath_dest *d; | ||
295 | list_for_each_entry_rcu(d, &r->dests, list) { | ||
296 | list_del_rcu(&d->list); | ||
297 | call_rcu(&d->rcu, | ||
298 | __multipath_free_dst); | ||
299 | } | ||
300 | list_del_rcu(&r->list); | ||
301 | call_rcu(&r->rcu, | ||
302 | __multipath_free); | ||
303 | } | ||
304 | |||
305 | spin_unlock_bh(&state[i].lock); | ||
306 | } | ||
307 | } | ||
308 | |||
309 | static struct ip_mp_alg_ops wrandom_ops = { | ||
310 | .mp_alg_select_route = wrandom_select_route, | ||
311 | .mp_alg_flush = wrandom_flush, | ||
312 | .mp_alg_set_nhinfo = wrandom_set_nhinfo, | ||
313 | }; | ||
314 | |||
315 | static int __init wrandom_init(void) | ||
316 | { | ||
317 | wrandom_init_state(); | ||
318 | |||
319 | return multipath_alg_register(&wrandom_ops, IP_MP_ALG_WRANDOM); | ||
320 | } | ||
321 | |||
322 | static void __exit wrandom_exit(void) | ||
323 | { | ||
324 | multipath_alg_unregister(&wrandom_ops, IP_MP_ALG_WRANDOM); | ||
325 | } | ||
326 | |||
327 | module_init(wrandom_init); | ||
328 | module_exit(wrandom_exit); | ||
329 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 46509fae9fd8..fa97947c6ae1 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
@@ -230,7 +230,7 @@ config IP_NF_TARGET_NETMAP | |||
230 | To compile it as a module, choose M here. If unsure, say N. | 230 | To compile it as a module, choose M here. If unsure, say N. |
231 | 231 | ||
232 | config IP_NF_TARGET_SAME | 232 | config IP_NF_TARGET_SAME |
233 | tristate "SAME target support" | 233 | tristate "SAME target support (OBSOLETE)" |
234 | depends on NF_NAT | 234 | depends on NF_NAT |
235 | help | 235 | help |
236 | This option adds a `SAME' target, which works like the standard SNAT | 236 | This option adds a `SAME' target, which works like the standard SNAT |
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index cae41215e3c7..d1149aba9351 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -224,7 +224,7 @@ unsigned int arpt_do_table(struct sk_buff **pskb, | |||
224 | static const char nulldevname[IFNAMSIZ]; | 224 | static const char nulldevname[IFNAMSIZ]; |
225 | unsigned int verdict = NF_DROP; | 225 | unsigned int verdict = NF_DROP; |
226 | struct arphdr *arp; | 226 | struct arphdr *arp; |
227 | int hotdrop = 0; | 227 | bool hotdrop = false; |
228 | struct arpt_entry *e, *back; | 228 | struct arpt_entry *e, *back; |
229 | const char *indev, *outdev; | 229 | const char *indev, *outdev; |
230 | void *table_base; | 230 | void *table_base; |
@@ -1140,13 +1140,13 @@ void arpt_unregister_table(struct arpt_table *table) | |||
1140 | } | 1140 | } |
1141 | 1141 | ||
1142 | /* The built-in targets: standard (NULL) and error. */ | 1142 | /* The built-in targets: standard (NULL) and error. */ |
1143 | static struct arpt_target arpt_standard_target = { | 1143 | static struct arpt_target arpt_standard_target __read_mostly = { |
1144 | .name = ARPT_STANDARD_TARGET, | 1144 | .name = ARPT_STANDARD_TARGET, |
1145 | .targetsize = sizeof(int), | 1145 | .targetsize = sizeof(int), |
1146 | .family = NF_ARP, | 1146 | .family = NF_ARP, |
1147 | }; | 1147 | }; |
1148 | 1148 | ||
1149 | static struct arpt_target arpt_error_target = { | 1149 | static struct arpt_target arpt_error_target __read_mostly = { |
1150 | .name = ARPT_ERROR_TARGET, | 1150 | .name = ARPT_ERROR_TARGET, |
1151 | .target = arpt_error, | 1151 | .target = arpt_error, |
1152 | .targetsize = ARPT_FUNCTION_MAXNAMELEN, | 1152 | .targetsize = ARPT_FUNCTION_MAXNAMELEN, |
@@ -1184,7 +1184,7 @@ static int __init arp_tables_init(void) | |||
1184 | if (ret < 0) | 1184 | if (ret < 0) |
1185 | goto err4; | 1185 | goto err4; |
1186 | 1186 | ||
1187 | printk("arp_tables: (C) 2002 David S. Miller\n"); | 1187 | printk(KERN_INFO "arp_tables: (C) 2002 David S. Miller\n"); |
1188 | return 0; | 1188 | return 0; |
1189 | 1189 | ||
1190 | err4: | 1190 | err4: |
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c index 6298d404e7c7..c4bdab47597f 100644 --- a/net/ipv4/netfilter/arpt_mangle.c +++ b/net/ipv4/netfilter/arpt_mangle.c | |||
@@ -65,7 +65,7 @@ target(struct sk_buff **pskb, | |||
65 | return mangle->target; | 65 | return mangle->target; |
66 | } | 66 | } |
67 | 67 | ||
68 | static int | 68 | static bool |
69 | checkentry(const char *tablename, const void *e, const struct xt_target *target, | 69 | checkentry(const char *tablename, const void *e, const struct xt_target *target, |
70 | void *targinfo, unsigned int hook_mask) | 70 | void *targinfo, unsigned int hook_mask) |
71 | { | 71 | { |
@@ -73,15 +73,15 @@ checkentry(const char *tablename, const void *e, const struct xt_target *target, | |||
73 | 73 | ||
74 | if (mangle->flags & ~ARPT_MANGLE_MASK || | 74 | if (mangle->flags & ~ARPT_MANGLE_MASK || |
75 | !(mangle->flags & ARPT_MANGLE_MASK)) | 75 | !(mangle->flags & ARPT_MANGLE_MASK)) |
76 | return 0; | 76 | return false; |
77 | 77 | ||
78 | if (mangle->target != NF_DROP && mangle->target != NF_ACCEPT && | 78 | if (mangle->target != NF_DROP && mangle->target != NF_ACCEPT && |
79 | mangle->target != ARPT_CONTINUE) | 79 | mangle->target != ARPT_CONTINUE) |
80 | return 0; | 80 | return false; |
81 | return 1; | 81 | return true; |
82 | } | 82 | } |
83 | 83 | ||
84 | static struct arpt_target arpt_mangle_reg = { | 84 | static struct arpt_target arpt_mangle_reg __read_mostly = { |
85 | .name = "mangle", | 85 | .name = "mangle", |
86 | .target = target, | 86 | .target = target, |
87 | .targetsize = sizeof(struct arpt_mangle), | 87 | .targetsize = sizeof(struct arpt_mangle), |
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 9bacf1a03630..e1b402c6b855 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
@@ -152,20 +152,20 @@ ip_packet_match(const struct iphdr *ip, | |||
152 | return 1; | 152 | return 1; |
153 | } | 153 | } |
154 | 154 | ||
155 | static inline int | 155 | static inline bool |
156 | ip_checkentry(const struct ipt_ip *ip) | 156 | ip_checkentry(const struct ipt_ip *ip) |
157 | { | 157 | { |
158 | if (ip->flags & ~IPT_F_MASK) { | 158 | if (ip->flags & ~IPT_F_MASK) { |
159 | duprintf("Unknown flag bits set: %08X\n", | 159 | duprintf("Unknown flag bits set: %08X\n", |
160 | ip->flags & ~IPT_F_MASK); | 160 | ip->flags & ~IPT_F_MASK); |
161 | return 0; | 161 | return false; |
162 | } | 162 | } |
163 | if (ip->invflags & ~IPT_INV_MASK) { | 163 | if (ip->invflags & ~IPT_INV_MASK) { |
164 | duprintf("Unknown invflag bits set: %08X\n", | 164 | duprintf("Unknown invflag bits set: %08X\n", |
165 | ip->invflags & ~IPT_INV_MASK); | 165 | ip->invflags & ~IPT_INV_MASK); |
166 | return 0; | 166 | return false; |
167 | } | 167 | } |
168 | return 1; | 168 | return true; |
169 | } | 169 | } |
170 | 170 | ||
171 | static unsigned int | 171 | static unsigned int |
@@ -183,19 +183,19 @@ ipt_error(struct sk_buff **pskb, | |||
183 | } | 183 | } |
184 | 184 | ||
185 | static inline | 185 | static inline |
186 | int do_match(struct ipt_entry_match *m, | 186 | bool do_match(struct ipt_entry_match *m, |
187 | const struct sk_buff *skb, | 187 | const struct sk_buff *skb, |
188 | const struct net_device *in, | 188 | const struct net_device *in, |
189 | const struct net_device *out, | 189 | const struct net_device *out, |
190 | int offset, | 190 | int offset, |
191 | int *hotdrop) | 191 | bool *hotdrop) |
192 | { | 192 | { |
193 | /* Stop iteration if it doesn't match */ | 193 | /* Stop iteration if it doesn't match */ |
194 | if (!m->u.kernel.match->match(skb, in, out, m->u.kernel.match, m->data, | 194 | if (!m->u.kernel.match->match(skb, in, out, m->u.kernel.match, m->data, |
195 | offset, ip_hdrlen(skb), hotdrop)) | 195 | offset, ip_hdrlen(skb), hotdrop)) |
196 | return 1; | 196 | return true; |
197 | else | 197 | else |
198 | return 0; | 198 | return false; |
199 | } | 199 | } |
200 | 200 | ||
201 | static inline struct ipt_entry * | 201 | static inline struct ipt_entry * |
@@ -204,6 +204,112 @@ get_entry(void *base, unsigned int offset) | |||
204 | return (struct ipt_entry *)(base + offset); | 204 | return (struct ipt_entry *)(base + offset); |
205 | } | 205 | } |
206 | 206 | ||
207 | /* All zeroes == unconditional rule. */ | ||
208 | static inline int | ||
209 | unconditional(const struct ipt_ip *ip) | ||
210 | { | ||
211 | unsigned int i; | ||
212 | |||
213 | for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++) | ||
214 | if (((__u32 *)ip)[i]) | ||
215 | return 0; | ||
216 | |||
217 | return 1; | ||
218 | } | ||
219 | |||
220 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||
221 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | ||
222 | static const char *hooknames[] = { | ||
223 | [NF_IP_PRE_ROUTING] = "PREROUTING", | ||
224 | [NF_IP_LOCAL_IN] = "INPUT", | ||
225 | [NF_IP_FORWARD] = "FORWARD", | ||
226 | [NF_IP_LOCAL_OUT] = "OUTPUT", | ||
227 | [NF_IP_POST_ROUTING] = "POSTROUTING", | ||
228 | }; | ||
229 | |||
230 | enum nf_ip_trace_comments { | ||
231 | NF_IP_TRACE_COMMENT_RULE, | ||
232 | NF_IP_TRACE_COMMENT_RETURN, | ||
233 | NF_IP_TRACE_COMMENT_POLICY, | ||
234 | }; | ||
235 | |||
236 | static const char *comments[] = { | ||
237 | [NF_IP_TRACE_COMMENT_RULE] = "rule", | ||
238 | [NF_IP_TRACE_COMMENT_RETURN] = "return", | ||
239 | [NF_IP_TRACE_COMMENT_POLICY] = "policy", | ||
240 | }; | ||
241 | |||
242 | static struct nf_loginfo trace_loginfo = { | ||
243 | .type = NF_LOG_TYPE_LOG, | ||
244 | .u = { | ||
245 | .log = { | ||
246 | .level = 4, | ||
247 | .logflags = NF_LOG_MASK, | ||
248 | }, | ||
249 | }, | ||
250 | }; | ||
251 | |||
252 | static inline int | ||
253 | get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e, | ||
254 | char *hookname, char **chainname, | ||
255 | char **comment, unsigned int *rulenum) | ||
256 | { | ||
257 | struct ipt_standard_target *t = (void *)ipt_get_target(s); | ||
258 | |||
259 | if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) { | ||
260 | /* Head of user chain: ERROR target with chainname */ | ||
261 | *chainname = t->target.data; | ||
262 | (*rulenum) = 0; | ||
263 | } else if (s == e) { | ||
264 | (*rulenum)++; | ||
265 | |||
266 | if (s->target_offset == sizeof(struct ipt_entry) | ||
267 | && strcmp(t->target.u.kernel.target->name, | ||
268 | IPT_STANDARD_TARGET) == 0 | ||
269 | && t->verdict < 0 | ||
270 | && unconditional(&s->ip)) { | ||
271 | /* Tail of chains: STANDARD target (return/policy) */ | ||
272 | *comment = *chainname == hookname | ||
273 | ? (char *)comments[NF_IP_TRACE_COMMENT_POLICY] | ||
274 | : (char *)comments[NF_IP_TRACE_COMMENT_RETURN]; | ||
275 | } | ||
276 | return 1; | ||
277 | } else | ||
278 | (*rulenum)++; | ||
279 | |||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static void trace_packet(struct sk_buff *skb, | ||
284 | unsigned int hook, | ||
285 | const struct net_device *in, | ||
286 | const struct net_device *out, | ||
287 | char *tablename, | ||
288 | struct xt_table_info *private, | ||
289 | struct ipt_entry *e) | ||
290 | { | ||
291 | void *table_base; | ||
292 | struct ipt_entry *root; | ||
293 | char *hookname, *chainname, *comment; | ||
294 | unsigned int rulenum = 0; | ||
295 | |||
296 | table_base = (void *)private->entries[smp_processor_id()]; | ||
297 | root = get_entry(table_base, private->hook_entry[hook]); | ||
298 | |||
299 | hookname = chainname = (char *)hooknames[hook]; | ||
300 | comment = (char *)comments[NF_IP_TRACE_COMMENT_RULE]; | ||
301 | |||
302 | IPT_ENTRY_ITERATE(root, | ||
303 | private->size - private->hook_entry[hook], | ||
304 | get_chainname_rulenum, | ||
305 | e, hookname, &chainname, &comment, &rulenum); | ||
306 | |||
307 | nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo, | ||
308 | "TRACE: %s:%s:%s:%u ", | ||
309 | tablename, chainname, comment, rulenum); | ||
310 | } | ||
311 | #endif | ||
312 | |||
207 | /* Returns one of the generic firewall policies, like NF_ACCEPT. */ | 313 | /* Returns one of the generic firewall policies, like NF_ACCEPT. */ |
208 | unsigned int | 314 | unsigned int |
209 | ipt_do_table(struct sk_buff **pskb, | 315 | ipt_do_table(struct sk_buff **pskb, |
@@ -216,7 +322,7 @@ ipt_do_table(struct sk_buff **pskb, | |||
216 | u_int16_t offset; | 322 | u_int16_t offset; |
217 | struct iphdr *ip; | 323 | struct iphdr *ip; |
218 | u_int16_t datalen; | 324 | u_int16_t datalen; |
219 | int hotdrop = 0; | 325 | bool hotdrop = false; |
220 | /* Initializing verdict to NF_DROP keeps gcc happy. */ | 326 | /* Initializing verdict to NF_DROP keeps gcc happy. */ |
221 | unsigned int verdict = NF_DROP; | 327 | unsigned int verdict = NF_DROP; |
222 | const char *indev, *outdev; | 328 | const char *indev, *outdev; |
@@ -261,6 +367,14 @@ ipt_do_table(struct sk_buff **pskb, | |||
261 | 367 | ||
262 | t = ipt_get_target(e); | 368 | t = ipt_get_target(e); |
263 | IP_NF_ASSERT(t->u.kernel.target); | 369 | IP_NF_ASSERT(t->u.kernel.target); |
370 | |||
371 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||
372 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | ||
373 | /* The packet is traced: log it */ | ||
374 | if (unlikely((*pskb)->nf_trace)) | ||
375 | trace_packet(*pskb, hook, in, out, | ||
376 | table->name, private, e); | ||
377 | #endif | ||
264 | /* Standard target? */ | 378 | /* Standard target? */ |
265 | if (!t->u.kernel.target->target) { | 379 | if (!t->u.kernel.target->target) { |
266 | int v; | 380 | int v; |
@@ -341,19 +455,6 @@ ipt_do_table(struct sk_buff **pskb, | |||
341 | #endif | 455 | #endif |
342 | } | 456 | } |
343 | 457 | ||
344 | /* All zeroes == unconditional rule. */ | ||
345 | static inline int | ||
346 | unconditional(const struct ipt_ip *ip) | ||
347 | { | ||
348 | unsigned int i; | ||
349 | |||
350 | for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++) | ||
351 | if (((__u32 *)ip)[i]) | ||
352 | return 0; | ||
353 | |||
354 | return 1; | ||
355 | } | ||
356 | |||
357 | /* Figures out from what hook each rule can be called: returns 0 if | 458 | /* Figures out from what hook each rule can be called: returns 0 if |
358 | there are loops. Puts hook bitmask in comefrom. */ | 459 | there are loops. Puts hook bitmask in comefrom. */ |
359 | static int | 460 | static int |
@@ -2105,16 +2206,16 @@ void ipt_unregister_table(struct xt_table *table) | |||
2105 | } | 2206 | } |
2106 | 2207 | ||
2107 | /* Returns 1 if the type and code is matched by the range, 0 otherwise */ | 2208 | /* Returns 1 if the type and code is matched by the range, 0 otherwise */ |
2108 | static inline int | 2209 | static inline bool |
2109 | icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code, | 2210 | icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code, |
2110 | u_int8_t type, u_int8_t code, | 2211 | u_int8_t type, u_int8_t code, |
2111 | int invert) | 2212 | bool invert) |
2112 | { | 2213 | { |
2113 | return ((test_type == 0xFF) || (type == test_type && code >= min_code && code <= max_code)) | 2214 | return ((test_type == 0xFF) || (type == test_type && code >= min_code && code <= max_code)) |
2114 | ^ invert; | 2215 | ^ invert; |
2115 | } | 2216 | } |
2116 | 2217 | ||
2117 | static int | 2218 | static bool |
2118 | icmp_match(const struct sk_buff *skb, | 2219 | icmp_match(const struct sk_buff *skb, |
2119 | const struct net_device *in, | 2220 | const struct net_device *in, |
2120 | const struct net_device *out, | 2221 | const struct net_device *out, |
@@ -2122,14 +2223,14 @@ icmp_match(const struct sk_buff *skb, | |||
2122 | const void *matchinfo, | 2223 | const void *matchinfo, |
2123 | int offset, | 2224 | int offset, |
2124 | unsigned int protoff, | 2225 | unsigned int protoff, |
2125 | int *hotdrop) | 2226 | bool *hotdrop) |
2126 | { | 2227 | { |
2127 | struct icmphdr _icmph, *ic; | 2228 | struct icmphdr _icmph, *ic; |
2128 | const struct ipt_icmp *icmpinfo = matchinfo; | 2229 | const struct ipt_icmp *icmpinfo = matchinfo; |
2129 | 2230 | ||
2130 | /* Must not be a fragment. */ | 2231 | /* Must not be a fragment. */ |
2131 | if (offset) | 2232 | if (offset) |
2132 | return 0; | 2233 | return false; |
2133 | 2234 | ||
2134 | ic = skb_header_pointer(skb, protoff, sizeof(_icmph), &_icmph); | 2235 | ic = skb_header_pointer(skb, protoff, sizeof(_icmph), &_icmph); |
2135 | if (ic == NULL) { | 2236 | if (ic == NULL) { |
@@ -2137,8 +2238,8 @@ icmp_match(const struct sk_buff *skb, | |||
2137 | * can't. Hence, no choice but to drop. | 2238 | * can't. Hence, no choice but to drop. |
2138 | */ | 2239 | */ |
2139 | duprintf("Dropping evil ICMP tinygram.\n"); | 2240 | duprintf("Dropping evil ICMP tinygram.\n"); |
2140 | *hotdrop = 1; | 2241 | *hotdrop = true; |
2141 | return 0; | 2242 | return false; |
2142 | } | 2243 | } |
2143 | 2244 | ||
2144 | return icmp_type_code_match(icmpinfo->type, | 2245 | return icmp_type_code_match(icmpinfo->type, |
@@ -2149,7 +2250,7 @@ icmp_match(const struct sk_buff *skb, | |||
2149 | } | 2250 | } |
2150 | 2251 | ||
2151 | /* Called when user tries to insert an entry of this type. */ | 2252 | /* Called when user tries to insert an entry of this type. */ |
2152 | static int | 2253 | static bool |
2153 | icmp_checkentry(const char *tablename, | 2254 | icmp_checkentry(const char *tablename, |
2154 | const void *info, | 2255 | const void *info, |
2155 | const struct xt_match *match, | 2256 | const struct xt_match *match, |
@@ -2163,7 +2264,7 @@ icmp_checkentry(const char *tablename, | |||
2163 | } | 2264 | } |
2164 | 2265 | ||
2165 | /* The built-in targets: standard (NULL) and error. */ | 2266 | /* The built-in targets: standard (NULL) and error. */ |
2166 | static struct xt_target ipt_standard_target = { | 2267 | static struct xt_target ipt_standard_target __read_mostly = { |
2167 | .name = IPT_STANDARD_TARGET, | 2268 | .name = IPT_STANDARD_TARGET, |
2168 | .targetsize = sizeof(int), | 2269 | .targetsize = sizeof(int), |
2169 | .family = AF_INET, | 2270 | .family = AF_INET, |
@@ -2174,7 +2275,7 @@ static struct xt_target ipt_standard_target = { | |||
2174 | #endif | 2275 | #endif |
2175 | }; | 2276 | }; |
2176 | 2277 | ||
2177 | static struct xt_target ipt_error_target = { | 2278 | static struct xt_target ipt_error_target __read_mostly = { |
2178 | .name = IPT_ERROR_TARGET, | 2279 | .name = IPT_ERROR_TARGET, |
2179 | .target = ipt_error, | 2280 | .target = ipt_error, |
2180 | .targetsize = IPT_FUNCTION_MAXNAMELEN, | 2281 | .targetsize = IPT_FUNCTION_MAXNAMELEN, |
@@ -2197,7 +2298,7 @@ static struct nf_sockopt_ops ipt_sockopts = { | |||
2197 | #endif | 2298 | #endif |
2198 | }; | 2299 | }; |
2199 | 2300 | ||
2200 | static struct xt_match icmp_matchstruct = { | 2301 | static struct xt_match icmp_matchstruct __read_mostly = { |
2201 | .name = "icmp", | 2302 | .name = "icmp", |
2202 | .match = icmp_match, | 2303 | .match = icmp_match, |
2203 | .matchsize = sizeof(struct ipt_icmp), | 2304 | .matchsize = sizeof(struct ipt_icmp), |
@@ -2230,7 +2331,7 @@ static int __init ip_tables_init(void) | |||
2230 | if (ret < 0) | 2331 | if (ret < 0) |
2231 | goto err5; | 2332 | goto err5; |
2232 | 2333 | ||
2233 | printk("ip_tables: (C) 2000-2006 Netfilter Core Team\n"); | 2334 | printk(KERN_INFO "ip_tables: (C) 2000-2006 Netfilter Core Team\n"); |
2234 | return 0; | 2335 | return 0; |
2235 | 2336 | ||
2236 | err5: | 2337 | err5: |
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 40e273421398..dcc12b183474 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c | |||
@@ -30,14 +30,6 @@ | |||
30 | 30 | ||
31 | #define CLUSTERIP_VERSION "0.8" | 31 | #define CLUSTERIP_VERSION "0.8" |
32 | 32 | ||
33 | #define DEBUG_CLUSTERIP | ||
34 | |||
35 | #ifdef DEBUG_CLUSTERIP | ||
36 | #define DEBUGP printk | ||
37 | #else | ||
38 | #define DEBUGP | ||
39 | #endif | ||
40 | |||
41 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
42 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | 34 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); |
43 | MODULE_DESCRIPTION("iptables target for CLUSTERIP"); | 35 | MODULE_DESCRIPTION("iptables target for CLUSTERIP"); |
@@ -122,9 +114,8 @@ __clusterip_config_find(__be32 clusterip) | |||
122 | list_for_each(pos, &clusterip_configs) { | 114 | list_for_each(pos, &clusterip_configs) { |
123 | struct clusterip_config *c = list_entry(pos, | 115 | struct clusterip_config *c = list_entry(pos, |
124 | struct clusterip_config, list); | 116 | struct clusterip_config, list); |
125 | if (c->clusterip == clusterip) { | 117 | if (c->clusterip == clusterip) |
126 | return c; | 118 | return c; |
127 | } | ||
128 | } | 119 | } |
129 | 120 | ||
130 | return NULL; | 121 | return NULL; |
@@ -155,9 +146,8 @@ clusterip_config_init_nodelist(struct clusterip_config *c, | |||
155 | { | 146 | { |
156 | int n; | 147 | int n; |
157 | 148 | ||
158 | for (n = 0; n < i->num_local_nodes; n++) { | 149 | for (n = 0; n < i->num_local_nodes; n++) |
159 | set_bit(i->local_nodes[n] - 1, &c->local_nodes); | 150 | set_bit(i->local_nodes[n] - 1, &c->local_nodes); |
160 | } | ||
161 | } | 151 | } |
162 | 152 | ||
163 | static struct clusterip_config * | 153 | static struct clusterip_config * |
@@ -220,27 +210,28 @@ clusterip_add_node(struct clusterip_config *c, u_int16_t nodenum) | |||
220 | return 0; | 210 | return 0; |
221 | } | 211 | } |
222 | 212 | ||
223 | static int | 213 | static bool |
224 | clusterip_del_node(struct clusterip_config *c, u_int16_t nodenum) | 214 | clusterip_del_node(struct clusterip_config *c, u_int16_t nodenum) |
225 | { | 215 | { |
226 | if (nodenum == 0 || | 216 | if (nodenum == 0 || |
227 | nodenum > c->num_total_nodes) | 217 | nodenum > c->num_total_nodes) |
228 | return 1; | 218 | return true; |
229 | 219 | ||
230 | if (test_and_clear_bit(nodenum - 1, &c->local_nodes)) | 220 | if (test_and_clear_bit(nodenum - 1, &c->local_nodes)) |
231 | return 0; | 221 | return false; |
232 | 222 | ||
233 | return 1; | 223 | return true; |
234 | } | 224 | } |
235 | #endif | 225 | #endif |
236 | 226 | ||
237 | static inline u_int32_t | 227 | static inline u_int32_t |
238 | clusterip_hashfn(struct sk_buff *skb, struct clusterip_config *config) | 228 | clusterip_hashfn(const struct sk_buff *skb, |
229 | const struct clusterip_config *config) | ||
239 | { | 230 | { |
240 | struct iphdr *iph = ip_hdr(skb); | 231 | const struct iphdr *iph = ip_hdr(skb); |
241 | unsigned long hashval; | 232 | unsigned long hashval; |
242 | u_int16_t sport, dport; | 233 | u_int16_t sport, dport; |
243 | u_int16_t *ports; | 234 | const u_int16_t *ports; |
244 | 235 | ||
245 | switch (iph->protocol) { | 236 | switch (iph->protocol) { |
246 | case IPPROTO_TCP: | 237 | case IPPROTO_TCP: |
@@ -249,15 +240,14 @@ clusterip_hashfn(struct sk_buff *skb, struct clusterip_config *config) | |||
249 | case IPPROTO_SCTP: | 240 | case IPPROTO_SCTP: |
250 | case IPPROTO_DCCP: | 241 | case IPPROTO_DCCP: |
251 | case IPPROTO_ICMP: | 242 | case IPPROTO_ICMP: |
252 | ports = (void *)iph+iph->ihl*4; | 243 | ports = (const void *)iph+iph->ihl*4; |
253 | sport = ports[0]; | 244 | sport = ports[0]; |
254 | dport = ports[1]; | 245 | dport = ports[1]; |
255 | break; | 246 | break; |
256 | default: | 247 | default: |
257 | if (net_ratelimit()) { | 248 | if (net_ratelimit()) |
258 | printk(KERN_NOTICE "CLUSTERIP: unknown protocol `%u'\n", | 249 | printk(KERN_NOTICE "CLUSTERIP: unknown protocol `%u'\n", |
259 | iph->protocol); | 250 | iph->protocol); |
260 | } | ||
261 | sport = dport = 0; | 251 | sport = dport = 0; |
262 | } | 252 | } |
263 | 253 | ||
@@ -285,11 +275,11 @@ clusterip_hashfn(struct sk_buff *skb, struct clusterip_config *config) | |||
285 | } | 275 | } |
286 | 276 | ||
287 | /* node numbers are 1..n, not 0..n */ | 277 | /* node numbers are 1..n, not 0..n */ |
288 | return ((hashval % config->num_total_nodes)+1); | 278 | return (hashval % config->num_total_nodes) + 1; |
289 | } | 279 | } |
290 | 280 | ||
291 | static inline int | 281 | static inline int |
292 | clusterip_responsible(struct clusterip_config *config, u_int32_t hash) | 282 | clusterip_responsible(const struct clusterip_config *config, u_int32_t hash) |
293 | { | 283 | { |
294 | return test_bit(hash - 1, &config->local_nodes); | 284 | return test_bit(hash - 1, &config->local_nodes); |
295 | } | 285 | } |
@@ -353,15 +343,15 @@ target(struct sk_buff **pskb, | |||
353 | break; | 343 | break; |
354 | } | 344 | } |
355 | 345 | ||
356 | #ifdef DEBUG_CLUSTERP | 346 | #ifdef DEBUG |
357 | DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); | 347 | DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); |
358 | #endif | 348 | #endif |
359 | DEBUGP("hash=%u ct_hash=%u ", hash, ct->mark); | 349 | pr_debug("hash=%u ct_hash=%u ", hash, ct->mark); |
360 | if (!clusterip_responsible(cipinfo->config, hash)) { | 350 | if (!clusterip_responsible(cipinfo->config, hash)) { |
361 | DEBUGP("not responsible\n"); | 351 | pr_debug("not responsible\n"); |
362 | return NF_DROP; | 352 | return NF_DROP; |
363 | } | 353 | } |
364 | DEBUGP("responsible\n"); | 354 | pr_debug("responsible\n"); |
365 | 355 | ||
366 | /* despite being received via linklayer multicast, this is | 356 | /* despite being received via linklayer multicast, this is |
367 | * actually a unicast IP packet. TCP doesn't like PACKET_MULTICAST */ | 357 | * actually a unicast IP packet. TCP doesn't like PACKET_MULTICAST */ |
@@ -370,7 +360,7 @@ target(struct sk_buff **pskb, | |||
370 | return XT_CONTINUE; | 360 | return XT_CONTINUE; |
371 | } | 361 | } |
372 | 362 | ||
373 | static int | 363 | static bool |
374 | checkentry(const char *tablename, | 364 | checkentry(const char *tablename, |
375 | const void *e_void, | 365 | const void *e_void, |
376 | const struct xt_target *target, | 366 | const struct xt_target *target, |
@@ -387,50 +377,34 @@ checkentry(const char *tablename, | |||
387 | cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT_DPT) { | 377 | cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT_DPT) { |
388 | printk(KERN_WARNING "CLUSTERIP: unknown mode `%u'\n", | 378 | printk(KERN_WARNING "CLUSTERIP: unknown mode `%u'\n", |
389 | cipinfo->hash_mode); | 379 | cipinfo->hash_mode); |
390 | return 0; | 380 | return false; |
391 | 381 | ||
392 | } | 382 | } |
393 | if (e->ip.dmsk.s_addr != htonl(0xffffffff) | 383 | if (e->ip.dmsk.s_addr != htonl(0xffffffff) |
394 | || e->ip.dst.s_addr == 0) { | 384 | || e->ip.dst.s_addr == 0) { |
395 | printk(KERN_ERR "CLUSTERIP: Please specify destination IP\n"); | 385 | printk(KERN_ERR "CLUSTERIP: Please specify destination IP\n"); |
396 | return 0; | 386 | return false; |
397 | } | 387 | } |
398 | 388 | ||
399 | /* FIXME: further sanity checks */ | 389 | /* FIXME: further sanity checks */ |
400 | 390 | ||
401 | config = clusterip_config_find_get(e->ip.dst.s_addr, 1); | 391 | config = clusterip_config_find_get(e->ip.dst.s_addr, 1); |
402 | if (config) { | 392 | if (!config) { |
403 | if (cipinfo->config != NULL) { | ||
404 | /* Case A: This is an entry that gets reloaded, since | ||
405 | * it still has a cipinfo->config pointer. Simply | ||
406 | * increase the entry refcount and return */ | ||
407 | if (cipinfo->config != config) { | ||
408 | printk(KERN_ERR "CLUSTERIP: Reloaded entry " | ||
409 | "has invalid config pointer!\n"); | ||
410 | return 0; | ||
411 | } | ||
412 | } else { | ||
413 | /* Case B: This is a new rule referring to an existing | ||
414 | * clusterip config. */ | ||
415 | cipinfo->config = config; | ||
416 | } | ||
417 | } else { | ||
418 | /* Case C: This is a completely new clusterip config */ | ||
419 | if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) { | 393 | if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) { |
420 | printk(KERN_WARNING "CLUSTERIP: no config found for %u.%u.%u.%u, need 'new'\n", NIPQUAD(e->ip.dst.s_addr)); | 394 | printk(KERN_WARNING "CLUSTERIP: no config found for %u.%u.%u.%u, need 'new'\n", NIPQUAD(e->ip.dst.s_addr)); |
421 | return 0; | 395 | return false; |
422 | } else { | 396 | } else { |
423 | struct net_device *dev; | 397 | struct net_device *dev; |
424 | 398 | ||
425 | if (e->ip.iniface[0] == '\0') { | 399 | if (e->ip.iniface[0] == '\0') { |
426 | printk(KERN_WARNING "CLUSTERIP: Please specify an interface name\n"); | 400 | printk(KERN_WARNING "CLUSTERIP: Please specify an interface name\n"); |
427 | return 0; | 401 | return false; |
428 | } | 402 | } |
429 | 403 | ||
430 | dev = dev_get_by_name(e->ip.iniface); | 404 | dev = dev_get_by_name(e->ip.iniface); |
431 | if (!dev) { | 405 | if (!dev) { |
432 | printk(KERN_WARNING "CLUSTERIP: no such interface %s\n", e->ip.iniface); | 406 | printk(KERN_WARNING "CLUSTERIP: no such interface %s\n", e->ip.iniface); |
433 | return 0; | 407 | return false; |
434 | } | 408 | } |
435 | 409 | ||
436 | config = clusterip_config_init(cipinfo, | 410 | config = clusterip_config_init(cipinfo, |
@@ -438,20 +412,20 @@ checkentry(const char *tablename, | |||
438 | if (!config) { | 412 | if (!config) { |
439 | printk(KERN_WARNING "CLUSTERIP: cannot allocate config\n"); | 413 | printk(KERN_WARNING "CLUSTERIP: cannot allocate config\n"); |
440 | dev_put(dev); | 414 | dev_put(dev); |
441 | return 0; | 415 | return false; |
442 | } | 416 | } |
443 | dev_mc_add(config->dev,config->clustermac, ETH_ALEN, 0); | 417 | dev_mc_add(config->dev,config->clustermac, ETH_ALEN, 0); |
444 | } | 418 | } |
445 | cipinfo->config = config; | ||
446 | } | 419 | } |
420 | cipinfo->config = config; | ||
447 | 421 | ||
448 | if (nf_ct_l3proto_try_module_get(target->family) < 0) { | 422 | if (nf_ct_l3proto_try_module_get(target->family) < 0) { |
449 | printk(KERN_WARNING "can't load conntrack support for " | 423 | printk(KERN_WARNING "can't load conntrack support for " |
450 | "proto=%d\n", target->family); | 424 | "proto=%d\n", target->family); |
451 | return 0; | 425 | return false; |
452 | } | 426 | } |
453 | 427 | ||
454 | return 1; | 428 | return true; |
455 | } | 429 | } |
456 | 430 | ||
457 | /* drop reference count of cluster config when rule is deleted */ | 431 | /* drop reference count of cluster config when rule is deleted */ |
@@ -468,13 +442,30 @@ static void destroy(const struct xt_target *target, void *targinfo) | |||
468 | nf_ct_l3proto_module_put(target->family); | 442 | nf_ct_l3proto_module_put(target->family); |
469 | } | 443 | } |
470 | 444 | ||
471 | static struct xt_target clusterip_tgt = { | 445 | #ifdef CONFIG_COMPAT |
446 | struct compat_ipt_clusterip_tgt_info | ||
447 | { | ||
448 | u_int32_t flags; | ||
449 | u_int8_t clustermac[6]; | ||
450 | u_int16_t num_total_nodes; | ||
451 | u_int16_t num_local_nodes; | ||
452 | u_int16_t local_nodes[CLUSTERIP_MAX_NODES]; | ||
453 | u_int32_t hash_mode; | ||
454 | u_int32_t hash_initval; | ||
455 | compat_uptr_t config; | ||
456 | }; | ||
457 | #endif /* CONFIG_COMPAT */ | ||
458 | |||
459 | static struct xt_target clusterip_tgt __read_mostly = { | ||
472 | .name = "CLUSTERIP", | 460 | .name = "CLUSTERIP", |
473 | .family = AF_INET, | 461 | .family = AF_INET, |
474 | .target = target, | 462 | .target = target, |
475 | .targetsize = sizeof(struct ipt_clusterip_tgt_info), | ||
476 | .checkentry = checkentry, | 463 | .checkentry = checkentry, |
477 | .destroy = destroy, | 464 | .destroy = destroy, |
465 | .targetsize = sizeof(struct ipt_clusterip_tgt_info), | ||
466 | #ifdef CONFIG_COMPAT | ||
467 | .compatsize = sizeof(struct compat_ipt_clusterip_tgt_info), | ||
468 | #endif /* CONFIG_COMPAT */ | ||
478 | .me = THIS_MODULE | 469 | .me = THIS_MODULE |
479 | }; | 470 | }; |
480 | 471 | ||
@@ -491,7 +482,7 @@ struct arp_payload { | |||
491 | __be32 dst_ip; | 482 | __be32 dst_ip; |
492 | } __attribute__ ((packed)); | 483 | } __attribute__ ((packed)); |
493 | 484 | ||
494 | #ifdef CLUSTERIP_DEBUG | 485 | #ifdef DEBUG |
495 | static void arp_print(struct arp_payload *payload) | 486 | static void arp_print(struct arp_payload *payload) |
496 | { | 487 | { |
497 | #define HBUFFERLEN 30 | 488 | #define HBUFFERLEN 30 |
@@ -547,8 +538,9 @@ arp_mangle(unsigned int hook, | |||
547 | * this wouldn't work, since we didn't subscribe the mcast group on | 538 | * this wouldn't work, since we didn't subscribe the mcast group on |
548 | * other interfaces */ | 539 | * other interfaces */ |
549 | if (c->dev != out) { | 540 | if (c->dev != out) { |
550 | DEBUGP("CLUSTERIP: not mangling arp reply on different " | 541 | pr_debug("CLUSTERIP: not mangling arp reply on different " |
551 | "interface: cip'%s'-skb'%s'\n", c->dev->name, out->name); | 542 | "interface: cip'%s'-skb'%s'\n", |
543 | c->dev->name, out->name); | ||
552 | clusterip_config_put(c); | 544 | clusterip_config_put(c); |
553 | return NF_ACCEPT; | 545 | return NF_ACCEPT; |
554 | } | 546 | } |
@@ -556,8 +548,8 @@ arp_mangle(unsigned int hook, | |||
556 | /* mangle reply hardware address */ | 548 | /* mangle reply hardware address */ |
557 | memcpy(payload->src_hw, c->clustermac, arp->ar_hln); | 549 | memcpy(payload->src_hw, c->clustermac, arp->ar_hln); |
558 | 550 | ||
559 | #ifdef CLUSTERIP_DEBUG | 551 | #ifdef DEBUG |
560 | DEBUGP(KERN_DEBUG "CLUSTERIP mangled arp reply: "); | 552 | pr_debug(KERN_DEBUG "CLUSTERIP mangled arp reply: "); |
561 | arp_print(payload); | 553 | arp_print(payload); |
562 | #endif | 554 | #endif |
563 | 555 | ||
@@ -647,7 +639,7 @@ static int clusterip_seq_show(struct seq_file *s, void *v) | |||
647 | return 0; | 639 | return 0; |
648 | } | 640 | } |
649 | 641 | ||
650 | static struct seq_operations clusterip_seq_ops = { | 642 | static const struct seq_operations clusterip_seq_ops = { |
651 | .start = clusterip_seq_start, | 643 | .start = clusterip_seq_start, |
652 | .next = clusterip_seq_next, | 644 | .next = clusterip_seq_next, |
653 | .stop = clusterip_seq_stop, | 645 | .stop = clusterip_seq_stop, |
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c index 918ca92e534a..f1253bd3837f 100644 --- a/net/ipv4/netfilter/ipt_ECN.c +++ b/net/ipv4/netfilter/ipt_ECN.c | |||
@@ -24,8 +24,8 @@ MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | |||
24 | MODULE_DESCRIPTION("iptables ECN modification module"); | 24 | MODULE_DESCRIPTION("iptables ECN modification module"); |
25 | 25 | ||
26 | /* set ECT codepoint from IP header. | 26 | /* set ECT codepoint from IP header. |
27 | * return 0 if there was an error. */ | 27 | * return false if there was an error. */ |
28 | static inline int | 28 | static inline bool |
29 | set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) | 29 | set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) |
30 | { | 30 | { |
31 | struct iphdr *iph = ip_hdr(*pskb); | 31 | struct iphdr *iph = ip_hdr(*pskb); |
@@ -33,18 +33,18 @@ set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) | |||
33 | if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) { | 33 | if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) { |
34 | __u8 oldtos; | 34 | __u8 oldtos; |
35 | if (!skb_make_writable(pskb, sizeof(struct iphdr))) | 35 | if (!skb_make_writable(pskb, sizeof(struct iphdr))) |
36 | return 0; | 36 | return false; |
37 | iph = ip_hdr(*pskb); | 37 | iph = ip_hdr(*pskb); |
38 | oldtos = iph->tos; | 38 | oldtos = iph->tos; |
39 | iph->tos &= ~IPT_ECN_IP_MASK; | 39 | iph->tos &= ~IPT_ECN_IP_MASK; |
40 | iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK); | 40 | iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK); |
41 | nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos)); | 41 | nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos)); |
42 | } | 42 | } |
43 | return 1; | 43 | return true; |
44 | } | 44 | } |
45 | 45 | ||
46 | /* Return 0 if there was an error. */ | 46 | /* Return false if there was an error. */ |
47 | static inline int | 47 | static inline bool |
48 | set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) | 48 | set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) |
49 | { | 49 | { |
50 | struct tcphdr _tcph, *tcph; | 50 | struct tcphdr _tcph, *tcph; |
@@ -54,16 +54,16 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) | |||
54 | tcph = skb_header_pointer(*pskb, ip_hdrlen(*pskb), | 54 | tcph = skb_header_pointer(*pskb, ip_hdrlen(*pskb), |
55 | sizeof(_tcph), &_tcph); | 55 | sizeof(_tcph), &_tcph); |
56 | if (!tcph) | 56 | if (!tcph) |
57 | return 0; | 57 | return false; |
58 | 58 | ||
59 | if ((!(einfo->operation & IPT_ECN_OP_SET_ECE) || | 59 | if ((!(einfo->operation & IPT_ECN_OP_SET_ECE) || |
60 | tcph->ece == einfo->proto.tcp.ece) && | 60 | tcph->ece == einfo->proto.tcp.ece) && |
61 | ((!(einfo->operation & IPT_ECN_OP_SET_CWR) || | 61 | (!(einfo->operation & IPT_ECN_OP_SET_CWR) || |
62 | tcph->cwr == einfo->proto.tcp.cwr))) | 62 | tcph->cwr == einfo->proto.tcp.cwr)) |
63 | return 1; | 63 | return true; |
64 | 64 | ||
65 | if (!skb_make_writable(pskb, ip_hdrlen(*pskb) + sizeof(*tcph))) | 65 | if (!skb_make_writable(pskb, ip_hdrlen(*pskb) + sizeof(*tcph))) |
66 | return 0; | 66 | return false; |
67 | tcph = (void *)ip_hdr(*pskb) + ip_hdrlen(*pskb); | 67 | tcph = (void *)ip_hdr(*pskb) + ip_hdrlen(*pskb); |
68 | 68 | ||
69 | oldval = ((__be16 *)tcph)[6]; | 69 | oldval = ((__be16 *)tcph)[6]; |
@@ -74,7 +74,7 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) | |||
74 | 74 | ||
75 | nf_proto_csum_replace2(&tcph->check, *pskb, | 75 | nf_proto_csum_replace2(&tcph->check, *pskb, |
76 | oldval, ((__be16 *)tcph)[6], 0); | 76 | oldval, ((__be16 *)tcph)[6], 0); |
77 | return 1; | 77 | return true; |
78 | } | 78 | } |
79 | 79 | ||
80 | static unsigned int | 80 | static unsigned int |
@@ -99,7 +99,7 @@ target(struct sk_buff **pskb, | |||
99 | return XT_CONTINUE; | 99 | return XT_CONTINUE; |
100 | } | 100 | } |
101 | 101 | ||
102 | static int | 102 | static bool |
103 | checkentry(const char *tablename, | 103 | checkentry(const char *tablename, |
104 | const void *e_void, | 104 | const void *e_void, |
105 | const struct xt_target *target, | 105 | const struct xt_target *target, |
@@ -112,23 +112,23 @@ checkentry(const char *tablename, | |||
112 | if (einfo->operation & IPT_ECN_OP_MASK) { | 112 | if (einfo->operation & IPT_ECN_OP_MASK) { |
113 | printk(KERN_WARNING "ECN: unsupported ECN operation %x\n", | 113 | printk(KERN_WARNING "ECN: unsupported ECN operation %x\n", |
114 | einfo->operation); | 114 | einfo->operation); |
115 | return 0; | 115 | return false; |
116 | } | 116 | } |
117 | if (einfo->ip_ect & ~IPT_ECN_IP_MASK) { | 117 | if (einfo->ip_ect & ~IPT_ECN_IP_MASK) { |
118 | printk(KERN_WARNING "ECN: new ECT codepoint %x out of mask\n", | 118 | printk(KERN_WARNING "ECN: new ECT codepoint %x out of mask\n", |
119 | einfo->ip_ect); | 119 | einfo->ip_ect); |
120 | return 0; | 120 | return false; |
121 | } | 121 | } |
122 | if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)) | 122 | if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)) |
123 | && (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & XT_INV_PROTO))) { | 123 | && (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & XT_INV_PROTO))) { |
124 | printk(KERN_WARNING "ECN: cannot use TCP operations on a " | 124 | printk(KERN_WARNING "ECN: cannot use TCP operations on a " |
125 | "non-tcp rule\n"); | 125 | "non-tcp rule\n"); |
126 | return 0; | 126 | return false; |
127 | } | 127 | } |
128 | return 1; | 128 | return true; |
129 | } | 129 | } |
130 | 130 | ||
131 | static struct xt_target ipt_ecn_reg = { | 131 | static struct xt_target ipt_ecn_reg __read_mostly = { |
132 | .name = "ECN", | 132 | .name = "ECN", |
133 | .family = AF_INET, | 133 | .family = AF_INET, |
134 | .target = target, | 134 | .target = target, |
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c index a42c5cd968b1..5937ad150b9f 100644 --- a/net/ipv4/netfilter/ipt_LOG.c +++ b/net/ipv4/netfilter/ipt_LOG.c | |||
@@ -27,12 +27,6 @@ MODULE_LICENSE("GPL"); | |||
27 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | 27 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); |
28 | MODULE_DESCRIPTION("iptables syslog logging module"); | 28 | MODULE_DESCRIPTION("iptables syslog logging module"); |
29 | 29 | ||
30 | #if 0 | ||
31 | #define DEBUGP printk | ||
32 | #else | ||
33 | #define DEBUGP(format, args...) | ||
34 | #endif | ||
35 | |||
36 | /* Use lock to serialize, so printks don't overlap */ | 30 | /* Use lock to serialize, so printks don't overlap */ |
37 | static DEFINE_SPINLOCK(log_lock); | 31 | static DEFINE_SPINLOCK(log_lock); |
38 | 32 | ||
@@ -41,7 +35,8 @@ static void dump_packet(const struct nf_loginfo *info, | |||
41 | const struct sk_buff *skb, | 35 | const struct sk_buff *skb, |
42 | unsigned int iphoff) | 36 | unsigned int iphoff) |
43 | { | 37 | { |
44 | struct iphdr _iph, *ih; | 38 | struct iphdr _iph; |
39 | const struct iphdr *ih; | ||
45 | unsigned int logflags; | 40 | unsigned int logflags; |
46 | 41 | ||
47 | if (info->type == NF_LOG_TYPE_LOG) | 42 | if (info->type == NF_LOG_TYPE_LOG) |
@@ -100,7 +95,8 @@ static void dump_packet(const struct nf_loginfo *info, | |||
100 | 95 | ||
101 | switch (ih->protocol) { | 96 | switch (ih->protocol) { |
102 | case IPPROTO_TCP: { | 97 | case IPPROTO_TCP: { |
103 | struct tcphdr _tcph, *th; | 98 | struct tcphdr _tcph; |
99 | const struct tcphdr *th; | ||
104 | 100 | ||
105 | /* Max length: 10 "PROTO=TCP " */ | 101 | /* Max length: 10 "PROTO=TCP " */ |
106 | printk("PROTO=TCP "); | 102 | printk("PROTO=TCP "); |
@@ -151,7 +147,7 @@ static void dump_packet(const struct nf_loginfo *info, | |||
151 | if ((logflags & IPT_LOG_TCPOPT) | 147 | if ((logflags & IPT_LOG_TCPOPT) |
152 | && th->doff * 4 > sizeof(struct tcphdr)) { | 148 | && th->doff * 4 > sizeof(struct tcphdr)) { |
153 | unsigned char _opt[4 * 15 - sizeof(struct tcphdr)]; | 149 | unsigned char _opt[4 * 15 - sizeof(struct tcphdr)]; |
154 | unsigned char *op; | 150 | const unsigned char *op; |
155 | unsigned int i, optsize; | 151 | unsigned int i, optsize; |
156 | 152 | ||
157 | optsize = th->doff * 4 - sizeof(struct tcphdr); | 153 | optsize = th->doff * 4 - sizeof(struct tcphdr); |
@@ -173,7 +169,8 @@ static void dump_packet(const struct nf_loginfo *info, | |||
173 | } | 169 | } |
174 | case IPPROTO_UDP: | 170 | case IPPROTO_UDP: |
175 | case IPPROTO_UDPLITE: { | 171 | case IPPROTO_UDPLITE: { |
176 | struct udphdr _udph, *uh; | 172 | struct udphdr _udph; |
173 | const struct udphdr *uh; | ||
177 | 174 | ||
178 | if (ih->protocol == IPPROTO_UDP) | 175 | if (ih->protocol == IPPROTO_UDP) |
179 | /* Max length: 10 "PROTO=UDP " */ | 176 | /* Max length: 10 "PROTO=UDP " */ |
@@ -200,7 +197,8 @@ static void dump_packet(const struct nf_loginfo *info, | |||
200 | break; | 197 | break; |
201 | } | 198 | } |
202 | case IPPROTO_ICMP: { | 199 | case IPPROTO_ICMP: { |
203 | struct icmphdr _icmph, *ich; | 200 | struct icmphdr _icmph; |
201 | const struct icmphdr *ich; | ||
204 | static const size_t required_len[NR_ICMP_TYPES+1] | 202 | static const size_t required_len[NR_ICMP_TYPES+1] |
205 | = { [ICMP_ECHOREPLY] = 4, | 203 | = { [ICMP_ECHOREPLY] = 4, |
206 | [ICMP_DEST_UNREACH] | 204 | [ICMP_DEST_UNREACH] |
@@ -285,7 +283,8 @@ static void dump_packet(const struct nf_loginfo *info, | |||
285 | } | 283 | } |
286 | /* Max Length */ | 284 | /* Max Length */ |
287 | case IPPROTO_AH: { | 285 | case IPPROTO_AH: { |
288 | struct ip_auth_hdr _ahdr, *ah; | 286 | struct ip_auth_hdr _ahdr; |
287 | const struct ip_auth_hdr *ah; | ||
289 | 288 | ||
290 | if (ntohs(ih->frag_off) & IP_OFFSET) | 289 | if (ntohs(ih->frag_off) & IP_OFFSET) |
291 | break; | 290 | break; |
@@ -307,7 +306,8 @@ static void dump_packet(const struct nf_loginfo *info, | |||
307 | break; | 306 | break; |
308 | } | 307 | } |
309 | case IPPROTO_ESP: { | 308 | case IPPROTO_ESP: { |
310 | struct ip_esp_hdr _esph, *eh; | 309 | struct ip_esp_hdr _esph; |
310 | const struct ip_esp_hdr *eh; | ||
311 | 311 | ||
312 | /* Max length: 10 "PROTO=ESP " */ | 312 | /* Max length: 10 "PROTO=ESP " */ |
313 | printk("PROTO=ESP "); | 313 | printk("PROTO=ESP "); |
@@ -385,11 +385,13 @@ ipt_log_packet(unsigned int pf, | |||
385 | out ? out->name : ""); | 385 | out ? out->name : ""); |
386 | #ifdef CONFIG_BRIDGE_NETFILTER | 386 | #ifdef CONFIG_BRIDGE_NETFILTER |
387 | if (skb->nf_bridge) { | 387 | if (skb->nf_bridge) { |
388 | struct net_device *physindev = skb->nf_bridge->physindev; | 388 | const struct net_device *physindev; |
389 | struct net_device *physoutdev = skb->nf_bridge->physoutdev; | 389 | const struct net_device *physoutdev; |
390 | 390 | ||
391 | physindev = skb->nf_bridge->physindev; | ||
391 | if (physindev && in != physindev) | 392 | if (physindev && in != physindev) |
392 | printk("PHYSIN=%s ", physindev->name); | 393 | printk("PHYSIN=%s ", physindev->name); |
394 | physoutdev = skb->nf_bridge->physoutdev; | ||
393 | if (physoutdev && out != physoutdev) | 395 | if (physoutdev && out != physoutdev) |
394 | printk("PHYSOUT=%s ", physoutdev->name); | 396 | printk("PHYSOUT=%s ", physoutdev->name); |
395 | } | 397 | } |
@@ -435,27 +437,27 @@ ipt_log_target(struct sk_buff **pskb, | |||
435 | return XT_CONTINUE; | 437 | return XT_CONTINUE; |
436 | } | 438 | } |
437 | 439 | ||
438 | static int ipt_log_checkentry(const char *tablename, | 440 | static bool ipt_log_checkentry(const char *tablename, |
439 | const void *e, | 441 | const void *e, |
440 | const struct xt_target *target, | 442 | const struct xt_target *target, |
441 | void *targinfo, | 443 | void *targinfo, |
442 | unsigned int hook_mask) | 444 | unsigned int hook_mask) |
443 | { | 445 | { |
444 | const struct ipt_log_info *loginfo = targinfo; | 446 | const struct ipt_log_info *loginfo = targinfo; |
445 | 447 | ||
446 | if (loginfo->level >= 8) { | 448 | if (loginfo->level >= 8) { |
447 | DEBUGP("LOG: level %u >= 8\n", loginfo->level); | 449 | pr_debug("LOG: level %u >= 8\n", loginfo->level); |
448 | return 0; | 450 | return false; |
449 | } | 451 | } |
450 | if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') { | 452 | if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') { |
451 | DEBUGP("LOG: prefix term %i\n", | 453 | pr_debug("LOG: prefix term %i\n", |
452 | loginfo->prefix[sizeof(loginfo->prefix)-1]); | 454 | loginfo->prefix[sizeof(loginfo->prefix)-1]); |
453 | return 0; | 455 | return false; |
454 | } | 456 | } |
455 | return 1; | 457 | return true; |
456 | } | 458 | } |
457 | 459 | ||
458 | static struct xt_target ipt_log_reg = { | 460 | static struct xt_target ipt_log_reg __read_mostly = { |
459 | .name = "LOG", | 461 | .name = "LOG", |
460 | .family = AF_INET, | 462 | .family = AF_INET, |
461 | .target = ipt_log_target, | 463 | .target = ipt_log_target, |
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index d4f2d7775330..7c4e4be7c8b3 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c | |||
@@ -27,17 +27,11 @@ MODULE_LICENSE("GPL"); | |||
27 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | 27 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); |
28 | MODULE_DESCRIPTION("iptables MASQUERADE target module"); | 28 | MODULE_DESCRIPTION("iptables MASQUERADE target module"); |
29 | 29 | ||
30 | #if 0 | ||
31 | #define DEBUGP printk | ||
32 | #else | ||
33 | #define DEBUGP(format, args...) | ||
34 | #endif | ||
35 | |||
36 | /* Lock protects masq region inside conntrack */ | 30 | /* Lock protects masq region inside conntrack */ |
37 | static DEFINE_RWLOCK(masq_lock); | 31 | static DEFINE_RWLOCK(masq_lock); |
38 | 32 | ||
39 | /* FIXME: Multiple targets. --RR */ | 33 | /* FIXME: Multiple targets. --RR */ |
40 | static int | 34 | static bool |
41 | masquerade_check(const char *tablename, | 35 | masquerade_check(const char *tablename, |
42 | const void *e, | 36 | const void *e, |
43 | const struct xt_target *target, | 37 | const struct xt_target *target, |
@@ -47,14 +41,14 @@ masquerade_check(const char *tablename, | |||
47 | const struct nf_nat_multi_range_compat *mr = targinfo; | 41 | const struct nf_nat_multi_range_compat *mr = targinfo; |
48 | 42 | ||
49 | if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { | 43 | if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { |
50 | DEBUGP("masquerade_check: bad MAP_IPS.\n"); | 44 | pr_debug("masquerade_check: bad MAP_IPS.\n"); |
51 | return 0; | 45 | return false; |
52 | } | 46 | } |
53 | if (mr->rangesize != 1) { | 47 | if (mr->rangesize != 1) { |
54 | DEBUGP("masquerade_check: bad rangesize %u.\n", mr->rangesize); | 48 | pr_debug("masquerade_check: bad rangesize %u\n", mr->rangesize); |
55 | return 0; | 49 | return false; |
56 | } | 50 | } |
57 | return 1; | 51 | return true; |
58 | } | 52 | } |
59 | 53 | ||
60 | static unsigned int | 54 | static unsigned int |
@@ -70,7 +64,7 @@ masquerade_target(struct sk_buff **pskb, | |||
70 | enum ip_conntrack_info ctinfo; | 64 | enum ip_conntrack_info ctinfo; |
71 | struct nf_nat_range newrange; | 65 | struct nf_nat_range newrange; |
72 | const struct nf_nat_multi_range_compat *mr; | 66 | const struct nf_nat_multi_range_compat *mr; |
73 | struct rtable *rt; | 67 | const struct rtable *rt; |
74 | __be32 newsrc; | 68 | __be32 newsrc; |
75 | 69 | ||
76 | NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING); | 70 | NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING); |
@@ -109,10 +103,10 @@ masquerade_target(struct sk_buff **pskb, | |||
109 | return nf_nat_setup_info(ct, &newrange, hooknum); | 103 | return nf_nat_setup_info(ct, &newrange, hooknum); |
110 | } | 104 | } |
111 | 105 | ||
112 | static inline int | 106 | static int |
113 | device_cmp(struct nf_conn *i, void *ifindex) | 107 | device_cmp(struct nf_conn *i, void *ifindex) |
114 | { | 108 | { |
115 | struct nf_conn_nat *nat = nfct_nat(i); | 109 | const struct nf_conn_nat *nat = nfct_nat(i); |
116 | int ret; | 110 | int ret; |
117 | 111 | ||
118 | if (!nat) | 112 | if (!nat) |
@@ -129,7 +123,7 @@ static int masq_device_event(struct notifier_block *this, | |||
129 | unsigned long event, | 123 | unsigned long event, |
130 | void *ptr) | 124 | void *ptr) |
131 | { | 125 | { |
132 | struct net_device *dev = ptr; | 126 | const struct net_device *dev = ptr; |
133 | 127 | ||
134 | if (event == NETDEV_DOWN) { | 128 | if (event == NETDEV_DOWN) { |
135 | /* Device was downed. Search entire table for | 129 | /* Device was downed. Search entire table for |
@@ -147,7 +141,7 @@ static int masq_inet_event(struct notifier_block *this, | |||
147 | unsigned long event, | 141 | unsigned long event, |
148 | void *ptr) | 142 | void *ptr) |
149 | { | 143 | { |
150 | struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev; | 144 | const struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev; |
151 | 145 | ||
152 | if (event == NETDEV_DOWN) { | 146 | if (event == NETDEV_DOWN) { |
153 | /* IP address was deleted. Search entire table for | 147 | /* IP address was deleted. Search entire table for |
@@ -169,7 +163,7 @@ static struct notifier_block masq_inet_notifier = { | |||
169 | .notifier_call = masq_inet_event, | 163 | .notifier_call = masq_inet_event, |
170 | }; | 164 | }; |
171 | 165 | ||
172 | static struct xt_target masquerade = { | 166 | static struct xt_target masquerade __read_mostly = { |
173 | .name = "MASQUERADE", | 167 | .name = "MASQUERADE", |
174 | .family = AF_INET, | 168 | .family = AF_INET, |
175 | .target = masquerade_target, | 169 | .target = masquerade_target, |
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c index 068c69bce30e..41a011d5a065 100644 --- a/net/ipv4/netfilter/ipt_NETMAP.c +++ b/net/ipv4/netfilter/ipt_NETMAP.c | |||
@@ -18,18 +18,11 @@ | |||
18 | #include <linux/netfilter/x_tables.h> | 18 | #include <linux/netfilter/x_tables.h> |
19 | #include <net/netfilter/nf_nat_rule.h> | 19 | #include <net/netfilter/nf_nat_rule.h> |
20 | 20 | ||
21 | #define MODULENAME "NETMAP" | ||
22 | MODULE_LICENSE("GPL"); | 21 | MODULE_LICENSE("GPL"); |
23 | MODULE_AUTHOR("Svenning Soerensen <svenning@post5.tele.dk>"); | 22 | MODULE_AUTHOR("Svenning Soerensen <svenning@post5.tele.dk>"); |
24 | MODULE_DESCRIPTION("iptables 1:1 NAT mapping of IP networks target"); | 23 | MODULE_DESCRIPTION("iptables 1:1 NAT mapping of IP networks target"); |
25 | 24 | ||
26 | #if 0 | 25 | static bool |
27 | #define DEBUGP printk | ||
28 | #else | ||
29 | #define DEBUGP(format, args...) | ||
30 | #endif | ||
31 | |||
32 | static int | ||
33 | check(const char *tablename, | 26 | check(const char *tablename, |
34 | const void *e, | 27 | const void *e, |
35 | const struct xt_target *target, | 28 | const struct xt_target *target, |
@@ -39,14 +32,14 @@ check(const char *tablename, | |||
39 | const struct nf_nat_multi_range_compat *mr = targinfo; | 32 | const struct nf_nat_multi_range_compat *mr = targinfo; |
40 | 33 | ||
41 | if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) { | 34 | if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) { |
42 | DEBUGP(MODULENAME":check: bad MAP_IPS.\n"); | 35 | pr_debug("NETMAP:check: bad MAP_IPS.\n"); |
43 | return 0; | 36 | return false; |
44 | } | 37 | } |
45 | if (mr->rangesize != 1) { | 38 | if (mr->rangesize != 1) { |
46 | DEBUGP(MODULENAME":check: bad rangesize %u.\n", mr->rangesize); | 39 | pr_debug("NETMAP:check: bad rangesize %u.\n", mr->rangesize); |
47 | return 0; | 40 | return false; |
48 | } | 41 | } |
49 | return 1; | 42 | return true; |
50 | } | 43 | } |
51 | 44 | ||
52 | static unsigned int | 45 | static unsigned int |
@@ -85,8 +78,8 @@ target(struct sk_buff **pskb, | |||
85 | return nf_nat_setup_info(ct, &newrange, hooknum); | 78 | return nf_nat_setup_info(ct, &newrange, hooknum); |
86 | } | 79 | } |
87 | 80 | ||
88 | static struct xt_target target_module = { | 81 | static struct xt_target target_module __read_mostly = { |
89 | .name = MODULENAME, | 82 | .name = "NETMAP", |
90 | .family = AF_INET, | 83 | .family = AF_INET, |
91 | .target = target, | 84 | .target = target, |
92 | .targetsize = sizeof(struct nf_nat_multi_range_compat), | 85 | .targetsize = sizeof(struct nf_nat_multi_range_compat), |
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c index 68cc76a198eb..6ac7a2373316 100644 --- a/net/ipv4/netfilter/ipt_REDIRECT.c +++ b/net/ipv4/netfilter/ipt_REDIRECT.c | |||
@@ -25,14 +25,8 @@ MODULE_LICENSE("GPL"); | |||
25 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | 25 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); |
26 | MODULE_DESCRIPTION("iptables REDIRECT target module"); | 26 | MODULE_DESCRIPTION("iptables REDIRECT target module"); |
27 | 27 | ||
28 | #if 0 | ||
29 | #define DEBUGP printk | ||
30 | #else | ||
31 | #define DEBUGP(format, args...) | ||
32 | #endif | ||
33 | |||
34 | /* FIXME: Take multiple ranges --RR */ | 28 | /* FIXME: Take multiple ranges --RR */ |
35 | static int | 29 | static bool |
36 | redirect_check(const char *tablename, | 30 | redirect_check(const char *tablename, |
37 | const void *e, | 31 | const void *e, |
38 | const struct xt_target *target, | 32 | const struct xt_target *target, |
@@ -42,14 +36,14 @@ redirect_check(const char *tablename, | |||
42 | const struct nf_nat_multi_range_compat *mr = targinfo; | 36 | const struct nf_nat_multi_range_compat *mr = targinfo; |
43 | 37 | ||
44 | if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { | 38 | if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { |
45 | DEBUGP("redirect_check: bad MAP_IPS.\n"); | 39 | pr_debug("redirect_check: bad MAP_IPS.\n"); |
46 | return 0; | 40 | return false; |
47 | } | 41 | } |
48 | if (mr->rangesize != 1) { | 42 | if (mr->rangesize != 1) { |
49 | DEBUGP("redirect_check: bad rangesize %u.\n", mr->rangesize); | 43 | pr_debug("redirect_check: bad rangesize %u.\n", mr->rangesize); |
50 | return 0; | 44 | return false; |
51 | } | 45 | } |
52 | return 1; | 46 | return true; |
53 | } | 47 | } |
54 | 48 | ||
55 | static unsigned int | 49 | static unsigned int |
@@ -101,7 +95,7 @@ redirect_target(struct sk_buff **pskb, | |||
101 | return nf_nat_setup_info(ct, &newrange, hooknum); | 95 | return nf_nat_setup_info(ct, &newrange, hooknum); |
102 | } | 96 | } |
103 | 97 | ||
104 | static struct xt_target redirect_reg = { | 98 | static struct xt_target redirect_reg __read_mostly = { |
105 | .name = "REDIRECT", | 99 | .name = "REDIRECT", |
106 | .family = AF_INET, | 100 | .family = AF_INET, |
107 | .target = redirect_target, | 101 | .target = redirect_target, |
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index 9041e0741f6f..cb038c8fbc9d 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c | |||
@@ -31,12 +31,6 @@ MODULE_LICENSE("GPL"); | |||
31 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | 31 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); |
32 | MODULE_DESCRIPTION("iptables REJECT target module"); | 32 | MODULE_DESCRIPTION("iptables REJECT target module"); |
33 | 33 | ||
34 | #if 0 | ||
35 | #define DEBUGP printk | ||
36 | #else | ||
37 | #define DEBUGP(format, args...) | ||
38 | #endif | ||
39 | |||
40 | /* Send RST reply */ | 34 | /* Send RST reply */ |
41 | static void send_reset(struct sk_buff *oldskb, int hook) | 35 | static void send_reset(struct sk_buff *oldskb, int hook) |
42 | { | 36 | { |
@@ -122,7 +116,7 @@ static void send_reset(struct sk_buff *oldskb, int hook) | |||
122 | tcph->check = 0; | 116 | tcph->check = 0; |
123 | tcph->check = tcp_v4_check(sizeof(struct tcphdr), | 117 | tcph->check = tcp_v4_check(sizeof(struct tcphdr), |
124 | niph->saddr, niph->daddr, | 118 | niph->saddr, niph->daddr, |
125 | csum_partial((char *)tcph, | 119 | csum_partial(tcph, |
126 | sizeof(struct tcphdr), 0)); | 120 | sizeof(struct tcphdr), 0)); |
127 | 121 | ||
128 | /* Set DF, id = 0 */ | 122 | /* Set DF, id = 0 */ |
@@ -217,30 +211,30 @@ static unsigned int reject(struct sk_buff **pskb, | |||
217 | return NF_DROP; | 211 | return NF_DROP; |
218 | } | 212 | } |
219 | 213 | ||
220 | static int check(const char *tablename, | 214 | static bool check(const char *tablename, |
221 | const void *e_void, | 215 | const void *e_void, |
222 | const struct xt_target *target, | 216 | const struct xt_target *target, |
223 | void *targinfo, | 217 | void *targinfo, |
224 | unsigned int hook_mask) | 218 | unsigned int hook_mask) |
225 | { | 219 | { |
226 | const struct ipt_reject_info *rejinfo = targinfo; | 220 | const struct ipt_reject_info *rejinfo = targinfo; |
227 | const struct ipt_entry *e = e_void; | 221 | const struct ipt_entry *e = e_void; |
228 | 222 | ||
229 | if (rejinfo->with == IPT_ICMP_ECHOREPLY) { | 223 | if (rejinfo->with == IPT_ICMP_ECHOREPLY) { |
230 | printk("REJECT: ECHOREPLY no longer supported.\n"); | 224 | printk("ipt_REJECT: ECHOREPLY no longer supported.\n"); |
231 | return 0; | 225 | return false; |
232 | } else if (rejinfo->with == IPT_TCP_RESET) { | 226 | } else if (rejinfo->with == IPT_TCP_RESET) { |
233 | /* Must specify that it's a TCP packet */ | 227 | /* Must specify that it's a TCP packet */ |
234 | if (e->ip.proto != IPPROTO_TCP | 228 | if (e->ip.proto != IPPROTO_TCP |
235 | || (e->ip.invflags & XT_INV_PROTO)) { | 229 | || (e->ip.invflags & XT_INV_PROTO)) { |
236 | DEBUGP("REJECT: TCP_RESET invalid for non-tcp\n"); | 230 | printk("ipt_REJECT: TCP_RESET invalid for non-tcp\n"); |
237 | return 0; | 231 | return false; |
238 | } | 232 | } |
239 | } | 233 | } |
240 | return 1; | 234 | return true; |
241 | } | 235 | } |
242 | 236 | ||
243 | static struct xt_target ipt_reject_reg = { | 237 | static struct xt_target ipt_reject_reg __read_mostly = { |
244 | .name = "REJECT", | 238 | .name = "REJECT", |
245 | .family = AF_INET, | 239 | .family = AF_INET, |
246 | .target = reject, | 240 | .target = reject, |
diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c index 511e5ff84938..97641f1a97f6 100644 --- a/net/ipv4/netfilter/ipt_SAME.c +++ b/net/ipv4/netfilter/ipt_SAME.c | |||
@@ -27,13 +27,7 @@ MODULE_LICENSE("GPL"); | |||
27 | MODULE_AUTHOR("Martin Josefsson <gandalf@wlug.westbo.se>"); | 27 | MODULE_AUTHOR("Martin Josefsson <gandalf@wlug.westbo.se>"); |
28 | MODULE_DESCRIPTION("iptables special SNAT module for consistent sourceip"); | 28 | MODULE_DESCRIPTION("iptables special SNAT module for consistent sourceip"); |
29 | 29 | ||
30 | #if 0 | 30 | static bool |
31 | #define DEBUGP printk | ||
32 | #else | ||
33 | #define DEBUGP(format, args...) | ||
34 | #endif | ||
35 | |||
36 | static int | ||
37 | same_check(const char *tablename, | 31 | same_check(const char *tablename, |
38 | const void *e, | 32 | const void *e, |
39 | const struct xt_target *target, | 33 | const struct xt_target *target, |
@@ -46,58 +40,56 @@ same_check(const char *tablename, | |||
46 | mr->ipnum = 0; | 40 | mr->ipnum = 0; |
47 | 41 | ||
48 | if (mr->rangesize < 1) { | 42 | if (mr->rangesize < 1) { |
49 | DEBUGP("same_check: need at least one dest range.\n"); | 43 | pr_debug("same_check: need at least one dest range.\n"); |
50 | return 0; | 44 | return false; |
51 | } | 45 | } |
52 | if (mr->rangesize > IPT_SAME_MAX_RANGE) { | 46 | if (mr->rangesize > IPT_SAME_MAX_RANGE) { |
53 | DEBUGP("same_check: too many ranges specified, maximum " | 47 | pr_debug("same_check: too many ranges specified, maximum " |
54 | "is %u ranges\n", | 48 | "is %u ranges\n", IPT_SAME_MAX_RANGE); |
55 | IPT_SAME_MAX_RANGE); | 49 | return false; |
56 | return 0; | ||
57 | } | 50 | } |
58 | for (count = 0; count < mr->rangesize; count++) { | 51 | for (count = 0; count < mr->rangesize; count++) { |
59 | if (ntohl(mr->range[count].min_ip) > | 52 | if (ntohl(mr->range[count].min_ip) > |
60 | ntohl(mr->range[count].max_ip)) { | 53 | ntohl(mr->range[count].max_ip)) { |
61 | DEBUGP("same_check: min_ip is larger than max_ip in " | 54 | pr_debug("same_check: min_ip is larger than max_ip in " |
62 | "range `%u.%u.%u.%u-%u.%u.%u.%u'.\n", | 55 | "range `%u.%u.%u.%u-%u.%u.%u.%u'.\n", |
63 | NIPQUAD(mr->range[count].min_ip), | 56 | NIPQUAD(mr->range[count].min_ip), |
64 | NIPQUAD(mr->range[count].max_ip)); | 57 | NIPQUAD(mr->range[count].max_ip)); |
65 | return 0; | 58 | return false; |
66 | } | 59 | } |
67 | if (!(mr->range[count].flags & IP_NAT_RANGE_MAP_IPS)) { | 60 | if (!(mr->range[count].flags & IP_NAT_RANGE_MAP_IPS)) { |
68 | DEBUGP("same_check: bad MAP_IPS.\n"); | 61 | pr_debug("same_check: bad MAP_IPS.\n"); |
69 | return 0; | 62 | return false; |
70 | } | 63 | } |
71 | rangeip = (ntohl(mr->range[count].max_ip) - | 64 | rangeip = (ntohl(mr->range[count].max_ip) - |
72 | ntohl(mr->range[count].min_ip) + 1); | 65 | ntohl(mr->range[count].min_ip) + 1); |
73 | mr->ipnum += rangeip; | 66 | mr->ipnum += rangeip; |
74 | 67 | ||
75 | DEBUGP("same_check: range %u, ipnum = %u\n", count, rangeip); | 68 | pr_debug("same_check: range %u, ipnum = %u\n", count, rangeip); |
76 | } | 69 | } |
77 | DEBUGP("same_check: total ipaddresses = %u\n", mr->ipnum); | 70 | pr_debug("same_check: total ipaddresses = %u\n", mr->ipnum); |
78 | 71 | ||
79 | mr->iparray = kmalloc((sizeof(u_int32_t) * mr->ipnum), GFP_KERNEL); | 72 | mr->iparray = kmalloc((sizeof(u_int32_t) * mr->ipnum), GFP_KERNEL); |
80 | if (!mr->iparray) { | 73 | if (!mr->iparray) { |
81 | DEBUGP("same_check: Couldn't allocate %u bytes " | 74 | pr_debug("same_check: Couldn't allocate %Zu bytes " |
82 | "for %u ipaddresses!\n", | 75 | "for %u ipaddresses!\n", |
83 | (sizeof(u_int32_t) * mr->ipnum), mr->ipnum); | 76 | (sizeof(u_int32_t) * mr->ipnum), mr->ipnum); |
84 | return 0; | 77 | return false; |
85 | } | 78 | } |
86 | DEBUGP("same_check: Allocated %u bytes for %u ipaddresses.\n", | 79 | pr_debug("same_check: Allocated %Zu bytes for %u ipaddresses.\n", |
87 | (sizeof(u_int32_t) * mr->ipnum), mr->ipnum); | 80 | (sizeof(u_int32_t) * mr->ipnum), mr->ipnum); |
88 | 81 | ||
89 | for (count = 0; count < mr->rangesize; count++) { | 82 | for (count = 0; count < mr->rangesize; count++) { |
90 | for (countess = ntohl(mr->range[count].min_ip); | 83 | for (countess = ntohl(mr->range[count].min_ip); |
91 | countess <= ntohl(mr->range[count].max_ip); | 84 | countess <= ntohl(mr->range[count].max_ip); |
92 | countess++) { | 85 | countess++) { |
93 | mr->iparray[index] = countess; | 86 | mr->iparray[index] = countess; |
94 | DEBUGP("same_check: Added ipaddress `%u.%u.%u.%u' " | 87 | pr_debug("same_check: Added ipaddress `%u.%u.%u.%u' " |
95 | "in index %u.\n", | 88 | "in index %u.\n", HIPQUAD(countess), index); |
96 | HIPQUAD(countess), index); | ||
97 | index++; | 89 | index++; |
98 | } | 90 | } |
99 | } | 91 | } |
100 | return 1; | 92 | return true; |
101 | } | 93 | } |
102 | 94 | ||
103 | static void | 95 | static void |
@@ -107,8 +99,8 @@ same_destroy(const struct xt_target *target, void *targinfo) | |||
107 | 99 | ||
108 | kfree(mr->iparray); | 100 | kfree(mr->iparray); |
109 | 101 | ||
110 | DEBUGP("same_destroy: Deallocated %u bytes for %u ipaddresses.\n", | 102 | pr_debug("same_destroy: Deallocated %Zu bytes for %u ipaddresses.\n", |
111 | (sizeof(u_int32_t) * mr->ipnum), mr->ipnum); | 103 | (sizeof(u_int32_t) * mr->ipnum), mr->ipnum); |
112 | } | 104 | } |
113 | 105 | ||
114 | static unsigned int | 106 | static unsigned int |
@@ -146,10 +138,9 @@ same_target(struct sk_buff **pskb, | |||
146 | 138 | ||
147 | new_ip = htonl(same->iparray[aindex]); | 139 | new_ip = htonl(same->iparray[aindex]); |
148 | 140 | ||
149 | DEBUGP("ipt_SAME: src=%u.%u.%u.%u dst=%u.%u.%u.%u, " | 141 | pr_debug("ipt_SAME: src=%u.%u.%u.%u dst=%u.%u.%u.%u, " |
150 | "new src=%u.%u.%u.%u\n", | 142 | "new src=%u.%u.%u.%u\n", |
151 | NIPQUAD(t->src.ip), NIPQUAD(t->dst.ip), | 143 | NIPQUAD(t->src.u3.ip), NIPQUAD(t->dst.u3.ip), NIPQUAD(new_ip)); |
152 | NIPQUAD(new_ip)); | ||
153 | 144 | ||
154 | /* Transfer from original range. */ | 145 | /* Transfer from original range. */ |
155 | newrange = ((struct nf_nat_range) | 146 | newrange = ((struct nf_nat_range) |
@@ -161,7 +152,7 @@ same_target(struct sk_buff **pskb, | |||
161 | return nf_nat_setup_info(ct, &newrange, hooknum); | 152 | return nf_nat_setup_info(ct, &newrange, hooknum); |
162 | } | 153 | } |
163 | 154 | ||
164 | static struct xt_target same_reg = { | 155 | static struct xt_target same_reg __read_mostly = { |
165 | .name = "SAME", | 156 | .name = "SAME", |
166 | .family = AF_INET, | 157 | .family = AF_INET, |
167 | .target = same_target, | 158 | .target = same_target, |
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c index 0ad02f249837..25f5d0b39065 100644 --- a/net/ipv4/netfilter/ipt_TOS.c +++ b/net/ipv4/netfilter/ipt_TOS.c | |||
@@ -43,7 +43,7 @@ target(struct sk_buff **pskb, | |||
43 | return XT_CONTINUE; | 43 | return XT_CONTINUE; |
44 | } | 44 | } |
45 | 45 | ||
46 | static int | 46 | static bool |
47 | checkentry(const char *tablename, | 47 | checkentry(const char *tablename, |
48 | const void *e_void, | 48 | const void *e_void, |
49 | const struct xt_target *target, | 49 | const struct xt_target *target, |
@@ -58,12 +58,12 @@ checkentry(const char *tablename, | |||
58 | && tos != IPTOS_MINCOST | 58 | && tos != IPTOS_MINCOST |
59 | && tos != IPTOS_NORMALSVC) { | 59 | && tos != IPTOS_NORMALSVC) { |
60 | printk(KERN_WARNING "TOS: bad tos value %#x\n", tos); | 60 | printk(KERN_WARNING "TOS: bad tos value %#x\n", tos); |
61 | return 0; | 61 | return false; |
62 | } | 62 | } |
63 | return 1; | 63 | return true; |
64 | } | 64 | } |
65 | 65 | ||
66 | static struct xt_target ipt_tos_reg = { | 66 | static struct xt_target ipt_tos_reg __read_mostly = { |
67 | .name = "TOS", | 67 | .name = "TOS", |
68 | .family = AF_INET, | 68 | .family = AF_INET, |
69 | .target = target, | 69 | .target = target, |
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c index a991ec7bd4e7..2b54e7b0cfe8 100644 --- a/net/ipv4/netfilter/ipt_TTL.c +++ b/net/ipv4/netfilter/ipt_TTL.c | |||
@@ -62,25 +62,25 @@ ipt_ttl_target(struct sk_buff **pskb, | |||
62 | return XT_CONTINUE; | 62 | return XT_CONTINUE; |
63 | } | 63 | } |
64 | 64 | ||
65 | static int ipt_ttl_checkentry(const char *tablename, | 65 | static bool ipt_ttl_checkentry(const char *tablename, |
66 | const void *e, | 66 | const void *e, |
67 | const struct xt_target *target, | 67 | const struct xt_target *target, |
68 | void *targinfo, | 68 | void *targinfo, |
69 | unsigned int hook_mask) | 69 | unsigned int hook_mask) |
70 | { | 70 | { |
71 | struct ipt_TTL_info *info = targinfo; | 71 | const struct ipt_TTL_info *info = targinfo; |
72 | 72 | ||
73 | if (info->mode > IPT_TTL_MAXMODE) { | 73 | if (info->mode > IPT_TTL_MAXMODE) { |
74 | printk(KERN_WARNING "ipt_TTL: invalid or unknown Mode %u\n", | 74 | printk(KERN_WARNING "ipt_TTL: invalid or unknown Mode %u\n", |
75 | info->mode); | 75 | info->mode); |
76 | return 0; | 76 | return false; |
77 | } | 77 | } |
78 | if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) | 78 | if (info->mode != IPT_TTL_SET && info->ttl == 0) |
79 | return 0; | 79 | return false; |
80 | return 1; | 80 | return true; |
81 | } | 81 | } |
82 | 82 | ||
83 | static struct xt_target ipt_TTL = { | 83 | static struct xt_target ipt_TTL __read_mostly = { |
84 | .name = "TTL", | 84 | .name = "TTL", |
85 | .family = AF_INET, | 85 | .family = AF_INET, |
86 | .target = ipt_ttl_target, | 86 | .target = ipt_ttl_target, |
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index 23b607b33b32..6ca43e4ca7e3 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c | |||
@@ -55,13 +55,6 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NFLOG); | |||
55 | #define ULOG_NL_EVENT 111 /* Harald's favorite number */ | 55 | #define ULOG_NL_EVENT 111 /* Harald's favorite number */ |
56 | #define ULOG_MAXNLGROUPS 32 /* numer of nlgroups */ | 56 | #define ULOG_MAXNLGROUPS 32 /* numer of nlgroups */ |
57 | 57 | ||
58 | #if 0 | ||
59 | #define DEBUGP(format, args...) printk("%s:%s:" format, \ | ||
60 | __FILE__, __FUNCTION__ , ## args) | ||
61 | #else | ||
62 | #define DEBUGP(format, args...) | ||
63 | #endif | ||
64 | |||
65 | #define PRINTR(format, args...) do { if (net_ratelimit()) printk(format , ## args); } while (0) | 58 | #define PRINTR(format, args...) do { if (net_ratelimit()) printk(format , ## args); } while (0) |
66 | 59 | ||
67 | static unsigned int nlbufsiz = NLMSG_GOODSIZE; | 60 | static unsigned int nlbufsiz = NLMSG_GOODSIZE; |
@@ -96,12 +89,12 @@ static void ulog_send(unsigned int nlgroupnum) | |||
96 | ulog_buff_t *ub = &ulog_buffers[nlgroupnum]; | 89 | ulog_buff_t *ub = &ulog_buffers[nlgroupnum]; |
97 | 90 | ||
98 | if (timer_pending(&ub->timer)) { | 91 | if (timer_pending(&ub->timer)) { |
99 | DEBUGP("ipt_ULOG: ulog_send: timer was pending, deleting\n"); | 92 | pr_debug("ipt_ULOG: ulog_send: timer was pending, deleting\n"); |
100 | del_timer(&ub->timer); | 93 | del_timer(&ub->timer); |
101 | } | 94 | } |
102 | 95 | ||
103 | if (!ub->skb) { | 96 | if (!ub->skb) { |
104 | DEBUGP("ipt_ULOG: ulog_send: nothing to send\n"); | 97 | pr_debug("ipt_ULOG: ulog_send: nothing to send\n"); |
105 | return; | 98 | return; |
106 | } | 99 | } |
107 | 100 | ||
@@ -110,8 +103,8 @@ static void ulog_send(unsigned int nlgroupnum) | |||
110 | ub->lastnlh->nlmsg_type = NLMSG_DONE; | 103 | ub->lastnlh->nlmsg_type = NLMSG_DONE; |
111 | 104 | ||
112 | NETLINK_CB(ub->skb).dst_group = nlgroupnum + 1; | 105 | NETLINK_CB(ub->skb).dst_group = nlgroupnum + 1; |
113 | DEBUGP("ipt_ULOG: throwing %d packets to netlink group %u\n", | 106 | pr_debug("ipt_ULOG: throwing %d packets to netlink group %u\n", |
114 | ub->qlen, nlgroupnum + 1); | 107 | ub->qlen, nlgroupnum + 1); |
115 | netlink_broadcast(nflognl, ub->skb, 0, nlgroupnum + 1, GFP_ATOMIC); | 108 | netlink_broadcast(nflognl, ub->skb, 0, nlgroupnum + 1, GFP_ATOMIC); |
116 | 109 | ||
117 | ub->qlen = 0; | 110 | ub->qlen = 0; |
@@ -123,7 +116,7 @@ static void ulog_send(unsigned int nlgroupnum) | |||
123 | /* timer function to flush queue in flushtimeout time */ | 116 | /* timer function to flush queue in flushtimeout time */ |
124 | static void ulog_timer(unsigned long data) | 117 | static void ulog_timer(unsigned long data) |
125 | { | 118 | { |
126 | DEBUGP("ipt_ULOG: timer function called, calling ulog_send\n"); | 119 | pr_debug("ipt_ULOG: timer function called, calling ulog_send\n"); |
127 | 120 | ||
128 | /* lock to protect against somebody modifying our structure | 121 | /* lock to protect against somebody modifying our structure |
129 | * from ipt_ulog_target at the same time */ | 122 | * from ipt_ulog_target at the same time */ |
@@ -179,12 +172,10 @@ static void ipt_ulog_packet(unsigned int hooknum, | |||
179 | unsigned int groupnum = ffs(loginfo->nl_group) - 1; | 172 | unsigned int groupnum = ffs(loginfo->nl_group) - 1; |
180 | 173 | ||
181 | /* calculate the size of the skb needed */ | 174 | /* calculate the size of the skb needed */ |
182 | if ((loginfo->copy_range == 0) || | 175 | if (loginfo->copy_range == 0 || loginfo->copy_range > skb->len) |
183 | (loginfo->copy_range > skb->len)) { | ||
184 | copy_len = skb->len; | 176 | copy_len = skb->len; |
185 | } else { | 177 | else |
186 | copy_len = loginfo->copy_range; | 178 | copy_len = loginfo->copy_range; |
187 | } | ||
188 | 179 | ||
189 | size = NLMSG_SPACE(sizeof(*pm) + copy_len); | 180 | size = NLMSG_SPACE(sizeof(*pm) + copy_len); |
190 | 181 | ||
@@ -206,8 +197,8 @@ static void ipt_ulog_packet(unsigned int hooknum, | |||
206 | goto alloc_failure; | 197 | goto alloc_failure; |
207 | } | 198 | } |
208 | 199 | ||
209 | DEBUGP("ipt_ULOG: qlen %d, qthreshold %d\n", ub->qlen, | 200 | pr_debug("ipt_ULOG: qlen %d, qthreshold %Zu\n", ub->qlen, |
210 | loginfo->qthreshold); | 201 | loginfo->qthreshold); |
211 | 202 | ||
212 | /* NLMSG_PUT contains a hidden goto nlmsg_failure !!! */ | 203 | /* NLMSG_PUT contains a hidden goto nlmsg_failure !!! */ |
213 | nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, ULOG_NL_EVENT, | 204 | nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, ULOG_NL_EVENT, |
@@ -257,9 +248,8 @@ static void ipt_ulog_packet(unsigned int hooknum, | |||
257 | BUG(); | 248 | BUG(); |
258 | 249 | ||
259 | /* check if we are building multi-part messages */ | 250 | /* check if we are building multi-part messages */ |
260 | if (ub->qlen > 1) { | 251 | if (ub->qlen > 1) |
261 | ub->lastnlh->nlmsg_flags |= NLM_F_MULTI; | 252 | ub->lastnlh->nlmsg_flags |= NLM_F_MULTI; |
262 | } | ||
263 | 253 | ||
264 | ub->lastnlh = nlh; | 254 | ub->lastnlh = nlh; |
265 | 255 | ||
@@ -328,25 +318,25 @@ static void ipt_logfn(unsigned int pf, | |||
328 | ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix); | 318 | ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix); |
329 | } | 319 | } |
330 | 320 | ||
331 | static int ipt_ulog_checkentry(const char *tablename, | 321 | static bool ipt_ulog_checkentry(const char *tablename, |
332 | const void *e, | 322 | const void *e, |
333 | const struct xt_target *target, | 323 | const struct xt_target *target, |
334 | void *targinfo, | 324 | void *targinfo, |
335 | unsigned int hookmask) | 325 | unsigned int hookmask) |
336 | { | 326 | { |
337 | struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo; | 327 | const struct ipt_ulog_info *loginfo = targinfo; |
338 | 328 | ||
339 | if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') { | 329 | if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') { |
340 | DEBUGP("ipt_ULOG: prefix term %i\n", | 330 | pr_debug("ipt_ULOG: prefix term %i\n", |
341 | loginfo->prefix[sizeof(loginfo->prefix) - 1]); | 331 | loginfo->prefix[sizeof(loginfo->prefix) - 1]); |
342 | return 0; | 332 | return false; |
343 | } | 333 | } |
344 | if (loginfo->qthreshold > ULOG_MAX_QLEN) { | 334 | if (loginfo->qthreshold > ULOG_MAX_QLEN) { |
345 | DEBUGP("ipt_ULOG: queue threshold %i > MAX_QLEN\n", | 335 | pr_debug("ipt_ULOG: queue threshold %Zu > MAX_QLEN\n", |
346 | loginfo->qthreshold); | 336 | loginfo->qthreshold); |
347 | return 0; | 337 | return false; |
348 | } | 338 | } |
349 | return 1; | 339 | return true; |
350 | } | 340 | } |
351 | 341 | ||
352 | #ifdef CONFIG_COMPAT | 342 | #ifdef CONFIG_COMPAT |
@@ -359,7 +349,7 @@ struct compat_ipt_ulog_info { | |||
359 | 349 | ||
360 | static void compat_from_user(void *dst, void *src) | 350 | static void compat_from_user(void *dst, void *src) |
361 | { | 351 | { |
362 | struct compat_ipt_ulog_info *cl = src; | 352 | const struct compat_ipt_ulog_info *cl = src; |
363 | struct ipt_ulog_info l = { | 353 | struct ipt_ulog_info l = { |
364 | .nl_group = cl->nl_group, | 354 | .nl_group = cl->nl_group, |
365 | .copy_range = cl->copy_range, | 355 | .copy_range = cl->copy_range, |
@@ -372,7 +362,7 @@ static void compat_from_user(void *dst, void *src) | |||
372 | 362 | ||
373 | static int compat_to_user(void __user *dst, void *src) | 363 | static int compat_to_user(void __user *dst, void *src) |
374 | { | 364 | { |
375 | struct ipt_ulog_info *l = src; | 365 | const struct ipt_ulog_info *l = src; |
376 | struct compat_ipt_ulog_info cl = { | 366 | struct compat_ipt_ulog_info cl = { |
377 | .nl_group = l->nl_group, | 367 | .nl_group = l->nl_group, |
378 | .copy_range = l->copy_range, | 368 | .copy_range = l->copy_range, |
@@ -384,7 +374,7 @@ static int compat_to_user(void __user *dst, void *src) | |||
384 | } | 374 | } |
385 | #endif /* CONFIG_COMPAT */ | 375 | #endif /* CONFIG_COMPAT */ |
386 | 376 | ||
387 | static struct xt_target ipt_ulog_reg = { | 377 | static struct xt_target ipt_ulog_reg __read_mostly = { |
388 | .name = "ULOG", | 378 | .name = "ULOG", |
389 | .family = AF_INET, | 379 | .family = AF_INET, |
390 | .target = ipt_ulog_target, | 380 | .target = ipt_ulog_target, |
@@ -408,7 +398,7 @@ static int __init ipt_ulog_init(void) | |||
408 | { | 398 | { |
409 | int ret, i; | 399 | int ret, i; |
410 | 400 | ||
411 | DEBUGP("ipt_ULOG: init module\n"); | 401 | pr_debug("ipt_ULOG: init module\n"); |
412 | 402 | ||
413 | if (nlbufsiz > 128*1024) { | 403 | if (nlbufsiz > 128*1024) { |
414 | printk("Netlink buffer has to be <= 128kB\n"); | 404 | printk("Netlink buffer has to be <= 128kB\n"); |
@@ -440,7 +430,7 @@ static void __exit ipt_ulog_fini(void) | |||
440 | ulog_buff_t *ub; | 430 | ulog_buff_t *ub; |
441 | int i; | 431 | int i; |
442 | 432 | ||
443 | DEBUGP("ipt_ULOG: cleanup_module\n"); | 433 | pr_debug("ipt_ULOG: cleanup_module\n"); |
444 | 434 | ||
445 | if (nflog) | 435 | if (nflog) |
446 | nf_log_unregister(&ipt_ulog_logger); | 436 | nf_log_unregister(&ipt_ulog_logger); |
@@ -451,7 +441,7 @@ static void __exit ipt_ulog_fini(void) | |||
451 | for (i = 0; i < ULOG_MAXNLGROUPS; i++) { | 441 | for (i = 0; i < ULOG_MAXNLGROUPS; i++) { |
452 | ub = &ulog_buffers[i]; | 442 | ub = &ulog_buffers[i]; |
453 | if (timer_pending(&ub->timer)) { | 443 | if (timer_pending(&ub->timer)) { |
454 | DEBUGP("timer was pending, deleting\n"); | 444 | pr_debug("timer was pending, deleting\n"); |
455 | del_timer(&ub->timer); | 445 | del_timer(&ub->timer); |
456 | } | 446 | } |
457 | 447 | ||
diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c index a652a1451552..59f01f7ba6b4 100644 --- a/net/ipv4/netfilter/ipt_addrtype.c +++ b/net/ipv4/netfilter/ipt_addrtype.c | |||
@@ -22,19 +22,19 @@ MODULE_LICENSE("GPL"); | |||
22 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | 22 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); |
23 | MODULE_DESCRIPTION("iptables addrtype match"); | 23 | MODULE_DESCRIPTION("iptables addrtype match"); |
24 | 24 | ||
25 | static inline int match_type(__be32 addr, u_int16_t mask) | 25 | static inline bool match_type(__be32 addr, u_int16_t mask) |
26 | { | 26 | { |
27 | return !!(mask & (1 << inet_addr_type(addr))); | 27 | return !!(mask & (1 << inet_addr_type(addr))); |
28 | } | 28 | } |
29 | 29 | ||
30 | static int match(const struct sk_buff *skb, | 30 | static bool match(const struct sk_buff *skb, |
31 | const struct net_device *in, const struct net_device *out, | 31 | const struct net_device *in, const struct net_device *out, |
32 | const struct xt_match *match, const void *matchinfo, | 32 | const struct xt_match *match, const void *matchinfo, |
33 | int offset, unsigned int protoff, int *hotdrop) | 33 | int offset, unsigned int protoff, bool *hotdrop) |
34 | { | 34 | { |
35 | const struct ipt_addrtype_info *info = matchinfo; | 35 | const struct ipt_addrtype_info *info = matchinfo; |
36 | const struct iphdr *iph = ip_hdr(skb); | 36 | const struct iphdr *iph = ip_hdr(skb); |
37 | int ret = 1; | 37 | bool ret = true; |
38 | 38 | ||
39 | if (info->source) | 39 | if (info->source) |
40 | ret &= match_type(iph->saddr, info->source)^info->invert_source; | 40 | ret &= match_type(iph->saddr, info->source)^info->invert_source; |
@@ -44,7 +44,7 @@ static int match(const struct sk_buff *skb, | |||
44 | return ret; | 44 | return ret; |
45 | } | 45 | } |
46 | 46 | ||
47 | static struct xt_match addrtype_match = { | 47 | static struct xt_match addrtype_match __read_mostly = { |
48 | .name = "addrtype", | 48 | .name = "addrtype", |
49 | .family = AF_INET, | 49 | .family = AF_INET, |
50 | .match = match, | 50 | .match = match, |
diff --git a/net/ipv4/netfilter/ipt_ah.c b/net/ipv4/netfilter/ipt_ah.c index 18a16782cf40..61b017fd743c 100644 --- a/net/ipv4/netfilter/ipt_ah.c +++ b/net/ipv4/netfilter/ipt_ah.c | |||
@@ -25,10 +25,10 @@ MODULE_DESCRIPTION("iptables AH SPI match module"); | |||
25 | #endif | 25 | #endif |
26 | 26 | ||
27 | /* Returns 1 if the spi is matched by the range, 0 otherwise */ | 27 | /* Returns 1 if the spi is matched by the range, 0 otherwise */ |
28 | static inline int | 28 | static inline bool |
29 | spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert) | 29 | spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert) |
30 | { | 30 | { |
31 | int r=0; | 31 | bool r; |
32 | duprintf("ah spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ', | 32 | duprintf("ah spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ', |
33 | min,spi,max); | 33 | min,spi,max); |
34 | r=(spi >= min && spi <= max) ^ invert; | 34 | r=(spi >= min && spi <= max) ^ invert; |
@@ -36,7 +36,7 @@ spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert) | |||
36 | return r; | 36 | return r; |
37 | } | 37 | } |
38 | 38 | ||
39 | static int | 39 | static bool |
40 | match(const struct sk_buff *skb, | 40 | match(const struct sk_buff *skb, |
41 | const struct net_device *in, | 41 | const struct net_device *in, |
42 | const struct net_device *out, | 42 | const struct net_device *out, |
@@ -44,14 +44,15 @@ match(const struct sk_buff *skb, | |||
44 | const void *matchinfo, | 44 | const void *matchinfo, |
45 | int offset, | 45 | int offset, |
46 | unsigned int protoff, | 46 | unsigned int protoff, |
47 | int *hotdrop) | 47 | bool *hotdrop) |
48 | { | 48 | { |
49 | struct ip_auth_hdr _ahdr, *ah; | 49 | struct ip_auth_hdr _ahdr; |
50 | const struct ip_auth_hdr *ah; | ||
50 | const struct ipt_ah *ahinfo = matchinfo; | 51 | const struct ipt_ah *ahinfo = matchinfo; |
51 | 52 | ||
52 | /* Must not be a fragment. */ | 53 | /* Must not be a fragment. */ |
53 | if (offset) | 54 | if (offset) |
54 | return 0; | 55 | return false; |
55 | 56 | ||
56 | ah = skb_header_pointer(skb, protoff, | 57 | ah = skb_header_pointer(skb, protoff, |
57 | sizeof(_ahdr), &_ahdr); | 58 | sizeof(_ahdr), &_ahdr); |
@@ -60,7 +61,7 @@ match(const struct sk_buff *skb, | |||
60 | * can't. Hence, no choice but to drop. | 61 | * can't. Hence, no choice but to drop. |
61 | */ | 62 | */ |
62 | duprintf("Dropping evil AH tinygram.\n"); | 63 | duprintf("Dropping evil AH tinygram.\n"); |
63 | *hotdrop = 1; | 64 | *hotdrop = true; |
64 | return 0; | 65 | return 0; |
65 | } | 66 | } |
66 | 67 | ||
@@ -70,7 +71,7 @@ match(const struct sk_buff *skb, | |||
70 | } | 71 | } |
71 | 72 | ||
72 | /* Called when user tries to insert an entry of this type. */ | 73 | /* Called when user tries to insert an entry of this type. */ |
73 | static int | 74 | static bool |
74 | checkentry(const char *tablename, | 75 | checkentry(const char *tablename, |
75 | const void *ip_void, | 76 | const void *ip_void, |
76 | const struct xt_match *match, | 77 | const struct xt_match *match, |
@@ -82,12 +83,12 @@ checkentry(const char *tablename, | |||
82 | /* Must specify no unknown invflags */ | 83 | /* Must specify no unknown invflags */ |
83 | if (ahinfo->invflags & ~IPT_AH_INV_MASK) { | 84 | if (ahinfo->invflags & ~IPT_AH_INV_MASK) { |
84 | duprintf("ipt_ah: unknown flags %X\n", ahinfo->invflags); | 85 | duprintf("ipt_ah: unknown flags %X\n", ahinfo->invflags); |
85 | return 0; | 86 | return false; |
86 | } | 87 | } |
87 | return 1; | 88 | return true; |
88 | } | 89 | } |
89 | 90 | ||
90 | static struct xt_match ah_match = { | 91 | static struct xt_match ah_match __read_mostly = { |
91 | .name = "ah", | 92 | .name = "ah", |
92 | .family = AF_INET, | 93 | .family = AF_INET, |
93 | .match = match, | 94 | .match = match, |
diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c index 26218122f865..d6925c674069 100644 --- a/net/ipv4/netfilter/ipt_ecn.c +++ b/net/ipv4/netfilter/ipt_ecn.c | |||
@@ -22,95 +22,96 @@ MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | |||
22 | MODULE_DESCRIPTION("iptables ECN matching module"); | 22 | MODULE_DESCRIPTION("iptables ECN matching module"); |
23 | MODULE_LICENSE("GPL"); | 23 | MODULE_LICENSE("GPL"); |
24 | 24 | ||
25 | static inline int match_ip(const struct sk_buff *skb, | 25 | static inline bool match_ip(const struct sk_buff *skb, |
26 | const struct ipt_ecn_info *einfo) | 26 | const struct ipt_ecn_info *einfo) |
27 | { | 27 | { |
28 | return (ip_hdr(skb)->tos & IPT_ECN_IP_MASK) == einfo->ip_ect; | 28 | return (ip_hdr(skb)->tos & IPT_ECN_IP_MASK) == einfo->ip_ect; |
29 | } | 29 | } |
30 | 30 | ||
31 | static inline int match_tcp(const struct sk_buff *skb, | 31 | static inline bool match_tcp(const struct sk_buff *skb, |
32 | const struct ipt_ecn_info *einfo, | 32 | const struct ipt_ecn_info *einfo, |
33 | int *hotdrop) | 33 | bool *hotdrop) |
34 | { | 34 | { |
35 | struct tcphdr _tcph, *th; | 35 | struct tcphdr _tcph; |
36 | const struct tcphdr *th; | ||
36 | 37 | ||
37 | /* In practice, TCP match does this, so can't fail. But let's | 38 | /* In practice, TCP match does this, so can't fail. But let's |
38 | * be good citizens. | 39 | * be good citizens. |
39 | */ | 40 | */ |
40 | th = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_tcph), &_tcph); | 41 | th = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_tcph), &_tcph); |
41 | if (th == NULL) { | 42 | if (th == NULL) { |
42 | *hotdrop = 0; | 43 | *hotdrop = false; |
43 | return 0; | 44 | return false; |
44 | } | 45 | } |
45 | 46 | ||
46 | if (einfo->operation & IPT_ECN_OP_MATCH_ECE) { | 47 | if (einfo->operation & IPT_ECN_OP_MATCH_ECE) { |
47 | if (einfo->invert & IPT_ECN_OP_MATCH_ECE) { | 48 | if (einfo->invert & IPT_ECN_OP_MATCH_ECE) { |
48 | if (th->ece == 1) | 49 | if (th->ece == 1) |
49 | return 0; | 50 | return false; |
50 | } else { | 51 | } else { |
51 | if (th->ece == 0) | 52 | if (th->ece == 0) |
52 | return 0; | 53 | return false; |
53 | } | 54 | } |
54 | } | 55 | } |
55 | 56 | ||
56 | if (einfo->operation & IPT_ECN_OP_MATCH_CWR) { | 57 | if (einfo->operation & IPT_ECN_OP_MATCH_CWR) { |
57 | if (einfo->invert & IPT_ECN_OP_MATCH_CWR) { | 58 | if (einfo->invert & IPT_ECN_OP_MATCH_CWR) { |
58 | if (th->cwr == 1) | 59 | if (th->cwr == 1) |
59 | return 0; | 60 | return false; |
60 | } else { | 61 | } else { |
61 | if (th->cwr == 0) | 62 | if (th->cwr == 0) |
62 | return 0; | 63 | return false; |
63 | } | 64 | } |
64 | } | 65 | } |
65 | 66 | ||
66 | return 1; | 67 | return true; |
67 | } | 68 | } |
68 | 69 | ||
69 | static int match(const struct sk_buff *skb, | 70 | static bool match(const struct sk_buff *skb, |
70 | const struct net_device *in, const struct net_device *out, | 71 | const struct net_device *in, const struct net_device *out, |
71 | const struct xt_match *match, const void *matchinfo, | 72 | const struct xt_match *match, const void *matchinfo, |
72 | int offset, unsigned int protoff, int *hotdrop) | 73 | int offset, unsigned int protoff, bool *hotdrop) |
73 | { | 74 | { |
74 | const struct ipt_ecn_info *info = matchinfo; | 75 | const struct ipt_ecn_info *info = matchinfo; |
75 | 76 | ||
76 | if (info->operation & IPT_ECN_OP_MATCH_IP) | 77 | if (info->operation & IPT_ECN_OP_MATCH_IP) |
77 | if (!match_ip(skb, info)) | 78 | if (!match_ip(skb, info)) |
78 | return 0; | 79 | return false; |
79 | 80 | ||
80 | if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)) { | 81 | if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)) { |
81 | if (ip_hdr(skb)->protocol != IPPROTO_TCP) | 82 | if (ip_hdr(skb)->protocol != IPPROTO_TCP) |
82 | return 0; | 83 | return false; |
83 | if (!match_tcp(skb, info, hotdrop)) | 84 | if (!match_tcp(skb, info, hotdrop)) |
84 | return 0; | 85 | return false; |
85 | } | 86 | } |
86 | 87 | ||
87 | return 1; | 88 | return true; |
88 | } | 89 | } |
89 | 90 | ||
90 | static int checkentry(const char *tablename, const void *ip_void, | 91 | static bool checkentry(const char *tablename, const void *ip_void, |
91 | const struct xt_match *match, | 92 | const struct xt_match *match, |
92 | void *matchinfo, unsigned int hook_mask) | 93 | void *matchinfo, unsigned int hook_mask) |
93 | { | 94 | { |
94 | const struct ipt_ecn_info *info = matchinfo; | 95 | const struct ipt_ecn_info *info = matchinfo; |
95 | const struct ipt_ip *ip = ip_void; | 96 | const struct ipt_ip *ip = ip_void; |
96 | 97 | ||
97 | if (info->operation & IPT_ECN_OP_MATCH_MASK) | 98 | if (info->operation & IPT_ECN_OP_MATCH_MASK) |
98 | return 0; | 99 | return false; |
99 | 100 | ||
100 | if (info->invert & IPT_ECN_OP_MATCH_MASK) | 101 | if (info->invert & IPT_ECN_OP_MATCH_MASK) |
101 | return 0; | 102 | return false; |
102 | 103 | ||
103 | if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR) | 104 | if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR) |
104 | && ip->proto != IPPROTO_TCP) { | 105 | && ip->proto != IPPROTO_TCP) { |
105 | printk(KERN_WARNING "ipt_ecn: can't match TCP bits in rule for" | 106 | printk(KERN_WARNING "ipt_ecn: can't match TCP bits in rule for" |
106 | " non-tcp packets\n"); | 107 | " non-tcp packets\n"); |
107 | return 0; | 108 | return false; |
108 | } | 109 | } |
109 | 110 | ||
110 | return 1; | 111 | return true; |
111 | } | 112 | } |
112 | 113 | ||
113 | static struct xt_match ecn_match = { | 114 | static struct xt_match ecn_match __read_mostly = { |
114 | .name = "ecn", | 115 | .name = "ecn", |
115 | .family = AF_INET, | 116 | .family = AF_INET, |
116 | .match = match, | 117 | .match = match, |
diff --git a/net/ipv4/netfilter/ipt_iprange.c b/net/ipv4/netfilter/ipt_iprange.c index 33af9e940887..0106dc955a69 100644 --- a/net/ipv4/netfilter/ipt_iprange.c +++ b/net/ipv4/netfilter/ipt_iprange.c | |||
@@ -17,53 +17,47 @@ MODULE_LICENSE("GPL"); | |||
17 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); | 17 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); |
18 | MODULE_DESCRIPTION("iptables arbitrary IP range match module"); | 18 | MODULE_DESCRIPTION("iptables arbitrary IP range match module"); |
19 | 19 | ||
20 | #if 0 | 20 | static bool |
21 | #define DEBUGP printk | ||
22 | #else | ||
23 | #define DEBUGP(format, args...) | ||
24 | #endif | ||
25 | |||
26 | static int | ||
27 | match(const struct sk_buff *skb, | 21 | match(const struct sk_buff *skb, |
28 | const struct net_device *in, | 22 | const struct net_device *in, |
29 | const struct net_device *out, | 23 | const struct net_device *out, |
30 | const struct xt_match *match, | 24 | const struct xt_match *match, |
31 | const void *matchinfo, | 25 | const void *matchinfo, |
32 | int offset, unsigned int protoff, int *hotdrop) | 26 | int offset, unsigned int protoff, bool *hotdrop) |
33 | { | 27 | { |
34 | const struct ipt_iprange_info *info = matchinfo; | 28 | const struct ipt_iprange_info *info = matchinfo; |
35 | const struct iphdr *iph = ip_hdr(skb); | 29 | const struct iphdr *iph = ip_hdr(skb); |
36 | 30 | ||
37 | if (info->flags & IPRANGE_SRC) { | 31 | if (info->flags & IPRANGE_SRC) { |
38 | if (((ntohl(iph->saddr) < ntohl(info->src.min_ip)) | 32 | if ((ntohl(iph->saddr) < ntohl(info->src.min_ip) |
39 | || (ntohl(iph->saddr) > ntohl(info->src.max_ip))) | 33 | || ntohl(iph->saddr) > ntohl(info->src.max_ip)) |
40 | ^ !!(info->flags & IPRANGE_SRC_INV)) { | 34 | ^ !!(info->flags & IPRANGE_SRC_INV)) { |
41 | DEBUGP("src IP %u.%u.%u.%u NOT in range %s" | 35 | pr_debug("src IP %u.%u.%u.%u NOT in range %s" |
42 | "%u.%u.%u.%u-%u.%u.%u.%u\n", | 36 | "%u.%u.%u.%u-%u.%u.%u.%u\n", |
43 | NIPQUAD(iph->saddr), | 37 | NIPQUAD(iph->saddr), |
44 | info->flags & IPRANGE_SRC_INV ? "(INV) " : "", | 38 | info->flags & IPRANGE_SRC_INV ? "(INV) " : "", |
45 | NIPQUAD(info->src.min_ip), | 39 | NIPQUAD(info->src.min_ip), |
46 | NIPQUAD(info->src.max_ip)); | 40 | NIPQUAD(info->src.max_ip)); |
47 | return 0; | 41 | return false; |
48 | } | 42 | } |
49 | } | 43 | } |
50 | if (info->flags & IPRANGE_DST) { | 44 | if (info->flags & IPRANGE_DST) { |
51 | if (((ntohl(iph->daddr) < ntohl(info->dst.min_ip)) | 45 | if ((ntohl(iph->daddr) < ntohl(info->dst.min_ip) |
52 | || (ntohl(iph->daddr) > ntohl(info->dst.max_ip))) | 46 | || ntohl(iph->daddr) > ntohl(info->dst.max_ip)) |
53 | ^ !!(info->flags & IPRANGE_DST_INV)) { | 47 | ^ !!(info->flags & IPRANGE_DST_INV)) { |
54 | DEBUGP("dst IP %u.%u.%u.%u NOT in range %s" | 48 | pr_debug("dst IP %u.%u.%u.%u NOT in range %s" |
55 | "%u.%u.%u.%u-%u.%u.%u.%u\n", | 49 | "%u.%u.%u.%u-%u.%u.%u.%u\n", |
56 | NIPQUAD(iph->daddr), | 50 | NIPQUAD(iph->daddr), |
57 | info->flags & IPRANGE_DST_INV ? "(INV) " : "", | 51 | info->flags & IPRANGE_DST_INV ? "(INV) " : "", |
58 | NIPQUAD(info->dst.min_ip), | 52 | NIPQUAD(info->dst.min_ip), |
59 | NIPQUAD(info->dst.max_ip)); | 53 | NIPQUAD(info->dst.max_ip)); |
60 | return 0; | 54 | return false; |
61 | } | 55 | } |
62 | } | 56 | } |
63 | return 1; | 57 | return true; |
64 | } | 58 | } |
65 | 59 | ||
66 | static struct xt_match iprange_match = { | 60 | static struct xt_match iprange_match __read_mostly = { |
67 | .name = "iprange", | 61 | .name = "iprange", |
68 | .family = AF_INET, | 62 | .family = AF_INET, |
69 | .match = match, | 63 | .match = match, |
diff --git a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c index 7fae9aa8944c..b14e77da7a33 100644 --- a/net/ipv4/netfilter/ipt_owner.c +++ b/net/ipv4/netfilter/ipt_owner.c | |||
@@ -21,7 +21,7 @@ MODULE_LICENSE("GPL"); | |||
21 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); | 21 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); |
22 | MODULE_DESCRIPTION("iptables owner match"); | 22 | MODULE_DESCRIPTION("iptables owner match"); |
23 | 23 | ||
24 | static int | 24 | static bool |
25 | match(const struct sk_buff *skb, | 25 | match(const struct sk_buff *skb, |
26 | const struct net_device *in, | 26 | const struct net_device *in, |
27 | const struct net_device *out, | 27 | const struct net_device *out, |
@@ -29,29 +29,29 @@ match(const struct sk_buff *skb, | |||
29 | const void *matchinfo, | 29 | const void *matchinfo, |
30 | int offset, | 30 | int offset, |
31 | unsigned int protoff, | 31 | unsigned int protoff, |
32 | int *hotdrop) | 32 | bool *hotdrop) |
33 | { | 33 | { |
34 | const struct ipt_owner_info *info = matchinfo; | 34 | const struct ipt_owner_info *info = matchinfo; |
35 | 35 | ||
36 | if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file) | 36 | if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file) |
37 | return 0; | 37 | return false; |
38 | 38 | ||
39 | if(info->match & IPT_OWNER_UID) { | 39 | if(info->match & IPT_OWNER_UID) { |
40 | if ((skb->sk->sk_socket->file->f_uid != info->uid) ^ | 40 | if ((skb->sk->sk_socket->file->f_uid != info->uid) ^ |
41 | !!(info->invert & IPT_OWNER_UID)) | 41 | !!(info->invert & IPT_OWNER_UID)) |
42 | return 0; | 42 | return false; |
43 | } | 43 | } |
44 | 44 | ||
45 | if(info->match & IPT_OWNER_GID) { | 45 | if(info->match & IPT_OWNER_GID) { |
46 | if ((skb->sk->sk_socket->file->f_gid != info->gid) ^ | 46 | if ((skb->sk->sk_socket->file->f_gid != info->gid) ^ |
47 | !!(info->invert & IPT_OWNER_GID)) | 47 | !!(info->invert & IPT_OWNER_GID)) |
48 | return 0; | 48 | return false; |
49 | } | 49 | } |
50 | 50 | ||
51 | return 1; | 51 | return true; |
52 | } | 52 | } |
53 | 53 | ||
54 | static int | 54 | static bool |
55 | checkentry(const char *tablename, | 55 | checkentry(const char *tablename, |
56 | const void *ip, | 56 | const void *ip, |
57 | const struct xt_match *match, | 57 | const struct xt_match *match, |
@@ -63,12 +63,12 @@ checkentry(const char *tablename, | |||
63 | if (info->match & (IPT_OWNER_PID|IPT_OWNER_SID|IPT_OWNER_COMM)) { | 63 | if (info->match & (IPT_OWNER_PID|IPT_OWNER_SID|IPT_OWNER_COMM)) { |
64 | printk("ipt_owner: pid, sid and command matching " | 64 | printk("ipt_owner: pid, sid and command matching " |
65 | "not supported anymore\n"); | 65 | "not supported anymore\n"); |
66 | return 0; | 66 | return false; |
67 | } | 67 | } |
68 | return 1; | 68 | return true; |
69 | } | 69 | } |
70 | 70 | ||
71 | static struct xt_match owner_match = { | 71 | static struct xt_match owner_match __read_mostly = { |
72 | .name = "owner", | 72 | .name = "owner", |
73 | .family = AF_INET, | 73 | .family = AF_INET, |
74 | .match = match, | 74 | .match = match, |
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c index 15a9e8bbb7cc..321804315659 100644 --- a/net/ipv4/netfilter/ipt_recent.c +++ b/net/ipv4/netfilter/ipt_recent.c | |||
@@ -163,24 +163,23 @@ static void recent_table_flush(struct recent_table *t) | |||
163 | struct recent_entry *e, *next; | 163 | struct recent_entry *e, *next; |
164 | unsigned int i; | 164 | unsigned int i; |
165 | 165 | ||
166 | for (i = 0; i < ip_list_hash_size; i++) { | 166 | for (i = 0; i < ip_list_hash_size; i++) |
167 | list_for_each_entry_safe(e, next, &t->iphash[i], list) | 167 | list_for_each_entry_safe(e, next, &t->iphash[i], list) |
168 | recent_entry_remove(t, e); | 168 | recent_entry_remove(t, e); |
169 | } | ||
170 | } | 169 | } |
171 | 170 | ||
172 | static int | 171 | static bool |
173 | ipt_recent_match(const struct sk_buff *skb, | 172 | ipt_recent_match(const struct sk_buff *skb, |
174 | const struct net_device *in, const struct net_device *out, | 173 | const struct net_device *in, const struct net_device *out, |
175 | const struct xt_match *match, const void *matchinfo, | 174 | const struct xt_match *match, const void *matchinfo, |
176 | int offset, unsigned int protoff, int *hotdrop) | 175 | int offset, unsigned int protoff, bool *hotdrop) |
177 | { | 176 | { |
178 | const struct ipt_recent_info *info = matchinfo; | 177 | const struct ipt_recent_info *info = matchinfo; |
179 | struct recent_table *t; | 178 | struct recent_table *t; |
180 | struct recent_entry *e; | 179 | struct recent_entry *e; |
181 | __be32 addr; | 180 | __be32 addr; |
182 | u_int8_t ttl; | 181 | u_int8_t ttl; |
183 | int ret = info->invert; | 182 | bool ret = info->invert; |
184 | 183 | ||
185 | if (info->side == IPT_RECENT_DEST) | 184 | if (info->side == IPT_RECENT_DEST) |
186 | addr = ip_hdr(skb)->daddr; | 185 | addr = ip_hdr(skb)->daddr; |
@@ -201,16 +200,16 @@ ipt_recent_match(const struct sk_buff *skb, | |||
201 | goto out; | 200 | goto out; |
202 | e = recent_entry_init(t, addr, ttl); | 201 | e = recent_entry_init(t, addr, ttl); |
203 | if (e == NULL) | 202 | if (e == NULL) |
204 | *hotdrop = 1; | 203 | *hotdrop = true; |
205 | ret ^= 1; | 204 | ret = !ret; |
206 | goto out; | 205 | goto out; |
207 | } | 206 | } |
208 | 207 | ||
209 | if (info->check_set & IPT_RECENT_SET) | 208 | if (info->check_set & IPT_RECENT_SET) |
210 | ret ^= 1; | 209 | ret = !ret; |
211 | else if (info->check_set & IPT_RECENT_REMOVE) { | 210 | else if (info->check_set & IPT_RECENT_REMOVE) { |
212 | recent_entry_remove(t, e); | 211 | recent_entry_remove(t, e); |
213 | ret ^= 1; | 212 | ret = !ret; |
214 | } else if (info->check_set & (IPT_RECENT_CHECK | IPT_RECENT_UPDATE)) { | 213 | } else if (info->check_set & (IPT_RECENT_CHECK | IPT_RECENT_UPDATE)) { |
215 | unsigned long t = jiffies - info->seconds * HZ; | 214 | unsigned long t = jiffies - info->seconds * HZ; |
216 | unsigned int i, hits = 0; | 215 | unsigned int i, hits = 0; |
@@ -219,7 +218,7 @@ ipt_recent_match(const struct sk_buff *skb, | |||
219 | if (info->seconds && time_after(t, e->stamps[i])) | 218 | if (info->seconds && time_after(t, e->stamps[i])) |
220 | continue; | 219 | continue; |
221 | if (++hits >= info->hit_count) { | 220 | if (++hits >= info->hit_count) { |
222 | ret ^= 1; | 221 | ret = !ret; |
223 | break; | 222 | break; |
224 | } | 223 | } |
225 | } | 224 | } |
@@ -235,7 +234,7 @@ out: | |||
235 | return ret; | 234 | return ret; |
236 | } | 235 | } |
237 | 236 | ||
238 | static int | 237 | static bool |
239 | ipt_recent_checkentry(const char *tablename, const void *ip, | 238 | ipt_recent_checkentry(const char *tablename, const void *ip, |
240 | const struct xt_match *match, void *matchinfo, | 239 | const struct xt_match *match, void *matchinfo, |
241 | unsigned int hook_mask) | 240 | unsigned int hook_mask) |
@@ -243,24 +242,24 @@ ipt_recent_checkentry(const char *tablename, const void *ip, | |||
243 | const struct ipt_recent_info *info = matchinfo; | 242 | const struct ipt_recent_info *info = matchinfo; |
244 | struct recent_table *t; | 243 | struct recent_table *t; |
245 | unsigned i; | 244 | unsigned i; |
246 | int ret = 0; | 245 | bool ret = false; |
247 | 246 | ||
248 | if (hweight8(info->check_set & | 247 | if (hweight8(info->check_set & |
249 | (IPT_RECENT_SET | IPT_RECENT_REMOVE | | 248 | (IPT_RECENT_SET | IPT_RECENT_REMOVE | |
250 | IPT_RECENT_CHECK | IPT_RECENT_UPDATE)) != 1) | 249 | IPT_RECENT_CHECK | IPT_RECENT_UPDATE)) != 1) |
251 | return 0; | 250 | return false; |
252 | if ((info->check_set & (IPT_RECENT_SET | IPT_RECENT_REMOVE)) && | 251 | if ((info->check_set & (IPT_RECENT_SET | IPT_RECENT_REMOVE)) && |
253 | (info->seconds || info->hit_count)) | 252 | (info->seconds || info->hit_count)) |
254 | return 0; | 253 | return false; |
255 | if (info->name[0] == '\0' || | 254 | if (info->name[0] == '\0' || |
256 | strnlen(info->name, IPT_RECENT_NAME_LEN) == IPT_RECENT_NAME_LEN) | 255 | strnlen(info->name, IPT_RECENT_NAME_LEN) == IPT_RECENT_NAME_LEN) |
257 | return 0; | 256 | return false; |
258 | 257 | ||
259 | mutex_lock(&recent_mutex); | 258 | mutex_lock(&recent_mutex); |
260 | t = recent_table_lookup(info->name); | 259 | t = recent_table_lookup(info->name); |
261 | if (t != NULL) { | 260 | if (t != NULL) { |
262 | t->refcnt++; | 261 | t->refcnt++; |
263 | ret = 1; | 262 | ret = true; |
264 | goto out; | 263 | goto out; |
265 | } | 264 | } |
266 | 265 | ||
@@ -287,7 +286,7 @@ ipt_recent_checkentry(const char *tablename, const void *ip, | |||
287 | spin_lock_bh(&recent_lock); | 286 | spin_lock_bh(&recent_lock); |
288 | list_add_tail(&t->list, &tables); | 287 | list_add_tail(&t->list, &tables); |
289 | spin_unlock_bh(&recent_lock); | 288 | spin_unlock_bh(&recent_lock); |
290 | ret = 1; | 289 | ret = true; |
291 | out: | 290 | out: |
292 | mutex_unlock(&recent_mutex); | 291 | mutex_unlock(&recent_mutex); |
293 | return ret; | 292 | return ret; |
@@ -323,18 +322,16 @@ struct recent_iter_state { | |||
323 | static void *recent_seq_start(struct seq_file *seq, loff_t *pos) | 322 | static void *recent_seq_start(struct seq_file *seq, loff_t *pos) |
324 | { | 323 | { |
325 | struct recent_iter_state *st = seq->private; | 324 | struct recent_iter_state *st = seq->private; |
326 | struct recent_table *t = st->table; | 325 | const struct recent_table *t = st->table; |
327 | struct recent_entry *e; | 326 | struct recent_entry *e; |
328 | loff_t p = *pos; | 327 | loff_t p = *pos; |
329 | 328 | ||
330 | spin_lock_bh(&recent_lock); | 329 | spin_lock_bh(&recent_lock); |
331 | 330 | ||
332 | for (st->bucket = 0; st->bucket < ip_list_hash_size; st->bucket++) { | 331 | for (st->bucket = 0; st->bucket < ip_list_hash_size; st->bucket++) |
333 | list_for_each_entry(e, &t->iphash[st->bucket], list) { | 332 | list_for_each_entry(e, &t->iphash[st->bucket], list) |
334 | if (p-- == 0) | 333 | if (p-- == 0) |
335 | return e; | 334 | return e; |
336 | } | ||
337 | } | ||
338 | return NULL; | 335 | return NULL; |
339 | } | 336 | } |
340 | 337 | ||
@@ -373,7 +370,7 @@ static int recent_seq_show(struct seq_file *seq, void *v) | |||
373 | return 0; | 370 | return 0; |
374 | } | 371 | } |
375 | 372 | ||
376 | static struct seq_operations recent_seq_ops = { | 373 | static const struct seq_operations recent_seq_ops = { |
377 | .start = recent_seq_start, | 374 | .start = recent_seq_start, |
378 | .next = recent_seq_next, | 375 | .next = recent_seq_next, |
379 | .stop = recent_seq_stop, | 376 | .stop = recent_seq_stop, |
@@ -463,7 +460,7 @@ static const struct file_operations recent_fops = { | |||
463 | }; | 460 | }; |
464 | #endif /* CONFIG_PROC_FS */ | 461 | #endif /* CONFIG_PROC_FS */ |
465 | 462 | ||
466 | static struct xt_match recent_match = { | 463 | static struct xt_match recent_match __read_mostly = { |
467 | .name = "recent", | 464 | .name = "recent", |
468 | .family = AF_INET, | 465 | .family = AF_INET, |
469 | .match = ipt_recent_match, | 466 | .match = ipt_recent_match, |
diff --git a/net/ipv4/netfilter/ipt_tos.c b/net/ipv4/netfilter/ipt_tos.c index d314844af12b..e740441c973d 100644 --- a/net/ipv4/netfilter/ipt_tos.c +++ b/net/ipv4/netfilter/ipt_tos.c | |||
@@ -18,7 +18,7 @@ | |||
18 | MODULE_LICENSE("GPL"); | 18 | MODULE_LICENSE("GPL"); |
19 | MODULE_DESCRIPTION("iptables TOS match module"); | 19 | MODULE_DESCRIPTION("iptables TOS match module"); |
20 | 20 | ||
21 | static int | 21 | static bool |
22 | match(const struct sk_buff *skb, | 22 | match(const struct sk_buff *skb, |
23 | const struct net_device *in, | 23 | const struct net_device *in, |
24 | const struct net_device *out, | 24 | const struct net_device *out, |
@@ -26,14 +26,14 @@ match(const struct sk_buff *skb, | |||
26 | const void *matchinfo, | 26 | const void *matchinfo, |
27 | int offset, | 27 | int offset, |
28 | unsigned int protoff, | 28 | unsigned int protoff, |
29 | int *hotdrop) | 29 | bool *hotdrop) |
30 | { | 30 | { |
31 | const struct ipt_tos_info *info = matchinfo; | 31 | const struct ipt_tos_info *info = matchinfo; |
32 | 32 | ||
33 | return (ip_hdr(skb)->tos == info->tos) ^ info->invert; | 33 | return (ip_hdr(skb)->tos == info->tos) ^ info->invert; |
34 | } | 34 | } |
35 | 35 | ||
36 | static struct xt_match tos_match = { | 36 | static struct xt_match tos_match __read_mostly = { |
37 | .name = "tos", | 37 | .name = "tos", |
38 | .family = AF_INET, | 38 | .family = AF_INET, |
39 | .match = match, | 39 | .match = match, |
diff --git a/net/ipv4/netfilter/ipt_ttl.c b/net/ipv4/netfilter/ipt_ttl.c index ab02d9e3139c..a439900a4ba5 100644 --- a/net/ipv4/netfilter/ipt_ttl.c +++ b/net/ipv4/netfilter/ipt_ttl.c | |||
@@ -18,37 +18,33 @@ MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | |||
18 | MODULE_DESCRIPTION("IP tables TTL matching module"); | 18 | MODULE_DESCRIPTION("IP tables TTL matching module"); |
19 | MODULE_LICENSE("GPL"); | 19 | MODULE_LICENSE("GPL"); |
20 | 20 | ||
21 | static int match(const struct sk_buff *skb, | 21 | static bool match(const struct sk_buff *skb, |
22 | const struct net_device *in, const struct net_device *out, | 22 | const struct net_device *in, const struct net_device *out, |
23 | const struct xt_match *match, const void *matchinfo, | 23 | const struct xt_match *match, const void *matchinfo, |
24 | int offset, unsigned int protoff, int *hotdrop) | 24 | int offset, unsigned int protoff, bool *hotdrop) |
25 | { | 25 | { |
26 | const struct ipt_ttl_info *info = matchinfo; | 26 | const struct ipt_ttl_info *info = matchinfo; |
27 | const u8 ttl = ip_hdr(skb)->ttl; | 27 | const u8 ttl = ip_hdr(skb)->ttl; |
28 | 28 | ||
29 | switch (info->mode) { | 29 | switch (info->mode) { |
30 | case IPT_TTL_EQ: | 30 | case IPT_TTL_EQ: |
31 | return (ttl == info->ttl); | 31 | return ttl == info->ttl; |
32 | break; | ||
33 | case IPT_TTL_NE: | 32 | case IPT_TTL_NE: |
34 | return (!(ttl == info->ttl)); | 33 | return ttl != info->ttl; |
35 | break; | ||
36 | case IPT_TTL_LT: | 34 | case IPT_TTL_LT: |
37 | return (ttl < info->ttl); | 35 | return ttl < info->ttl; |
38 | break; | ||
39 | case IPT_TTL_GT: | 36 | case IPT_TTL_GT: |
40 | return (ttl > info->ttl); | 37 | return ttl > info->ttl; |
41 | break; | ||
42 | default: | 38 | default: |
43 | printk(KERN_WARNING "ipt_ttl: unknown mode %d\n", | 39 | printk(KERN_WARNING "ipt_ttl: unknown mode %d\n", |
44 | info->mode); | 40 | info->mode); |
45 | return 0; | 41 | return false; |
46 | } | 42 | } |
47 | 43 | ||
48 | return 0; | 44 | return false; |
49 | } | 45 | } |
50 | 46 | ||
51 | static struct xt_match ttl_match = { | 47 | static struct xt_match ttl_match __read_mostly = { |
52 | .name = "ttl", | 48 | .name = "ttl", |
53 | .family = AF_INET, | 49 | .family = AF_INET, |
54 | .match = match, | 50 | .match = match, |
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 6dc72a815f77..64552afd01cb 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
@@ -24,12 +24,6 @@ | |||
24 | #include <net/netfilter/nf_conntrack_core.h> | 24 | #include <net/netfilter/nf_conntrack_core.h> |
25 | #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> | 25 | #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> |
26 | 26 | ||
27 | #if 0 | ||
28 | #define DEBUGP printk | ||
29 | #else | ||
30 | #define DEBUGP(format, args...) | ||
31 | #endif | ||
32 | |||
33 | static int ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, | 27 | static int ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, |
34 | struct nf_conntrack_tuple *tuple) | 28 | struct nf_conntrack_tuple *tuple) |
35 | { | 29 | { |
@@ -84,36 +78,30 @@ nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user) | |||
84 | return skb; | 78 | return skb; |
85 | } | 79 | } |
86 | 80 | ||
87 | static int | 81 | static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, |
88 | ipv4_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff, | 82 | unsigned int *dataoff, u_int8_t *protonum) |
89 | u_int8_t *protonum) | ||
90 | { | 83 | { |
84 | struct iphdr _iph, *iph; | ||
85 | |||
86 | iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph); | ||
87 | if (iph == NULL) | ||
88 | return -NF_DROP; | ||
89 | |||
91 | /* Never happen */ | 90 | /* Never happen */ |
92 | if (ip_hdr(*pskb)->frag_off & htons(IP_OFFSET)) { | 91 | if (iph->frag_off & htons(IP_OFFSET)) { |
93 | if (net_ratelimit()) { | 92 | if (net_ratelimit()) { |
94 | printk(KERN_ERR "ipv4_prepare: Frag of proto %u (hook=%u)\n", | 93 | printk(KERN_ERR "ipv4_get_l4proto: Frag of proto %u\n", |
95 | ip_hdr(*pskb)->protocol, hooknum); | 94 | iph->protocol); |
96 | } | 95 | } |
97 | return -NF_DROP; | 96 | return -NF_DROP; |
98 | } | 97 | } |
99 | 98 | ||
100 | *dataoff = skb_network_offset(*pskb) + ip_hdrlen(*pskb); | 99 | *dataoff = nhoff + (iph->ihl << 2); |
101 | *protonum = ip_hdr(*pskb)->protocol; | 100 | *protonum = iph->protocol; |
102 | 101 | ||
103 | return NF_ACCEPT; | 102 | return NF_ACCEPT; |
104 | } | 103 | } |
105 | 104 | ||
106 | int nf_nat_module_is_loaded = 0; | ||
107 | EXPORT_SYMBOL_GPL(nf_nat_module_is_loaded); | ||
108 | |||
109 | static u_int32_t ipv4_get_features(const struct nf_conntrack_tuple *tuple) | ||
110 | { | ||
111 | if (nf_nat_module_is_loaded) | ||
112 | return NF_CT_F_NAT; | ||
113 | |||
114 | return NF_CT_F_BASIC; | ||
115 | } | ||
116 | |||
117 | static unsigned int ipv4_confirm(unsigned int hooknum, | 105 | static unsigned int ipv4_confirm(unsigned int hooknum, |
118 | struct sk_buff **pskb, | 106 | struct sk_buff **pskb, |
119 | const struct net_device *in, | 107 | const struct net_device *in, |
@@ -335,17 +323,17 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len) | |||
335 | 323 | ||
336 | /* We only do TCP at the moment: is there a better way? */ | 324 | /* We only do TCP at the moment: is there a better way? */ |
337 | if (strcmp(sk->sk_prot->name, "TCP")) { | 325 | if (strcmp(sk->sk_prot->name, "TCP")) { |
338 | DEBUGP("SO_ORIGINAL_DST: Not a TCP socket\n"); | 326 | pr_debug("SO_ORIGINAL_DST: Not a TCP socket\n"); |
339 | return -ENOPROTOOPT; | 327 | return -ENOPROTOOPT; |
340 | } | 328 | } |
341 | 329 | ||
342 | if ((unsigned int) *len < sizeof(struct sockaddr_in)) { | 330 | if ((unsigned int) *len < sizeof(struct sockaddr_in)) { |
343 | DEBUGP("SO_ORIGINAL_DST: len %u not %u\n", | 331 | pr_debug("SO_ORIGINAL_DST: len %d not %Zu\n", |
344 | *len, sizeof(struct sockaddr_in)); | 332 | *len, sizeof(struct sockaddr_in)); |
345 | return -EINVAL; | 333 | return -EINVAL; |
346 | } | 334 | } |
347 | 335 | ||
348 | h = nf_conntrack_find_get(&tuple, NULL); | 336 | h = nf_conntrack_find_get(&tuple); |
349 | if (h) { | 337 | if (h) { |
350 | struct sockaddr_in sin; | 338 | struct sockaddr_in sin; |
351 | struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); | 339 | struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); |
@@ -357,17 +345,17 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len) | |||
357 | .tuple.dst.u3.ip; | 345 | .tuple.dst.u3.ip; |
358 | memset(sin.sin_zero, 0, sizeof(sin.sin_zero)); | 346 | memset(sin.sin_zero, 0, sizeof(sin.sin_zero)); |
359 | 347 | ||
360 | DEBUGP("SO_ORIGINAL_DST: %u.%u.%u.%u %u\n", | 348 | pr_debug("SO_ORIGINAL_DST: %u.%u.%u.%u %u\n", |
361 | NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port)); | 349 | NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port)); |
362 | nf_ct_put(ct); | 350 | nf_ct_put(ct); |
363 | if (copy_to_user(user, &sin, sizeof(sin)) != 0) | 351 | if (copy_to_user(user, &sin, sizeof(sin)) != 0) |
364 | return -EFAULT; | 352 | return -EFAULT; |
365 | else | 353 | else |
366 | return 0; | 354 | return 0; |
367 | } | 355 | } |
368 | DEBUGP("SO_ORIGINAL_DST: Can't find %u.%u.%u.%u/%u-%u.%u.%u.%u/%u.\n", | 356 | pr_debug("SO_ORIGINAL_DST: Can't find %u.%u.%u.%u/%u-%u.%u.%u.%u/%u.\n", |
369 | NIPQUAD(tuple.src.u3.ip), ntohs(tuple.src.u.tcp.port), | 357 | NIPQUAD(tuple.src.u3.ip), ntohs(tuple.src.u.tcp.port), |
370 | NIPQUAD(tuple.dst.u3.ip), ntohs(tuple.dst.u.tcp.port)); | 358 | NIPQUAD(tuple.dst.u3.ip), ntohs(tuple.dst.u.tcp.port)); |
371 | return -ENOENT; | 359 | return -ENOENT; |
372 | } | 360 | } |
373 | 361 | ||
@@ -417,15 +405,14 @@ static struct nf_sockopt_ops so_getorigdst = { | |||
417 | .get = &getorigdst, | 405 | .get = &getorigdst, |
418 | }; | 406 | }; |
419 | 407 | ||
420 | struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = { | 408 | struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 __read_mostly = { |
421 | .l3proto = PF_INET, | 409 | .l3proto = PF_INET, |
422 | .name = "ipv4", | 410 | .name = "ipv4", |
423 | .pkt_to_tuple = ipv4_pkt_to_tuple, | 411 | .pkt_to_tuple = ipv4_pkt_to_tuple, |
424 | .invert_tuple = ipv4_invert_tuple, | 412 | .invert_tuple = ipv4_invert_tuple, |
425 | .print_tuple = ipv4_print_tuple, | 413 | .print_tuple = ipv4_print_tuple, |
426 | .print_conntrack = ipv4_print_conntrack, | 414 | .print_conntrack = ipv4_print_conntrack, |
427 | .prepare = ipv4_prepare, | 415 | .get_l4proto = ipv4_get_l4proto, |
428 | .get_features = ipv4_get_features, | ||
429 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 416 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
430 | .tuple_to_nfattr = ipv4_tuple_to_nfattr, | 417 | .tuple_to_nfattr = ipv4_tuple_to_nfattr, |
431 | .nfattr_to_tuple = ipv4_nfattr_to_tuple, | 418 | .nfattr_to_tuple = ipv4_nfattr_to_tuple, |
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c index 89f933e81035..3da9d73d1b52 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c | |||
@@ -18,12 +18,6 @@ | |||
18 | #include <net/netfilter/nf_conntrack_l4proto.h> | 18 | #include <net/netfilter/nf_conntrack_l4proto.h> |
19 | #include <net/netfilter/nf_conntrack_expect.h> | 19 | #include <net/netfilter/nf_conntrack_expect.h> |
20 | 20 | ||
21 | #if 0 | ||
22 | #define DEBUGP printk | ||
23 | #else | ||
24 | #define DEBUGP(format, args...) | ||
25 | #endif | ||
26 | |||
27 | #ifdef CONFIG_NF_CT_ACCT | 21 | #ifdef CONFIG_NF_CT_ACCT |
28 | static unsigned int | 22 | static unsigned int |
29 | seq_print_counters(struct seq_file *s, | 23 | seq_print_counters(struct seq_file *s, |
@@ -41,35 +35,36 @@ struct ct_iter_state { | |||
41 | unsigned int bucket; | 35 | unsigned int bucket; |
42 | }; | 36 | }; |
43 | 37 | ||
44 | static struct list_head *ct_get_first(struct seq_file *seq) | 38 | static struct hlist_node *ct_get_first(struct seq_file *seq) |
45 | { | 39 | { |
46 | struct ct_iter_state *st = seq->private; | 40 | struct ct_iter_state *st = seq->private; |
47 | 41 | ||
48 | for (st->bucket = 0; | 42 | for (st->bucket = 0; |
49 | st->bucket < nf_conntrack_htable_size; | 43 | st->bucket < nf_conntrack_htable_size; |
50 | st->bucket++) { | 44 | st->bucket++) { |
51 | if (!list_empty(&nf_conntrack_hash[st->bucket])) | 45 | if (!hlist_empty(&nf_conntrack_hash[st->bucket])) |
52 | return nf_conntrack_hash[st->bucket].next; | 46 | return nf_conntrack_hash[st->bucket].first; |
53 | } | 47 | } |
54 | return NULL; | 48 | return NULL; |
55 | } | 49 | } |
56 | 50 | ||
57 | static struct list_head *ct_get_next(struct seq_file *seq, struct list_head *head) | 51 | static struct hlist_node *ct_get_next(struct seq_file *seq, |
52 | struct hlist_node *head) | ||
58 | { | 53 | { |
59 | struct ct_iter_state *st = seq->private; | 54 | struct ct_iter_state *st = seq->private; |
60 | 55 | ||
61 | head = head->next; | 56 | head = head->next; |
62 | while (head == &nf_conntrack_hash[st->bucket]) { | 57 | while (head == NULL) { |
63 | if (++st->bucket >= nf_conntrack_htable_size) | 58 | if (++st->bucket >= nf_conntrack_htable_size) |
64 | return NULL; | 59 | return NULL; |
65 | head = nf_conntrack_hash[st->bucket].next; | 60 | head = nf_conntrack_hash[st->bucket].first; |
66 | } | 61 | } |
67 | return head; | 62 | return head; |
68 | } | 63 | } |
69 | 64 | ||
70 | static struct list_head *ct_get_idx(struct seq_file *seq, loff_t pos) | 65 | static struct hlist_node *ct_get_idx(struct seq_file *seq, loff_t pos) |
71 | { | 66 | { |
72 | struct list_head *head = ct_get_first(seq); | 67 | struct hlist_node *head = ct_get_first(seq); |
73 | 68 | ||
74 | if (head) | 69 | if (head) |
75 | while (pos && (head = ct_get_next(seq, head))) | 70 | while (pos && (head = ct_get_next(seq, head))) |
@@ -169,7 +164,7 @@ static int ct_seq_show(struct seq_file *s, void *v) | |||
169 | return 0; | 164 | return 0; |
170 | } | 165 | } |
171 | 166 | ||
172 | static struct seq_operations ct_seq_ops = { | 167 | static const struct seq_operations ct_seq_ops = { |
173 | .start = ct_seq_start, | 168 | .start = ct_seq_start, |
174 | .next = ct_seq_next, | 169 | .next = ct_seq_next, |
175 | .stop = ct_seq_stop, | 170 | .stop = ct_seq_stop, |
@@ -206,47 +201,68 @@ static const struct file_operations ct_file_ops = { | |||
206 | }; | 201 | }; |
207 | 202 | ||
208 | /* expects */ | 203 | /* expects */ |
209 | static void *exp_seq_start(struct seq_file *s, loff_t *pos) | 204 | struct ct_expect_iter_state { |
205 | unsigned int bucket; | ||
206 | }; | ||
207 | |||
208 | static struct hlist_node *ct_expect_get_first(struct seq_file *seq) | ||
210 | { | 209 | { |
211 | struct list_head *e = &nf_conntrack_expect_list; | 210 | struct ct_expect_iter_state *st = seq->private; |
212 | loff_t i; | ||
213 | 211 | ||
214 | /* strange seq_file api calls stop even if we fail, | 212 | for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) { |
215 | * thus we need to grab lock since stop unlocks */ | 213 | if (!hlist_empty(&nf_ct_expect_hash[st->bucket])) |
216 | read_lock_bh(&nf_conntrack_lock); | 214 | return nf_ct_expect_hash[st->bucket].first; |
215 | } | ||
216 | return NULL; | ||
217 | } | ||
217 | 218 | ||
218 | if (list_empty(e)) | 219 | static struct hlist_node *ct_expect_get_next(struct seq_file *seq, |
219 | return NULL; | 220 | struct hlist_node *head) |
221 | { | ||
222 | struct ct_expect_iter_state *st = seq->private; | ||
220 | 223 | ||
221 | for (i = 0; i <= *pos; i++) { | 224 | head = head->next; |
222 | e = e->next; | 225 | while (head == NULL) { |
223 | if (e == &nf_conntrack_expect_list) | 226 | if (++st->bucket >= nf_ct_expect_hsize) |
224 | return NULL; | 227 | return NULL; |
228 | head = nf_ct_expect_hash[st->bucket].first; | ||
225 | } | 229 | } |
226 | return e; | 230 | return head; |
227 | } | 231 | } |
228 | 232 | ||
229 | static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos) | 233 | static struct hlist_node *ct_expect_get_idx(struct seq_file *seq, loff_t pos) |
230 | { | 234 | { |
231 | struct list_head *e = v; | 235 | struct hlist_node *head = ct_expect_get_first(seq); |
232 | 236 | ||
233 | ++*pos; | 237 | if (head) |
234 | e = e->next; | 238 | while (pos && (head = ct_expect_get_next(seq, head))) |
239 | pos--; | ||
240 | return pos ? NULL : head; | ||
241 | } | ||
235 | 242 | ||
236 | if (e == &nf_conntrack_expect_list) | 243 | static void *exp_seq_start(struct seq_file *seq, loff_t *pos) |
237 | return NULL; | 244 | { |
245 | read_lock_bh(&nf_conntrack_lock); | ||
246 | return ct_expect_get_idx(seq, *pos); | ||
247 | } | ||
238 | 248 | ||
239 | return e; | 249 | static void *exp_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
250 | { | ||
251 | (*pos)++; | ||
252 | return ct_expect_get_next(seq, v); | ||
240 | } | 253 | } |
241 | 254 | ||
242 | static void exp_seq_stop(struct seq_file *s, void *v) | 255 | static void exp_seq_stop(struct seq_file *seq, void *v) |
243 | { | 256 | { |
244 | read_unlock_bh(&nf_conntrack_lock); | 257 | read_unlock_bh(&nf_conntrack_lock); |
245 | } | 258 | } |
246 | 259 | ||
247 | static int exp_seq_show(struct seq_file *s, void *v) | 260 | static int exp_seq_show(struct seq_file *s, void *v) |
248 | { | 261 | { |
249 | struct nf_conntrack_expect *exp = v; | 262 | struct nf_conntrack_expect *exp; |
263 | struct hlist_node *n = v; | ||
264 | |||
265 | exp = hlist_entry(n, struct nf_conntrack_expect, hnode); | ||
250 | 266 | ||
251 | if (exp->tuple.src.l3num != AF_INET) | 267 | if (exp->tuple.src.l3num != AF_INET) |
252 | return 0; | 268 | return 0; |
@@ -266,7 +282,7 @@ static int exp_seq_show(struct seq_file *s, void *v) | |||
266 | return seq_putc(s, '\n'); | 282 | return seq_putc(s, '\n'); |
267 | } | 283 | } |
268 | 284 | ||
269 | static struct seq_operations exp_seq_ops = { | 285 | static const struct seq_operations exp_seq_ops = { |
270 | .start = exp_seq_start, | 286 | .start = exp_seq_start, |
271 | .next = exp_seq_next, | 287 | .next = exp_seq_next, |
272 | .stop = exp_seq_stop, | 288 | .stop = exp_seq_stop, |
@@ -275,7 +291,23 @@ static struct seq_operations exp_seq_ops = { | |||
275 | 291 | ||
276 | static int exp_open(struct inode *inode, struct file *file) | 292 | static int exp_open(struct inode *inode, struct file *file) |
277 | { | 293 | { |
278 | return seq_open(file, &exp_seq_ops); | 294 | struct seq_file *seq; |
295 | struct ct_expect_iter_state *st; | ||
296 | int ret; | ||
297 | |||
298 | st = kmalloc(sizeof(struct ct_expect_iter_state), GFP_KERNEL); | ||
299 | if (st == NULL) | ||
300 | return -ENOMEM; | ||
301 | ret = seq_open(file, &exp_seq_ops); | ||
302 | if (ret) | ||
303 | goto out_free; | ||
304 | seq = file->private_data; | ||
305 | seq->private = st; | ||
306 | memset(st, 0, sizeof(struct ct_expect_iter_state)); | ||
307 | return ret; | ||
308 | out_free: | ||
309 | kfree(st); | ||
310 | return ret; | ||
279 | } | 311 | } |
280 | 312 | ||
281 | static const struct file_operations ip_exp_file_ops = { | 313 | static const struct file_operations ip_exp_file_ops = { |
@@ -283,7 +315,7 @@ static const struct file_operations ip_exp_file_ops = { | |||
283 | .open = exp_open, | 315 | .open = exp_open, |
284 | .read = seq_read, | 316 | .read = seq_read, |
285 | .llseek = seq_lseek, | 317 | .llseek = seq_lseek, |
286 | .release = seq_release | 318 | .release = seq_release_private, |
287 | }; | 319 | }; |
288 | 320 | ||
289 | static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos) | 321 | static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos) |
@@ -354,7 +386,7 @@ static int ct_cpu_seq_show(struct seq_file *seq, void *v) | |||
354 | return 0; | 386 | return 0; |
355 | } | 387 | } |
356 | 388 | ||
357 | static struct seq_operations ct_cpu_seq_ops = { | 389 | static const struct seq_operations ct_cpu_seq_ops = { |
358 | .start = ct_cpu_seq_start, | 390 | .start = ct_cpu_seq_start, |
359 | .next = ct_cpu_seq_next, | 391 | .next = ct_cpu_seq_next, |
360 | .stop = ct_cpu_seq_stop, | 392 | .stop = ct_cpu_seq_stop, |
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index f4fc657c1983..6593fd2c5b10 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c | |||
@@ -21,12 +21,6 @@ | |||
21 | 21 | ||
22 | static unsigned long nf_ct_icmp_timeout __read_mostly = 30*HZ; | 22 | static unsigned long nf_ct_icmp_timeout __read_mostly = 30*HZ; |
23 | 23 | ||
24 | #if 0 | ||
25 | #define DEBUGP printk | ||
26 | #else | ||
27 | #define DEBUGP(format, args...) | ||
28 | #endif | ||
29 | |||
30 | static int icmp_pkt_to_tuple(const struct sk_buff *skb, | 24 | static int icmp_pkt_to_tuple(const struct sk_buff *skb, |
31 | unsigned int dataoff, | 25 | unsigned int dataoff, |
32 | struct nf_conntrack_tuple *tuple) | 26 | struct nf_conntrack_tuple *tuple) |
@@ -125,8 +119,8 @@ static int icmp_new(struct nf_conn *conntrack, | |||
125 | if (conntrack->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new) | 119 | if (conntrack->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new) |
126 | || !valid_new[conntrack->tuplehash[0].tuple.dst.u.icmp.type]) { | 120 | || !valid_new[conntrack->tuplehash[0].tuple.dst.u.icmp.type]) { |
127 | /* Can't create a new ICMP `conn' with this. */ | 121 | /* Can't create a new ICMP `conn' with this. */ |
128 | DEBUGP("icmp: can't create new conn with type %u\n", | 122 | pr_debug("icmp: can't create new conn with type %u\n", |
129 | conntrack->tuplehash[0].tuple.dst.u.icmp.type); | 123 | conntrack->tuplehash[0].tuple.dst.u.icmp.type); |
130 | NF_CT_DUMP_TUPLE(&conntrack->tuplehash[0].tuple); | 124 | NF_CT_DUMP_TUPLE(&conntrack->tuplehash[0].tuple); |
131 | return 0; | 125 | return 0; |
132 | } | 126 | } |
@@ -142,72 +136,42 @@ icmp_error_message(struct sk_buff *skb, | |||
142 | unsigned int hooknum) | 136 | unsigned int hooknum) |
143 | { | 137 | { |
144 | struct nf_conntrack_tuple innertuple, origtuple; | 138 | struct nf_conntrack_tuple innertuple, origtuple; |
145 | struct { | ||
146 | struct icmphdr icmp; | ||
147 | struct iphdr ip; | ||
148 | } _in, *inside; | ||
149 | struct nf_conntrack_l4proto *innerproto; | 139 | struct nf_conntrack_l4proto *innerproto; |
150 | struct nf_conntrack_tuple_hash *h; | 140 | struct nf_conntrack_tuple_hash *h; |
151 | int dataoff; | ||
152 | 141 | ||
153 | NF_CT_ASSERT(skb->nfct == NULL); | 142 | NF_CT_ASSERT(skb->nfct == NULL); |
154 | 143 | ||
155 | /* Not enough header? */ | 144 | /* Are they talking about one of our connections? */ |
156 | inside = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_in), &_in); | 145 | if (!nf_ct_get_tuplepr(skb, |
157 | if (inside == NULL) | 146 | skb_network_offset(skb) + ip_hdrlen(skb) |
158 | return -NF_ACCEPT; | 147 | + sizeof(struct icmphdr), |
159 | 148 | PF_INET, &origtuple)) { | |
160 | /* Ignore ICMP's containing fragments (shouldn't happen) */ | 149 | pr_debug("icmp_error_message: failed to get tuple\n"); |
161 | if (inside->ip.frag_off & htons(IP_OFFSET)) { | ||
162 | DEBUGP("icmp_error_message: fragment of proto %u\n", | ||
163 | inside->ip.protocol); | ||
164 | return -NF_ACCEPT; | 150 | return -NF_ACCEPT; |
165 | } | 151 | } |
166 | 152 | ||
167 | /* rcu_read_lock()ed by nf_hook_slow */ | 153 | /* rcu_read_lock()ed by nf_hook_slow */ |
168 | innerproto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol); | 154 | innerproto = __nf_ct_l4proto_find(PF_INET, origtuple.dst.protonum); |
169 | |||
170 | dataoff = ip_hdrlen(skb) + sizeof(inside->icmp); | ||
171 | /* Are they talking about one of our connections? */ | ||
172 | if (!nf_ct_get_tuple(skb, dataoff, dataoff + inside->ip.ihl*4, PF_INET, | ||
173 | inside->ip.protocol, &origtuple, | ||
174 | &nf_conntrack_l3proto_ipv4, innerproto)) { | ||
175 | DEBUGP("icmp_error_message: ! get_tuple p=%u", | ||
176 | inside->ip.protocol); | ||
177 | return -NF_ACCEPT; | ||
178 | } | ||
179 | 155 | ||
180 | /* Ordinarily, we'd expect the inverted tupleproto, but it's | 156 | /* Ordinarily, we'd expect the inverted tupleproto, but it's |
181 | been preserved inside the ICMP. */ | 157 | been preserved inside the ICMP. */ |
182 | if (!nf_ct_invert_tuple(&innertuple, &origtuple, | 158 | if (!nf_ct_invert_tuple(&innertuple, &origtuple, |
183 | &nf_conntrack_l3proto_ipv4, innerproto)) { | 159 | &nf_conntrack_l3proto_ipv4, innerproto)) { |
184 | DEBUGP("icmp_error_message: no match\n"); | 160 | pr_debug("icmp_error_message: no match\n"); |
185 | return -NF_ACCEPT; | 161 | return -NF_ACCEPT; |
186 | } | 162 | } |
187 | 163 | ||
188 | *ctinfo = IP_CT_RELATED; | 164 | *ctinfo = IP_CT_RELATED; |
189 | 165 | ||
190 | h = nf_conntrack_find_get(&innertuple, NULL); | 166 | h = nf_conntrack_find_get(&innertuple); |
191 | if (!h) { | 167 | if (!h) { |
192 | /* Locally generated ICMPs will match inverted if they | 168 | pr_debug("icmp_error_message: no match\n"); |
193 | haven't been SNAT'ed yet */ | 169 | return -NF_ACCEPT; |
194 | /* FIXME: NAT code has to handle half-done double NAT --RR */ | ||
195 | if (hooknum == NF_IP_LOCAL_OUT) | ||
196 | h = nf_conntrack_find_get(&origtuple, NULL); | ||
197 | |||
198 | if (!h) { | ||
199 | DEBUGP("icmp_error_message: no match\n"); | ||
200 | return -NF_ACCEPT; | ||
201 | } | ||
202 | |||
203 | /* Reverse direction from that found */ | ||
204 | if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) | ||
205 | *ctinfo += IP_CT_IS_REPLY; | ||
206 | } else { | ||
207 | if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) | ||
208 | *ctinfo += IP_CT_IS_REPLY; | ||
209 | } | 170 | } |
210 | 171 | ||
172 | if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) | ||
173 | *ctinfo += IP_CT_IS_REPLY; | ||
174 | |||
211 | /* Update skb to refer to this connection */ | 175 | /* Update skb to refer to this connection */ |
212 | skb->nfct = &nf_ct_tuplehash_to_ctrack(h)->ct_general; | 176 | skb->nfct = &nf_ct_tuplehash_to_ctrack(h)->ct_general; |
213 | skb->nfctinfo = *ctinfo; | 177 | skb->nfctinfo = *ctinfo; |
@@ -348,7 +312,7 @@ static struct ctl_table icmp_compat_sysctl_table[] = { | |||
348 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ | 312 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ |
349 | #endif /* CONFIG_SYSCTL */ | 313 | #endif /* CONFIG_SYSCTL */ |
350 | 314 | ||
351 | struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp = | 315 | struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly = |
352 | { | 316 | { |
353 | .l3proto = PF_INET, | 317 | .l3proto = PF_INET, |
354 | .l4proto = IPPROTO_ICMP, | 318 | .l4proto = IPPROTO_ICMP, |
@@ -374,4 +338,3 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp = | |||
374 | #endif | 338 | #endif |
375 | #endif | 339 | #endif |
376 | }; | 340 | }; |
377 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_icmp); | ||
diff --git a/net/ipv4/netfilter/nf_nat_amanda.c b/net/ipv4/netfilter/nf_nat_amanda.c index 0f17098917bc..bd93a1d71052 100644 --- a/net/ipv4/netfilter/nf_nat_amanda.c +++ b/net/ipv4/netfilter/nf_nat_amanda.c | |||
@@ -45,7 +45,7 @@ static unsigned int help(struct sk_buff **pskb, | |||
45 | /* Try to get same port: if not, try to change it. */ | 45 | /* Try to get same port: if not, try to change it. */ |
46 | for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) { | 46 | for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) { |
47 | exp->tuple.dst.u.tcp.port = htons(port); | 47 | exp->tuple.dst.u.tcp.port = htons(port); |
48 | if (nf_conntrack_expect_related(exp) == 0) | 48 | if (nf_ct_expect_related(exp) == 0) |
49 | break; | 49 | break; |
50 | } | 50 | } |
51 | 51 | ||
@@ -57,7 +57,7 @@ static unsigned int help(struct sk_buff **pskb, | |||
57 | matchoff, matchlen, | 57 | matchoff, matchlen, |
58 | buffer, strlen(buffer)); | 58 | buffer, strlen(buffer)); |
59 | if (ret != NF_ACCEPT) | 59 | if (ret != NF_ACCEPT) |
60 | nf_conntrack_unexpect_related(exp); | 60 | nf_ct_unexpect_related(exp); |
61 | return ret; | 61 | return ret; |
62 | } | 62 | } |
63 | 63 | ||
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index ea02f00d2dac..e848d8d6292f 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | #include <linux/timer.h> | 13 | #include <linux/timer.h> |
14 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
15 | #include <linux/vmalloc.h> | ||
16 | #include <net/checksum.h> | 15 | #include <net/checksum.h> |
17 | #include <net/icmp.h> | 16 | #include <net/icmp.h> |
18 | #include <net/ip.h> | 17 | #include <net/ip.h> |
@@ -32,20 +31,15 @@ | |||
32 | #include <net/netfilter/nf_conntrack_l3proto.h> | 31 | #include <net/netfilter/nf_conntrack_l3proto.h> |
33 | #include <net/netfilter/nf_conntrack_l4proto.h> | 32 | #include <net/netfilter/nf_conntrack_l4proto.h> |
34 | 33 | ||
35 | #if 0 | ||
36 | #define DEBUGP printk | ||
37 | #else | ||
38 | #define DEBUGP(format, args...) | ||
39 | #endif | ||
40 | |||
41 | static DEFINE_RWLOCK(nf_nat_lock); | 34 | static DEFINE_RWLOCK(nf_nat_lock); |
42 | 35 | ||
43 | static struct nf_conntrack_l3proto *l3proto = NULL; | 36 | static struct nf_conntrack_l3proto *l3proto = NULL; |
44 | 37 | ||
45 | /* Calculated at init based on memory size */ | 38 | /* Calculated at init based on memory size */ |
46 | static unsigned int nf_nat_htable_size; | 39 | static unsigned int nf_nat_htable_size; |
40 | static int nf_nat_vmalloced; | ||
47 | 41 | ||
48 | static struct list_head *bysource; | 42 | static struct hlist_head *bysource; |
49 | 43 | ||
50 | #define MAX_IP_NAT_PROTO 256 | 44 | #define MAX_IP_NAT_PROTO 256 |
51 | static struct nf_nat_protocol *nf_nat_protos[MAX_IP_NAT_PROTO]; | 45 | static struct nf_nat_protocol *nf_nat_protos[MAX_IP_NAT_PROTO]; |
@@ -87,19 +81,6 @@ hash_by_src(const struct nf_conntrack_tuple *tuple) | |||
87 | tuple->dst.protonum, 0) % nf_nat_htable_size; | 81 | tuple->dst.protonum, 0) % nf_nat_htable_size; |
88 | } | 82 | } |
89 | 83 | ||
90 | /* Noone using conntrack by the time this called. */ | ||
91 | static void nf_nat_cleanup_conntrack(struct nf_conn *conn) | ||
92 | { | ||
93 | struct nf_conn_nat *nat; | ||
94 | if (!(conn->status & IPS_NAT_DONE_MASK)) | ||
95 | return; | ||
96 | |||
97 | nat = nfct_nat(conn); | ||
98 | write_lock_bh(&nf_nat_lock); | ||
99 | list_del(&nat->info.bysource); | ||
100 | write_unlock_bh(&nf_nat_lock); | ||
101 | } | ||
102 | |||
103 | /* Is this tuple already taken? (not by us) */ | 84 | /* Is this tuple already taken? (not by us) */ |
104 | int | 85 | int |
105 | nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple, | 86 | nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple, |
@@ -166,10 +147,11 @@ find_appropriate_src(const struct nf_conntrack_tuple *tuple, | |||
166 | unsigned int h = hash_by_src(tuple); | 147 | unsigned int h = hash_by_src(tuple); |
167 | struct nf_conn_nat *nat; | 148 | struct nf_conn_nat *nat; |
168 | struct nf_conn *ct; | 149 | struct nf_conn *ct; |
150 | struct hlist_node *n; | ||
169 | 151 | ||
170 | read_lock_bh(&nf_nat_lock); | 152 | read_lock_bh(&nf_nat_lock); |
171 | list_for_each_entry(nat, &bysource[h], info.bysource) { | 153 | hlist_for_each_entry(nat, n, &bysource[h], bysource) { |
172 | ct = (struct nf_conn *)((char *)nat - offsetof(struct nf_conn, data)); | 154 | ct = nat->ct; |
173 | if (same_src(ct, tuple)) { | 155 | if (same_src(ct, tuple)) { |
174 | /* Copy source part from reply tuple. */ | 156 | /* Copy source part from reply tuple. */ |
175 | nf_ct_invert_tuplepr(result, | 157 | nf_ct_invert_tuplepr(result, |
@@ -254,7 +236,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
254 | manips not an issue. */ | 236 | manips not an issue. */ |
255 | if (maniptype == IP_NAT_MANIP_SRC) { | 237 | if (maniptype == IP_NAT_MANIP_SRC) { |
256 | if (find_appropriate_src(orig_tuple, tuple, range)) { | 238 | if (find_appropriate_src(orig_tuple, tuple, range)) { |
257 | DEBUGP("get_unique_tuple: Found current src map\n"); | 239 | pr_debug("get_unique_tuple: Found current src map\n"); |
258 | if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) | 240 | if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) |
259 | if (!nf_nat_used_tuple(tuple, ct)) | 241 | if (!nf_nat_used_tuple(tuple, ct)) |
260 | return; | 242 | return; |
@@ -296,11 +278,20 @@ nf_nat_setup_info(struct nf_conn *ct, | |||
296 | unsigned int hooknum) | 278 | unsigned int hooknum) |
297 | { | 279 | { |
298 | struct nf_conntrack_tuple curr_tuple, new_tuple; | 280 | struct nf_conntrack_tuple curr_tuple, new_tuple; |
299 | struct nf_conn_nat *nat = nfct_nat(ct); | 281 | struct nf_conn_nat *nat; |
300 | struct nf_nat_info *info = &nat->info; | ||
301 | int have_to_hash = !(ct->status & IPS_NAT_DONE_MASK); | 282 | int have_to_hash = !(ct->status & IPS_NAT_DONE_MASK); |
302 | enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum); | 283 | enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum); |
303 | 284 | ||
285 | /* nat helper or nfctnetlink also setup binding */ | ||
286 | nat = nfct_nat(ct); | ||
287 | if (!nat) { | ||
288 | nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC); | ||
289 | if (nat == NULL) { | ||
290 | pr_debug("failed to add NAT extension\n"); | ||
291 | return NF_ACCEPT; | ||
292 | } | ||
293 | } | ||
294 | |||
304 | NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING || | 295 | NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING || |
305 | hooknum == NF_IP_POST_ROUTING || | 296 | hooknum == NF_IP_POST_ROUTING || |
306 | hooknum == NF_IP_LOCAL_IN || | 297 | hooknum == NF_IP_LOCAL_IN || |
@@ -337,7 +328,10 @@ nf_nat_setup_info(struct nf_conn *ct, | |||
337 | 328 | ||
338 | srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); | 329 | srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); |
339 | write_lock_bh(&nf_nat_lock); | 330 | write_lock_bh(&nf_nat_lock); |
340 | list_add(&info->bysource, &bysource[srchash]); | 331 | /* nf_conntrack_alter_reply might re-allocate exntension aera */ |
332 | nat = nfct_nat(ct); | ||
333 | nat->ct = ct; | ||
334 | hlist_add_head(&nat->bysource, &bysource[srchash]); | ||
341 | write_unlock_bh(&nf_nat_lock); | 335 | write_unlock_bh(&nf_nat_lock); |
342 | } | 336 | } |
343 | 337 | ||
@@ -462,8 +456,9 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct, | |||
462 | return 0; | 456 | return 0; |
463 | } | 457 | } |
464 | 458 | ||
465 | DEBUGP("icmp_reply_translation: translating error %p manp %u dir %s\n", | 459 | pr_debug("icmp_reply_translation: translating error %p manip %u " |
466 | *pskb, manip, dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY"); | 460 | "dir %s\n", *pskb, manip, |
461 | dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY"); | ||
467 | 462 | ||
468 | /* rcu_read_lock()ed by nf_hook_slow */ | 463 | /* rcu_read_lock()ed by nf_hook_slow */ |
469 | l4proto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol); | 464 | l4proto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol); |
@@ -590,17 +585,69 @@ nf_nat_port_nfattr_to_range(struct nfattr *tb[], struct nf_nat_range *range) | |||
590 | EXPORT_SYMBOL_GPL(nf_nat_port_range_to_nfattr); | 585 | EXPORT_SYMBOL_GPL(nf_nat_port_range_to_nfattr); |
591 | #endif | 586 | #endif |
592 | 587 | ||
588 | /* Noone using conntrack by the time this called. */ | ||
589 | static void nf_nat_cleanup_conntrack(struct nf_conn *ct) | ||
590 | { | ||
591 | struct nf_conn_nat *nat = nf_ct_ext_find(ct, NF_CT_EXT_NAT); | ||
592 | |||
593 | if (nat == NULL || nat->ct == NULL) | ||
594 | return; | ||
595 | |||
596 | NF_CT_ASSERT(nat->ct->status & IPS_NAT_DONE_MASK); | ||
597 | |||
598 | write_lock_bh(&nf_nat_lock); | ||
599 | hlist_del(&nat->bysource); | ||
600 | nat->ct = NULL; | ||
601 | write_unlock_bh(&nf_nat_lock); | ||
602 | } | ||
603 | |||
604 | static void nf_nat_move_storage(struct nf_conn *conntrack, void *old) | ||
605 | { | ||
606 | struct nf_conn_nat *new_nat = nf_ct_ext_find(conntrack, NF_CT_EXT_NAT); | ||
607 | struct nf_conn_nat *old_nat = (struct nf_conn_nat *)old; | ||
608 | struct nf_conn *ct = old_nat->ct; | ||
609 | unsigned int srchash; | ||
610 | |||
611 | if (!(ct->status & IPS_NAT_DONE_MASK)) | ||
612 | return; | ||
613 | |||
614 | srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); | ||
615 | |||
616 | write_lock_bh(&nf_nat_lock); | ||
617 | hlist_replace_rcu(&old_nat->bysource, &new_nat->bysource); | ||
618 | new_nat->ct = ct; | ||
619 | write_unlock_bh(&nf_nat_lock); | ||
620 | } | ||
621 | |||
622 | static struct nf_ct_ext_type nat_extend __read_mostly = { | ||
623 | .len = sizeof(struct nf_conn_nat), | ||
624 | .align = __alignof__(struct nf_conn_nat), | ||
625 | .destroy = nf_nat_cleanup_conntrack, | ||
626 | .move = nf_nat_move_storage, | ||
627 | .id = NF_CT_EXT_NAT, | ||
628 | .flags = NF_CT_EXT_F_PREALLOC, | ||
629 | }; | ||
630 | |||
593 | static int __init nf_nat_init(void) | 631 | static int __init nf_nat_init(void) |
594 | { | 632 | { |
595 | size_t i; | 633 | size_t i; |
634 | int ret; | ||
635 | |||
636 | ret = nf_ct_extend_register(&nat_extend); | ||
637 | if (ret < 0) { | ||
638 | printk(KERN_ERR "nf_nat_core: Unable to register extension\n"); | ||
639 | return ret; | ||
640 | } | ||
596 | 641 | ||
597 | /* Leave them the same for the moment. */ | 642 | /* Leave them the same for the moment. */ |
598 | nf_nat_htable_size = nf_conntrack_htable_size; | 643 | nf_nat_htable_size = nf_conntrack_htable_size; |
599 | 644 | ||
600 | /* One vmalloc for both hash tables */ | 645 | bysource = nf_ct_alloc_hashtable(&nf_nat_htable_size, |
601 | bysource = vmalloc(sizeof(struct list_head) * nf_nat_htable_size); | 646 | &nf_nat_vmalloced); |
602 | if (!bysource) | 647 | if (!bysource) { |
603 | return -ENOMEM; | 648 | ret = -ENOMEM; |
649 | goto cleanup_extend; | ||
650 | } | ||
604 | 651 | ||
605 | /* Sew in builtin protocols. */ | 652 | /* Sew in builtin protocols. */ |
606 | write_lock_bh(&nf_nat_lock); | 653 | write_lock_bh(&nf_nat_lock); |
@@ -612,18 +659,18 @@ static int __init nf_nat_init(void) | |||
612 | write_unlock_bh(&nf_nat_lock); | 659 | write_unlock_bh(&nf_nat_lock); |
613 | 660 | ||
614 | for (i = 0; i < nf_nat_htable_size; i++) { | 661 | for (i = 0; i < nf_nat_htable_size; i++) { |
615 | INIT_LIST_HEAD(&bysource[i]); | 662 | INIT_HLIST_HEAD(&bysource[i]); |
616 | } | 663 | } |
617 | 664 | ||
618 | /* FIXME: Man, this is a hack. <SIGH> */ | ||
619 | NF_CT_ASSERT(rcu_dereference(nf_conntrack_destroyed) == NULL); | ||
620 | rcu_assign_pointer(nf_conntrack_destroyed, nf_nat_cleanup_conntrack); | ||
621 | |||
622 | /* Initialize fake conntrack so that NAT will skip it */ | 665 | /* Initialize fake conntrack so that NAT will skip it */ |
623 | nf_conntrack_untracked.status |= IPS_NAT_DONE_MASK; | 666 | nf_conntrack_untracked.status |= IPS_NAT_DONE_MASK; |
624 | 667 | ||
625 | l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET); | 668 | l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET); |
626 | return 0; | 669 | return 0; |
670 | |||
671 | cleanup_extend: | ||
672 | nf_ct_extend_unregister(&nat_extend); | ||
673 | return ret; | ||
627 | } | 674 | } |
628 | 675 | ||
629 | /* Clear NAT section of all conntracks, in case we're loaded again. */ | 676 | /* Clear NAT section of all conntracks, in case we're loaded again. */ |
@@ -641,10 +688,10 @@ static int clean_nat(struct nf_conn *i, void *data) | |||
641 | static void __exit nf_nat_cleanup(void) | 688 | static void __exit nf_nat_cleanup(void) |
642 | { | 689 | { |
643 | nf_ct_iterate_cleanup(&clean_nat, NULL); | 690 | nf_ct_iterate_cleanup(&clean_nat, NULL); |
644 | rcu_assign_pointer(nf_conntrack_destroyed, NULL); | ||
645 | synchronize_rcu(); | 691 | synchronize_rcu(); |
646 | vfree(bysource); | 692 | nf_ct_free_hashtable(bysource, nf_nat_vmalloced, nf_nat_htable_size); |
647 | nf_ct_l3proto_put(l3proto); | 693 | nf_ct_l3proto_put(l3proto); |
694 | nf_ct_extend_unregister(&nat_extend); | ||
648 | } | 695 | } |
649 | 696 | ||
650 | MODULE_LICENSE("GPL"); | 697 | MODULE_LICENSE("GPL"); |
diff --git a/net/ipv4/netfilter/nf_nat_ftp.c b/net/ipv4/netfilter/nf_nat_ftp.c index e6bc8e5a72f1..3663bd879c39 100644 --- a/net/ipv4/netfilter/nf_nat_ftp.c +++ b/net/ipv4/netfilter/nf_nat_ftp.c | |||
@@ -25,12 +25,6 @@ MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>"); | |||
25 | MODULE_DESCRIPTION("ftp NAT helper"); | 25 | MODULE_DESCRIPTION("ftp NAT helper"); |
26 | MODULE_ALIAS("ip_nat_ftp"); | 26 | MODULE_ALIAS("ip_nat_ftp"); |
27 | 27 | ||
28 | #if 0 | ||
29 | #define DEBUGP printk | ||
30 | #else | ||
31 | #define DEBUGP(format, args...) | ||
32 | #endif | ||
33 | |||
34 | /* FIXME: Time out? --RR */ | 28 | /* FIXME: Time out? --RR */ |
35 | 29 | ||
36 | static int | 30 | static int |
@@ -47,7 +41,7 @@ mangle_rfc959_packet(struct sk_buff **pskb, | |||
47 | sprintf(buffer, "%u,%u,%u,%u,%u,%u", | 41 | sprintf(buffer, "%u,%u,%u,%u,%u,%u", |
48 | NIPQUAD(newip), port>>8, port&0xFF); | 42 | NIPQUAD(newip), port>>8, port&0xFF); |
49 | 43 | ||
50 | DEBUGP("calling nf_nat_mangle_tcp_packet\n"); | 44 | pr_debug("calling nf_nat_mangle_tcp_packet\n"); |
51 | 45 | ||
52 | return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, | 46 | return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, |
53 | matchlen, buffer, strlen(buffer)); | 47 | matchlen, buffer, strlen(buffer)); |
@@ -67,7 +61,7 @@ mangle_eprt_packet(struct sk_buff **pskb, | |||
67 | 61 | ||
68 | sprintf(buffer, "|1|%u.%u.%u.%u|%u|", NIPQUAD(newip), port); | 62 | sprintf(buffer, "|1|%u.%u.%u.%u|%u|", NIPQUAD(newip), port); |
69 | 63 | ||
70 | DEBUGP("calling nf_nat_mangle_tcp_packet\n"); | 64 | pr_debug("calling nf_nat_mangle_tcp_packet\n"); |
71 | 65 | ||
72 | return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, | 66 | return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, |
73 | matchlen, buffer, strlen(buffer)); | 67 | matchlen, buffer, strlen(buffer)); |
@@ -87,7 +81,7 @@ mangle_epsv_packet(struct sk_buff **pskb, | |||
87 | 81 | ||
88 | sprintf(buffer, "|||%u|", port); | 82 | sprintf(buffer, "|||%u|", port); |
89 | 83 | ||
90 | DEBUGP("calling nf_nat_mangle_tcp_packet\n"); | 84 | pr_debug("calling nf_nat_mangle_tcp_packet\n"); |
91 | 85 | ||
92 | return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, | 86 | return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, |
93 | matchlen, buffer, strlen(buffer)); | 87 | matchlen, buffer, strlen(buffer)); |
@@ -117,7 +111,7 @@ static unsigned int nf_nat_ftp(struct sk_buff **pskb, | |||
117 | int dir = CTINFO2DIR(ctinfo); | 111 | int dir = CTINFO2DIR(ctinfo); |
118 | struct nf_conn *ct = exp->master; | 112 | struct nf_conn *ct = exp->master; |
119 | 113 | ||
120 | DEBUGP("FTP_NAT: type %i, off %u len %u\n", type, matchoff, matchlen); | 114 | pr_debug("FTP_NAT: type %i, off %u len %u\n", type, matchoff, matchlen); |
121 | 115 | ||
122 | /* Connection will come from wherever this packet goes, hence !dir */ | 116 | /* Connection will come from wherever this packet goes, hence !dir */ |
123 | newip = ct->tuplehash[!dir].tuple.dst.u3.ip; | 117 | newip = ct->tuplehash[!dir].tuple.dst.u3.ip; |
@@ -131,7 +125,7 @@ static unsigned int nf_nat_ftp(struct sk_buff **pskb, | |||
131 | /* Try to get same port: if not, try to change it. */ | 125 | /* Try to get same port: if not, try to change it. */ |
132 | for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) { | 126 | for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) { |
133 | exp->tuple.dst.u.tcp.port = htons(port); | 127 | exp->tuple.dst.u.tcp.port = htons(port); |
134 | if (nf_conntrack_expect_related(exp) == 0) | 128 | if (nf_ct_expect_related(exp) == 0) |
135 | break; | 129 | break; |
136 | } | 130 | } |
137 | 131 | ||
@@ -139,7 +133,7 @@ static unsigned int nf_nat_ftp(struct sk_buff **pskb, | |||
139 | return NF_DROP; | 133 | return NF_DROP; |
140 | 134 | ||
141 | if (!mangle[type](pskb, newip, port, matchoff, matchlen, ct, ctinfo)) { | 135 | if (!mangle[type](pskb, newip, port, matchoff, matchlen, ct, ctinfo)) { |
142 | nf_conntrack_unexpect_related(exp); | 136 | nf_ct_unexpect_related(exp); |
143 | return NF_DROP; | 137 | return NF_DROP; |
144 | } | 138 | } |
145 | return NF_ACCEPT; | 139 | return NF_ACCEPT; |
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c index c5d2a2d690b8..c1b059a73708 100644 --- a/net/ipv4/netfilter/nf_nat_h323.c +++ b/net/ipv4/netfilter/nf_nat_h323.c | |||
@@ -21,12 +21,6 @@ | |||
21 | #include <net/netfilter/nf_conntrack_expect.h> | 21 | #include <net/netfilter/nf_conntrack_expect.h> |
22 | #include <linux/netfilter/nf_conntrack_h323.h> | 22 | #include <linux/netfilter/nf_conntrack_h323.h> |
23 | 23 | ||
24 | #if 0 | ||
25 | #define DEBUGP printk | ||
26 | #else | ||
27 | #define DEBUGP(format, args...) | ||
28 | #endif | ||
29 | |||
30 | /****************************************************************************/ | 24 | /****************************************************************************/ |
31 | static int set_addr(struct sk_buff **pskb, | 25 | static int set_addr(struct sk_buff **pskb, |
32 | unsigned char **data, int dataoff, | 26 | unsigned char **data, int dataoff, |
@@ -126,12 +120,11 @@ static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct, | |||
126 | (ntohl(addr.ip) & 0xff000000) == 0x7f000000) | 120 | (ntohl(addr.ip) & 0xff000000) == 0x7f000000) |
127 | i = 0; | 121 | i = 0; |
128 | 122 | ||
129 | DEBUGP | 123 | pr_debug("nf_nat_ras: set signal address " |
130 | ("nf_nat_ras: set signal address " | 124 | "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", |
131 | "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", | 125 | NIPQUAD(addr.ip), port, |
132 | NIPQUAD(ip), port, | 126 | NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip), |
133 | NIPQUAD(ct->tuplehash[!dir].tuple.dst. | 127 | info->sig_port[!dir]); |
134 | ip), info->sig_port[!dir]); | ||
135 | return set_h225_addr(pskb, data, 0, &taddr[i], | 128 | return set_h225_addr(pskb, data, 0, &taddr[i], |
136 | &ct->tuplehash[!dir]. | 129 | &ct->tuplehash[!dir]. |
137 | tuple.dst.u3, | 130 | tuple.dst.u3, |
@@ -139,12 +132,11 @@ static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct, | |||
139 | } else if (addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip && | 132 | } else if (addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip && |
140 | port == info->sig_port[dir]) { | 133 | port == info->sig_port[dir]) { |
141 | /* GK->GW */ | 134 | /* GK->GW */ |
142 | DEBUGP | 135 | pr_debug("nf_nat_ras: set signal address " |
143 | ("nf_nat_ras: set signal address " | 136 | "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", |
144 | "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", | 137 | NIPQUAD(addr.ip), port, |
145 | NIPQUAD(ip), port, | 138 | NIPQUAD(ct->tuplehash[!dir].tuple.src.u3.ip), |
146 | NIPQUAD(ct->tuplehash[!dir].tuple.src. | 139 | info->sig_port[!dir]); |
147 | ip), info->sig_port[!dir]); | ||
148 | return set_h225_addr(pskb, data, 0, &taddr[i], | 140 | return set_h225_addr(pskb, data, 0, &taddr[i], |
149 | &ct->tuplehash[!dir]. | 141 | &ct->tuplehash[!dir]. |
150 | tuple.src.u3, | 142 | tuple.src.u3, |
@@ -171,12 +163,11 @@ static int set_ras_addr(struct sk_buff **pskb, struct nf_conn *ct, | |||
171 | if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) && | 163 | if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) && |
172 | addr.ip == ct->tuplehash[dir].tuple.src.u3.ip && | 164 | addr.ip == ct->tuplehash[dir].tuple.src.u3.ip && |
173 | port == ct->tuplehash[dir].tuple.src.u.udp.port) { | 165 | port == ct->tuplehash[dir].tuple.src.u.udp.port) { |
174 | DEBUGP("nf_nat_ras: set rasAddress " | 166 | pr_debug("nf_nat_ras: set rasAddress " |
175 | "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", | 167 | "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", |
176 | NIPQUAD(ip), ntohs(port), | 168 | NIPQUAD(addr.ip), ntohs(port), |
177 | NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip), | 169 | NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip), |
178 | ntohs(ct->tuplehash[!dir].tuple.dst.u.udp. | 170 | ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port)); |
179 | port)); | ||
180 | return set_h225_addr(pskb, data, 0, &taddr[i], | 171 | return set_h225_addr(pskb, data, 0, &taddr[i], |
181 | &ct->tuplehash[!dir].tuple.dst.u3, | 172 | &ct->tuplehash[!dir].tuple.dst.u3, |
182 | ct->tuplehash[!dir].tuple. | 173 | ct->tuplehash[!dir].tuple. |
@@ -237,12 +228,12 @@ static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, | |||
237 | for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port); | 228 | for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port); |
238 | nated_port != 0; nated_port += 2) { | 229 | nated_port != 0; nated_port += 2) { |
239 | rtp_exp->tuple.dst.u.udp.port = htons(nated_port); | 230 | rtp_exp->tuple.dst.u.udp.port = htons(nated_port); |
240 | if (nf_conntrack_expect_related(rtp_exp) == 0) { | 231 | if (nf_ct_expect_related(rtp_exp) == 0) { |
241 | rtcp_exp->tuple.dst.u.udp.port = | 232 | rtcp_exp->tuple.dst.u.udp.port = |
242 | htons(nated_port + 1); | 233 | htons(nated_port + 1); |
243 | if (nf_conntrack_expect_related(rtcp_exp) == 0) | 234 | if (nf_ct_expect_related(rtcp_exp) == 0) |
244 | break; | 235 | break; |
245 | nf_conntrack_unexpect_related(rtp_exp); | 236 | nf_ct_unexpect_related(rtp_exp); |
246 | } | 237 | } |
247 | } | 238 | } |
248 | 239 | ||
@@ -261,22 +252,22 @@ static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, | |||
261 | info->rtp_port[i][dir] = rtp_port; | 252 | info->rtp_port[i][dir] = rtp_port; |
262 | info->rtp_port[i][!dir] = htons(nated_port); | 253 | info->rtp_port[i][!dir] = htons(nated_port); |
263 | } else { | 254 | } else { |
264 | nf_conntrack_unexpect_related(rtp_exp); | 255 | nf_ct_unexpect_related(rtp_exp); |
265 | nf_conntrack_unexpect_related(rtcp_exp); | 256 | nf_ct_unexpect_related(rtcp_exp); |
266 | return -1; | 257 | return -1; |
267 | } | 258 | } |
268 | 259 | ||
269 | /* Success */ | 260 | /* Success */ |
270 | DEBUGP("nf_nat_h323: expect RTP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", | 261 | pr_debug("nf_nat_h323: expect RTP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", |
271 | NIPQUAD(rtp_exp->tuple.src.ip), | 262 | NIPQUAD(rtp_exp->tuple.src.u3.ip), |
272 | ntohs(rtp_exp->tuple.src.u.udp.port), | 263 | ntohs(rtp_exp->tuple.src.u.udp.port), |
273 | NIPQUAD(rtp_exp->tuple.dst.ip), | 264 | NIPQUAD(rtp_exp->tuple.dst.u3.ip), |
274 | ntohs(rtp_exp->tuple.dst.u.udp.port)); | 265 | ntohs(rtp_exp->tuple.dst.u.udp.port)); |
275 | DEBUGP("nf_nat_h323: expect RTCP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", | 266 | pr_debug("nf_nat_h323: expect RTCP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", |
276 | NIPQUAD(rtcp_exp->tuple.src.ip), | 267 | NIPQUAD(rtcp_exp->tuple.src.u3.ip), |
277 | ntohs(rtcp_exp->tuple.src.u.udp.port), | 268 | ntohs(rtcp_exp->tuple.src.u.udp.port), |
278 | NIPQUAD(rtcp_exp->tuple.dst.ip), | 269 | NIPQUAD(rtcp_exp->tuple.dst.u3.ip), |
279 | ntohs(rtcp_exp->tuple.dst.u.udp.port)); | 270 | ntohs(rtcp_exp->tuple.dst.u.udp.port)); |
280 | 271 | ||
281 | return 0; | 272 | return 0; |
282 | } | 273 | } |
@@ -299,7 +290,7 @@ static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct, | |||
299 | /* Try to get same port: if not, try to change it. */ | 290 | /* Try to get same port: if not, try to change it. */ |
300 | for (; nated_port != 0; nated_port++) { | 291 | for (; nated_port != 0; nated_port++) { |
301 | exp->tuple.dst.u.tcp.port = htons(nated_port); | 292 | exp->tuple.dst.u.tcp.port = htons(nated_port); |
302 | if (nf_conntrack_expect_related(exp) == 0) | 293 | if (nf_ct_expect_related(exp) == 0) |
303 | break; | 294 | break; |
304 | } | 295 | } |
305 | 296 | ||
@@ -313,13 +304,15 @@ static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct, | |||
313 | if (set_h245_addr(pskb, data, dataoff, taddr, | 304 | if (set_h245_addr(pskb, data, dataoff, taddr, |
314 | &ct->tuplehash[!dir].tuple.dst.u3, | 305 | &ct->tuplehash[!dir].tuple.dst.u3, |
315 | htons(nated_port)) < 0) { | 306 | htons(nated_port)) < 0) { |
316 | nf_conntrack_unexpect_related(exp); | 307 | nf_ct_unexpect_related(exp); |
317 | return -1; | 308 | return -1; |
318 | } | 309 | } |
319 | 310 | ||
320 | DEBUGP("nf_nat_h323: expect T.120 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", | 311 | pr_debug("nf_nat_h323: expect T.120 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", |
321 | NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port), | 312 | NIPQUAD(exp->tuple.src.u3.ip), |
322 | NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port)); | 313 | ntohs(exp->tuple.src.u.tcp.port), |
314 | NIPQUAD(exp->tuple.dst.u3.ip), | ||
315 | ntohs(exp->tuple.dst.u.tcp.port)); | ||
323 | 316 | ||
324 | return 0; | 317 | return 0; |
325 | } | 318 | } |
@@ -347,7 +340,7 @@ static int nat_h245(struct sk_buff **pskb, struct nf_conn *ct, | |||
347 | /* Try to get same port: if not, try to change it. */ | 340 | /* Try to get same port: if not, try to change it. */ |
348 | for (; nated_port != 0; nated_port++) { | 341 | for (; nated_port != 0; nated_port++) { |
349 | exp->tuple.dst.u.tcp.port = htons(nated_port); | 342 | exp->tuple.dst.u.tcp.port = htons(nated_port); |
350 | if (nf_conntrack_expect_related(exp) == 0) | 343 | if (nf_ct_expect_related(exp) == 0) |
351 | break; | 344 | break; |
352 | } | 345 | } |
353 | 346 | ||
@@ -365,13 +358,15 @@ static int nat_h245(struct sk_buff **pskb, struct nf_conn *ct, | |||
365 | info->sig_port[dir] = port; | 358 | info->sig_port[dir] = port; |
366 | info->sig_port[!dir] = htons(nated_port); | 359 | info->sig_port[!dir] = htons(nated_port); |
367 | } else { | 360 | } else { |
368 | nf_conntrack_unexpect_related(exp); | 361 | nf_ct_unexpect_related(exp); |
369 | return -1; | 362 | return -1; |
370 | } | 363 | } |
371 | 364 | ||
372 | DEBUGP("nf_nat_q931: expect H.245 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", | 365 | pr_debug("nf_nat_q931: expect H.245 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", |
373 | NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port), | 366 | NIPQUAD(exp->tuple.src.u3.ip), |
374 | NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port)); | 367 | ntohs(exp->tuple.src.u.tcp.port), |
368 | NIPQUAD(exp->tuple.dst.u3.ip), | ||
369 | ntohs(exp->tuple.dst.u.tcp.port)); | ||
375 | 370 | ||
376 | return 0; | 371 | return 0; |
377 | } | 372 | } |
@@ -433,7 +428,7 @@ static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct, | |||
433 | /* Try to get same port: if not, try to change it. */ | 428 | /* Try to get same port: if not, try to change it. */ |
434 | for (; nated_port != 0; nated_port++) { | 429 | for (; nated_port != 0; nated_port++) { |
435 | exp->tuple.dst.u.tcp.port = htons(nated_port); | 430 | exp->tuple.dst.u.tcp.port = htons(nated_port); |
436 | if (nf_conntrack_expect_related(exp) == 0) | 431 | if (nf_ct_expect_related(exp) == 0) |
437 | break; | 432 | break; |
438 | } | 433 | } |
439 | 434 | ||
@@ -460,14 +455,16 @@ static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct, | |||
460 | info->sig_port[!dir]); | 455 | info->sig_port[!dir]); |
461 | } | 456 | } |
462 | } else { | 457 | } else { |
463 | nf_conntrack_unexpect_related(exp); | 458 | nf_ct_unexpect_related(exp); |
464 | return -1; | 459 | return -1; |
465 | } | 460 | } |
466 | 461 | ||
467 | /* Success */ | 462 | /* Success */ |
468 | DEBUGP("nf_nat_ras: expect Q.931 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", | 463 | pr_debug("nf_nat_ras: expect Q.931 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", |
469 | NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port), | 464 | NIPQUAD(exp->tuple.src.u3.ip), |
470 | NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port)); | 465 | ntohs(exp->tuple.src.u.tcp.port), |
466 | NIPQUAD(exp->tuple.dst.u3.ip), | ||
467 | ntohs(exp->tuple.dst.u.tcp.port)); | ||
471 | 468 | ||
472 | return 0; | 469 | return 0; |
473 | } | 470 | } |
@@ -517,7 +514,7 @@ static int nat_callforwarding(struct sk_buff **pskb, struct nf_conn *ct, | |||
517 | /* Try to get same port: if not, try to change it. */ | 514 | /* Try to get same port: if not, try to change it. */ |
518 | for (nated_port = ntohs(port); nated_port != 0; nated_port++) { | 515 | for (nated_port = ntohs(port); nated_port != 0; nated_port++) { |
519 | exp->tuple.dst.u.tcp.port = htons(nated_port); | 516 | exp->tuple.dst.u.tcp.port = htons(nated_port); |
520 | if (nf_conntrack_expect_related(exp) == 0) | 517 | if (nf_ct_expect_related(exp) == 0) |
521 | break; | 518 | break; |
522 | } | 519 | } |
523 | 520 | ||
@@ -531,15 +528,17 @@ static int nat_callforwarding(struct sk_buff **pskb, struct nf_conn *ct, | |||
531 | if (!set_h225_addr(pskb, data, dataoff, taddr, | 528 | if (!set_h225_addr(pskb, data, dataoff, taddr, |
532 | &ct->tuplehash[!dir].tuple.dst.u3, | 529 | &ct->tuplehash[!dir].tuple.dst.u3, |
533 | htons(nated_port)) == 0) { | 530 | htons(nated_port)) == 0) { |
534 | nf_conntrack_unexpect_related(exp); | 531 | nf_ct_unexpect_related(exp); |
535 | return -1; | 532 | return -1; |
536 | } | 533 | } |
537 | 534 | ||
538 | /* Success */ | 535 | /* Success */ |
539 | DEBUGP("nf_nat_q931: expect Call Forwarding " | 536 | pr_debug("nf_nat_q931: expect Call Forwarding " |
540 | "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", | 537 | "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", |
541 | NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port), | 538 | NIPQUAD(exp->tuple.src.u3.ip), |
542 | NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port)); | 539 | ntohs(exp->tuple.src.u.tcp.port), |
540 | NIPQUAD(exp->tuple.dst.u3.ip), | ||
541 | ntohs(exp->tuple.dst.u.tcp.port)); | ||
543 | 542 | ||
544 | return 0; | 543 | return 0; |
545 | } | 544 | } |
@@ -566,8 +565,6 @@ static int __init init(void) | |||
566 | rcu_assign_pointer(nat_h245_hook, nat_h245); | 565 | rcu_assign_pointer(nat_h245_hook, nat_h245); |
567 | rcu_assign_pointer(nat_callforwarding_hook, nat_callforwarding); | 566 | rcu_assign_pointer(nat_callforwarding_hook, nat_callforwarding); |
568 | rcu_assign_pointer(nat_q931_hook, nat_q931); | 567 | rcu_assign_pointer(nat_q931_hook, nat_q931); |
569 | |||
570 | DEBUGP("nf_nat_h323: init success\n"); | ||
571 | return 0; | 568 | return 0; |
572 | } | 569 | } |
573 | 570 | ||
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index 15b6e5ce3a04..93d8a0a8f035 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c | |||
@@ -26,13 +26,9 @@ | |||
26 | #include <net/netfilter/nf_nat_core.h> | 26 | #include <net/netfilter/nf_nat_core.h> |
27 | #include <net/netfilter/nf_nat_helper.h> | 27 | #include <net/netfilter/nf_nat_helper.h> |
28 | 28 | ||
29 | #if 0 | 29 | #define DUMP_OFFSET(x) \ |
30 | #define DEBUGP printk | 30 | pr_debug("offset_before=%d, offset_after=%d, correction_pos=%u\n", \ |
31 | #define DUMP_OFFSET(x) printk("offset_before=%d, offset_after=%d, correction_pos=%u\n", x->offset_before, x->offset_after, x->correction_pos); | 31 | x->offset_before, x->offset_after, x->correction_pos); |
32 | #else | ||
33 | #define DEBUGP(format, args...) | ||
34 | #define DUMP_OFFSET(x) | ||
35 | #endif | ||
36 | 32 | ||
37 | static DEFINE_SPINLOCK(nf_nat_seqofs_lock); | 33 | static DEFINE_SPINLOCK(nf_nat_seqofs_lock); |
38 | 34 | ||
@@ -47,15 +43,15 @@ adjust_tcp_sequence(u32 seq, | |||
47 | struct nf_nat_seq *this_way, *other_way; | 43 | struct nf_nat_seq *this_way, *other_way; |
48 | struct nf_conn_nat *nat = nfct_nat(ct); | 44 | struct nf_conn_nat *nat = nfct_nat(ct); |
49 | 45 | ||
50 | DEBUGP("nf_nat_resize_packet: old_size = %u, new_size = %u\n", | 46 | pr_debug("adjust_tcp_sequence: seq = %u, sizediff = %d\n", |
51 | (*skb)->len, new_size); | 47 | ntohl(seq), seq); |
52 | 48 | ||
53 | dir = CTINFO2DIR(ctinfo); | 49 | dir = CTINFO2DIR(ctinfo); |
54 | 50 | ||
55 | this_way = &nat->info.seq[dir]; | 51 | this_way = &nat->seq[dir]; |
56 | other_way = &nat->info.seq[!dir]; | 52 | other_way = &nat->seq[!dir]; |
57 | 53 | ||
58 | DEBUGP("nf_nat_resize_packet: Seq_offset before: "); | 54 | pr_debug("nf_nat_resize_packet: Seq_offset before: "); |
59 | DUMP_OFFSET(this_way); | 55 | DUMP_OFFSET(this_way); |
60 | 56 | ||
61 | spin_lock_bh(&nf_nat_seqofs_lock); | 57 | spin_lock_bh(&nf_nat_seqofs_lock); |
@@ -72,7 +68,7 @@ adjust_tcp_sequence(u32 seq, | |||
72 | } | 68 | } |
73 | spin_unlock_bh(&nf_nat_seqofs_lock); | 69 | spin_unlock_bh(&nf_nat_seqofs_lock); |
74 | 70 | ||
75 | DEBUGP("nf_nat_resize_packet: Seq_offset after: "); | 71 | pr_debug("nf_nat_resize_packet: Seq_offset after: "); |
76 | DUMP_OFFSET(this_way); | 72 | DUMP_OFFSET(this_way); |
77 | } | 73 | } |
78 | 74 | ||
@@ -100,14 +96,12 @@ static void mangle_contents(struct sk_buff *skb, | |||
100 | 96 | ||
101 | /* update skb info */ | 97 | /* update skb info */ |
102 | if (rep_len > match_len) { | 98 | if (rep_len > match_len) { |
103 | DEBUGP("nf_nat_mangle_packet: Extending packet by " | 99 | pr_debug("nf_nat_mangle_packet: Extending packet by " |
104 | "%u from %u bytes\n", rep_len - match_len, | 100 | "%u from %u bytes\n", rep_len - match_len, skb->len); |
105 | skb->len); | ||
106 | skb_put(skb, rep_len - match_len); | 101 | skb_put(skb, rep_len - match_len); |
107 | } else { | 102 | } else { |
108 | DEBUGP("nf_nat_mangle_packet: Shrinking packet from " | 103 | pr_debug("nf_nat_mangle_packet: Shrinking packet from " |
109 | "%u from %u bytes\n", match_len - rep_len, | 104 | "%u from %u bytes\n", match_len - rep_len, skb->len); |
110 | skb->len); | ||
111 | __skb_trim(skb, skb->len + rep_len - match_len); | 105 | __skb_trim(skb, skb->len + rep_len - match_len); |
112 | } | 106 | } |
113 | 107 | ||
@@ -178,7 +172,7 @@ nf_nat_mangle_tcp_packet(struct sk_buff **pskb, | |||
178 | datalen = (*pskb)->len - iph->ihl*4; | 172 | datalen = (*pskb)->len - iph->ihl*4; |
179 | if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) { | 173 | if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) { |
180 | if (!(rt->rt_flags & RTCF_LOCAL) && | 174 | if (!(rt->rt_flags & RTCF_LOCAL) && |
181 | (*pskb)->dev->features & NETIF_F_ALL_CSUM) { | 175 | (*pskb)->dev->features & NETIF_F_V4_CSUM) { |
182 | (*pskb)->ip_summed = CHECKSUM_PARTIAL; | 176 | (*pskb)->ip_summed = CHECKSUM_PARTIAL; |
183 | (*pskb)->csum_start = skb_headroom(*pskb) + | 177 | (*pskb)->csum_start = skb_headroom(*pskb) + |
184 | skb_network_offset(*pskb) + | 178 | skb_network_offset(*pskb) + |
@@ -190,7 +184,7 @@ nf_nat_mangle_tcp_packet(struct sk_buff **pskb, | |||
190 | tcph->check = 0; | 184 | tcph->check = 0; |
191 | tcph->check = tcp_v4_check(datalen, | 185 | tcph->check = tcp_v4_check(datalen, |
192 | iph->saddr, iph->daddr, | 186 | iph->saddr, iph->daddr, |
193 | csum_partial((char *)tcph, | 187 | csum_partial(tcph, |
194 | datalen, 0)); | 188 | datalen, 0)); |
195 | } | 189 | } |
196 | } else | 190 | } else |
@@ -265,7 +259,7 @@ nf_nat_mangle_udp_packet(struct sk_buff **pskb, | |||
265 | 259 | ||
266 | if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) { | 260 | if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) { |
267 | if (!(rt->rt_flags & RTCF_LOCAL) && | 261 | if (!(rt->rt_flags & RTCF_LOCAL) && |
268 | (*pskb)->dev->features & NETIF_F_ALL_CSUM) { | 262 | (*pskb)->dev->features & NETIF_F_V4_CSUM) { |
269 | (*pskb)->ip_summed = CHECKSUM_PARTIAL; | 263 | (*pskb)->ip_summed = CHECKSUM_PARTIAL; |
270 | (*pskb)->csum_start = skb_headroom(*pskb) + | 264 | (*pskb)->csum_start = skb_headroom(*pskb) + |
271 | skb_network_offset(*pskb) + | 265 | skb_network_offset(*pskb) + |
@@ -278,7 +272,7 @@ nf_nat_mangle_udp_packet(struct sk_buff **pskb, | |||
278 | udph->check = 0; | 272 | udph->check = 0; |
279 | udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, | 273 | udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, |
280 | datalen, IPPROTO_UDP, | 274 | datalen, IPPROTO_UDP, |
281 | csum_partial((char *)udph, | 275 | csum_partial(udph, |
282 | datalen, 0)); | 276 | datalen, 0)); |
283 | if (!udph->check) | 277 | if (!udph->check) |
284 | udph->check = CSUM_MANGLED_0; | 278 | udph->check = CSUM_MANGLED_0; |
@@ -320,9 +314,9 @@ sack_adjust(struct sk_buff *skb, | |||
320 | new_end_seq = htonl(ntohl(sack->end_seq) | 314 | new_end_seq = htonl(ntohl(sack->end_seq) |
321 | - natseq->offset_before); | 315 | - natseq->offset_before); |
322 | 316 | ||
323 | DEBUGP("sack_adjust: start_seq: %d->%d, end_seq: %d->%d\n", | 317 | pr_debug("sack_adjust: start_seq: %d->%d, end_seq: %d->%d\n", |
324 | ntohl(sack->start_seq), new_start_seq, | 318 | ntohl(sack->start_seq), new_start_seq, |
325 | ntohl(sack->end_seq), new_end_seq); | 319 | ntohl(sack->end_seq), new_end_seq); |
326 | 320 | ||
327 | nf_proto_csum_replace4(&tcph->check, skb, | 321 | nf_proto_csum_replace4(&tcph->check, skb, |
328 | sack->start_seq, new_start_seq, 0); | 322 | sack->start_seq, new_start_seq, 0); |
@@ -372,8 +366,7 @@ nf_nat_sack_adjust(struct sk_buff **pskb, | |||
372 | op[1] >= 2+TCPOLEN_SACK_PERBLOCK && | 366 | op[1] >= 2+TCPOLEN_SACK_PERBLOCK && |
373 | ((op[1] - 2) % TCPOLEN_SACK_PERBLOCK) == 0) | 367 | ((op[1] - 2) % TCPOLEN_SACK_PERBLOCK) == 0) |
374 | sack_adjust(*pskb, tcph, optoff+2, | 368 | sack_adjust(*pskb, tcph, optoff+2, |
375 | optoff+op[1], | 369 | optoff+op[1], &nat->seq[!dir]); |
376 | &nat->info.seq[!dir]); | ||
377 | optoff += op[1]; | 370 | optoff += op[1]; |
378 | } | 371 | } |
379 | } | 372 | } |
@@ -394,8 +387,8 @@ nf_nat_seq_adjust(struct sk_buff **pskb, | |||
394 | 387 | ||
395 | dir = CTINFO2DIR(ctinfo); | 388 | dir = CTINFO2DIR(ctinfo); |
396 | 389 | ||
397 | this_way = &nat->info.seq[dir]; | 390 | this_way = &nat->seq[dir]; |
398 | other_way = &nat->info.seq[!dir]; | 391 | other_way = &nat->seq[!dir]; |
399 | 392 | ||
400 | if (!skb_make_writable(pskb, ip_hdrlen(*pskb) + sizeof(*tcph))) | 393 | if (!skb_make_writable(pskb, ip_hdrlen(*pskb) + sizeof(*tcph))) |
401 | return 0; | 394 | return 0; |
@@ -415,9 +408,9 @@ nf_nat_seq_adjust(struct sk_buff **pskb, | |||
415 | nf_proto_csum_replace4(&tcph->check, *pskb, tcph->seq, newseq, 0); | 408 | nf_proto_csum_replace4(&tcph->check, *pskb, tcph->seq, newseq, 0); |
416 | nf_proto_csum_replace4(&tcph->check, *pskb, tcph->ack_seq, newack, 0); | 409 | nf_proto_csum_replace4(&tcph->check, *pskb, tcph->ack_seq, newack, 0); |
417 | 410 | ||
418 | DEBUGP("Adjusting sequence number from %u->%u, ack from %u->%u\n", | 411 | pr_debug("Adjusting sequence number from %u->%u, ack from %u->%u\n", |
419 | ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq), | 412 | ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq), |
420 | ntohl(newack)); | 413 | ntohl(newack)); |
421 | 414 | ||
422 | tcph->seq = newseq; | 415 | tcph->seq = newseq; |
423 | tcph->ack_seq = newack; | 416 | tcph->ack_seq = newack; |
diff --git a/net/ipv4/netfilter/nf_nat_irc.c b/net/ipv4/netfilter/nf_nat_irc.c index 9b8c0daea744..bcf274bba602 100644 --- a/net/ipv4/netfilter/nf_nat_irc.c +++ b/net/ipv4/netfilter/nf_nat_irc.c | |||
@@ -22,12 +22,6 @@ | |||
22 | #include <net/netfilter/nf_conntrack_expect.h> | 22 | #include <net/netfilter/nf_conntrack_expect.h> |
23 | #include <linux/netfilter/nf_conntrack_irc.h> | 23 | #include <linux/netfilter/nf_conntrack_irc.h> |
24 | 24 | ||
25 | #if 0 | ||
26 | #define DEBUGP printk | ||
27 | #else | ||
28 | #define DEBUGP(format, args...) | ||
29 | #endif | ||
30 | |||
31 | MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); | 25 | MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); |
32 | MODULE_DESCRIPTION("IRC (DCC) NAT helper"); | 26 | MODULE_DESCRIPTION("IRC (DCC) NAT helper"); |
33 | MODULE_LICENSE("GPL"); | 27 | MODULE_LICENSE("GPL"); |
@@ -44,9 +38,6 @@ static unsigned int help(struct sk_buff **pskb, | |||
44 | u_int16_t port; | 38 | u_int16_t port; |
45 | unsigned int ret; | 39 | unsigned int ret; |
46 | 40 | ||
47 | DEBUGP("IRC_NAT: info (seq %u + %u) in %u\n", | ||
48 | expect->seq, exp_irc_info->len, ntohl(tcph->seq)); | ||
49 | |||
50 | /* Reply comes from server. */ | 41 | /* Reply comes from server. */ |
51 | exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; | 42 | exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; |
52 | exp->dir = IP_CT_DIR_REPLY; | 43 | exp->dir = IP_CT_DIR_REPLY; |
@@ -55,7 +46,7 @@ static unsigned int help(struct sk_buff **pskb, | |||
55 | /* Try to get same port: if not, try to change it. */ | 46 | /* Try to get same port: if not, try to change it. */ |
56 | for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) { | 47 | for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) { |
57 | exp->tuple.dst.u.tcp.port = htons(port); | 48 | exp->tuple.dst.u.tcp.port = htons(port); |
58 | if (nf_conntrack_expect_related(exp) == 0) | 49 | if (nf_ct_expect_related(exp) == 0) |
59 | break; | 50 | break; |
60 | } | 51 | } |
61 | 52 | ||
@@ -64,14 +55,14 @@ static unsigned int help(struct sk_buff **pskb, | |||
64 | 55 | ||
65 | ip = ntohl(exp->master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip); | 56 | ip = ntohl(exp->master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip); |
66 | sprintf(buffer, "%u %u", ip, port); | 57 | sprintf(buffer, "%u %u", ip, port); |
67 | DEBUGP("nf_nat_irc: inserting '%s' == %u.%u.%u.%u, port %u\n", | 58 | pr_debug("nf_nat_irc: inserting '%s' == %u.%u.%u.%u, port %u\n", |
68 | buffer, NIPQUAD(ip), port); | 59 | buffer, NIPQUAD(ip), port); |
69 | 60 | ||
70 | ret = nf_nat_mangle_tcp_packet(pskb, exp->master, ctinfo, | 61 | ret = nf_nat_mangle_tcp_packet(pskb, exp->master, ctinfo, |
71 | matchoff, matchlen, buffer, | 62 | matchoff, matchlen, buffer, |
72 | strlen(buffer)); | 63 | strlen(buffer)); |
73 | if (ret != NF_ACCEPT) | 64 | if (ret != NF_ACCEPT) |
74 | nf_conntrack_unexpect_related(exp); | 65 | nf_ct_unexpect_related(exp); |
75 | return ret; | 66 | return ret; |
76 | } | 67 | } |
77 | 68 | ||
diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c index a66888749ceb..984ec8308b2e 100644 --- a/net/ipv4/netfilter/nf_nat_pptp.c +++ b/net/ipv4/netfilter/nf_nat_pptp.c | |||
@@ -37,14 +37,6 @@ MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); | |||
37 | MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP"); | 37 | MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP"); |
38 | MODULE_ALIAS("ip_nat_pptp"); | 38 | MODULE_ALIAS("ip_nat_pptp"); |
39 | 39 | ||
40 | #if 0 | ||
41 | extern const char *pptp_msg_name[]; | ||
42 | #define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \ | ||
43 | __FUNCTION__, ## args) | ||
44 | #else | ||
45 | #define DEBUGP(format, args...) | ||
46 | #endif | ||
47 | |||
48 | static void pptp_nat_expected(struct nf_conn *ct, | 40 | static void pptp_nat_expected(struct nf_conn *ct, |
49 | struct nf_conntrack_expect *exp) | 41 | struct nf_conntrack_expect *exp) |
50 | { | 42 | { |
@@ -60,7 +52,7 @@ static void pptp_nat_expected(struct nf_conn *ct, | |||
60 | 52 | ||
61 | /* And here goes the grand finale of corrosion... */ | 53 | /* And here goes the grand finale of corrosion... */ |
62 | if (exp->dir == IP_CT_DIR_ORIGINAL) { | 54 | if (exp->dir == IP_CT_DIR_ORIGINAL) { |
63 | DEBUGP("we are PNS->PAC\n"); | 55 | pr_debug("we are PNS->PAC\n"); |
64 | /* therefore, build tuple for PAC->PNS */ | 56 | /* therefore, build tuple for PAC->PNS */ |
65 | t.src.l3num = AF_INET; | 57 | t.src.l3num = AF_INET; |
66 | t.src.u3.ip = master->tuplehash[!exp->dir].tuple.src.u3.ip; | 58 | t.src.u3.ip = master->tuplehash[!exp->dir].tuple.src.u3.ip; |
@@ -69,7 +61,7 @@ static void pptp_nat_expected(struct nf_conn *ct, | |||
69 | t.dst.u.gre.key = ct_pptp_info->pns_call_id; | 61 | t.dst.u.gre.key = ct_pptp_info->pns_call_id; |
70 | t.dst.protonum = IPPROTO_GRE; | 62 | t.dst.protonum = IPPROTO_GRE; |
71 | } else { | 63 | } else { |
72 | DEBUGP("we are PAC->PNS\n"); | 64 | pr_debug("we are PAC->PNS\n"); |
73 | /* build tuple for PNS->PAC */ | 65 | /* build tuple for PNS->PAC */ |
74 | t.src.l3num = AF_INET; | 66 | t.src.l3num = AF_INET; |
75 | t.src.u3.ip = master->tuplehash[!exp->dir].tuple.src.u3.ip; | 67 | t.src.u3.ip = master->tuplehash[!exp->dir].tuple.src.u3.ip; |
@@ -79,15 +71,15 @@ static void pptp_nat_expected(struct nf_conn *ct, | |||
79 | t.dst.protonum = IPPROTO_GRE; | 71 | t.dst.protonum = IPPROTO_GRE; |
80 | } | 72 | } |
81 | 73 | ||
82 | DEBUGP("trying to unexpect other dir: "); | 74 | pr_debug("trying to unexpect other dir: "); |
83 | NF_CT_DUMP_TUPLE(&t); | 75 | NF_CT_DUMP_TUPLE(&t); |
84 | other_exp = nf_conntrack_expect_find_get(&t); | 76 | other_exp = nf_ct_expect_find_get(&t); |
85 | if (other_exp) { | 77 | if (other_exp) { |
86 | nf_conntrack_unexpect_related(other_exp); | 78 | nf_ct_unexpect_related(other_exp); |
87 | nf_conntrack_expect_put(other_exp); | 79 | nf_ct_expect_put(other_exp); |
88 | DEBUGP("success\n"); | 80 | pr_debug("success\n"); |
89 | } else { | 81 | } else { |
90 | DEBUGP("not found!\n"); | 82 | pr_debug("not found!\n"); |
91 | } | 83 | } |
92 | 84 | ||
93 | /* This must be a fresh one. */ | 85 | /* This must be a fresh one. */ |
@@ -161,9 +153,9 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
161 | cid_off = offsetof(union pptp_ctrl_union, clrreq.callID); | 153 | cid_off = offsetof(union pptp_ctrl_union, clrreq.callID); |
162 | break; | 154 | break; |
163 | default: | 155 | default: |
164 | DEBUGP("unknown outbound packet 0x%04x:%s\n", msg, | 156 | pr_debug("unknown outbound packet 0x%04x:%s\n", msg, |
165 | (msg <= PPTP_MSG_MAX)? | 157 | msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : |
166 | pptp_msg_name[msg]:pptp_msg_name[0]); | 158 | pptp_msg_name[0]); |
167 | /* fall through */ | 159 | /* fall through */ |
168 | case PPTP_SET_LINK_INFO: | 160 | case PPTP_SET_LINK_INFO: |
169 | /* only need to NAT in case PAC is behind NAT box */ | 161 | /* only need to NAT in case PAC is behind NAT box */ |
@@ -179,8 +171,8 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
179 | 171 | ||
180 | /* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass | 172 | /* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass |
181 | * down to here */ | 173 | * down to here */ |
182 | DEBUGP("altering call id from 0x%04x to 0x%04x\n", | 174 | pr_debug("altering call id from 0x%04x to 0x%04x\n", |
183 | ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid)); | 175 | ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid)); |
184 | 176 | ||
185 | /* mangle packet */ | 177 | /* mangle packet */ |
186 | if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, | 178 | if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, |
@@ -255,8 +247,9 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
255 | pcid_off = offsetof(union pptp_ctrl_union, setlink.peersCallID); | 247 | pcid_off = offsetof(union pptp_ctrl_union, setlink.peersCallID); |
256 | break; | 248 | break; |
257 | default: | 249 | default: |
258 | DEBUGP("unknown inbound packet %s\n", (msg <= PPTP_MSG_MAX)? | 250 | pr_debug("unknown inbound packet %s\n", |
259 | pptp_msg_name[msg]:pptp_msg_name[0]); | 251 | msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : |
252 | pptp_msg_name[0]); | ||
260 | /* fall through */ | 253 | /* fall through */ |
261 | case PPTP_START_SESSION_REQUEST: | 254 | case PPTP_START_SESSION_REQUEST: |
262 | case PPTP_START_SESSION_REPLY: | 255 | case PPTP_START_SESSION_REPLY: |
@@ -272,8 +265,8 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
272 | * WAN_ERROR_NOTIFY, CALL_DISCONNECT_NOTIFY pass down here */ | 265 | * WAN_ERROR_NOTIFY, CALL_DISCONNECT_NOTIFY pass down here */ |
273 | 266 | ||
274 | /* mangle packet */ | 267 | /* mangle packet */ |
275 | DEBUGP("altering peer call id from 0x%04x to 0x%04x\n", | 268 | pr_debug("altering peer call id from 0x%04x to 0x%04x\n", |
276 | ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid)); | 269 | ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid)); |
277 | 270 | ||
278 | if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, | 271 | if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, |
279 | pcid_off + sizeof(struct pptp_pkt_hdr) + | 272 | pcid_off + sizeof(struct pptp_pkt_hdr) + |
diff --git a/net/ipv4/netfilter/nf_nat_proto_gre.c b/net/ipv4/netfilter/nf_nat_proto_gre.c index c3908bc5a709..2e40cc83526a 100644 --- a/net/ipv4/netfilter/nf_nat_proto_gre.c +++ b/net/ipv4/netfilter/nf_nat_proto_gre.c | |||
@@ -36,13 +36,6 @@ MODULE_LICENSE("GPL"); | |||
36 | MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); | 36 | MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); |
37 | MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE"); | 37 | MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE"); |
38 | 38 | ||
39 | #if 0 | ||
40 | #define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \ | ||
41 | __FUNCTION__, ## args) | ||
42 | #else | ||
43 | #define DEBUGP(x, args...) | ||
44 | #endif | ||
45 | |||
46 | /* is key in given range between min and max */ | 39 | /* is key in given range between min and max */ |
47 | static int | 40 | static int |
48 | gre_in_range(const struct nf_conntrack_tuple *tuple, | 41 | gre_in_range(const struct nf_conntrack_tuple *tuple, |
@@ -83,7 +76,7 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
83 | keyptr = &tuple->dst.u.gre.key; | 76 | keyptr = &tuple->dst.u.gre.key; |
84 | 77 | ||
85 | if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) { | 78 | if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) { |
86 | DEBUGP("%p: NATing GRE PPTP\n", conntrack); | 79 | pr_debug("%p: NATing GRE PPTP\n", conntrack); |
87 | min = 1; | 80 | min = 1; |
88 | range_size = 0xffff; | 81 | range_size = 0xffff; |
89 | } else { | 82 | } else { |
@@ -91,7 +84,7 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
91 | range_size = ntohs(range->max.gre.key) - min + 1; | 84 | range_size = ntohs(range->max.gre.key) - min + 1; |
92 | } | 85 | } |
93 | 86 | ||
94 | DEBUGP("min = %u, range_size = %u\n", min, range_size); | 87 | pr_debug("min = %u, range_size = %u\n", min, range_size); |
95 | 88 | ||
96 | for (i = 0; i < range_size; i++, key++) { | 89 | for (i = 0; i < range_size; i++, key++) { |
97 | *keyptr = htons(min + key % range_size); | 90 | *keyptr = htons(min + key % range_size); |
@@ -99,7 +92,7 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
99 | return 1; | 92 | return 1; |
100 | } | 93 | } |
101 | 94 | ||
102 | DEBUGP("%p: no NAT mapping\n", conntrack); | 95 | pr_debug("%p: no NAT mapping\n", conntrack); |
103 | return 0; | 96 | return 0; |
104 | } | 97 | } |
105 | 98 | ||
@@ -132,11 +125,11 @@ gre_manip_pkt(struct sk_buff **pskb, unsigned int iphdroff, | |||
132 | * Try to behave like "nf_nat_proto_unknown" */ | 125 | * Try to behave like "nf_nat_proto_unknown" */ |
133 | break; | 126 | break; |
134 | case GRE_VERSION_PPTP: | 127 | case GRE_VERSION_PPTP: |
135 | DEBUGP("call_id -> 0x%04x\n", ntohs(tuple->dst.u.gre.key)); | 128 | pr_debug("call_id -> 0x%04x\n", ntohs(tuple->dst.u.gre.key)); |
136 | pgreh->call_id = tuple->dst.u.gre.key; | 129 | pgreh->call_id = tuple->dst.u.gre.key; |
137 | break; | 130 | break; |
138 | default: | 131 | default: |
139 | DEBUGP("can't nat unknown GRE version\n"); | 132 | pr_debug("can't nat unknown GRE version\n"); |
140 | return 0; | 133 | return 0; |
141 | } | 134 | } |
142 | return 1; | 135 | return 1; |
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c index 6740736c5e79..0f45427e5fdc 100644 --- a/net/ipv4/netfilter/nf_nat_rule.c +++ b/net/ipv4/netfilter/nf_nat_rule.c | |||
@@ -24,12 +24,6 @@ | |||
24 | #include <net/netfilter/nf_nat_core.h> | 24 | #include <net/netfilter/nf_nat_core.h> |
25 | #include <net/netfilter/nf_nat_rule.h> | 25 | #include <net/netfilter/nf_nat_rule.h> |
26 | 26 | ||
27 | #if 0 | ||
28 | #define DEBUGP printk | ||
29 | #else | ||
30 | #define DEBUGP(format, args...) | ||
31 | #endif | ||
32 | |||
33 | #define NAT_VALID_HOOKS ((1<<NF_IP_PRE_ROUTING) | (1<<NF_IP_POST_ROUTING) | (1<<NF_IP_LOCAL_OUT)) | 27 | #define NAT_VALID_HOOKS ((1<<NF_IP_PRE_ROUTING) | (1<<NF_IP_POST_ROUTING) | (1<<NF_IP_LOCAL_OUT)) |
34 | 28 | ||
35 | static struct | 29 | static struct |
@@ -140,39 +134,39 @@ static unsigned int ipt_dnat_target(struct sk_buff **pskb, | |||
140 | return nf_nat_setup_info(ct, &mr->range[0], hooknum); | 134 | return nf_nat_setup_info(ct, &mr->range[0], hooknum); |
141 | } | 135 | } |
142 | 136 | ||
143 | static int ipt_snat_checkentry(const char *tablename, | 137 | static bool ipt_snat_checkentry(const char *tablename, |
144 | const void *entry, | 138 | const void *entry, |
145 | const struct xt_target *target, | 139 | const struct xt_target *target, |
146 | void *targinfo, | 140 | void *targinfo, |
147 | unsigned int hook_mask) | 141 | unsigned int hook_mask) |
148 | { | 142 | { |
149 | struct nf_nat_multi_range_compat *mr = targinfo; | 143 | struct nf_nat_multi_range_compat *mr = targinfo; |
150 | 144 | ||
151 | /* Must be a valid range */ | 145 | /* Must be a valid range */ |
152 | if (mr->rangesize != 1) { | 146 | if (mr->rangesize != 1) { |
153 | printk("SNAT: multiple ranges no longer supported\n"); | 147 | printk("SNAT: multiple ranges no longer supported\n"); |
154 | return 0; | 148 | return false; |
155 | } | 149 | } |
156 | return 1; | 150 | return true; |
157 | } | 151 | } |
158 | 152 | ||
159 | static int ipt_dnat_checkentry(const char *tablename, | 153 | static bool ipt_dnat_checkentry(const char *tablename, |
160 | const void *entry, | 154 | const void *entry, |
161 | const struct xt_target *target, | 155 | const struct xt_target *target, |
162 | void *targinfo, | 156 | void *targinfo, |
163 | unsigned int hook_mask) | 157 | unsigned int hook_mask) |
164 | { | 158 | { |
165 | struct nf_nat_multi_range_compat *mr = targinfo; | 159 | struct nf_nat_multi_range_compat *mr = targinfo; |
166 | 160 | ||
167 | /* Must be a valid range */ | 161 | /* Must be a valid range */ |
168 | if (mr->rangesize != 1) { | 162 | if (mr->rangesize != 1) { |
169 | printk("DNAT: multiple ranges no longer supported\n"); | 163 | printk("DNAT: multiple ranges no longer supported\n"); |
170 | return 0; | 164 | return false; |
171 | } | 165 | } |
172 | return 1; | 166 | return true; |
173 | } | 167 | } |
174 | 168 | ||
175 | inline unsigned int | 169 | unsigned int |
176 | alloc_null_binding(struct nf_conn *ct, unsigned int hooknum) | 170 | alloc_null_binding(struct nf_conn *ct, unsigned int hooknum) |
177 | { | 171 | { |
178 | /* Force range to this IP; let proto decide mapping for | 172 | /* Force range to this IP; let proto decide mapping for |
@@ -186,8 +180,8 @@ alloc_null_binding(struct nf_conn *ct, unsigned int hooknum) | |||
186 | struct nf_nat_range range | 180 | struct nf_nat_range range |
187 | = { IP_NAT_RANGE_MAP_IPS, ip, ip, { 0 }, { 0 } }; | 181 | = { IP_NAT_RANGE_MAP_IPS, ip, ip, { 0 }, { 0 } }; |
188 | 182 | ||
189 | DEBUGP("Allocating NULL binding for %p (%u.%u.%u.%u)\n", | 183 | pr_debug("Allocating NULL binding for %p (%u.%u.%u.%u)\n", |
190 | ct, NIPQUAD(ip)); | 184 | ct, NIPQUAD(ip)); |
191 | return nf_nat_setup_info(ct, &range, hooknum); | 185 | return nf_nat_setup_info(ct, &range, hooknum); |
192 | } | 186 | } |
193 | 187 | ||
@@ -205,8 +199,8 @@ alloc_null_binding_confirmed(struct nf_conn *ct, unsigned int hooknum) | |||
205 | struct nf_nat_range range | 199 | struct nf_nat_range range |
206 | = { IP_NAT_RANGE_MAP_IPS, ip, ip, { all }, { all } }; | 200 | = { IP_NAT_RANGE_MAP_IPS, ip, ip, { all }, { all } }; |
207 | 201 | ||
208 | DEBUGP("Allocating NULL binding for confirmed %p (%u.%u.%u.%u)\n", | 202 | pr_debug("Allocating NULL binding for confirmed %p (%u.%u.%u.%u)\n", |
209 | ct, NIPQUAD(ip)); | 203 | ct, NIPQUAD(ip)); |
210 | return nf_nat_setup_info(ct, &range, hooknum); | 204 | return nf_nat_setup_info(ct, &range, hooknum); |
211 | } | 205 | } |
212 | 206 | ||
@@ -228,7 +222,7 @@ int nf_nat_rule_find(struct sk_buff **pskb, | |||
228 | return ret; | 222 | return ret; |
229 | } | 223 | } |
230 | 224 | ||
231 | static struct xt_target ipt_snat_reg = { | 225 | static struct xt_target ipt_snat_reg __read_mostly = { |
232 | .name = "SNAT", | 226 | .name = "SNAT", |
233 | .target = ipt_snat_target, | 227 | .target = ipt_snat_target, |
234 | .targetsize = sizeof(struct nf_nat_multi_range_compat), | 228 | .targetsize = sizeof(struct nf_nat_multi_range_compat), |
@@ -238,7 +232,7 @@ static struct xt_target ipt_snat_reg = { | |||
238 | .family = AF_INET, | 232 | .family = AF_INET, |
239 | }; | 233 | }; |
240 | 234 | ||
241 | static struct xt_target ipt_dnat_reg = { | 235 | static struct xt_target ipt_dnat_reg __read_mostly = { |
242 | .name = "DNAT", | 236 | .name = "DNAT", |
243 | .target = ipt_dnat_target, | 237 | .target = ipt_dnat_target, |
244 | .targetsize = sizeof(struct nf_nat_multi_range_compat), | 238 | .targetsize = sizeof(struct nf_nat_multi_range_compat), |
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c index fac97cf51ae5..a889ec3ec83a 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/ipv4/netfilter/nf_nat_sip.c | |||
@@ -26,12 +26,6 @@ MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>"); | |||
26 | MODULE_DESCRIPTION("SIP NAT helper"); | 26 | MODULE_DESCRIPTION("SIP NAT helper"); |
27 | MODULE_ALIAS("ip_nat_sip"); | 27 | MODULE_ALIAS("ip_nat_sip"); |
28 | 28 | ||
29 | #if 0 | ||
30 | #define DEBUGP printk | ||
31 | #else | ||
32 | #define DEBUGP(format, args...) | ||
33 | #endif | ||
34 | |||
35 | struct addr_map { | 29 | struct addr_map { |
36 | struct { | 30 | struct { |
37 | char src[sizeof("nnn.nnn.nnn.nnn:nnnnn")]; | 31 | char src[sizeof("nnn.nnn.nnn.nnn:nnnnn")]; |
@@ -257,10 +251,12 @@ static unsigned int ip_nat_sdp(struct sk_buff **pskb, | |||
257 | __be32 newip; | 251 | __be32 newip; |
258 | u_int16_t port; | 252 | u_int16_t port; |
259 | 253 | ||
260 | DEBUGP("ip_nat_sdp():\n"); | ||
261 | |||
262 | /* Connection will come from reply */ | 254 | /* Connection will come from reply */ |
263 | newip = ct->tuplehash[!dir].tuple.dst.u3.ip; | 255 | if (ct->tuplehash[dir].tuple.src.u3.ip == |
256 | ct->tuplehash[!dir].tuple.dst.u3.ip) | ||
257 | newip = exp->tuple.dst.u3.ip; | ||
258 | else | ||
259 | newip = ct->tuplehash[!dir].tuple.dst.u3.ip; | ||
264 | 260 | ||
265 | exp->saved_ip = exp->tuple.dst.u3.ip; | 261 | exp->saved_ip = exp->tuple.dst.u3.ip; |
266 | exp->tuple.dst.u3.ip = newip; | 262 | exp->tuple.dst.u3.ip = newip; |
@@ -274,7 +270,7 @@ static unsigned int ip_nat_sdp(struct sk_buff **pskb, | |||
274 | /* Try to get same port: if not, try to change it. */ | 270 | /* Try to get same port: if not, try to change it. */ |
275 | for (port = ntohs(exp->saved_proto.udp.port); port != 0; port++) { | 271 | for (port = ntohs(exp->saved_proto.udp.port); port != 0; port++) { |
276 | exp->tuple.dst.u.udp.port = htons(port); | 272 | exp->tuple.dst.u.udp.port = htons(port); |
277 | if (nf_conntrack_expect_related(exp) == 0) | 273 | if (nf_ct_expect_related(exp) == 0) |
278 | break; | 274 | break; |
279 | } | 275 | } |
280 | 276 | ||
@@ -282,7 +278,7 @@ static unsigned int ip_nat_sdp(struct sk_buff **pskb, | |||
282 | return NF_DROP; | 278 | return NF_DROP; |
283 | 279 | ||
284 | if (!mangle_sdp(pskb, ctinfo, ct, newip, port, dptr)) { | 280 | if (!mangle_sdp(pskb, ctinfo, ct, newip, port, dptr)) { |
285 | nf_conntrack_unexpect_related(exp); | 281 | nf_ct_unexpect_related(exp); |
286 | return NF_DROP; | 282 | return NF_DROP; |
287 | } | 283 | } |
288 | return NF_ACCEPT; | 284 | return NF_ACCEPT; |
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c index 6e88505d6162..6bfcd3a90f08 100644 --- a/net/ipv4/netfilter/nf_nat_snmp_basic.c +++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c | |||
@@ -1276,9 +1276,6 @@ static struct nf_conntrack_helper snmp_helper __read_mostly = { | |||
1276 | .tuple.src.l3num = AF_INET, | 1276 | .tuple.src.l3num = AF_INET, |
1277 | .tuple.src.u.udp.port = __constant_htons(SNMP_PORT), | 1277 | .tuple.src.u.udp.port = __constant_htons(SNMP_PORT), |
1278 | .tuple.dst.protonum = IPPROTO_UDP, | 1278 | .tuple.dst.protonum = IPPROTO_UDP, |
1279 | .mask.src.l3num = 0xFFFF, | ||
1280 | .mask.src.u.udp.port = __constant_htons(0xFFFF), | ||
1281 | .mask.dst.protonum = 0xFF, | ||
1282 | }; | 1279 | }; |
1283 | 1280 | ||
1284 | static struct nf_conntrack_helper snmp_trap_helper __read_mostly = { | 1281 | static struct nf_conntrack_helper snmp_trap_helper __read_mostly = { |
@@ -1290,9 +1287,6 @@ static struct nf_conntrack_helper snmp_trap_helper __read_mostly = { | |||
1290 | .tuple.src.l3num = AF_INET, | 1287 | .tuple.src.l3num = AF_INET, |
1291 | .tuple.src.u.udp.port = __constant_htons(SNMP_TRAP_PORT), | 1288 | .tuple.src.u.udp.port = __constant_htons(SNMP_TRAP_PORT), |
1292 | .tuple.dst.protonum = IPPROTO_UDP, | 1289 | .tuple.dst.protonum = IPPROTO_UDP, |
1293 | .mask.src.l3num = 0xFFFF, | ||
1294 | .mask.src.u.udp.port = __constant_htons(0xFFFF), | ||
1295 | .mask.dst.protonum = 0xFF, | ||
1296 | }; | 1290 | }; |
1297 | 1291 | ||
1298 | /***************************************************************************** | 1292 | /***************************************************************************** |
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index 55dac36dbc85..332814dac503 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #include <net/netfilter/nf_conntrack.h> | 20 | #include <net/netfilter/nf_conntrack.h> |
21 | #include <net/netfilter/nf_conntrack_core.h> | 21 | #include <net/netfilter/nf_conntrack_core.h> |
22 | #include <net/netfilter/nf_conntrack_extend.h> | ||
22 | #include <net/netfilter/nf_nat.h> | 23 | #include <net/netfilter/nf_nat.h> |
23 | #include <net/netfilter/nf_nat_rule.h> | 24 | #include <net/netfilter/nf_nat_rule.h> |
24 | #include <net/netfilter/nf_nat_protocol.h> | 25 | #include <net/netfilter/nf_nat_protocol.h> |
@@ -26,12 +27,6 @@ | |||
26 | #include <net/netfilter/nf_nat_helper.h> | 27 | #include <net/netfilter/nf_nat_helper.h> |
27 | #include <linux/netfilter_ipv4/ip_tables.h> | 28 | #include <linux/netfilter_ipv4/ip_tables.h> |
28 | 29 | ||
29 | #if 0 | ||
30 | #define DEBUGP printk | ||
31 | #else | ||
32 | #define DEBUGP(format, args...) | ||
33 | #endif | ||
34 | |||
35 | #ifdef CONFIG_XFRM | 30 | #ifdef CONFIG_XFRM |
36 | static void nat_decode_session(struct sk_buff *skb, struct flowi *fl) | 31 | static void nat_decode_session(struct sk_buff *skb, struct flowi *fl) |
37 | { | 32 | { |
@@ -113,8 +108,13 @@ nf_nat_fn(unsigned int hooknum, | |||
113 | return NF_ACCEPT; | 108 | return NF_ACCEPT; |
114 | 109 | ||
115 | nat = nfct_nat(ct); | 110 | nat = nfct_nat(ct); |
116 | if (!nat) | 111 | if (!nat) { |
117 | return NF_ACCEPT; | 112 | nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC); |
113 | if (nat == NULL) { | ||
114 | pr_debug("failed to add NAT extension\n"); | ||
115 | return NF_ACCEPT; | ||
116 | } | ||
117 | } | ||
118 | 118 | ||
119 | switch (ctinfo) { | 119 | switch (ctinfo) { |
120 | case IP_CT_RELATED: | 120 | case IP_CT_RELATED: |
@@ -148,9 +148,9 @@ nf_nat_fn(unsigned int hooknum, | |||
148 | return ret; | 148 | return ret; |
149 | } | 149 | } |
150 | } else | 150 | } else |
151 | DEBUGP("Already setup manip %s for ct %p\n", | 151 | pr_debug("Already setup manip %s for ct %p\n", |
152 | maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST", | 152 | maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST", |
153 | ct); | 153 | ct); |
154 | break; | 154 | break; |
155 | 155 | ||
156 | default: | 156 | default: |
@@ -264,7 +264,7 @@ nf_nat_adjust(unsigned int hooknum, | |||
264 | 264 | ||
265 | ct = nf_ct_get(*pskb, &ctinfo); | 265 | ct = nf_ct_get(*pskb, &ctinfo); |
266 | if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) { | 266 | if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) { |
267 | DEBUGP("nf_nat_standalone: adjusting sequence number\n"); | 267 | pr_debug("nf_nat_standalone: adjusting sequence number\n"); |
268 | if (!nf_nat_seq_adjust(pskb, ct, ctinfo)) | 268 | if (!nf_nat_seq_adjust(pskb, ct, ctinfo)) |
269 | return NF_DROP; | 269 | return NF_DROP; |
270 | } | 270 | } |
@@ -326,26 +326,10 @@ static struct nf_hook_ops nf_nat_ops[] = { | |||
326 | 326 | ||
327 | static int __init nf_nat_standalone_init(void) | 327 | static int __init nf_nat_standalone_init(void) |
328 | { | 328 | { |
329 | int size, ret = 0; | 329 | int ret = 0; |
330 | 330 | ||
331 | need_conntrack(); | 331 | need_conntrack(); |
332 | 332 | ||
333 | size = ALIGN(sizeof(struct nf_conn), __alignof__(struct nf_conn_nat)) + | ||
334 | sizeof(struct nf_conn_nat); | ||
335 | ret = nf_conntrack_register_cache(NF_CT_F_NAT, "nf_nat:base", size); | ||
336 | if (ret < 0) { | ||
337 | printk(KERN_ERR "nf_nat_init: Unable to create slab cache\n"); | ||
338 | return ret; | ||
339 | } | ||
340 | |||
341 | size = ALIGN(size, __alignof__(struct nf_conn_help)) + | ||
342 | sizeof(struct nf_conn_help); | ||
343 | ret = nf_conntrack_register_cache(NF_CT_F_NAT|NF_CT_F_HELP, | ||
344 | "nf_nat:help", size); | ||
345 | if (ret < 0) { | ||
346 | printk(KERN_ERR "nf_nat_init: Unable to create slab cache\n"); | ||
347 | goto cleanup_register_cache; | ||
348 | } | ||
349 | #ifdef CONFIG_XFRM | 333 | #ifdef CONFIG_XFRM |
350 | BUG_ON(ip_nat_decode_session != NULL); | 334 | BUG_ON(ip_nat_decode_session != NULL); |
351 | ip_nat_decode_session = nat_decode_session; | 335 | ip_nat_decode_session = nat_decode_session; |
@@ -360,7 +344,6 @@ static int __init nf_nat_standalone_init(void) | |||
360 | printk("nf_nat_init: can't register hooks.\n"); | 344 | printk("nf_nat_init: can't register hooks.\n"); |
361 | goto cleanup_rule_init; | 345 | goto cleanup_rule_init; |
362 | } | 346 | } |
363 | nf_nat_module_is_loaded = 1; | ||
364 | return ret; | 347 | return ret; |
365 | 348 | ||
366 | cleanup_rule_init: | 349 | cleanup_rule_init: |
@@ -370,9 +353,6 @@ static int __init nf_nat_standalone_init(void) | |||
370 | ip_nat_decode_session = NULL; | 353 | ip_nat_decode_session = NULL; |
371 | synchronize_net(); | 354 | synchronize_net(); |
372 | #endif | 355 | #endif |
373 | nf_conntrack_unregister_cache(NF_CT_F_NAT|NF_CT_F_HELP); | ||
374 | cleanup_register_cache: | ||
375 | nf_conntrack_unregister_cache(NF_CT_F_NAT); | ||
376 | return ret; | 356 | return ret; |
377 | } | 357 | } |
378 | 358 | ||
@@ -380,7 +360,6 @@ static void __exit nf_nat_standalone_fini(void) | |||
380 | { | 360 | { |
381 | nf_unregister_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops)); | 361 | nf_unregister_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops)); |
382 | nf_nat_rule_cleanup(); | 362 | nf_nat_rule_cleanup(); |
383 | nf_nat_module_is_loaded = 0; | ||
384 | #ifdef CONFIG_XFRM | 363 | #ifdef CONFIG_XFRM |
385 | ip_nat_decode_session = NULL; | 364 | ip_nat_decode_session = NULL; |
386 | synchronize_net(); | 365 | synchronize_net(); |
diff --git a/net/ipv4/netfilter/nf_nat_tftp.c b/net/ipv4/netfilter/nf_nat_tftp.c index 2566b79de224..04dfeaefec02 100644 --- a/net/ipv4/netfilter/nf_nat_tftp.c +++ b/net/ipv4/netfilter/nf_nat_tftp.c | |||
@@ -30,7 +30,7 @@ static unsigned int help(struct sk_buff **pskb, | |||
30 | = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port; | 30 | = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port; |
31 | exp->dir = IP_CT_DIR_REPLY; | 31 | exp->dir = IP_CT_DIR_REPLY; |
32 | exp->expectfn = nf_nat_follow_master; | 32 | exp->expectfn = nf_nat_follow_master; |
33 | if (nf_conntrack_expect_related(exp) != 0) | 33 | if (nf_ct_expect_related(exp) != 0) |
34 | return NF_DROP; | 34 | return NF_DROP; |
35 | return NF_ACCEPT; | 35 | return NF_ACCEPT; |
36 | } | 36 | } |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 29ca63e81ced..88fa648d7ba3 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -101,7 +101,6 @@ | |||
101 | #include <net/tcp.h> | 101 | #include <net/tcp.h> |
102 | #include <net/icmp.h> | 102 | #include <net/icmp.h> |
103 | #include <net/xfrm.h> | 103 | #include <net/xfrm.h> |
104 | #include <net/ip_mp_alg.h> | ||
105 | #include <net/netevent.h> | 104 | #include <net/netevent.h> |
106 | #include <net/rtnetlink.h> | 105 | #include <net/rtnetlink.h> |
107 | #ifdef CONFIG_SYSCTL | 106 | #ifdef CONFIG_SYSCTL |
@@ -168,7 +167,7 @@ static struct dst_ops ipv4_dst_ops = { | |||
168 | 167 | ||
169 | #define ECN_OR_COST(class) TC_PRIO_##class | 168 | #define ECN_OR_COST(class) TC_PRIO_##class |
170 | 169 | ||
171 | __u8 ip_tos2prio[16] = { | 170 | const __u8 ip_tos2prio[16] = { |
172 | TC_PRIO_BESTEFFORT, | 171 | TC_PRIO_BESTEFFORT, |
173 | ECN_OR_COST(FILLER), | 172 | ECN_OR_COST(FILLER), |
174 | TC_PRIO_BESTEFFORT, | 173 | TC_PRIO_BESTEFFORT, |
@@ -495,13 +494,11 @@ static const struct file_operations rt_cpu_seq_fops = { | |||
495 | 494 | ||
496 | static __inline__ void rt_free(struct rtable *rt) | 495 | static __inline__ void rt_free(struct rtable *rt) |
497 | { | 496 | { |
498 | multipath_remove(rt); | ||
499 | call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free); | 497 | call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free); |
500 | } | 498 | } |
501 | 499 | ||
502 | static __inline__ void rt_drop(struct rtable *rt) | 500 | static __inline__ void rt_drop(struct rtable *rt) |
503 | { | 501 | { |
504 | multipath_remove(rt); | ||
505 | ip_rt_put(rt); | 502 | ip_rt_put(rt); |
506 | call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free); | 503 | call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free); |
507 | } | 504 | } |
@@ -574,52 +571,6 @@ static inline int compare_keys(struct flowi *fl1, struct flowi *fl2) | |||
574 | (fl1->iif ^ fl2->iif)) == 0; | 571 | (fl1->iif ^ fl2->iif)) == 0; |
575 | } | 572 | } |
576 | 573 | ||
577 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | ||
578 | static struct rtable **rt_remove_balanced_route(struct rtable **chain_head, | ||
579 | struct rtable *expentry, | ||
580 | int *removed_count) | ||
581 | { | ||
582 | int passedexpired = 0; | ||
583 | struct rtable **nextstep = NULL; | ||
584 | struct rtable **rthp = chain_head; | ||
585 | struct rtable *rth; | ||
586 | |||
587 | if (removed_count) | ||
588 | *removed_count = 0; | ||
589 | |||
590 | while ((rth = *rthp) != NULL) { | ||
591 | if (rth == expentry) | ||
592 | passedexpired = 1; | ||
593 | |||
594 | if (((*rthp)->u.dst.flags & DST_BALANCED) != 0 && | ||
595 | compare_keys(&(*rthp)->fl, &expentry->fl)) { | ||
596 | if (*rthp == expentry) { | ||
597 | *rthp = rth->u.dst.rt_next; | ||
598 | continue; | ||
599 | } else { | ||
600 | *rthp = rth->u.dst.rt_next; | ||
601 | rt_free(rth); | ||
602 | if (removed_count) | ||
603 | ++(*removed_count); | ||
604 | } | ||
605 | } else { | ||
606 | if (!((*rthp)->u.dst.flags & DST_BALANCED) && | ||
607 | passedexpired && !nextstep) | ||
608 | nextstep = &rth->u.dst.rt_next; | ||
609 | |||
610 | rthp = &rth->u.dst.rt_next; | ||
611 | } | ||
612 | } | ||
613 | |||
614 | rt_free(expentry); | ||
615 | if (removed_count) | ||
616 | ++(*removed_count); | ||
617 | |||
618 | return nextstep; | ||
619 | } | ||
620 | #endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ | ||
621 | |||
622 | |||
623 | /* This runs via a timer and thus is always in BH context. */ | 574 | /* This runs via a timer and thus is always in BH context. */ |
624 | static void rt_check_expire(unsigned long dummy) | 575 | static void rt_check_expire(unsigned long dummy) |
625 | { | 576 | { |
@@ -658,22 +609,8 @@ static void rt_check_expire(unsigned long dummy) | |||
658 | } | 609 | } |
659 | 610 | ||
660 | /* Cleanup aged off entries. */ | 611 | /* Cleanup aged off entries. */ |
661 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | ||
662 | /* remove all related balanced entries if necessary */ | ||
663 | if (rth->u.dst.flags & DST_BALANCED) { | ||
664 | rthp = rt_remove_balanced_route( | ||
665 | &rt_hash_table[i].chain, | ||
666 | rth, NULL); | ||
667 | if (!rthp) | ||
668 | break; | ||
669 | } else { | ||
670 | *rthp = rth->u.dst.rt_next; | ||
671 | rt_free(rth); | ||
672 | } | ||
673 | #else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ | ||
674 | *rthp = rth->u.dst.rt_next; | 612 | *rthp = rth->u.dst.rt_next; |
675 | rt_free(rth); | 613 | rt_free(rth); |
676 | #endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ | ||
677 | } | 614 | } |
678 | spin_unlock(rt_hash_lock_addr(i)); | 615 | spin_unlock(rt_hash_lock_addr(i)); |
679 | 616 | ||
@@ -721,9 +658,6 @@ void rt_cache_flush(int delay) | |||
721 | if (delay < 0) | 658 | if (delay < 0) |
722 | delay = ip_rt_min_delay; | 659 | delay = ip_rt_min_delay; |
723 | 660 | ||
724 | /* flush existing multipath state*/ | ||
725 | multipath_flush(); | ||
726 | |||
727 | spin_lock_bh(&rt_flush_lock); | 661 | spin_lock_bh(&rt_flush_lock); |
728 | 662 | ||
729 | if (del_timer(&rt_flush_timer) && delay > 0 && rt_deadline) { | 663 | if (del_timer(&rt_flush_timer) && delay > 0 && rt_deadline) { |
@@ -842,30 +776,9 @@ static int rt_garbage_collect(void) | |||
842 | rthp = &rth->u.dst.rt_next; | 776 | rthp = &rth->u.dst.rt_next; |
843 | continue; | 777 | continue; |
844 | } | 778 | } |
845 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | ||
846 | /* remove all related balanced entries | ||
847 | * if necessary | ||
848 | */ | ||
849 | if (rth->u.dst.flags & DST_BALANCED) { | ||
850 | int r; | ||
851 | |||
852 | rthp = rt_remove_balanced_route( | ||
853 | &rt_hash_table[k].chain, | ||
854 | rth, | ||
855 | &r); | ||
856 | goal -= r; | ||
857 | if (!rthp) | ||
858 | break; | ||
859 | } else { | ||
860 | *rthp = rth->u.dst.rt_next; | ||
861 | rt_free(rth); | ||
862 | goal--; | ||
863 | } | ||
864 | #else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ | ||
865 | *rthp = rth->u.dst.rt_next; | 779 | *rthp = rth->u.dst.rt_next; |
866 | rt_free(rth); | 780 | rt_free(rth); |
867 | goal--; | 781 | goal--; |
868 | #endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ | ||
869 | } | 782 | } |
870 | spin_unlock_bh(rt_hash_lock_addr(k)); | 783 | spin_unlock_bh(rt_hash_lock_addr(k)); |
871 | if (goal <= 0) | 784 | if (goal <= 0) |
@@ -939,12 +852,7 @@ restart: | |||
939 | 852 | ||
940 | spin_lock_bh(rt_hash_lock_addr(hash)); | 853 | spin_lock_bh(rt_hash_lock_addr(hash)); |
941 | while ((rth = *rthp) != NULL) { | 854 | while ((rth = *rthp) != NULL) { |
942 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | ||
943 | if (!(rth->u.dst.flags & DST_BALANCED) && | ||
944 | compare_keys(&rth->fl, &rt->fl)) { | ||
945 | #else | ||
946 | if (compare_keys(&rth->fl, &rt->fl)) { | 855 | if (compare_keys(&rth->fl, &rt->fl)) { |
947 | #endif | ||
948 | /* Put it first */ | 856 | /* Put it first */ |
949 | *rthp = rth->u.dst.rt_next; | 857 | *rthp = rth->u.dst.rt_next; |
950 | /* | 858 | /* |
@@ -1774,10 +1682,6 @@ static inline int __mkroute_input(struct sk_buff *skb, | |||
1774 | 1682 | ||
1775 | atomic_set(&rth->u.dst.__refcnt, 1); | 1683 | atomic_set(&rth->u.dst.__refcnt, 1); |
1776 | rth->u.dst.flags= DST_HOST; | 1684 | rth->u.dst.flags= DST_HOST; |
1777 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | ||
1778 | if (res->fi->fib_nhs > 1) | ||
1779 | rth->u.dst.flags |= DST_BALANCED; | ||
1780 | #endif | ||
1781 | if (IN_DEV_CONF_GET(in_dev, NOPOLICY)) | 1685 | if (IN_DEV_CONF_GET(in_dev, NOPOLICY)) |
1782 | rth->u.dst.flags |= DST_NOPOLICY; | 1686 | rth->u.dst.flags |= DST_NOPOLICY; |
1783 | if (IN_DEV_CONF_GET(out_dev, NOXFRM)) | 1687 | if (IN_DEV_CONF_GET(out_dev, NOXFRM)) |
@@ -1812,11 +1716,11 @@ static inline int __mkroute_input(struct sk_buff *skb, | |||
1812 | return err; | 1716 | return err; |
1813 | } | 1717 | } |
1814 | 1718 | ||
1815 | static inline int ip_mkroute_input_def(struct sk_buff *skb, | 1719 | static inline int ip_mkroute_input(struct sk_buff *skb, |
1816 | struct fib_result* res, | 1720 | struct fib_result* res, |
1817 | const struct flowi *fl, | 1721 | const struct flowi *fl, |
1818 | struct in_device *in_dev, | 1722 | struct in_device *in_dev, |
1819 | __be32 daddr, __be32 saddr, u32 tos) | 1723 | __be32 daddr, __be32 saddr, u32 tos) |
1820 | { | 1724 | { |
1821 | struct rtable* rth = NULL; | 1725 | struct rtable* rth = NULL; |
1822 | int err; | 1726 | int err; |
@@ -1837,63 +1741,6 @@ static inline int ip_mkroute_input_def(struct sk_buff *skb, | |||
1837 | return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst); | 1741 | return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst); |
1838 | } | 1742 | } |
1839 | 1743 | ||
1840 | static inline int ip_mkroute_input(struct sk_buff *skb, | ||
1841 | struct fib_result* res, | ||
1842 | const struct flowi *fl, | ||
1843 | struct in_device *in_dev, | ||
1844 | __be32 daddr, __be32 saddr, u32 tos) | ||
1845 | { | ||
1846 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | ||
1847 | struct rtable* rth = NULL, *rtres; | ||
1848 | unsigned char hop, hopcount; | ||
1849 | int err = -EINVAL; | ||
1850 | unsigned int hash; | ||
1851 | |||
1852 | if (res->fi) | ||
1853 | hopcount = res->fi->fib_nhs; | ||
1854 | else | ||
1855 | hopcount = 1; | ||
1856 | |||
1857 | /* distinguish between multipath and singlepath */ | ||
1858 | if (hopcount < 2) | ||
1859 | return ip_mkroute_input_def(skb, res, fl, in_dev, daddr, | ||
1860 | saddr, tos); | ||
1861 | |||
1862 | /* add all alternatives to the routing cache */ | ||
1863 | for (hop = 0; hop < hopcount; hop++) { | ||
1864 | res->nh_sel = hop; | ||
1865 | |||
1866 | /* put reference to previous result */ | ||
1867 | if (hop) | ||
1868 | ip_rt_put(rtres); | ||
1869 | |||
1870 | /* create a routing cache entry */ | ||
1871 | err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos, | ||
1872 | &rth); | ||
1873 | if (err) | ||
1874 | return err; | ||
1875 | |||
1876 | /* put it into the cache */ | ||
1877 | hash = rt_hash(daddr, saddr, fl->iif); | ||
1878 | err = rt_intern_hash(hash, rth, &rtres); | ||
1879 | if (err) | ||
1880 | return err; | ||
1881 | |||
1882 | /* forward hop information to multipath impl. */ | ||
1883 | multipath_set_nhinfo(rth, | ||
1884 | FIB_RES_NETWORK(*res), | ||
1885 | FIB_RES_NETMASK(*res), | ||
1886 | res->prefixlen, | ||
1887 | &FIB_RES_NH(*res)); | ||
1888 | } | ||
1889 | skb->dst = &rtres->u.dst; | ||
1890 | return err; | ||
1891 | #else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ | ||
1892 | return ip_mkroute_input_def(skb, res, fl, in_dev, daddr, saddr, tos); | ||
1893 | #endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ | ||
1894 | } | ||
1895 | |||
1896 | |||
1897 | /* | 1744 | /* |
1898 | * NOTE. We drop all the packets that has local source | 1745 | * NOTE. We drop all the packets that has local source |
1899 | * addresses, because every properly looped back packet | 1746 | * addresses, because every properly looped back packet |
@@ -2211,13 +2058,6 @@ static inline int __mkroute_output(struct rtable **result, | |||
2211 | 2058 | ||
2212 | atomic_set(&rth->u.dst.__refcnt, 1); | 2059 | atomic_set(&rth->u.dst.__refcnt, 1); |
2213 | rth->u.dst.flags= DST_HOST; | 2060 | rth->u.dst.flags= DST_HOST; |
2214 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | ||
2215 | if (res->fi) { | ||
2216 | rth->rt_multipath_alg = res->fi->fib_mp_alg; | ||
2217 | if (res->fi->fib_nhs > 1) | ||
2218 | rth->u.dst.flags |= DST_BALANCED; | ||
2219 | } | ||
2220 | #endif | ||
2221 | if (IN_DEV_CONF_GET(in_dev, NOXFRM)) | 2061 | if (IN_DEV_CONF_GET(in_dev, NOXFRM)) |
2222 | rth->u.dst.flags |= DST_NOXFRM; | 2062 | rth->u.dst.flags |= DST_NOXFRM; |
2223 | if (IN_DEV_CONF_GET(in_dev, NOPOLICY)) | 2063 | if (IN_DEV_CONF_GET(in_dev, NOPOLICY)) |
@@ -2277,12 +2117,12 @@ static inline int __mkroute_output(struct rtable **result, | |||
2277 | return err; | 2117 | return err; |
2278 | } | 2118 | } |
2279 | 2119 | ||
2280 | static inline int ip_mkroute_output_def(struct rtable **rp, | 2120 | static inline int ip_mkroute_output(struct rtable **rp, |
2281 | struct fib_result* res, | 2121 | struct fib_result* res, |
2282 | const struct flowi *fl, | 2122 | const struct flowi *fl, |
2283 | const struct flowi *oldflp, | 2123 | const struct flowi *oldflp, |
2284 | struct net_device *dev_out, | 2124 | struct net_device *dev_out, |
2285 | unsigned flags) | 2125 | unsigned flags) |
2286 | { | 2126 | { |
2287 | struct rtable *rth = NULL; | 2127 | struct rtable *rth = NULL; |
2288 | int err = __mkroute_output(&rth, res, fl, oldflp, dev_out, flags); | 2128 | int err = __mkroute_output(&rth, res, fl, oldflp, dev_out, flags); |
@@ -2295,68 +2135,6 @@ static inline int ip_mkroute_output_def(struct rtable **rp, | |||
2295 | return err; | 2135 | return err; |
2296 | } | 2136 | } |
2297 | 2137 | ||
2298 | static inline int ip_mkroute_output(struct rtable** rp, | ||
2299 | struct fib_result* res, | ||
2300 | const struct flowi *fl, | ||
2301 | const struct flowi *oldflp, | ||
2302 | struct net_device *dev_out, | ||
2303 | unsigned flags) | ||
2304 | { | ||
2305 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | ||
2306 | unsigned char hop; | ||
2307 | unsigned hash; | ||
2308 | int err = -EINVAL; | ||
2309 | struct rtable *rth = NULL; | ||
2310 | |||
2311 | if (res->fi && res->fi->fib_nhs > 1) { | ||
2312 | unsigned char hopcount = res->fi->fib_nhs; | ||
2313 | |||
2314 | for (hop = 0; hop < hopcount; hop++) { | ||
2315 | struct net_device *dev2nexthop; | ||
2316 | |||
2317 | res->nh_sel = hop; | ||
2318 | |||
2319 | /* hold a work reference to the output device */ | ||
2320 | dev2nexthop = FIB_RES_DEV(*res); | ||
2321 | dev_hold(dev2nexthop); | ||
2322 | |||
2323 | /* put reference to previous result */ | ||
2324 | if (hop) | ||
2325 | ip_rt_put(*rp); | ||
2326 | |||
2327 | err = __mkroute_output(&rth, res, fl, oldflp, | ||
2328 | dev2nexthop, flags); | ||
2329 | |||
2330 | if (err != 0) | ||
2331 | goto cleanup; | ||
2332 | |||
2333 | hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, | ||
2334 | oldflp->oif); | ||
2335 | err = rt_intern_hash(hash, rth, rp); | ||
2336 | |||
2337 | /* forward hop information to multipath impl. */ | ||
2338 | multipath_set_nhinfo(rth, | ||
2339 | FIB_RES_NETWORK(*res), | ||
2340 | FIB_RES_NETMASK(*res), | ||
2341 | res->prefixlen, | ||
2342 | &FIB_RES_NH(*res)); | ||
2343 | cleanup: | ||
2344 | /* release work reference to output device */ | ||
2345 | dev_put(dev2nexthop); | ||
2346 | |||
2347 | if (err != 0) | ||
2348 | return err; | ||
2349 | } | ||
2350 | return err; | ||
2351 | } else { | ||
2352 | return ip_mkroute_output_def(rp, res, fl, oldflp, dev_out, | ||
2353 | flags); | ||
2354 | } | ||
2355 | #else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ | ||
2356 | return ip_mkroute_output_def(rp, res, fl, oldflp, dev_out, flags); | ||
2357 | #endif | ||
2358 | } | ||
2359 | |||
2360 | /* | 2138 | /* |
2361 | * Major route resolver routine. | 2139 | * Major route resolver routine. |
2362 | */ | 2140 | */ |
@@ -2570,17 +2348,6 @@ int __ip_route_output_key(struct rtable **rp, const struct flowi *flp) | |||
2570 | rth->fl.mark == flp->mark && | 2348 | rth->fl.mark == flp->mark && |
2571 | !((rth->fl.fl4_tos ^ flp->fl4_tos) & | 2349 | !((rth->fl.fl4_tos ^ flp->fl4_tos) & |
2572 | (IPTOS_RT_MASK | RTO_ONLINK))) { | 2350 | (IPTOS_RT_MASK | RTO_ONLINK))) { |
2573 | |||
2574 | /* check for multipath routes and choose one if | ||
2575 | * necessary | ||
2576 | */ | ||
2577 | if (multipath_select_route(flp, rth, rp)) { | ||
2578 | dst_hold(&(*rp)->u.dst); | ||
2579 | RT_CACHE_STAT_INC(out_hit); | ||
2580 | rcu_read_unlock_bh(); | ||
2581 | return 0; | ||
2582 | } | ||
2583 | |||
2584 | rth->u.dst.lastuse = jiffies; | 2351 | rth->u.dst.lastuse = jiffies; |
2585 | dst_hold(&rth->u.dst); | 2352 | dst_hold(&rth->u.dst); |
2586 | rth->u.dst.__use++; | 2353 | rth->u.dst.__use++; |
@@ -2729,10 +2496,6 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, | |||
2729 | if (rt->u.dst.tclassid) | 2496 | if (rt->u.dst.tclassid) |
2730 | NLA_PUT_U32(skb, RTA_FLOW, rt->u.dst.tclassid); | 2497 | NLA_PUT_U32(skb, RTA_FLOW, rt->u.dst.tclassid); |
2731 | #endif | 2498 | #endif |
2732 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | ||
2733 | if (rt->rt_multipath_alg != IP_MP_ALG_NONE) | ||
2734 | NLA_PUT_U32(skb, RTA_MP_ALGO, rt->rt_multipath_alg); | ||
2735 | #endif | ||
2736 | if (rt->fl.iif) | 2499 | if (rt->fl.iif) |
2737 | NLA_PUT_BE32(skb, RTA_PREFSRC, rt->rt_spec_dst); | 2500 | NLA_PUT_BE32(skb, RTA_PREFSRC, rt->rt_spec_dst); |
2738 | else if (rt->rt_src != rt->fl.fl4_src) | 2501 | else if (rt->rt_src != rt->fl.fl4_src) |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 450f44bb2c8e..987b94403be5 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -1116,6 +1116,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
1116 | long timeo; | 1116 | long timeo; |
1117 | struct task_struct *user_recv = NULL; | 1117 | struct task_struct *user_recv = NULL; |
1118 | int copied_early = 0; | 1118 | int copied_early = 0; |
1119 | struct sk_buff *skb; | ||
1119 | 1120 | ||
1120 | lock_sock(sk); | 1121 | lock_sock(sk); |
1121 | 1122 | ||
@@ -1142,16 +1143,26 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
1142 | #ifdef CONFIG_NET_DMA | 1143 | #ifdef CONFIG_NET_DMA |
1143 | tp->ucopy.dma_chan = NULL; | 1144 | tp->ucopy.dma_chan = NULL; |
1144 | preempt_disable(); | 1145 | preempt_disable(); |
1145 | if ((len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) && | 1146 | skb = skb_peek_tail(&sk->sk_receive_queue); |
1146 | !sysctl_tcp_low_latency && __get_cpu_var(softnet_data).net_dma) { | 1147 | { |
1147 | preempt_enable_no_resched(); | 1148 | int available = 0; |
1148 | tp->ucopy.pinned_list = dma_pin_iovec_pages(msg->msg_iov, len); | 1149 | |
1149 | } else | 1150 | if (skb) |
1150 | preempt_enable_no_resched(); | 1151 | available = TCP_SKB_CB(skb)->seq + skb->len - (*seq); |
1152 | if ((available < target) && | ||
1153 | (len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) && | ||
1154 | !sysctl_tcp_low_latency && | ||
1155 | __get_cpu_var(softnet_data).net_dma) { | ||
1156 | preempt_enable_no_resched(); | ||
1157 | tp->ucopy.pinned_list = | ||
1158 | dma_pin_iovec_pages(msg->msg_iov, len); | ||
1159 | } else { | ||
1160 | preempt_enable_no_resched(); | ||
1161 | } | ||
1162 | } | ||
1151 | #endif | 1163 | #endif |
1152 | 1164 | ||
1153 | do { | 1165 | do { |
1154 | struct sk_buff *skb; | ||
1155 | u32 offset; | 1166 | u32 offset; |
1156 | 1167 | ||
1157 | /* Are we at urgent data? Stop if we have read anything or have SIGURG pending. */ | 1168 | /* Are we at urgent data? Stop if we have read anything or have SIGURG pending. */ |
@@ -1439,7 +1450,6 @@ skip_copy: | |||
1439 | 1450 | ||
1440 | #ifdef CONFIG_NET_DMA | 1451 | #ifdef CONFIG_NET_DMA |
1441 | if (tp->ucopy.dma_chan) { | 1452 | if (tp->ucopy.dma_chan) { |
1442 | struct sk_buff *skb; | ||
1443 | dma_cookie_t done, used; | 1453 | dma_cookie_t done, used; |
1444 | 1454 | ||
1445 | dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); | 1455 | dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 69f9f1ef3ef6..4e5884ac8f29 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -1398,7 +1398,9 @@ static void tcp_enter_frto_loss(struct sock *sk, int allowed_segments, int flag) | |||
1398 | * waiting for the first ACK and did not get it)... | 1398 | * waiting for the first ACK and did not get it)... |
1399 | */ | 1399 | */ |
1400 | if ((tp->frto_counter == 1) && !(flag&FLAG_DATA_ACKED)) { | 1400 | if ((tp->frto_counter == 1) && !(flag&FLAG_DATA_ACKED)) { |
1401 | tp->retrans_out += tcp_skb_pcount(skb); | 1401 | /* For some reason this R-bit might get cleared? */ |
1402 | if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS) | ||
1403 | tp->retrans_out += tcp_skb_pcount(skb); | ||
1402 | /* ...enter this if branch just for the first segment */ | 1404 | /* ...enter this if branch just for the first segment */ |
1403 | flag |= FLAG_DATA_ACKED; | 1405 | flag |= FLAG_DATA_ACKED; |
1404 | } else { | 1406 | } else { |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 354721d67f69..3f5f7423b95c 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -2045,10 +2045,7 @@ static void *established_get_first(struct seq_file *seq) | |||
2045 | struct hlist_node *node; | 2045 | struct hlist_node *node; |
2046 | struct inet_timewait_sock *tw; | 2046 | struct inet_timewait_sock *tw; |
2047 | 2047 | ||
2048 | /* We can reschedule _before_ having picked the target: */ | 2048 | read_lock_bh(&tcp_hashinfo.ehash[st->bucket].lock); |
2049 | cond_resched_softirq(); | ||
2050 | |||
2051 | read_lock(&tcp_hashinfo.ehash[st->bucket].lock); | ||
2052 | sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) { | 2049 | sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) { |
2053 | if (sk->sk_family != st->family) { | 2050 | if (sk->sk_family != st->family) { |
2054 | continue; | 2051 | continue; |
@@ -2065,7 +2062,7 @@ static void *established_get_first(struct seq_file *seq) | |||
2065 | rc = tw; | 2062 | rc = tw; |
2066 | goto out; | 2063 | goto out; |
2067 | } | 2064 | } |
2068 | read_unlock(&tcp_hashinfo.ehash[st->bucket].lock); | 2065 | read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock); |
2069 | st->state = TCP_SEQ_STATE_ESTABLISHED; | 2066 | st->state = TCP_SEQ_STATE_ESTABLISHED; |
2070 | } | 2067 | } |
2071 | out: | 2068 | out: |
@@ -2092,14 +2089,11 @@ get_tw: | |||
2092 | cur = tw; | 2089 | cur = tw; |
2093 | goto out; | 2090 | goto out; |
2094 | } | 2091 | } |
2095 | read_unlock(&tcp_hashinfo.ehash[st->bucket].lock); | 2092 | read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock); |
2096 | st->state = TCP_SEQ_STATE_ESTABLISHED; | 2093 | st->state = TCP_SEQ_STATE_ESTABLISHED; |
2097 | 2094 | ||
2098 | /* We can reschedule between buckets: */ | ||
2099 | cond_resched_softirq(); | ||
2100 | |||
2101 | if (++st->bucket < tcp_hashinfo.ehash_size) { | 2095 | if (++st->bucket < tcp_hashinfo.ehash_size) { |
2102 | read_lock(&tcp_hashinfo.ehash[st->bucket].lock); | 2096 | read_lock_bh(&tcp_hashinfo.ehash[st->bucket].lock); |
2103 | sk = sk_head(&tcp_hashinfo.ehash[st->bucket].chain); | 2097 | sk = sk_head(&tcp_hashinfo.ehash[st->bucket].chain); |
2104 | } else { | 2098 | } else { |
2105 | cur = NULL; | 2099 | cur = NULL; |
@@ -2144,7 +2138,6 @@ static void *tcp_get_idx(struct seq_file *seq, loff_t pos) | |||
2144 | 2138 | ||
2145 | if (!rc) { | 2139 | if (!rc) { |
2146 | inet_listen_unlock(&tcp_hashinfo); | 2140 | inet_listen_unlock(&tcp_hashinfo); |
2147 | local_bh_disable(); | ||
2148 | st->state = TCP_SEQ_STATE_ESTABLISHED; | 2141 | st->state = TCP_SEQ_STATE_ESTABLISHED; |
2149 | rc = established_get_idx(seq, pos); | 2142 | rc = established_get_idx(seq, pos); |
2150 | } | 2143 | } |
@@ -2177,7 +2170,6 @@ static void *tcp_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
2177 | rc = listening_get_next(seq, v); | 2170 | rc = listening_get_next(seq, v); |
2178 | if (!rc) { | 2171 | if (!rc) { |
2179 | inet_listen_unlock(&tcp_hashinfo); | 2172 | inet_listen_unlock(&tcp_hashinfo); |
2180 | local_bh_disable(); | ||
2181 | st->state = TCP_SEQ_STATE_ESTABLISHED; | 2173 | st->state = TCP_SEQ_STATE_ESTABLISHED; |
2182 | rc = established_get_first(seq); | 2174 | rc = established_get_first(seq); |
2183 | } | 2175 | } |
@@ -2209,8 +2201,7 @@ static void tcp_seq_stop(struct seq_file *seq, void *v) | |||
2209 | case TCP_SEQ_STATE_TIME_WAIT: | 2201 | case TCP_SEQ_STATE_TIME_WAIT: |
2210 | case TCP_SEQ_STATE_ESTABLISHED: | 2202 | case TCP_SEQ_STATE_ESTABLISHED: |
2211 | if (v) | 2203 | if (v) |
2212 | read_unlock(&tcp_hashinfo.ehash[st->bucket].lock); | 2204 | read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock); |
2213 | local_bh_enable(); | ||
2214 | break; | 2205 | break; |
2215 | } | 2206 | } |
2216 | } | 2207 | } |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 53232dd6fb48..20aea1595c4d 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -699,6 +699,14 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss | |||
699 | tp->fackets_out -= diff; | 699 | tp->fackets_out -= diff; |
700 | if ((int)tp->fackets_out < 0) | 700 | if ((int)tp->fackets_out < 0) |
701 | tp->fackets_out = 0; | 701 | tp->fackets_out = 0; |
702 | /* SACK fastpath might overwrite it unless dealt with */ | ||
703 | if (tp->fastpath_skb_hint != NULL && | ||
704 | after(TCP_SKB_CB(tp->fastpath_skb_hint)->seq, | ||
705 | TCP_SKB_CB(skb)->seq)) { | ||
706 | tp->fastpath_cnt_hint -= diff; | ||
707 | if ((int)tp->fastpath_cnt_hint < 0) | ||
708 | tp->fastpath_cnt_hint = 0; | ||
709 | } | ||
702 | } | 710 | } |
703 | } | 711 | } |
704 | 712 | ||
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c index d9323dfff826..f37d5928921a 100644 --- a/net/ipv4/tcp_probe.c +++ b/net/ipv4/tcp_probe.c | |||
@@ -6,8 +6,7 @@ | |||
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
9 | * the Free Software Foundation; either version 2 of the License, or | 9 | * the Free Software Foundation; either version 2 of the License. |
10 | * (at your option) any later version. | ||
11 | * | 10 | * |
12 | * This program is distributed in the hope that it will be useful, | 11 | * This program is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
@@ -25,23 +24,22 @@ | |||
25 | #include <linux/tcp.h> | 24 | #include <linux/tcp.h> |
26 | #include <linux/proc_fs.h> | 25 | #include <linux/proc_fs.h> |
27 | #include <linux/module.h> | 26 | #include <linux/module.h> |
28 | #include <linux/kfifo.h> | ||
29 | #include <linux/ktime.h> | 27 | #include <linux/ktime.h> |
30 | #include <linux/time.h> | 28 | #include <linux/time.h> |
31 | #include <linux/vmalloc.h> | ||
32 | 29 | ||
33 | #include <net/tcp.h> | 30 | #include <net/tcp.h> |
34 | 31 | ||
35 | MODULE_AUTHOR("Stephen Hemminger <shemminger@linux-foundation.org>"); | 32 | MODULE_AUTHOR("Stephen Hemminger <shemminger@linux-foundation.org>"); |
36 | MODULE_DESCRIPTION("TCP cwnd snooper"); | 33 | MODULE_DESCRIPTION("TCP cwnd snooper"); |
37 | MODULE_LICENSE("GPL"); | 34 | MODULE_LICENSE("GPL"); |
35 | MODULE_VERSION("1.1"); | ||
38 | 36 | ||
39 | static int port __read_mostly = 0; | 37 | static int port __read_mostly = 0; |
40 | MODULE_PARM_DESC(port, "Port to match (0=all)"); | 38 | MODULE_PARM_DESC(port, "Port to match (0=all)"); |
41 | module_param(port, int, 0); | 39 | module_param(port, int, 0); |
42 | 40 | ||
43 | static int bufsize __read_mostly = 64*1024; | 41 | static int bufsize __read_mostly = 4096; |
44 | MODULE_PARM_DESC(bufsize, "Log buffer size (default 64k)"); | 42 | MODULE_PARM_DESC(bufsize, "Log buffer size in packets (4096)"); |
45 | module_param(bufsize, int, 0); | 43 | module_param(bufsize, int, 0); |
46 | 44 | ||
47 | static int full __read_mostly; | 45 | static int full __read_mostly; |
@@ -50,39 +48,38 @@ module_param(full, int, 0); | |||
50 | 48 | ||
51 | static const char procname[] = "tcpprobe"; | 49 | static const char procname[] = "tcpprobe"; |
52 | 50 | ||
53 | struct { | 51 | struct tcp_log { |
54 | struct kfifo *fifo; | 52 | ktime_t tstamp; |
53 | __be32 saddr, daddr; | ||
54 | __be16 sport, dport; | ||
55 | u16 length; | ||
56 | u32 snd_nxt; | ||
57 | u32 snd_una; | ||
58 | u32 snd_wnd; | ||
59 | u32 snd_cwnd; | ||
60 | u32 ssthresh; | ||
61 | u32 srtt; | ||
62 | }; | ||
63 | |||
64 | static struct { | ||
55 | spinlock_t lock; | 65 | spinlock_t lock; |
56 | wait_queue_head_t wait; | 66 | wait_queue_head_t wait; |
57 | ktime_t start; | 67 | ktime_t start; |
58 | u32 lastcwnd; | 68 | u32 lastcwnd; |
59 | } tcpw; | ||
60 | 69 | ||
61 | /* | 70 | unsigned long head, tail; |
62 | * Print to log with timestamps. | 71 | struct tcp_log *log; |
63 | * FIXME: causes an extra copy | 72 | } tcp_probe; |
64 | */ | 73 | |
65 | static void printl(const char *fmt, ...) | ||
66 | __attribute__ ((format (printf, 1, 2))); | ||
67 | 74 | ||
68 | static void printl(const char *fmt, ...) | 75 | static inline int tcp_probe_used(void) |
69 | { | 76 | { |
70 | va_list args; | 77 | return (tcp_probe.head - tcp_probe.tail) % bufsize; |
71 | int len; | 78 | } |
72 | struct timespec tv; | 79 | |
73 | char tbuf[256]; | 80 | static inline int tcp_probe_avail(void) |
74 | 81 | { | |
75 | va_start(args, fmt); | 82 | return bufsize - tcp_probe_used(); |
76 | /* want monotonic time since start of tcp_probe */ | ||
77 | tv = ktime_to_timespec(ktime_sub(ktime_get(), tcpw.start)); | ||
78 | |||
79 | len = sprintf(tbuf, "%lu.%09lu ", | ||
80 | (unsigned long) tv.tv_sec, (unsigned long) tv.tv_nsec); | ||
81 | len += vscnprintf(tbuf+len, sizeof(tbuf)-len, fmt, args); | ||
82 | va_end(args); | ||
83 | |||
84 | kfifo_put(tcpw.fifo, tbuf, len); | ||
85 | wake_up(&tcpw.wait); | ||
86 | } | 83 | } |
87 | 84 | ||
88 | /* | 85 | /* |
@@ -97,63 +94,118 @@ static int jtcp_rcv_established(struct sock *sk, struct sk_buff *skb, | |||
97 | 94 | ||
98 | /* Only update if port matches */ | 95 | /* Only update if port matches */ |
99 | if ((port == 0 || ntohs(inet->dport) == port || ntohs(inet->sport) == port) | 96 | if ((port == 0 || ntohs(inet->dport) == port || ntohs(inet->sport) == port) |
100 | && (full || tp->snd_cwnd != tcpw.lastcwnd)) { | 97 | && (full || tp->snd_cwnd != tcp_probe.lastcwnd)) { |
101 | printl("%d.%d.%d.%d:%u %d.%d.%d.%d:%u %d %#x %#x %u %u %u %u\n", | 98 | |
102 | NIPQUAD(inet->saddr), ntohs(inet->sport), | 99 | spin_lock(&tcp_probe.lock); |
103 | NIPQUAD(inet->daddr), ntohs(inet->dport), | 100 | /* If log fills, just silently drop */ |
104 | skb->len, tp->snd_nxt, tp->snd_una, | 101 | if (tcp_probe_avail() > 1) { |
105 | tp->snd_cwnd, tcp_current_ssthresh(sk), | 102 | struct tcp_log *p = tcp_probe.log + tcp_probe.head; |
106 | tp->snd_wnd, tp->srtt >> 3); | 103 | |
107 | tcpw.lastcwnd = tp->snd_cwnd; | 104 | p->tstamp = ktime_get(); |
105 | p->saddr = inet->saddr; | ||
106 | p->sport = inet->sport; | ||
107 | p->daddr = inet->daddr; | ||
108 | p->dport = inet->dport; | ||
109 | p->length = skb->len; | ||
110 | p->snd_nxt = tp->snd_nxt; | ||
111 | p->snd_una = tp->snd_una; | ||
112 | p->snd_cwnd = tp->snd_cwnd; | ||
113 | p->snd_wnd = tp->snd_wnd; | ||
114 | p->ssthresh = tcp_current_ssthresh(sk); | ||
115 | p->srtt = tp->srtt >> 3; | ||
116 | |||
117 | tcp_probe.head = (tcp_probe.head + 1) % bufsize; | ||
118 | } | ||
119 | tcp_probe.lastcwnd = tp->snd_cwnd; | ||
120 | spin_unlock(&tcp_probe.lock); | ||
121 | |||
122 | wake_up(&tcp_probe.wait); | ||
108 | } | 123 | } |
109 | 124 | ||
110 | jprobe_return(); | 125 | jprobe_return(); |
111 | return 0; | 126 | return 0; |
112 | } | 127 | } |
113 | 128 | ||
114 | static struct jprobe tcp_probe = { | 129 | static struct jprobe tcp_jprobe = { |
115 | .kp = { | 130 | .kp = { |
116 | .symbol_name = "tcp_rcv_established", | 131 | .symbol_name = "tcp_rcv_established", |
117 | }, | 132 | }, |
118 | .entry = JPROBE_ENTRY(jtcp_rcv_established), | 133 | .entry = JPROBE_ENTRY(jtcp_rcv_established), |
119 | }; | 134 | }; |
120 | 135 | ||
121 | |||
122 | static int tcpprobe_open(struct inode * inode, struct file * file) | 136 | static int tcpprobe_open(struct inode * inode, struct file * file) |
123 | { | 137 | { |
124 | kfifo_reset(tcpw.fifo); | 138 | /* Reset (empty) log */ |
125 | tcpw.start = ktime_get(); | 139 | spin_lock_bh(&tcp_probe.lock); |
140 | tcp_probe.head = tcp_probe.tail = 0; | ||
141 | tcp_probe.start = ktime_get(); | ||
142 | spin_unlock_bh(&tcp_probe.lock); | ||
143 | |||
126 | return 0; | 144 | return 0; |
127 | } | 145 | } |
128 | 146 | ||
147 | static int tcpprobe_sprint(char *tbuf, int n) | ||
148 | { | ||
149 | const struct tcp_log *p | ||
150 | = tcp_probe.log + tcp_probe.tail % bufsize; | ||
151 | struct timespec tv | ||
152 | = ktime_to_timespec(ktime_sub(p->tstamp, tcp_probe.start)); | ||
153 | |||
154 | return snprintf(tbuf, n, | ||
155 | "%lu.%09lu %d.%d.%d.%d:%u %d.%d.%d.%d:%u" | ||
156 | " %d %#x %#x %u %u %u %u\n", | ||
157 | (unsigned long) tv.tv_sec, | ||
158 | (unsigned long) tv.tv_nsec, | ||
159 | NIPQUAD(p->saddr), ntohs(p->sport), | ||
160 | NIPQUAD(p->daddr), ntohs(p->dport), | ||
161 | p->length, p->snd_nxt, p->snd_una, | ||
162 | p->snd_cwnd, p->ssthresh, p->snd_wnd, p->srtt); | ||
163 | } | ||
164 | |||
129 | static ssize_t tcpprobe_read(struct file *file, char __user *buf, | 165 | static ssize_t tcpprobe_read(struct file *file, char __user *buf, |
130 | size_t len, loff_t *ppos) | 166 | size_t len, loff_t *ppos) |
131 | { | 167 | { |
132 | int error = 0, cnt = 0; | 168 | int error = 0, cnt = 0; |
133 | unsigned char *tbuf; | ||
134 | 169 | ||
135 | if (!buf || len < 0) | 170 | if (!buf || len < 0) |
136 | return -EINVAL; | 171 | return -EINVAL; |
137 | 172 | ||
138 | if (len == 0) | 173 | while (cnt < len) { |
139 | return 0; | 174 | char tbuf[128]; |
175 | int width; | ||
176 | |||
177 | /* Wait for data in buffer */ | ||
178 | error = wait_event_interruptible(tcp_probe.wait, | ||
179 | tcp_probe_used() > 0); | ||
180 | if (error) | ||
181 | break; | ||
140 | 182 | ||
141 | tbuf = vmalloc(len); | 183 | spin_lock_bh(&tcp_probe.lock); |
142 | if (!tbuf) | 184 | if (tcp_probe.head == tcp_probe.tail) { |
143 | return -ENOMEM; | 185 | /* multiple readers race? */ |
186 | spin_unlock_bh(&tcp_probe.lock); | ||
187 | continue; | ||
188 | } | ||
144 | 189 | ||
145 | error = wait_event_interruptible(tcpw.wait, | 190 | width = tcpprobe_sprint(tbuf, sizeof(tbuf)); |
146 | __kfifo_len(tcpw.fifo) != 0); | ||
147 | if (error) | ||
148 | goto out_free; | ||
149 | 191 | ||
150 | cnt = kfifo_get(tcpw.fifo, tbuf, len); | 192 | if (width < len) |
151 | error = copy_to_user(buf, tbuf, cnt); | 193 | tcp_probe.tail = (tcp_probe.tail + 1) % bufsize; |
152 | 194 | ||
153 | out_free: | 195 | spin_unlock_bh(&tcp_probe.lock); |
154 | vfree(tbuf); | 196 | |
197 | /* if record greater than space available | ||
198 | return partial buffer (so far) */ | ||
199 | if (width >= len) | ||
200 | break; | ||
201 | |||
202 | error = copy_to_user(buf + cnt, tbuf, width); | ||
203 | if (error) | ||
204 | break; | ||
205 | cnt += width; | ||
206 | } | ||
155 | 207 | ||
156 | return error ? error : cnt; | 208 | return cnt == 0 ? error : cnt; |
157 | } | 209 | } |
158 | 210 | ||
159 | static const struct file_operations tcpprobe_fops = { | 211 | static const struct file_operations tcpprobe_fops = { |
@@ -166,34 +218,37 @@ static __init int tcpprobe_init(void) | |||
166 | { | 218 | { |
167 | int ret = -ENOMEM; | 219 | int ret = -ENOMEM; |
168 | 220 | ||
169 | init_waitqueue_head(&tcpw.wait); | 221 | init_waitqueue_head(&tcp_probe.wait); |
170 | spin_lock_init(&tcpw.lock); | 222 | spin_lock_init(&tcp_probe.lock); |
171 | tcpw.fifo = kfifo_alloc(bufsize, GFP_KERNEL, &tcpw.lock); | 223 | |
172 | if (IS_ERR(tcpw.fifo)) | 224 | if (bufsize < 0) |
173 | return PTR_ERR(tcpw.fifo); | 225 | return -EINVAL; |
226 | |||
227 | tcp_probe.log = kcalloc(sizeof(struct tcp_log), bufsize, GFP_KERNEL); | ||
228 | if (!tcp_probe.log) | ||
229 | goto err0; | ||
174 | 230 | ||
175 | if (!proc_net_fops_create(procname, S_IRUSR, &tcpprobe_fops)) | 231 | if (!proc_net_fops_create(procname, S_IRUSR, &tcpprobe_fops)) |
176 | goto err0; | 232 | goto err0; |
177 | 233 | ||
178 | ret = register_jprobe(&tcp_probe); | 234 | ret = register_jprobe(&tcp_jprobe); |
179 | if (ret) | 235 | if (ret) |
180 | goto err1; | 236 | goto err1; |
181 | 237 | ||
182 | pr_info("TCP watch registered (port=%d)\n", port); | 238 | pr_info("TCP probe registered (port=%d)\n", port); |
183 | return 0; | 239 | return 0; |
184 | err1: | 240 | err1: |
185 | proc_net_remove(procname); | 241 | proc_net_remove(procname); |
186 | err0: | 242 | err0: |
187 | kfifo_free(tcpw.fifo); | 243 | kfree(tcp_probe.log); |
188 | return ret; | 244 | return ret; |
189 | } | 245 | } |
190 | module_init(tcpprobe_init); | 246 | module_init(tcpprobe_init); |
191 | 247 | ||
192 | static __exit void tcpprobe_exit(void) | 248 | static __exit void tcpprobe_exit(void) |
193 | { | 249 | { |
194 | kfifo_free(tcpw.fifo); | ||
195 | proc_net_remove(procname); | 250 | proc_net_remove(procname); |
196 | unregister_jprobe(&tcp_probe); | 251 | unregister_jprobe(&tcp_jprobe); |
197 | 252 | kfree(tcp_probe.log); | |
198 | } | 253 | } |
199 | module_exit(tcpprobe_exit); | 254 | module_exit(tcpprobe_exit); |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index facb7e29304e..28355350fb62 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -70,6 +70,7 @@ | |||
70 | * Alexey Kuznetsov: allow both IPv4 and IPv6 sockets to bind | 70 | * Alexey Kuznetsov: allow both IPv4 and IPv6 sockets to bind |
71 | * a single port at the same time. | 71 | * a single port at the same time. |
72 | * Derek Atkins <derek@ihtfp.com>: Add Encapulation Support | 72 | * Derek Atkins <derek@ihtfp.com>: Add Encapulation Support |
73 | * James Chapman : Add L2TP encapsulation type. | ||
73 | * | 74 | * |
74 | * | 75 | * |
75 | * This program is free software; you can redistribute it and/or | 76 | * This program is free software; you can redistribute it and/or |
@@ -919,104 +920,6 @@ int udp_disconnect(struct sock *sk, int flags) | |||
919 | return 0; | 920 | return 0; |
920 | } | 921 | } |
921 | 922 | ||
922 | /* return: | ||
923 | * 1 if the UDP system should process it | ||
924 | * 0 if we should drop this packet | ||
925 | * -1 if it should get processed by xfrm4_rcv_encap | ||
926 | */ | ||
927 | static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb) | ||
928 | { | ||
929 | #ifndef CONFIG_XFRM | ||
930 | return 1; | ||
931 | #else | ||
932 | struct udp_sock *up = udp_sk(sk); | ||
933 | struct udphdr *uh; | ||
934 | struct iphdr *iph; | ||
935 | int iphlen, len; | ||
936 | |||
937 | __u8 *udpdata; | ||
938 | __be32 *udpdata32; | ||
939 | __u16 encap_type = up->encap_type; | ||
940 | |||
941 | /* if we're overly short, let UDP handle it */ | ||
942 | len = skb->len - sizeof(struct udphdr); | ||
943 | if (len <= 0) | ||
944 | return 1; | ||
945 | |||
946 | /* if this is not encapsulated socket, then just return now */ | ||
947 | if (!encap_type) | ||
948 | return 1; | ||
949 | |||
950 | /* If this is a paged skb, make sure we pull up | ||
951 | * whatever data we need to look at. */ | ||
952 | if (!pskb_may_pull(skb, sizeof(struct udphdr) + min(len, 8))) | ||
953 | return 1; | ||
954 | |||
955 | /* Now we can get the pointers */ | ||
956 | uh = udp_hdr(skb); | ||
957 | udpdata = (__u8 *)uh + sizeof(struct udphdr); | ||
958 | udpdata32 = (__be32 *)udpdata; | ||
959 | |||
960 | switch (encap_type) { | ||
961 | default: | ||
962 | case UDP_ENCAP_ESPINUDP: | ||
963 | /* Check if this is a keepalive packet. If so, eat it. */ | ||
964 | if (len == 1 && udpdata[0] == 0xff) { | ||
965 | return 0; | ||
966 | } else if (len > sizeof(struct ip_esp_hdr) && udpdata32[0] != 0) { | ||
967 | /* ESP Packet without Non-ESP header */ | ||
968 | len = sizeof(struct udphdr); | ||
969 | } else | ||
970 | /* Must be an IKE packet.. pass it through */ | ||
971 | return 1; | ||
972 | break; | ||
973 | case UDP_ENCAP_ESPINUDP_NON_IKE: | ||
974 | /* Check if this is a keepalive packet. If so, eat it. */ | ||
975 | if (len == 1 && udpdata[0] == 0xff) { | ||
976 | return 0; | ||
977 | } else if (len > 2 * sizeof(u32) + sizeof(struct ip_esp_hdr) && | ||
978 | udpdata32[0] == 0 && udpdata32[1] == 0) { | ||
979 | |||
980 | /* ESP Packet with Non-IKE marker */ | ||
981 | len = sizeof(struct udphdr) + 2 * sizeof(u32); | ||
982 | } else | ||
983 | /* Must be an IKE packet.. pass it through */ | ||
984 | return 1; | ||
985 | break; | ||
986 | } | ||
987 | |||
988 | /* At this point we are sure that this is an ESPinUDP packet, | ||
989 | * so we need to remove 'len' bytes from the packet (the UDP | ||
990 | * header and optional ESP marker bytes) and then modify the | ||
991 | * protocol to ESP, and then call into the transform receiver. | ||
992 | */ | ||
993 | if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) | ||
994 | return 0; | ||
995 | |||
996 | /* Now we can update and verify the packet length... */ | ||
997 | iph = ip_hdr(skb); | ||
998 | iphlen = iph->ihl << 2; | ||
999 | iph->tot_len = htons(ntohs(iph->tot_len) - len); | ||
1000 | if (skb->len < iphlen + len) { | ||
1001 | /* packet is too small!?! */ | ||
1002 | return 0; | ||
1003 | } | ||
1004 | |||
1005 | /* pull the data buffer up to the ESP header and set the | ||
1006 | * transport header to point to ESP. Keep UDP on the stack | ||
1007 | * for later. | ||
1008 | */ | ||
1009 | __skb_pull(skb, len); | ||
1010 | skb_reset_transport_header(skb); | ||
1011 | |||
1012 | /* modify the protocol (it's ESP!) */ | ||
1013 | iph->protocol = IPPROTO_ESP; | ||
1014 | |||
1015 | /* and let the caller know to send this into the ESP processor... */ | ||
1016 | return -1; | ||
1017 | #endif | ||
1018 | } | ||
1019 | |||
1020 | /* returns: | 923 | /* returns: |
1021 | * -1: error | 924 | * -1: error |
1022 | * 0: success | 925 | * 0: success |
@@ -1039,28 +942,28 @@ int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | |||
1039 | 942 | ||
1040 | if (up->encap_type) { | 943 | if (up->encap_type) { |
1041 | /* | 944 | /* |
1042 | * This is an encapsulation socket, so let's see if this is | 945 | * This is an encapsulation socket so pass the skb to |
1043 | * an encapsulated packet. | 946 | * the socket's udp_encap_rcv() hook. Otherwise, just |
1044 | * If it's a keepalive packet, then just eat it. | 947 | * fall through and pass this up the UDP socket. |
1045 | * If it's an encapsulateed packet, then pass it to the | 948 | * up->encap_rcv() returns the following value: |
1046 | * IPsec xfrm input and return the response | 949 | * =0 if skb was successfully passed to the encap |
1047 | * appropriately. Otherwise, just fall through and | 950 | * handler or was discarded by it. |
1048 | * pass this up the UDP socket. | 951 | * >0 if skb should be passed on to UDP. |
952 | * <0 if skb should be resubmitted as proto -N | ||
1049 | */ | 953 | */ |
1050 | int ret; | ||
1051 | 954 | ||
1052 | ret = udp_encap_rcv(sk, skb); | 955 | /* if we're overly short, let UDP handle it */ |
1053 | if (ret == 0) { | 956 | if (skb->len > sizeof(struct udphdr) && |
1054 | /* Eat the packet .. */ | 957 | up->encap_rcv != NULL) { |
1055 | kfree_skb(skb); | 958 | int ret; |
1056 | return 0; | 959 | |
1057 | } | 960 | ret = (*up->encap_rcv)(sk, skb); |
1058 | if (ret < 0) { | 961 | if (ret <= 0) { |
1059 | /* process the ESP packet */ | 962 | UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag); |
1060 | ret = xfrm4_rcv_encap(skb, up->encap_type); | 963 | return -ret; |
1061 | UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag); | 964 | } |
1062 | return -ret; | ||
1063 | } | 965 | } |
966 | |||
1064 | /* FALLTHROUGH -- it's a UDP Packet */ | 967 | /* FALLTHROUGH -- it's a UDP Packet */ |
1065 | } | 968 | } |
1066 | 969 | ||
@@ -1349,6 +1252,9 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname, | |||
1349 | case 0: | 1252 | case 0: |
1350 | case UDP_ENCAP_ESPINUDP: | 1253 | case UDP_ENCAP_ESPINUDP: |
1351 | case UDP_ENCAP_ESPINUDP_NON_IKE: | 1254 | case UDP_ENCAP_ESPINUDP_NON_IKE: |
1255 | up->encap_rcv = xfrm4_udp_encap_rcv; | ||
1256 | /* FALLTHROUGH */ | ||
1257 | case UDP_ENCAP_L2TPINUDP: | ||
1352 | up->encap_type = val; | 1258 | up->encap_type = val; |
1353 | break; | 1259 | break; |
1354 | default: | 1260 | default: |
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c index fa1902dc81b8..2fa108245413 100644 --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c | |||
@@ -16,13 +16,6 @@ | |||
16 | #include <net/ip.h> | 16 | #include <net/ip.h> |
17 | #include <net/xfrm.h> | 17 | #include <net/xfrm.h> |
18 | 18 | ||
19 | int xfrm4_rcv(struct sk_buff *skb) | ||
20 | { | ||
21 | return xfrm4_rcv_encap(skb, 0); | ||
22 | } | ||
23 | |||
24 | EXPORT_SYMBOL(xfrm4_rcv); | ||
25 | |||
26 | static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq) | 19 | static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq) |
27 | { | 20 | { |
28 | switch (nexthdr) { | 21 | switch (nexthdr) { |
@@ -53,7 +46,7 @@ drop: | |||
53 | } | 46 | } |
54 | #endif | 47 | #endif |
55 | 48 | ||
56 | int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) | 49 | static int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) |
57 | { | 50 | { |
58 | __be32 spi, seq; | 51 | __be32 spi, seq; |
59 | struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH]; | 52 | struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH]; |
@@ -167,3 +160,108 @@ drop: | |||
167 | kfree_skb(skb); | 160 | kfree_skb(skb); |
168 | return 0; | 161 | return 0; |
169 | } | 162 | } |
163 | |||
164 | /* If it's a keepalive packet, then just eat it. | ||
165 | * If it's an encapsulated packet, then pass it to the | ||
166 | * IPsec xfrm input. | ||
167 | * Returns 0 if skb passed to xfrm or was dropped. | ||
168 | * Returns >0 if skb should be passed to UDP. | ||
169 | * Returns <0 if skb should be resubmitted (-ret is protocol) | ||
170 | */ | ||
171 | int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb) | ||
172 | { | ||
173 | struct udp_sock *up = udp_sk(sk); | ||
174 | struct udphdr *uh; | ||
175 | struct iphdr *iph; | ||
176 | int iphlen, len; | ||
177 | int ret; | ||
178 | |||
179 | __u8 *udpdata; | ||
180 | __be32 *udpdata32; | ||
181 | __u16 encap_type = up->encap_type; | ||
182 | |||
183 | /* if this is not encapsulated socket, then just return now */ | ||
184 | if (!encap_type) | ||
185 | return 1; | ||
186 | |||
187 | /* If this is a paged skb, make sure we pull up | ||
188 | * whatever data we need to look at. */ | ||
189 | len = skb->len - sizeof(struct udphdr); | ||
190 | if (!pskb_may_pull(skb, sizeof(struct udphdr) + min(len, 8))) | ||
191 | return 1; | ||
192 | |||
193 | /* Now we can get the pointers */ | ||
194 | uh = udp_hdr(skb); | ||
195 | udpdata = (__u8 *)uh + sizeof(struct udphdr); | ||
196 | udpdata32 = (__be32 *)udpdata; | ||
197 | |||
198 | switch (encap_type) { | ||
199 | default: | ||
200 | case UDP_ENCAP_ESPINUDP: | ||
201 | /* Check if this is a keepalive packet. If so, eat it. */ | ||
202 | if (len == 1 && udpdata[0] == 0xff) { | ||
203 | goto drop; | ||
204 | } else if (len > sizeof(struct ip_esp_hdr) && udpdata32[0] != 0) { | ||
205 | /* ESP Packet without Non-ESP header */ | ||
206 | len = sizeof(struct udphdr); | ||
207 | } else | ||
208 | /* Must be an IKE packet.. pass it through */ | ||
209 | return 1; | ||
210 | break; | ||
211 | case UDP_ENCAP_ESPINUDP_NON_IKE: | ||
212 | /* Check if this is a keepalive packet. If so, eat it. */ | ||
213 | if (len == 1 && udpdata[0] == 0xff) { | ||
214 | goto drop; | ||
215 | } else if (len > 2 * sizeof(u32) + sizeof(struct ip_esp_hdr) && | ||
216 | udpdata32[0] == 0 && udpdata32[1] == 0) { | ||
217 | |||
218 | /* ESP Packet with Non-IKE marker */ | ||
219 | len = sizeof(struct udphdr) + 2 * sizeof(u32); | ||
220 | } else | ||
221 | /* Must be an IKE packet.. pass it through */ | ||
222 | return 1; | ||
223 | break; | ||
224 | } | ||
225 | |||
226 | /* At this point we are sure that this is an ESPinUDP packet, | ||
227 | * so we need to remove 'len' bytes from the packet (the UDP | ||
228 | * header and optional ESP marker bytes) and then modify the | ||
229 | * protocol to ESP, and then call into the transform receiver. | ||
230 | */ | ||
231 | if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) | ||
232 | goto drop; | ||
233 | |||
234 | /* Now we can update and verify the packet length... */ | ||
235 | iph = ip_hdr(skb); | ||
236 | iphlen = iph->ihl << 2; | ||
237 | iph->tot_len = htons(ntohs(iph->tot_len) - len); | ||
238 | if (skb->len < iphlen + len) { | ||
239 | /* packet is too small!?! */ | ||
240 | goto drop; | ||
241 | } | ||
242 | |||
243 | /* pull the data buffer up to the ESP header and set the | ||
244 | * transport header to point to ESP. Keep UDP on the stack | ||
245 | * for later. | ||
246 | */ | ||
247 | __skb_pull(skb, len); | ||
248 | skb_reset_transport_header(skb); | ||
249 | |||
250 | /* modify the protocol (it's ESP!) */ | ||
251 | iph->protocol = IPPROTO_ESP; | ||
252 | |||
253 | /* process ESP */ | ||
254 | ret = xfrm4_rcv_encap(skb, encap_type); | ||
255 | return ret; | ||
256 | |||
257 | drop: | ||
258 | kfree_skb(skb); | ||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | int xfrm4_rcv(struct sk_buff *skb) | ||
263 | { | ||
264 | return xfrm4_rcv_encap(skb, 0); | ||
265 | } | ||
266 | |||
267 | EXPORT_SYMBOL(xfrm4_rcv); | ||
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c index 568510304553..9275c79119b6 100644 --- a/net/ipv4/xfrm4_tunnel.c +++ b/net/ipv4/xfrm4_tunnel.c | |||
@@ -109,3 +109,4 @@ static void __exit ipip_fini(void) | |||
109 | module_init(ipip_init); | 109 | module_init(ipip_init); |
110 | module_exit(ipip_fini); | 110 | module_exit(ipip_fini); |
111 | MODULE_LICENSE("GPL"); | 111 | MODULE_LICENSE("GPL"); |
112 | MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_IPIP); | ||
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index 8e5d54f23b49..eb0b8085949b 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig | |||
@@ -109,7 +109,7 @@ config INET6_IPCOMP | |||
109 | If unsure, say Y. | 109 | If unsure, say Y. |
110 | 110 | ||
111 | config IPV6_MIP6 | 111 | config IPV6_MIP6 |
112 | bool "IPv6: Mobility (EXPERIMENTAL)" | 112 | tristate "IPv6: Mobility (EXPERIMENTAL)" |
113 | depends on IPV6 && EXPERIMENTAL | 113 | depends on IPV6 && EXPERIMENTAL |
114 | select XFRM | 114 | select XFRM |
115 | ---help--- | 115 | ---help--- |
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index bb33309044c9..87c23a73d284 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile | |||
@@ -14,7 +14,6 @@ ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \ | |||
14 | xfrm6_output.o | 14 | xfrm6_output.o |
15 | ipv6-$(CONFIG_NETFILTER) += netfilter.o | 15 | ipv6-$(CONFIG_NETFILTER) += netfilter.o |
16 | ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o | 16 | ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o |
17 | ipv6-$(CONFIG_IPV6_MIP6) += mip6.o | ||
18 | ipv6-$(CONFIG_PROC_FS) += proc.o | 17 | ipv6-$(CONFIG_PROC_FS) += proc.o |
19 | 18 | ||
20 | ipv6-objs += $(ipv6-y) | 19 | ipv6-objs += $(ipv6-y) |
@@ -28,6 +27,7 @@ obj-$(CONFIG_INET6_XFRM_MODE_TRANSPORT) += xfrm6_mode_transport.o | |||
28 | obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o | 27 | obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o |
29 | obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o | 28 | obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o |
30 | obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o | 29 | obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o |
30 | obj-$(CONFIG_IPV6_MIP6) += mip6.o | ||
31 | obj-$(CONFIG_NETFILTER) += netfilter/ | 31 | obj-$(CONFIG_NETFILTER) += netfilter/ |
32 | 32 | ||
33 | obj-$(CONFIG_IPV6_SIT) += sit.o | 33 | obj-$(CONFIG_IPV6_SIT) += sit.o |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 79b79f3de24c..06012920912a 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -1034,7 +1034,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
1034 | } | 1034 | } |
1035 | 1035 | ||
1036 | /* Rule 4: Prefer home address */ | 1036 | /* Rule 4: Prefer home address */ |
1037 | #ifdef CONFIG_IPV6_MIP6 | 1037 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
1038 | if (hiscore.rule < 4) { | 1038 | if (hiscore.rule < 4) { |
1039 | if (ifa_result->flags & IFA_F_HOMEADDRESS) | 1039 | if (ifa_result->flags & IFA_F_HOMEADDRESS) |
1040 | hiscore.attrs |= IPV6_SADDR_SCORE_HOA; | 1040 | hiscore.attrs |= IPV6_SADDR_SCORE_HOA; |
@@ -2475,6 +2475,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2475 | write_unlock_bh(&idev->lock); | 2475 | write_unlock_bh(&idev->lock); |
2476 | 2476 | ||
2477 | __ipv6_ifa_notify(RTM_DELADDR, ifa); | 2477 | __ipv6_ifa_notify(RTM_DELADDR, ifa); |
2478 | atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa); | ||
2478 | in6_ifa_put(ifa); | 2479 | in6_ifa_put(ifa); |
2479 | 2480 | ||
2480 | write_lock_bh(&idev->lock); | 2481 | write_lock_bh(&idev->lock); |
@@ -2785,7 +2786,7 @@ static int if6_seq_show(struct seq_file *seq, void *v) | |||
2785 | return 0; | 2786 | return 0; |
2786 | } | 2787 | } |
2787 | 2788 | ||
2788 | static struct seq_operations if6_seq_ops = { | 2789 | static const struct seq_operations if6_seq_ops = { |
2789 | .start = if6_seq_start, | 2790 | .start = if6_seq_start, |
2790 | .next = if6_seq_next, | 2791 | .next = if6_seq_next, |
2791 | .show = if6_seq_show, | 2792 | .show = if6_seq_show, |
@@ -2835,7 +2836,7 @@ void if6_proc_exit(void) | |||
2835 | } | 2836 | } |
2836 | #endif /* CONFIG_PROC_FS */ | 2837 | #endif /* CONFIG_PROC_FS */ |
2837 | 2838 | ||
2838 | #ifdef CONFIG_IPV6_MIP6 | 2839 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
2839 | /* Check if address is a home address configured on any interface. */ | 2840 | /* Check if address is a home address configured on any interface. */ |
2840 | int ipv6_chk_home_addr(struct in6_addr *addr) | 2841 | int ipv6_chk_home_addr(struct in6_addr *addr) |
2841 | { | 2842 | { |
@@ -4243,7 +4244,6 @@ errout: | |||
4243 | void __exit addrconf_cleanup(void) | 4244 | void __exit addrconf_cleanup(void) |
4244 | { | 4245 | { |
4245 | struct net_device *dev; | 4246 | struct net_device *dev; |
4246 | struct inet6_dev *idev; | ||
4247 | struct inet6_ifaddr *ifa; | 4247 | struct inet6_ifaddr *ifa; |
4248 | int i; | 4248 | int i; |
4249 | 4249 | ||
@@ -4261,7 +4261,7 @@ void __exit addrconf_cleanup(void) | |||
4261 | */ | 4261 | */ |
4262 | 4262 | ||
4263 | for_each_netdev(dev) { | 4263 | for_each_netdev(dev) { |
4264 | if ((idev = __in6_dev_get(dev)) == NULL) | 4264 | if (__in6_dev_get(dev) == NULL) |
4265 | continue; | 4265 | continue; |
4266 | addrconf_ifdown(dev, 1); | 4266 | addrconf_ifdown(dev, 1); |
4267 | } | 4267 | } |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 6dd377253cf7..eed09373a45d 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -58,9 +58,6 @@ | |||
58 | #ifdef CONFIG_IPV6_TUNNEL | 58 | #ifdef CONFIG_IPV6_TUNNEL |
59 | #include <net/ip6_tunnel.h> | 59 | #include <net/ip6_tunnel.h> |
60 | #endif | 60 | #endif |
61 | #ifdef CONFIG_IPV6_MIP6 | ||
62 | #include <net/mip6.h> | ||
63 | #endif | ||
64 | 61 | ||
65 | #include <asm/uaccess.h> | 62 | #include <asm/uaccess.h> |
66 | #include <asm/system.h> | 63 | #include <asm/system.h> |
@@ -853,9 +850,6 @@ static int __init inet6_init(void) | |||
853 | ipv6_frag_init(); | 850 | ipv6_frag_init(); |
854 | ipv6_nodata_init(); | 851 | ipv6_nodata_init(); |
855 | ipv6_destopt_init(); | 852 | ipv6_destopt_init(); |
856 | #ifdef CONFIG_IPV6_MIP6 | ||
857 | mip6_init(); | ||
858 | #endif | ||
859 | 853 | ||
860 | /* Init v6 transport protocols. */ | 854 | /* Init v6 transport protocols. */ |
861 | udpv6_init(); | 855 | udpv6_init(); |
@@ -921,9 +915,7 @@ static void __exit inet6_exit(void) | |||
921 | 915 | ||
922 | /* Cleanup code parts. */ | 916 | /* Cleanup code parts. */ |
923 | ipv6_packet_cleanup(); | 917 | ipv6_packet_cleanup(); |
924 | #ifdef CONFIG_IPV6_MIP6 | 918 | |
925 | mip6_fini(); | ||
926 | #endif | ||
927 | addrconf_cleanup(); | 919 | addrconf_cleanup(); |
928 | ip6_flowlabel_cleanup(); | 920 | ip6_flowlabel_cleanup(); |
929 | ip6_route_cleanup(); | 921 | ip6_route_cleanup(); |
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 128f94c79c64..53f46ab6af70 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c | |||
@@ -74,7 +74,7 @@ bad: | |||
74 | return 0; | 74 | return 0; |
75 | } | 75 | } |
76 | 76 | ||
77 | #ifdef CONFIG_IPV6_MIP6 | 77 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
78 | /** | 78 | /** |
79 | * ipv6_rearrange_destopt - rearrange IPv6 destination options header | 79 | * ipv6_rearrange_destopt - rearrange IPv6 destination options header |
80 | * @iph: IPv6 header | 80 | * @iph: IPv6 header |
@@ -132,6 +132,8 @@ static void ipv6_rearrange_destopt(struct ipv6hdr *iph, struct ipv6_opt_hdr *des | |||
132 | bad: | 132 | bad: |
133 | return; | 133 | return; |
134 | } | 134 | } |
135 | #else | ||
136 | static void ipv6_rearrange_destopt(struct ipv6hdr *iph, struct ipv6_opt_hdr *destopt) {} | ||
135 | #endif | 137 | #endif |
136 | 138 | ||
137 | /** | 139 | /** |
@@ -189,10 +191,8 @@ static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len, int dir) | |||
189 | while (exthdr.raw < end) { | 191 | while (exthdr.raw < end) { |
190 | switch (nexthdr) { | 192 | switch (nexthdr) { |
191 | case NEXTHDR_DEST: | 193 | case NEXTHDR_DEST: |
192 | #ifdef CONFIG_IPV6_MIP6 | ||
193 | if (dir == XFRM_POLICY_OUT) | 194 | if (dir == XFRM_POLICY_OUT) |
194 | ipv6_rearrange_destopt(iph, exthdr.opth); | 195 | ipv6_rearrange_destopt(iph, exthdr.opth); |
195 | #endif | ||
196 | case NEXTHDR_HOP: | 196 | case NEXTHDR_HOP: |
197 | if (!zero_out_mutable_opts(exthdr.opth)) { | 197 | if (!zero_out_mutable_opts(exthdr.opth)) { |
198 | LIMIT_NETDEBUG( | 198 | LIMIT_NETDEBUG( |
@@ -228,7 +228,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
228 | u8 nexthdr; | 228 | u8 nexthdr; |
229 | char tmp_base[8]; | 229 | char tmp_base[8]; |
230 | struct { | 230 | struct { |
231 | #ifdef CONFIG_IPV6_MIP6 | 231 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
232 | struct in6_addr saddr; | 232 | struct in6_addr saddr; |
233 | #endif | 233 | #endif |
234 | struct in6_addr daddr; | 234 | struct in6_addr daddr; |
@@ -255,7 +255,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
255 | err = -ENOMEM; | 255 | err = -ENOMEM; |
256 | goto error; | 256 | goto error; |
257 | } | 257 | } |
258 | #ifdef CONFIG_IPV6_MIP6 | 258 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
259 | memcpy(tmp_ext, &top_iph->saddr, extlen); | 259 | memcpy(tmp_ext, &top_iph->saddr, extlen); |
260 | #else | 260 | #else |
261 | memcpy(tmp_ext, &top_iph->daddr, extlen); | 261 | memcpy(tmp_ext, &top_iph->daddr, extlen); |
@@ -294,7 +294,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
294 | 294 | ||
295 | memcpy(top_iph, tmp_base, sizeof(tmp_base)); | 295 | memcpy(top_iph, tmp_base, sizeof(tmp_base)); |
296 | if (tmp_ext) { | 296 | if (tmp_ext) { |
297 | #ifdef CONFIG_IPV6_MIP6 | 297 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
298 | memcpy(&top_iph->saddr, tmp_ext, extlen); | 298 | memcpy(&top_iph->saddr, tmp_ext, extlen); |
299 | #else | 299 | #else |
300 | memcpy(&top_iph->daddr, tmp_ext, extlen); | 300 | memcpy(&top_iph->daddr, tmp_ext, extlen); |
@@ -554,3 +554,4 @@ module_init(ah6_init); | |||
554 | module_exit(ah6_fini); | 554 | module_exit(ah6_fini); |
555 | 555 | ||
556 | MODULE_LICENSE("GPL"); | 556 | MODULE_LICENSE("GPL"); |
557 | MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_AH); | ||
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index 9b81264eb78f..b8c533fbdb63 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c | |||
@@ -539,7 +539,7 @@ static int ac6_seq_show(struct seq_file *seq, void *v) | |||
539 | return 0; | 539 | return 0; |
540 | } | 540 | } |
541 | 541 | ||
542 | static struct seq_operations ac6_seq_ops = { | 542 | static const struct seq_operations ac6_seq_ops = { |
543 | .start = ac6_seq_start, | 543 | .start = ac6_seq_start, |
544 | .next = ac6_seq_next, | 544 | .next = ac6_seq_next, |
545 | .stop = ac6_seq_stop, | 545 | .stop = ac6_seq_stop, |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index b1fe7ac5dc90..fe0f49024a0a 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -657,11 +657,10 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, | |||
657 | rthdr = (struct ipv6_rt_hdr *)CMSG_DATA(cmsg); | 657 | rthdr = (struct ipv6_rt_hdr *)CMSG_DATA(cmsg); |
658 | 658 | ||
659 | switch (rthdr->type) { | 659 | switch (rthdr->type) { |
660 | case IPV6_SRCRT_TYPE_0: | 660 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
661 | #ifdef CONFIG_IPV6_MIP6 | ||
662 | case IPV6_SRCRT_TYPE_2: | 661 | case IPV6_SRCRT_TYPE_2: |
663 | #endif | ||
664 | break; | 662 | break; |
663 | #endif | ||
665 | default: | 664 | default: |
666 | err = -EINVAL; | 665 | err = -EINVAL; |
667 | goto exit_f; | 666 | goto exit_f; |
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 7107bb7e2e62..2db31ce3c7e6 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
@@ -421,3 +421,4 @@ module_init(esp6_init); | |||
421 | module_exit(esp6_fini); | 421 | module_exit(esp6_fini); |
422 | 422 | ||
423 | MODULE_LICENSE("GPL"); | 423 | MODULE_LICENSE("GPL"); |
424 | MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_ESP); | ||
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 14be0b9b77a5..c82d4d49f71f 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
@@ -42,7 +42,7 @@ | |||
42 | #include <net/ndisc.h> | 42 | #include <net/ndisc.h> |
43 | #include <net/ip6_route.h> | 43 | #include <net/ip6_route.h> |
44 | #include <net/addrconf.h> | 44 | #include <net/addrconf.h> |
45 | #ifdef CONFIG_IPV6_MIP6 | 45 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
46 | #include <net/xfrm.h> | 46 | #include <net/xfrm.h> |
47 | #endif | 47 | #endif |
48 | 48 | ||
@@ -90,6 +90,7 @@ int ipv6_find_tlv(struct sk_buff *skb, int offset, int type) | |||
90 | bad: | 90 | bad: |
91 | return -1; | 91 | return -1; |
92 | } | 92 | } |
93 | EXPORT_SYMBOL_GPL(ipv6_find_tlv); | ||
93 | 94 | ||
94 | /* | 95 | /* |
95 | * Parsing tlv encoded headers. | 96 | * Parsing tlv encoded headers. |
@@ -196,7 +197,7 @@ bad: | |||
196 | Destination options header. | 197 | Destination options header. |
197 | *****************************/ | 198 | *****************************/ |
198 | 199 | ||
199 | #ifdef CONFIG_IPV6_MIP6 | 200 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
200 | static int ipv6_dest_hao(struct sk_buff **skbp, int optoff) | 201 | static int ipv6_dest_hao(struct sk_buff **skbp, int optoff) |
201 | { | 202 | { |
202 | struct sk_buff *skb = *skbp; | 203 | struct sk_buff *skb = *skbp; |
@@ -270,7 +271,7 @@ static int ipv6_dest_hao(struct sk_buff **skbp, int optoff) | |||
270 | #endif | 271 | #endif |
271 | 272 | ||
272 | static struct tlvtype_proc tlvprocdestopt_lst[] = { | 273 | static struct tlvtype_proc tlvprocdestopt_lst[] = { |
273 | #ifdef CONFIG_IPV6_MIP6 | 274 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
274 | { | 275 | { |
275 | .type = IPV6_TLV_HAO, | 276 | .type = IPV6_TLV_HAO, |
276 | .func = ipv6_dest_hao, | 277 | .func = ipv6_dest_hao, |
@@ -283,7 +284,7 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) | |||
283 | { | 284 | { |
284 | struct sk_buff *skb = *skbp; | 285 | struct sk_buff *skb = *skbp; |
285 | struct inet6_skb_parm *opt = IP6CB(skb); | 286 | struct inet6_skb_parm *opt = IP6CB(skb); |
286 | #ifdef CONFIG_IPV6_MIP6 | 287 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
287 | __u16 dstbuf; | 288 | __u16 dstbuf; |
288 | #endif | 289 | #endif |
289 | struct dst_entry *dst; | 290 | struct dst_entry *dst; |
@@ -298,7 +299,7 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) | |||
298 | } | 299 | } |
299 | 300 | ||
300 | opt->lastopt = opt->dst1 = skb_network_header_len(skb); | 301 | opt->lastopt = opt->dst1 = skb_network_header_len(skb); |
301 | #ifdef CONFIG_IPV6_MIP6 | 302 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
302 | dstbuf = opt->dst1; | 303 | dstbuf = opt->dst1; |
303 | #endif | 304 | #endif |
304 | 305 | ||
@@ -308,7 +309,7 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) | |||
308 | skb = *skbp; | 309 | skb = *skbp; |
309 | skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3; | 310 | skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3; |
310 | opt = IP6CB(skb); | 311 | opt = IP6CB(skb); |
311 | #ifdef CONFIG_IPV6_MIP6 | 312 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
312 | opt->nhoff = dstbuf; | 313 | opt->nhoff = dstbuf; |
313 | #else | 314 | #else |
314 | opt->nhoff = opt->dst1; | 315 | opt->nhoff = opt->dst1; |
@@ -371,22 +372,13 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) | |||
371 | struct rt0_hdr *rthdr; | 372 | struct rt0_hdr *rthdr; |
372 | int accept_source_route = ipv6_devconf.accept_source_route; | 373 | int accept_source_route = ipv6_devconf.accept_source_route; |
373 | 374 | ||
374 | if (accept_source_route < 0 || | 375 | idev = in6_dev_get(skb->dev); |
375 | ((idev = in6_dev_get(skb->dev)) == NULL)) { | 376 | if (idev) { |
376 | kfree_skb(skb); | 377 | if (accept_source_route > idev->cnf.accept_source_route) |
377 | return -1; | 378 | accept_source_route = idev->cnf.accept_source_route; |
378 | } | ||
379 | if (idev->cnf.accept_source_route < 0) { | ||
380 | in6_dev_put(idev); | 379 | in6_dev_put(idev); |
381 | kfree_skb(skb); | ||
382 | return -1; | ||
383 | } | 380 | } |
384 | 381 | ||
385 | if (accept_source_route > idev->cnf.accept_source_route) | ||
386 | accept_source_route = idev->cnf.accept_source_route; | ||
387 | |||
388 | in6_dev_put(idev); | ||
389 | |||
390 | if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) || | 382 | if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) || |
391 | !pskb_may_pull(skb, (skb_transport_offset(skb) + | 383 | !pskb_may_pull(skb, (skb_transport_offset(skb) + |
392 | ((skb_transport_header(skb)[1] + 1) << 3)))) { | 384 | ((skb_transport_header(skb)[1] + 1) << 3)))) { |
@@ -398,24 +390,6 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) | |||
398 | 390 | ||
399 | hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb); | 391 | hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb); |
400 | 392 | ||
401 | switch (hdr->type) { | ||
402 | #ifdef CONFIG_IPV6_MIP6 | ||
403 | case IPV6_SRCRT_TYPE_2: | ||
404 | break; | ||
405 | #endif | ||
406 | case IPV6_SRCRT_TYPE_0: | ||
407 | if (accept_source_route > 0) | ||
408 | break; | ||
409 | kfree_skb(skb); | ||
410 | return -1; | ||
411 | default: | ||
412 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | ||
413 | IPSTATS_MIB_INHDRERRORS); | ||
414 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, | ||
415 | (&hdr->type) - skb_network_header(skb)); | ||
416 | return -1; | ||
417 | } | ||
418 | |||
419 | if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) || | 393 | if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) || |
420 | skb->pkt_type != PACKET_HOST) { | 394 | skb->pkt_type != PACKET_HOST) { |
421 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | 395 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
@@ -427,7 +401,7 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) | |||
427 | looped_back: | 401 | looped_back: |
428 | if (hdr->segments_left == 0) { | 402 | if (hdr->segments_left == 0) { |
429 | switch (hdr->type) { | 403 | switch (hdr->type) { |
430 | #ifdef CONFIG_IPV6_MIP6 | 404 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
431 | case IPV6_SRCRT_TYPE_2: | 405 | case IPV6_SRCRT_TYPE_2: |
432 | /* Silently discard type 2 header unless it was | 406 | /* Silently discard type 2 header unless it was |
433 | * processed by own | 407 | * processed by own |
@@ -453,18 +427,10 @@ looped_back: | |||
453 | } | 427 | } |
454 | 428 | ||
455 | switch (hdr->type) { | 429 | switch (hdr->type) { |
456 | case IPV6_SRCRT_TYPE_0: | 430 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
457 | if (hdr->hdrlen & 0x01) { | ||
458 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | ||
459 | IPSTATS_MIB_INHDRERRORS); | ||
460 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, | ||
461 | ((&hdr->hdrlen) - | ||
462 | skb_network_header(skb))); | ||
463 | return -1; | ||
464 | } | ||
465 | break; | ||
466 | #ifdef CONFIG_IPV6_MIP6 | ||
467 | case IPV6_SRCRT_TYPE_2: | 431 | case IPV6_SRCRT_TYPE_2: |
432 | if (accept_source_route < 0) | ||
433 | goto unknown_rh; | ||
468 | /* Silently discard invalid RTH type 2 */ | 434 | /* Silently discard invalid RTH type 2 */ |
469 | if (hdr->hdrlen != 2 || hdr->segments_left != 1) { | 435 | if (hdr->hdrlen != 2 || hdr->segments_left != 1) { |
470 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | 436 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
@@ -474,6 +440,8 @@ looped_back: | |||
474 | } | 440 | } |
475 | break; | 441 | break; |
476 | #endif | 442 | #endif |
443 | default: | ||
444 | goto unknown_rh; | ||
477 | } | 445 | } |
478 | 446 | ||
479 | /* | 447 | /* |
@@ -520,7 +488,7 @@ looped_back: | |||
520 | addr += i - 1; | 488 | addr += i - 1; |
521 | 489 | ||
522 | switch (hdr->type) { | 490 | switch (hdr->type) { |
523 | #ifdef CONFIG_IPV6_MIP6 | 491 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
524 | case IPV6_SRCRT_TYPE_2: | 492 | case IPV6_SRCRT_TYPE_2: |
525 | if (xfrm6_input_addr(skb, (xfrm_address_t *)addr, | 493 | if (xfrm6_input_addr(skb, (xfrm_address_t *)addr, |
526 | (xfrm_address_t *)&ipv6_hdr(skb)->saddr, | 494 | (xfrm_address_t *)&ipv6_hdr(skb)->saddr, |
@@ -577,6 +545,12 @@ looped_back: | |||
577 | skb_push(skb, skb->data - skb_network_header(skb)); | 545 | skb_push(skb, skb->data - skb_network_header(skb)); |
578 | dst_input(skb); | 546 | dst_input(skb); |
579 | return -1; | 547 | return -1; |
548 | |||
549 | unknown_rh: | ||
550 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); | ||
551 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, | ||
552 | (&hdr->type) - skb_network_header(skb)); | ||
553 | return -1; | ||
580 | } | 554 | } |
581 | 555 | ||
582 | static struct inet6_protocol rthdr_protocol = { | 556 | static struct inet6_protocol rthdr_protocol = { |
@@ -590,72 +564,6 @@ void __init ipv6_rthdr_init(void) | |||
590 | printk(KERN_ERR "ipv6_rthdr_init: Could not register protocol\n"); | 564 | printk(KERN_ERR "ipv6_rthdr_init: Could not register protocol\n"); |
591 | }; | 565 | }; |
592 | 566 | ||
593 | /* | ||
594 | This function inverts received rthdr. | ||
595 | NOTE: specs allow to make it automatically only if | ||
596 | packet authenticated. | ||
597 | |||
598 | I will not discuss it here (though, I am really pissed off at | ||
599 | this stupid requirement making rthdr idea useless) | ||
600 | |||
601 | Actually, it creates severe problems for us. | ||
602 | Embryonic requests has no associated sockets, | ||
603 | so that user have no control over it and | ||
604 | cannot not only to set reply options, but | ||
605 | even to know, that someone wants to connect | ||
606 | without success. :-( | ||
607 | |||
608 | For now we need to test the engine, so that I created | ||
609 | temporary (or permanent) backdoor. | ||
610 | If listening socket set IPV6_RTHDR to 2, then we invert header. | ||
611 | --ANK (980729) | ||
612 | */ | ||
613 | |||
614 | struct ipv6_txoptions * | ||
615 | ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr) | ||
616 | { | ||
617 | /* Received rthdr: | ||
618 | |||
619 | [ H1 -> H2 -> ... H_prev ] daddr=ME | ||
620 | |||
621 | Inverted result: | ||
622 | [ H_prev -> ... -> H1 ] daddr =sender | ||
623 | |||
624 | Note, that IP output engine will rewrite this rthdr | ||
625 | by rotating it left by one addr. | ||
626 | */ | ||
627 | |||
628 | int n, i; | ||
629 | struct rt0_hdr *rthdr = (struct rt0_hdr*)hdr; | ||
630 | struct rt0_hdr *irthdr; | ||
631 | struct ipv6_txoptions *opt; | ||
632 | int hdrlen = ipv6_optlen(hdr); | ||
633 | |||
634 | if (hdr->segments_left || | ||
635 | hdr->type != IPV6_SRCRT_TYPE_0 || | ||
636 | hdr->hdrlen & 0x01) | ||
637 | return NULL; | ||
638 | |||
639 | n = hdr->hdrlen >> 1; | ||
640 | opt = sock_kmalloc(sk, sizeof(*opt) + hdrlen, GFP_ATOMIC); | ||
641 | if (opt == NULL) | ||
642 | return NULL; | ||
643 | memset(opt, 0, sizeof(*opt)); | ||
644 | opt->tot_len = sizeof(*opt) + hdrlen; | ||
645 | opt->srcrt = (void*)(opt+1); | ||
646 | opt->opt_nflen = hdrlen; | ||
647 | |||
648 | memcpy(opt->srcrt, hdr, sizeof(*hdr)); | ||
649 | irthdr = (struct rt0_hdr*)opt->srcrt; | ||
650 | irthdr->reserved = 0; | ||
651 | opt->srcrt->segments_left = n; | ||
652 | for (i=0; i<n; i++) | ||
653 | memcpy(irthdr->addr+i, rthdr->addr+(n-1-i), 16); | ||
654 | return opt; | ||
655 | } | ||
656 | |||
657 | EXPORT_SYMBOL_GPL(ipv6_invert_rthdr); | ||
658 | |||
659 | /********************************** | 567 | /********************************** |
660 | Hop-by-hop options. | 568 | Hop-by-hop options. |
661 | **********************************/ | 569 | **********************************/ |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index e9bcce9e7bdf..6a6714d154ed 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -272,7 +272,7 @@ static int icmpv6_getfrag(void *from, char *to, int offset, int len, int odd, st | |||
272 | return 0; | 272 | return 0; |
273 | } | 273 | } |
274 | 274 | ||
275 | #ifdef CONFIG_IPV6_MIP6 | 275 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
276 | static void mip6_addr_swap(struct sk_buff *skb) | 276 | static void mip6_addr_swap(struct sk_buff *skb) |
277 | { | 277 | { |
278 | struct ipv6hdr *iph = ipv6_hdr(skb); | 278 | struct ipv6hdr *iph = ipv6_hdr(skb); |
@@ -604,7 +604,7 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) | |||
604 | 604 | ||
605 | read_lock(&raw_v6_lock); | 605 | read_lock(&raw_v6_lock); |
606 | if ((sk = sk_head(&raw_v6_htable[hash])) != NULL) { | 606 | if ((sk = sk_head(&raw_v6_htable[hash])) != NULL) { |
607 | while((sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr, | 607 | while ((sk = __raw_v6_lookup(sk, nexthdr, saddr, daddr, |
608 | IP6CB(skb)->iif))) { | 608 | IP6CB(skb)->iif))) { |
609 | rawv6_err(sk, skb, NULL, type, code, inner_offset, info); | 609 | rawv6_err(sk, skb, NULL, type, code, inner_offset, info); |
610 | sk = sk_next(sk); | 610 | sk = sk_next(sk); |
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index c206a152ed9d..413a4ebb195c 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
@@ -648,7 +648,7 @@ static int ip6fl_seq_show(struct seq_file *seq, void *v) | |||
648 | return 0; | 648 | return 0; |
649 | } | 649 | } |
650 | 650 | ||
651 | static struct seq_operations ip6fl_seq_ops = { | 651 | static const struct seq_operations ip6fl_seq_ops = { |
652 | .start = ip6fl_seq_start, | 652 | .start = ip6fl_seq_start, |
653 | .next = ip6fl_seq_next, | 653 | .next = ip6fl_seq_next, |
654 | .stop = ip6fl_seq_stop, | 654 | .stop = ip6fl_seq_stop, |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 4704b5fc3085..50d86e94d9ed 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -521,6 +521,10 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) | |||
521 | to->tc_index = from->tc_index; | 521 | to->tc_index = from->tc_index; |
522 | #endif | 522 | #endif |
523 | nf_copy(to, from); | 523 | nf_copy(to, from); |
524 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||
525 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | ||
526 | to->nf_trace = from->nf_trace; | ||
527 | #endif | ||
524 | skb_copy_secmark(to, from); | 528 | skb_copy_secmark(to, from); |
525 | } | 529 | } |
526 | 530 | ||
@@ -543,7 +547,7 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) | |||
543 | found_rhdr = 1; | 547 | found_rhdr = 1; |
544 | break; | 548 | break; |
545 | case NEXTHDR_DEST: | 549 | case NEXTHDR_DEST: |
546 | #ifdef CONFIG_IPV6_MIP6 | 550 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
547 | if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0) | 551 | if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0) |
548 | break; | 552 | break; |
549 | #endif | 553 | #endif |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index a0902fbdb4e1..281aee42d3f0 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -883,8 +883,8 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, | |||
883 | */ | 883 | */ |
884 | max_headroom += LL_RESERVED_SPACE(tdev); | 884 | max_headroom += LL_RESERVED_SPACE(tdev); |
885 | 885 | ||
886 | if (skb_headroom(skb) < max_headroom || | 886 | if (skb_headroom(skb) < max_headroom || skb_shared(skb) || |
887 | skb_cloned(skb) || skb_shared(skb)) { | 887 | (skb_cloned(skb) && !skb_clone_writable(skb, 0))) { |
888 | struct sk_buff *new_skb; | 888 | struct sk_buff *new_skb; |
889 | 889 | ||
890 | if (!(new_skb = skb_realloc_headroom(skb, max_headroom))) | 890 | if (!(new_skb = skb_realloc_headroom(skb, max_headroom))) |
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 1ee50b5782e1..473f165310ea 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c | |||
@@ -500,4 +500,4 @@ MODULE_LICENSE("GPL"); | |||
500 | MODULE_DESCRIPTION("IP Payload Compression Protocol (IPComp) for IPv6 - RFC3173"); | 500 | MODULE_DESCRIPTION("IP Payload Compression Protocol (IPComp) for IPv6 - RFC3173"); |
501 | MODULE_AUTHOR("Mitsuru KANDA <mk@linux-ipv6.org>"); | 501 | MODULE_AUTHOR("Mitsuru KANDA <mk@linux-ipv6.org>"); |
502 | 502 | ||
503 | 503 | MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_COMP); | |
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index aa3d07c52a8f..d6846393182d 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -123,7 +123,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features) | |||
123 | struct ipv6hdr *ipv6h; | 123 | struct ipv6hdr *ipv6h; |
124 | struct inet6_protocol *ops; | 124 | struct inet6_protocol *ops; |
125 | 125 | ||
126 | if (!(features & NETIF_F_HW_CSUM)) | 126 | if (!(features & NETIF_F_V6_CSUM)) |
127 | features &= ~NETIF_F_SG; | 127 | features &= ~NETIF_F_SG; |
128 | 128 | ||
129 | if (unlikely(skb_shinfo(skb)->gso_type & | 129 | if (unlikely(skb_shinfo(skb)->gso_type & |
@@ -336,16 +336,12 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
336 | break; | 336 | break; |
337 | 337 | ||
338 | case IPV6_RECVRTHDR: | 338 | case IPV6_RECVRTHDR: |
339 | if (val < 0 || val > 2) | 339 | np->rxopt.bits.srcrt = valbool; |
340 | goto e_inval; | ||
341 | np->rxopt.bits.srcrt = val; | ||
342 | retv = 0; | 340 | retv = 0; |
343 | break; | 341 | break; |
344 | 342 | ||
345 | case IPV6_2292RTHDR: | 343 | case IPV6_2292RTHDR: |
346 | if (val < 0 || val > 2) | 344 | np->rxopt.bits.osrcrt = valbool; |
347 | goto e_inval; | ||
348 | np->rxopt.bits.osrcrt = val; | ||
349 | retv = 0; | 345 | retv = 0; |
350 | break; | 346 | break; |
351 | 347 | ||
@@ -416,11 +412,10 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
416 | if (optname == IPV6_RTHDR && opt && opt->srcrt) { | 412 | if (optname == IPV6_RTHDR && opt && opt->srcrt) { |
417 | struct ipv6_rt_hdr *rthdr = opt->srcrt; | 413 | struct ipv6_rt_hdr *rthdr = opt->srcrt; |
418 | switch (rthdr->type) { | 414 | switch (rthdr->type) { |
419 | case IPV6_SRCRT_TYPE_0: | 415 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
420 | #ifdef CONFIG_IPV6_MIP6 | ||
421 | case IPV6_SRCRT_TYPE_2: | 416 | case IPV6_SRCRT_TYPE_2: |
422 | #endif | ||
423 | break; | 417 | break; |
418 | #endif | ||
424 | default: | 419 | default: |
425 | goto sticky_done; | 420 | goto sticky_done; |
426 | } | 421 | } |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 3e308fb41b49..ae9881832a7e 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -2423,7 +2423,7 @@ static int igmp6_mc_seq_show(struct seq_file *seq, void *v) | |||
2423 | return 0; | 2423 | return 0; |
2424 | } | 2424 | } |
2425 | 2425 | ||
2426 | static struct seq_operations igmp6_mc_seq_ops = { | 2426 | static const struct seq_operations igmp6_mc_seq_ops = { |
2427 | .start = igmp6_mc_seq_start, | 2427 | .start = igmp6_mc_seq_start, |
2428 | .next = igmp6_mc_seq_next, | 2428 | .next = igmp6_mc_seq_next, |
2429 | .stop = igmp6_mc_seq_stop, | 2429 | .stop = igmp6_mc_seq_stop, |
@@ -2597,7 +2597,7 @@ static int igmp6_mcf_seq_show(struct seq_file *seq, void *v) | |||
2597 | return 0; | 2597 | return 0; |
2598 | } | 2598 | } |
2599 | 2599 | ||
2600 | static struct seq_operations igmp6_mcf_seq_ops = { | 2600 | static const struct seq_operations igmp6_mcf_seq_ops = { |
2601 | .start = igmp6_mcf_seq_start, | 2601 | .start = igmp6_mcf_seq_start, |
2602 | .next = igmp6_mcf_seq_next, | 2602 | .next = igmp6_mcf_seq_next, |
2603 | .stop = igmp6_mcf_seq_stop, | 2603 | .stop = igmp6_mcf_seq_stop, |
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index 13b7160fb892..8a1399ce38ce 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <net/sock.h> | 30 | #include <net/sock.h> |
31 | #include <net/ipv6.h> | 31 | #include <net/ipv6.h> |
32 | #include <net/ip6_checksum.h> | 32 | #include <net/ip6_checksum.h> |
33 | #include <net/rawv6.h> | ||
33 | #include <net/xfrm.h> | 34 | #include <net/xfrm.h> |
34 | #include <net/mip6.h> | 35 | #include <net/mip6.h> |
35 | 36 | ||
@@ -86,7 +87,7 @@ static int mip6_mh_len(int type) | |||
86 | return len; | 87 | return len; |
87 | } | 88 | } |
88 | 89 | ||
89 | int mip6_mh_filter(struct sock *sk, struct sk_buff *skb) | 90 | static int mip6_mh_filter(struct sock *sk, struct sk_buff *skb) |
90 | { | 91 | { |
91 | struct ip6_mh *mh; | 92 | struct ip6_mh *mh; |
92 | 93 | ||
@@ -471,7 +472,7 @@ static struct xfrm_type mip6_rthdr_type = | |||
471 | .remote_addr = mip6_xfrm_addr, | 472 | .remote_addr = mip6_xfrm_addr, |
472 | }; | 473 | }; |
473 | 474 | ||
474 | int __init mip6_init(void) | 475 | static int __init mip6_init(void) |
475 | { | 476 | { |
476 | printk(KERN_INFO "Mobile IPv6\n"); | 477 | printk(KERN_INFO "Mobile IPv6\n"); |
477 | 478 | ||
@@ -483,18 +484,35 @@ int __init mip6_init(void) | |||
483 | printk(KERN_INFO "%s: can't add xfrm type(rthdr)\n", __FUNCTION__); | 484 | printk(KERN_INFO "%s: can't add xfrm type(rthdr)\n", __FUNCTION__); |
484 | goto mip6_rthdr_xfrm_fail; | 485 | goto mip6_rthdr_xfrm_fail; |
485 | } | 486 | } |
487 | if (rawv6_mh_filter_register(mip6_mh_filter) < 0) { | ||
488 | printk(KERN_INFO "%s: can't add rawv6 mh filter\n", __FUNCTION__); | ||
489 | goto mip6_rawv6_mh_fail; | ||
490 | } | ||
491 | |||
492 | |||
486 | return 0; | 493 | return 0; |
487 | 494 | ||
495 | mip6_rawv6_mh_fail: | ||
496 | xfrm_unregister_type(&mip6_rthdr_type, AF_INET6); | ||
488 | mip6_rthdr_xfrm_fail: | 497 | mip6_rthdr_xfrm_fail: |
489 | xfrm_unregister_type(&mip6_destopt_type, AF_INET6); | 498 | xfrm_unregister_type(&mip6_destopt_type, AF_INET6); |
490 | mip6_destopt_xfrm_fail: | 499 | mip6_destopt_xfrm_fail: |
491 | return -EAGAIN; | 500 | return -EAGAIN; |
492 | } | 501 | } |
493 | 502 | ||
494 | void __exit mip6_fini(void) | 503 | static void __exit mip6_fini(void) |
495 | { | 504 | { |
505 | if (rawv6_mh_filter_unregister(mip6_mh_filter) < 0) | ||
506 | printk(KERN_INFO "%s: can't remove rawv6 mh filter\n", __FUNCTION__); | ||
496 | if (xfrm_unregister_type(&mip6_rthdr_type, AF_INET6) < 0) | 507 | if (xfrm_unregister_type(&mip6_rthdr_type, AF_INET6) < 0) |
497 | printk(KERN_INFO "%s: can't remove xfrm type(rthdr)\n", __FUNCTION__); | 508 | printk(KERN_INFO "%s: can't remove xfrm type(rthdr)\n", __FUNCTION__); |
498 | if (xfrm_unregister_type(&mip6_destopt_type, AF_INET6) < 0) | 509 | if (xfrm_unregister_type(&mip6_destopt_type, AF_INET6) < 0) |
499 | printk(KERN_INFO "%s: can't remove xfrm type(destopt)\n", __FUNCTION__); | 510 | printk(KERN_INFO "%s: can't remove xfrm type(destopt)\n", __FUNCTION__); |
500 | } | 511 | } |
512 | |||
513 | module_init(mip6_init); | ||
514 | module_exit(mip6_fini); | ||
515 | |||
516 | MODULE_LICENSE("GPL"); | ||
517 | MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_DSTOPTS); | ||
518 | MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_ROUTING); | ||
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 9aa624026688..aeda617246b7 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -96,13 +96,13 @@ ip6t_ext_hdr(u8 nexthdr) | |||
96 | } | 96 | } |
97 | 97 | ||
98 | /* Returns whether matches rule or not. */ | 98 | /* Returns whether matches rule or not. */ |
99 | static inline int | 99 | static inline bool |
100 | ip6_packet_match(const struct sk_buff *skb, | 100 | ip6_packet_match(const struct sk_buff *skb, |
101 | const char *indev, | 101 | const char *indev, |
102 | const char *outdev, | 102 | const char *outdev, |
103 | const struct ip6t_ip6 *ip6info, | 103 | const struct ip6t_ip6 *ip6info, |
104 | unsigned int *protoff, | 104 | unsigned int *protoff, |
105 | int *fragoff, int *hotdrop) | 105 | int *fragoff, bool *hotdrop) |
106 | { | 106 | { |
107 | size_t i; | 107 | size_t i; |
108 | unsigned long ret; | 108 | unsigned long ret; |
@@ -122,7 +122,7 @@ ip6_packet_match(const struct sk_buff *skb, | |||
122 | dprintf("DST: %u. Mask: %u. Target: %u.%s\n", ip->daddr, | 122 | dprintf("DST: %u. Mask: %u. Target: %u.%s\n", ip->daddr, |
123 | ipinfo->dmsk.s_addr, ipinfo->dst.s_addr, | 123 | ipinfo->dmsk.s_addr, ipinfo->dst.s_addr, |
124 | ipinfo->invflags & IP6T_INV_DSTIP ? " (INV)" : "");*/ | 124 | ipinfo->invflags & IP6T_INV_DSTIP ? " (INV)" : "");*/ |
125 | return 0; | 125 | return false; |
126 | } | 126 | } |
127 | 127 | ||
128 | /* Look for ifname matches; this should unroll nicely. */ | 128 | /* Look for ifname matches; this should unroll nicely. */ |
@@ -136,7 +136,7 @@ ip6_packet_match(const struct sk_buff *skb, | |||
136 | dprintf("VIA in mismatch (%s vs %s).%s\n", | 136 | dprintf("VIA in mismatch (%s vs %s).%s\n", |
137 | indev, ip6info->iniface, | 137 | indev, ip6info->iniface, |
138 | ip6info->invflags&IP6T_INV_VIA_IN ?" (INV)":""); | 138 | ip6info->invflags&IP6T_INV_VIA_IN ?" (INV)":""); |
139 | return 0; | 139 | return false; |
140 | } | 140 | } |
141 | 141 | ||
142 | for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) { | 142 | for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) { |
@@ -149,7 +149,7 @@ ip6_packet_match(const struct sk_buff *skb, | |||
149 | dprintf("VIA out mismatch (%s vs %s).%s\n", | 149 | dprintf("VIA out mismatch (%s vs %s).%s\n", |
150 | outdev, ip6info->outiface, | 150 | outdev, ip6info->outiface, |
151 | ip6info->invflags&IP6T_INV_VIA_OUT ?" (INV)":""); | 151 | ip6info->invflags&IP6T_INV_VIA_OUT ?" (INV)":""); |
152 | return 0; | 152 | return false; |
153 | } | 153 | } |
154 | 154 | ||
155 | /* ... might want to do something with class and flowlabel here ... */ | 155 | /* ... might want to do something with class and flowlabel here ... */ |
@@ -162,8 +162,8 @@ ip6_packet_match(const struct sk_buff *skb, | |||
162 | protohdr = ipv6_find_hdr(skb, protoff, -1, &_frag_off); | 162 | protohdr = ipv6_find_hdr(skb, protoff, -1, &_frag_off); |
163 | if (protohdr < 0) { | 163 | if (protohdr < 0) { |
164 | if (_frag_off == 0) | 164 | if (_frag_off == 0) |
165 | *hotdrop = 1; | 165 | *hotdrop = true; |
166 | return 0; | 166 | return false; |
167 | } | 167 | } |
168 | *fragoff = _frag_off; | 168 | *fragoff = _frag_off; |
169 | 169 | ||
@@ -174,34 +174,34 @@ ip6_packet_match(const struct sk_buff *skb, | |||
174 | 174 | ||
175 | if (ip6info->proto == protohdr) { | 175 | if (ip6info->proto == protohdr) { |
176 | if(ip6info->invflags & IP6T_INV_PROTO) { | 176 | if(ip6info->invflags & IP6T_INV_PROTO) { |
177 | return 0; | 177 | return false; |
178 | } | 178 | } |
179 | return 1; | 179 | return true; |
180 | } | 180 | } |
181 | 181 | ||
182 | /* We need match for the '-p all', too! */ | 182 | /* We need match for the '-p all', too! */ |
183 | if ((ip6info->proto != 0) && | 183 | if ((ip6info->proto != 0) && |
184 | !(ip6info->invflags & IP6T_INV_PROTO)) | 184 | !(ip6info->invflags & IP6T_INV_PROTO)) |
185 | return 0; | 185 | return false; |
186 | } | 186 | } |
187 | return 1; | 187 | return true; |
188 | } | 188 | } |
189 | 189 | ||
190 | /* should be ip6 safe */ | 190 | /* should be ip6 safe */ |
191 | static inline int | 191 | static inline bool |
192 | ip6_checkentry(const struct ip6t_ip6 *ipv6) | 192 | ip6_checkentry(const struct ip6t_ip6 *ipv6) |
193 | { | 193 | { |
194 | if (ipv6->flags & ~IP6T_F_MASK) { | 194 | if (ipv6->flags & ~IP6T_F_MASK) { |
195 | duprintf("Unknown flag bits set: %08X\n", | 195 | duprintf("Unknown flag bits set: %08X\n", |
196 | ipv6->flags & ~IP6T_F_MASK); | 196 | ipv6->flags & ~IP6T_F_MASK); |
197 | return 0; | 197 | return false; |
198 | } | 198 | } |
199 | if (ipv6->invflags & ~IP6T_INV_MASK) { | 199 | if (ipv6->invflags & ~IP6T_INV_MASK) { |
200 | duprintf("Unknown invflag bits set: %08X\n", | 200 | duprintf("Unknown invflag bits set: %08X\n", |
201 | ipv6->invflags & ~IP6T_INV_MASK); | 201 | ipv6->invflags & ~IP6T_INV_MASK); |
202 | return 0; | 202 | return false; |
203 | } | 203 | } |
204 | return 1; | 204 | return true; |
205 | } | 205 | } |
206 | 206 | ||
207 | static unsigned int | 207 | static unsigned int |
@@ -219,20 +219,20 @@ ip6t_error(struct sk_buff **pskb, | |||
219 | } | 219 | } |
220 | 220 | ||
221 | static inline | 221 | static inline |
222 | int do_match(struct ip6t_entry_match *m, | 222 | bool do_match(struct ip6t_entry_match *m, |
223 | const struct sk_buff *skb, | 223 | const struct sk_buff *skb, |
224 | const struct net_device *in, | 224 | const struct net_device *in, |
225 | const struct net_device *out, | 225 | const struct net_device *out, |
226 | int offset, | 226 | int offset, |
227 | unsigned int protoff, | 227 | unsigned int protoff, |
228 | int *hotdrop) | 228 | bool *hotdrop) |
229 | { | 229 | { |
230 | /* Stop iteration if it doesn't match */ | 230 | /* Stop iteration if it doesn't match */ |
231 | if (!m->u.kernel.match->match(skb, in, out, m->u.kernel.match, m->data, | 231 | if (!m->u.kernel.match->match(skb, in, out, m->u.kernel.match, m->data, |
232 | offset, protoff, hotdrop)) | 232 | offset, protoff, hotdrop)) |
233 | return 1; | 233 | return true; |
234 | else | 234 | else |
235 | return 0; | 235 | return false; |
236 | } | 236 | } |
237 | 237 | ||
238 | static inline struct ip6t_entry * | 238 | static inline struct ip6t_entry * |
@@ -241,6 +241,113 @@ get_entry(void *base, unsigned int offset) | |||
241 | return (struct ip6t_entry *)(base + offset); | 241 | return (struct ip6t_entry *)(base + offset); |
242 | } | 242 | } |
243 | 243 | ||
244 | /* All zeroes == unconditional rule. */ | ||
245 | static inline int | ||
246 | unconditional(const struct ip6t_ip6 *ipv6) | ||
247 | { | ||
248 | unsigned int i; | ||
249 | |||
250 | for (i = 0; i < sizeof(*ipv6); i++) | ||
251 | if (((char *)ipv6)[i]) | ||
252 | break; | ||
253 | |||
254 | return (i == sizeof(*ipv6)); | ||
255 | } | ||
256 | |||
257 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||
258 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | ||
259 | /* This cries for unification! */ | ||
260 | static const char *hooknames[] = { | ||
261 | [NF_IP6_PRE_ROUTING] = "PREROUTING", | ||
262 | [NF_IP6_LOCAL_IN] = "INPUT", | ||
263 | [NF_IP6_FORWARD] = "FORWARD", | ||
264 | [NF_IP6_LOCAL_OUT] = "OUTPUT", | ||
265 | [NF_IP6_POST_ROUTING] = "POSTROUTING", | ||
266 | }; | ||
267 | |||
268 | enum nf_ip_trace_comments { | ||
269 | NF_IP6_TRACE_COMMENT_RULE, | ||
270 | NF_IP6_TRACE_COMMENT_RETURN, | ||
271 | NF_IP6_TRACE_COMMENT_POLICY, | ||
272 | }; | ||
273 | |||
274 | static const char *comments[] = { | ||
275 | [NF_IP6_TRACE_COMMENT_RULE] = "rule", | ||
276 | [NF_IP6_TRACE_COMMENT_RETURN] = "return", | ||
277 | [NF_IP6_TRACE_COMMENT_POLICY] = "policy", | ||
278 | }; | ||
279 | |||
280 | static struct nf_loginfo trace_loginfo = { | ||
281 | .type = NF_LOG_TYPE_LOG, | ||
282 | .u = { | ||
283 | .log = { | ||
284 | .level = 4, | ||
285 | .logflags = NF_LOG_MASK, | ||
286 | }, | ||
287 | }, | ||
288 | }; | ||
289 | |||
290 | static inline int | ||
291 | get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e, | ||
292 | char *hookname, char **chainname, | ||
293 | char **comment, unsigned int *rulenum) | ||
294 | { | ||
295 | struct ip6t_standard_target *t = (void *)ip6t_get_target(s); | ||
296 | |||
297 | if (strcmp(t->target.u.kernel.target->name, IP6T_ERROR_TARGET) == 0) { | ||
298 | /* Head of user chain: ERROR target with chainname */ | ||
299 | *chainname = t->target.data; | ||
300 | (*rulenum) = 0; | ||
301 | } else if (s == e) { | ||
302 | (*rulenum)++; | ||
303 | |||
304 | if (s->target_offset == sizeof(struct ip6t_entry) | ||
305 | && strcmp(t->target.u.kernel.target->name, | ||
306 | IP6T_STANDARD_TARGET) == 0 | ||
307 | && t->verdict < 0 | ||
308 | && unconditional(&s->ipv6)) { | ||
309 | /* Tail of chains: STANDARD target (return/policy) */ | ||
310 | *comment = *chainname == hookname | ||
311 | ? (char *)comments[NF_IP6_TRACE_COMMENT_POLICY] | ||
312 | : (char *)comments[NF_IP6_TRACE_COMMENT_RETURN]; | ||
313 | } | ||
314 | return 1; | ||
315 | } else | ||
316 | (*rulenum)++; | ||
317 | |||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | static void trace_packet(struct sk_buff *skb, | ||
322 | unsigned int hook, | ||
323 | const struct net_device *in, | ||
324 | const struct net_device *out, | ||
325 | char *tablename, | ||
326 | struct xt_table_info *private, | ||
327 | struct ip6t_entry *e) | ||
328 | { | ||
329 | void *table_base; | ||
330 | struct ip6t_entry *root; | ||
331 | char *hookname, *chainname, *comment; | ||
332 | unsigned int rulenum = 0; | ||
333 | |||
334 | table_base = (void *)private->entries[smp_processor_id()]; | ||
335 | root = get_entry(table_base, private->hook_entry[hook]); | ||
336 | |||
337 | hookname = chainname = (char *)hooknames[hook]; | ||
338 | comment = (char *)comments[NF_IP6_TRACE_COMMENT_RULE]; | ||
339 | |||
340 | IP6T_ENTRY_ITERATE(root, | ||
341 | private->size - private->hook_entry[hook], | ||
342 | get_chainname_rulenum, | ||
343 | e, hookname, &chainname, &comment, &rulenum); | ||
344 | |||
345 | nf_log_packet(AF_INET6, hook, skb, in, out, &trace_loginfo, | ||
346 | "TRACE: %s:%s:%s:%u ", | ||
347 | tablename, chainname, comment, rulenum); | ||
348 | } | ||
349 | #endif | ||
350 | |||
244 | /* Returns one of the generic firewall policies, like NF_ACCEPT. */ | 351 | /* Returns one of the generic firewall policies, like NF_ACCEPT. */ |
245 | unsigned int | 352 | unsigned int |
246 | ip6t_do_table(struct sk_buff **pskb, | 353 | ip6t_do_table(struct sk_buff **pskb, |
@@ -252,7 +359,7 @@ ip6t_do_table(struct sk_buff **pskb, | |||
252 | static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); | 359 | static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); |
253 | int offset = 0; | 360 | int offset = 0; |
254 | unsigned int protoff = 0; | 361 | unsigned int protoff = 0; |
255 | int hotdrop = 0; | 362 | bool hotdrop = false; |
256 | /* Initializing verdict to NF_DROP keeps gcc happy. */ | 363 | /* Initializing verdict to NF_DROP keeps gcc happy. */ |
257 | unsigned int verdict = NF_DROP; | 364 | unsigned int verdict = NF_DROP; |
258 | const char *indev, *outdev; | 365 | const char *indev, *outdev; |
@@ -298,6 +405,14 @@ ip6t_do_table(struct sk_buff **pskb, | |||
298 | 405 | ||
299 | t = ip6t_get_target(e); | 406 | t = ip6t_get_target(e); |
300 | IP_NF_ASSERT(t->u.kernel.target); | 407 | IP_NF_ASSERT(t->u.kernel.target); |
408 | |||
409 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||
410 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | ||
411 | /* The packet is traced: log it */ | ||
412 | if (unlikely((*pskb)->nf_trace)) | ||
413 | trace_packet(*pskb, hook, in, out, | ||
414 | table->name, private, e); | ||
415 | #endif | ||
301 | /* Standard target? */ | 416 | /* Standard target? */ |
302 | if (!t->u.kernel.target->target) { | 417 | if (!t->u.kernel.target->target) { |
303 | int v; | 418 | int v; |
@@ -377,19 +492,6 @@ ip6t_do_table(struct sk_buff **pskb, | |||
377 | #endif | 492 | #endif |
378 | } | 493 | } |
379 | 494 | ||
380 | /* All zeroes == unconditional rule. */ | ||
381 | static inline int | ||
382 | unconditional(const struct ip6t_ip6 *ipv6) | ||
383 | { | ||
384 | unsigned int i; | ||
385 | |||
386 | for (i = 0; i < sizeof(*ipv6); i++) | ||
387 | if (((char *)ipv6)[i]) | ||
388 | break; | ||
389 | |||
390 | return (i == sizeof(*ipv6)); | ||
391 | } | ||
392 | |||
393 | /* Figures out from what hook each rule can be called: returns 0 if | 495 | /* Figures out from what hook each rule can be called: returns 0 if |
394 | there are loops. Puts hook bitmask in comefrom. */ | 496 | there are loops. Puts hook bitmask in comefrom. */ |
395 | static int | 497 | static int |
@@ -1282,16 +1384,16 @@ void ip6t_unregister_table(struct xt_table *table) | |||
1282 | } | 1384 | } |
1283 | 1385 | ||
1284 | /* Returns 1 if the type and code is matched by the range, 0 otherwise */ | 1386 | /* Returns 1 if the type and code is matched by the range, 0 otherwise */ |
1285 | static inline int | 1387 | static inline bool |
1286 | icmp6_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code, | 1388 | icmp6_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code, |
1287 | u_int8_t type, u_int8_t code, | 1389 | u_int8_t type, u_int8_t code, |
1288 | int invert) | 1390 | bool invert) |
1289 | { | 1391 | { |
1290 | return (type == test_type && code >= min_code && code <= max_code) | 1392 | return (type == test_type && code >= min_code && code <= max_code) |
1291 | ^ invert; | 1393 | ^ invert; |
1292 | } | 1394 | } |
1293 | 1395 | ||
1294 | static int | 1396 | static bool |
1295 | icmp6_match(const struct sk_buff *skb, | 1397 | icmp6_match(const struct sk_buff *skb, |
1296 | const struct net_device *in, | 1398 | const struct net_device *in, |
1297 | const struct net_device *out, | 1399 | const struct net_device *out, |
@@ -1299,22 +1401,22 @@ icmp6_match(const struct sk_buff *skb, | |||
1299 | const void *matchinfo, | 1401 | const void *matchinfo, |
1300 | int offset, | 1402 | int offset, |
1301 | unsigned int protoff, | 1403 | unsigned int protoff, |
1302 | int *hotdrop) | 1404 | bool *hotdrop) |
1303 | { | 1405 | { |
1304 | struct icmp6hdr _icmp, *ic; | 1406 | struct icmp6hdr _icmp, *ic; |
1305 | const struct ip6t_icmp *icmpinfo = matchinfo; | 1407 | const struct ip6t_icmp *icmpinfo = matchinfo; |
1306 | 1408 | ||
1307 | /* Must not be a fragment. */ | 1409 | /* Must not be a fragment. */ |
1308 | if (offset) | 1410 | if (offset) |
1309 | return 0; | 1411 | return false; |
1310 | 1412 | ||
1311 | ic = skb_header_pointer(skb, protoff, sizeof(_icmp), &_icmp); | 1413 | ic = skb_header_pointer(skb, protoff, sizeof(_icmp), &_icmp); |
1312 | if (ic == NULL) { | 1414 | if (ic == NULL) { |
1313 | /* We've been asked to examine this packet, and we | 1415 | /* We've been asked to examine this packet, and we |
1314 | can't. Hence, no choice but to drop. */ | 1416 | can't. Hence, no choice but to drop. */ |
1315 | duprintf("Dropping evil ICMP tinygram.\n"); | 1417 | duprintf("Dropping evil ICMP tinygram.\n"); |
1316 | *hotdrop = 1; | 1418 | *hotdrop = true; |
1317 | return 0; | 1419 | return false; |
1318 | } | 1420 | } |
1319 | 1421 | ||
1320 | return icmp6_type_code_match(icmpinfo->type, | 1422 | return icmp6_type_code_match(icmpinfo->type, |
@@ -1325,7 +1427,7 @@ icmp6_match(const struct sk_buff *skb, | |||
1325 | } | 1427 | } |
1326 | 1428 | ||
1327 | /* Called when user tries to insert an entry of this type. */ | 1429 | /* Called when user tries to insert an entry of this type. */ |
1328 | static int | 1430 | static bool |
1329 | icmp6_checkentry(const char *tablename, | 1431 | icmp6_checkentry(const char *tablename, |
1330 | const void *entry, | 1432 | const void *entry, |
1331 | const struct xt_match *match, | 1433 | const struct xt_match *match, |
@@ -1339,13 +1441,13 @@ icmp6_checkentry(const char *tablename, | |||
1339 | } | 1441 | } |
1340 | 1442 | ||
1341 | /* The built-in targets: standard (NULL) and error. */ | 1443 | /* The built-in targets: standard (NULL) and error. */ |
1342 | static struct xt_target ip6t_standard_target = { | 1444 | static struct xt_target ip6t_standard_target __read_mostly = { |
1343 | .name = IP6T_STANDARD_TARGET, | 1445 | .name = IP6T_STANDARD_TARGET, |
1344 | .targetsize = sizeof(int), | 1446 | .targetsize = sizeof(int), |
1345 | .family = AF_INET6, | 1447 | .family = AF_INET6, |
1346 | }; | 1448 | }; |
1347 | 1449 | ||
1348 | static struct xt_target ip6t_error_target = { | 1450 | static struct xt_target ip6t_error_target __read_mostly = { |
1349 | .name = IP6T_ERROR_TARGET, | 1451 | .name = IP6T_ERROR_TARGET, |
1350 | .target = ip6t_error, | 1452 | .target = ip6t_error, |
1351 | .targetsize = IP6T_FUNCTION_MAXNAMELEN, | 1453 | .targetsize = IP6T_FUNCTION_MAXNAMELEN, |
@@ -1362,7 +1464,7 @@ static struct nf_sockopt_ops ip6t_sockopts = { | |||
1362 | .get = do_ip6t_get_ctl, | 1464 | .get = do_ip6t_get_ctl, |
1363 | }; | 1465 | }; |
1364 | 1466 | ||
1365 | static struct xt_match icmp6_matchstruct = { | 1467 | static struct xt_match icmp6_matchstruct __read_mostly = { |
1366 | .name = "icmp6", | 1468 | .name = "icmp6", |
1367 | .match = &icmp6_match, | 1469 | .match = &icmp6_match, |
1368 | .matchsize = sizeof(struct ip6t_icmp), | 1470 | .matchsize = sizeof(struct ip6t_icmp), |
@@ -1395,7 +1497,7 @@ static int __init ip6_tables_init(void) | |||
1395 | if (ret < 0) | 1497 | if (ret < 0) |
1396 | goto err5; | 1498 | goto err5; |
1397 | 1499 | ||
1398 | printk("ip6_tables: (C) 2000-2006 Netfilter Core Team\n"); | 1500 | printk(KERN_INFO "ip6_tables: (C) 2000-2006 Netfilter Core Team\n"); |
1399 | return 0; | 1501 | return 0; |
1400 | 1502 | ||
1401 | err5: | 1503 | err5: |
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c index 4115a576ba25..ad4d94310b87 100644 --- a/net/ipv6/netfilter/ip6t_HL.c +++ b/net/ipv6/netfilter/ip6t_HL.c | |||
@@ -58,28 +58,28 @@ static unsigned int ip6t_hl_target(struct sk_buff **pskb, | |||
58 | return XT_CONTINUE; | 58 | return XT_CONTINUE; |
59 | } | 59 | } |
60 | 60 | ||
61 | static int ip6t_hl_checkentry(const char *tablename, | 61 | static bool ip6t_hl_checkentry(const char *tablename, |
62 | const void *entry, | 62 | const void *entry, |
63 | const struct xt_target *target, | 63 | const struct xt_target *target, |
64 | void *targinfo, | 64 | void *targinfo, |
65 | unsigned int hook_mask) | 65 | unsigned int hook_mask) |
66 | { | 66 | { |
67 | struct ip6t_HL_info *info = targinfo; | 67 | const struct ip6t_HL_info *info = targinfo; |
68 | 68 | ||
69 | if (info->mode > IP6T_HL_MAXMODE) { | 69 | if (info->mode > IP6T_HL_MAXMODE) { |
70 | printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n", | 70 | printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n", |
71 | info->mode); | 71 | info->mode); |
72 | return 0; | 72 | return false; |
73 | } | 73 | } |
74 | if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) { | 74 | if (info->mode != IP6T_HL_SET && info->hop_limit == 0) { |
75 | printk(KERN_WARNING "ip6t_HL: increment/decrement doesn't " | 75 | printk(KERN_WARNING "ip6t_HL: increment/decrement doesn't " |
76 | "make sense with value 0\n"); | 76 | "make sense with value 0\n"); |
77 | return 0; | 77 | return false; |
78 | } | 78 | } |
79 | return 1; | 79 | return true; |
80 | } | 80 | } |
81 | 81 | ||
82 | static struct xt_target ip6t_HL = { | 82 | static struct xt_target ip6t_HL __read_mostly = { |
83 | .name = "HL", | 83 | .name = "HL", |
84 | .family = AF_INET6, | 84 | .family = AF_INET6, |
85 | .target = ip6t_hl_target, | 85 | .target = ip6t_hl_target, |
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index 5bb9cd349350..b05327ebd332 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c | |||
@@ -32,12 +32,6 @@ struct in_device; | |||
32 | #include <net/route.h> | 32 | #include <net/route.h> |
33 | #include <linux/netfilter_ipv6/ip6t_LOG.h> | 33 | #include <linux/netfilter_ipv6/ip6t_LOG.h> |
34 | 34 | ||
35 | #if 0 | ||
36 | #define DEBUGP printk | ||
37 | #else | ||
38 | #define DEBUGP(format, args...) | ||
39 | #endif | ||
40 | |||
41 | /* Use lock to serialize, so printks don't overlap */ | 35 | /* Use lock to serialize, so printks don't overlap */ |
42 | static DEFINE_SPINLOCK(log_lock); | 36 | static DEFINE_SPINLOCK(log_lock); |
43 | 37 | ||
@@ -48,7 +42,8 @@ static void dump_packet(const struct nf_loginfo *info, | |||
48 | { | 42 | { |
49 | u_int8_t currenthdr; | 43 | u_int8_t currenthdr; |
50 | int fragment; | 44 | int fragment; |
51 | struct ipv6hdr _ip6h, *ih; | 45 | struct ipv6hdr _ip6h; |
46 | const struct ipv6hdr *ih; | ||
52 | unsigned int ptr; | 47 | unsigned int ptr; |
53 | unsigned int hdrlen = 0; | 48 | unsigned int hdrlen = 0; |
54 | unsigned int logflags; | 49 | unsigned int logflags; |
@@ -78,7 +73,8 @@ static void dump_packet(const struct nf_loginfo *info, | |||
78 | ptr = ip6hoff + sizeof(struct ipv6hdr); | 73 | ptr = ip6hoff + sizeof(struct ipv6hdr); |
79 | currenthdr = ih->nexthdr; | 74 | currenthdr = ih->nexthdr; |
80 | while (currenthdr != NEXTHDR_NONE && ip6t_ext_hdr(currenthdr)) { | 75 | while (currenthdr != NEXTHDR_NONE && ip6t_ext_hdr(currenthdr)) { |
81 | struct ipv6_opt_hdr _hdr, *hp; | 76 | struct ipv6_opt_hdr _hdr; |
77 | const struct ipv6_opt_hdr *hp; | ||
82 | 78 | ||
83 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | 79 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); |
84 | if (hp == NULL) { | 80 | if (hp == NULL) { |
@@ -92,7 +88,8 @@ static void dump_packet(const struct nf_loginfo *info, | |||
92 | 88 | ||
93 | switch (currenthdr) { | 89 | switch (currenthdr) { |
94 | case IPPROTO_FRAGMENT: { | 90 | case IPPROTO_FRAGMENT: { |
95 | struct frag_hdr _fhdr, *fh; | 91 | struct frag_hdr _fhdr; |
92 | const struct frag_hdr *fh; | ||
96 | 93 | ||
97 | printk("FRAG:"); | 94 | printk("FRAG:"); |
98 | fh = skb_header_pointer(skb, ptr, sizeof(_fhdr), | 95 | fh = skb_header_pointer(skb, ptr, sizeof(_fhdr), |
@@ -131,7 +128,8 @@ static void dump_packet(const struct nf_loginfo *info, | |||
131 | /* Max Length */ | 128 | /* Max Length */ |
132 | case IPPROTO_AH: | 129 | case IPPROTO_AH: |
133 | if (logflags & IP6T_LOG_IPOPT) { | 130 | if (logflags & IP6T_LOG_IPOPT) { |
134 | struct ip_auth_hdr _ahdr, *ah; | 131 | struct ip_auth_hdr _ahdr; |
132 | const struct ip_auth_hdr *ah; | ||
135 | 133 | ||
136 | /* Max length: 3 "AH " */ | 134 | /* Max length: 3 "AH " */ |
137 | printk("AH "); | 135 | printk("AH "); |
@@ -162,7 +160,8 @@ static void dump_packet(const struct nf_loginfo *info, | |||
162 | break; | 160 | break; |
163 | case IPPROTO_ESP: | 161 | case IPPROTO_ESP: |
164 | if (logflags & IP6T_LOG_IPOPT) { | 162 | if (logflags & IP6T_LOG_IPOPT) { |
165 | struct ip_esp_hdr _esph, *eh; | 163 | struct ip_esp_hdr _esph; |
164 | const struct ip_esp_hdr *eh; | ||
166 | 165 | ||
167 | /* Max length: 4 "ESP " */ | 166 | /* Max length: 4 "ESP " */ |
168 | printk("ESP "); | 167 | printk("ESP "); |
@@ -202,7 +201,8 @@ static void dump_packet(const struct nf_loginfo *info, | |||
202 | 201 | ||
203 | switch (currenthdr) { | 202 | switch (currenthdr) { |
204 | case IPPROTO_TCP: { | 203 | case IPPROTO_TCP: { |
205 | struct tcphdr _tcph, *th; | 204 | struct tcphdr _tcph; |
205 | const struct tcphdr *th; | ||
206 | 206 | ||
207 | /* Max length: 10 "PROTO=TCP " */ | 207 | /* Max length: 10 "PROTO=TCP " */ |
208 | printk("PROTO=TCP "); | 208 | printk("PROTO=TCP "); |
@@ -250,7 +250,8 @@ static void dump_packet(const struct nf_loginfo *info, | |||
250 | 250 | ||
251 | if ((logflags & IP6T_LOG_TCPOPT) | 251 | if ((logflags & IP6T_LOG_TCPOPT) |
252 | && th->doff * 4 > sizeof(struct tcphdr)) { | 252 | && th->doff * 4 > sizeof(struct tcphdr)) { |
253 | u_int8_t _opt[60 - sizeof(struct tcphdr)], *op; | 253 | u_int8_t _opt[60 - sizeof(struct tcphdr)]; |
254 | const u_int8_t *op; | ||
254 | unsigned int i; | 255 | unsigned int i; |
255 | unsigned int optsize = th->doff * 4 | 256 | unsigned int optsize = th->doff * 4 |
256 | - sizeof(struct tcphdr); | 257 | - sizeof(struct tcphdr); |
@@ -273,7 +274,8 @@ static void dump_packet(const struct nf_loginfo *info, | |||
273 | } | 274 | } |
274 | case IPPROTO_UDP: | 275 | case IPPROTO_UDP: |
275 | case IPPROTO_UDPLITE: { | 276 | case IPPROTO_UDPLITE: { |
276 | struct udphdr _udph, *uh; | 277 | struct udphdr _udph; |
278 | const struct udphdr *uh; | ||
277 | 279 | ||
278 | if (currenthdr == IPPROTO_UDP) | 280 | if (currenthdr == IPPROTO_UDP) |
279 | /* Max length: 10 "PROTO=UDP " */ | 281 | /* Max length: 10 "PROTO=UDP " */ |
@@ -298,7 +300,8 @@ static void dump_packet(const struct nf_loginfo *info, | |||
298 | break; | 300 | break; |
299 | } | 301 | } |
300 | case IPPROTO_ICMPV6: { | 302 | case IPPROTO_ICMPV6: { |
301 | struct icmp6hdr _icmp6h, *ic; | 303 | struct icmp6hdr _icmp6h; |
304 | const struct icmp6hdr *ic; | ||
302 | 305 | ||
303 | /* Max length: 13 "PROTO=ICMPv6 " */ | 306 | /* Max length: 13 "PROTO=ICMPv6 " */ |
304 | printk("PROTO=ICMPv6 "); | 307 | printk("PROTO=ICMPv6 "); |
@@ -448,27 +451,27 @@ ip6t_log_target(struct sk_buff **pskb, | |||
448 | } | 451 | } |
449 | 452 | ||
450 | 453 | ||
451 | static int ip6t_log_checkentry(const char *tablename, | 454 | static bool ip6t_log_checkentry(const char *tablename, |
452 | const void *entry, | 455 | const void *entry, |
453 | const struct xt_target *target, | 456 | const struct xt_target *target, |
454 | void *targinfo, | 457 | void *targinfo, |
455 | unsigned int hook_mask) | 458 | unsigned int hook_mask) |
456 | { | 459 | { |
457 | const struct ip6t_log_info *loginfo = targinfo; | 460 | const struct ip6t_log_info *loginfo = targinfo; |
458 | 461 | ||
459 | if (loginfo->level >= 8) { | 462 | if (loginfo->level >= 8) { |
460 | DEBUGP("LOG: level %u >= 8\n", loginfo->level); | 463 | pr_debug("LOG: level %u >= 8\n", loginfo->level); |
461 | return 0; | 464 | return false; |
462 | } | 465 | } |
463 | if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') { | 466 | if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') { |
464 | DEBUGP("LOG: prefix term %i\n", | 467 | pr_debug("LOG: prefix term %i\n", |
465 | loginfo->prefix[sizeof(loginfo->prefix)-1]); | 468 | loginfo->prefix[sizeof(loginfo->prefix)-1]); |
466 | return 0; | 469 | return false; |
467 | } | 470 | } |
468 | return 1; | 471 | return true; |
469 | } | 472 | } |
470 | 473 | ||
471 | static struct xt_target ip6t_log_reg = { | 474 | static struct xt_target ip6t_log_reg __read_mostly = { |
472 | .name = "LOG", | 475 | .name = "LOG", |
473 | .family = AF_INET6, | 476 | .family = AF_INET6, |
474 | .target = ip6t_log_target, | 477 | .target = ip6t_log_target, |
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index cb3d2415a064..2f487cda3b6b 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c | |||
@@ -34,12 +34,6 @@ MODULE_AUTHOR("Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>"); | |||
34 | MODULE_DESCRIPTION("IP6 tables REJECT target module"); | 34 | MODULE_DESCRIPTION("IP6 tables REJECT target module"); |
35 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
36 | 36 | ||
37 | #if 0 | ||
38 | #define DEBUGP printk | ||
39 | #else | ||
40 | #define DEBUGP(format, args...) | ||
41 | #endif | ||
42 | |||
43 | /* Send RST reply */ | 37 | /* Send RST reply */ |
44 | static void send_reset(struct sk_buff *oldskb) | 38 | static void send_reset(struct sk_buff *oldskb) |
45 | { | 39 | { |
@@ -54,7 +48,7 @@ static void send_reset(struct sk_buff *oldskb) | |||
54 | 48 | ||
55 | if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) || | 49 | if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) || |
56 | (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) { | 50 | (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) { |
57 | DEBUGP("ip6t_REJECT: addr is not unicast.\n"); | 51 | pr_debug("ip6t_REJECT: addr is not unicast.\n"); |
58 | return; | 52 | return; |
59 | } | 53 | } |
60 | 54 | ||
@@ -62,16 +56,17 @@ static void send_reset(struct sk_buff *oldskb) | |||
62 | tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto); | 56 | tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto); |
63 | 57 | ||
64 | if ((tcphoff < 0) || (tcphoff > oldskb->len)) { | 58 | if ((tcphoff < 0) || (tcphoff > oldskb->len)) { |
65 | DEBUGP("ip6t_REJECT: Can't get TCP header.\n"); | 59 | pr_debug("ip6t_REJECT: Can't get TCP header.\n"); |
66 | return; | 60 | return; |
67 | } | 61 | } |
68 | 62 | ||
69 | otcplen = oldskb->len - tcphoff; | 63 | otcplen = oldskb->len - tcphoff; |
70 | 64 | ||
71 | /* IP header checks: fragment, too short. */ | 65 | /* IP header checks: fragment, too short. */ |
72 | if ((proto != IPPROTO_TCP) || (otcplen < sizeof(struct tcphdr))) { | 66 | if (proto != IPPROTO_TCP || otcplen < sizeof(struct tcphdr)) { |
73 | DEBUGP("ip6t_REJECT: proto(%d) != IPPROTO_TCP, or too short. otcplen = %d\n", | 67 | pr_debug("ip6t_REJECT: proto(%d) != IPPROTO_TCP, " |
74 | proto, otcplen); | 68 | "or too short. otcplen = %d\n", |
69 | proto, otcplen); | ||
75 | return; | 70 | return; |
76 | } | 71 | } |
77 | 72 | ||
@@ -80,14 +75,14 @@ static void send_reset(struct sk_buff *oldskb) | |||
80 | 75 | ||
81 | /* No RST for RST. */ | 76 | /* No RST for RST. */ |
82 | if (otcph.rst) { | 77 | if (otcph.rst) { |
83 | DEBUGP("ip6t_REJECT: RST is set\n"); | 78 | pr_debug("ip6t_REJECT: RST is set\n"); |
84 | return; | 79 | return; |
85 | } | 80 | } |
86 | 81 | ||
87 | /* Check checksum. */ | 82 | /* Check checksum. */ |
88 | if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP, | 83 | if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP, |
89 | skb_checksum(oldskb, tcphoff, otcplen, 0))) { | 84 | skb_checksum(oldskb, tcphoff, otcplen, 0))) { |
90 | DEBUGP("ip6t_REJECT: TCP checksum is invalid\n"); | 85 | pr_debug("ip6t_REJECT: TCP checksum is invalid\n"); |
91 | return; | 86 | return; |
92 | } | 87 | } |
93 | 88 | ||
@@ -159,7 +154,7 @@ static void send_reset(struct sk_buff *oldskb) | |||
159 | tcph->check = csum_ipv6_magic(&ipv6_hdr(nskb)->saddr, | 154 | tcph->check = csum_ipv6_magic(&ipv6_hdr(nskb)->saddr, |
160 | &ipv6_hdr(nskb)->daddr, | 155 | &ipv6_hdr(nskb)->daddr, |
161 | sizeof(struct tcphdr), IPPROTO_TCP, | 156 | sizeof(struct tcphdr), IPPROTO_TCP, |
162 | csum_partial((char *)tcph, | 157 | csum_partial(tcph, |
163 | sizeof(struct tcphdr), 0)); | 158 | sizeof(struct tcphdr), 0)); |
164 | 159 | ||
165 | nf_ct_attach(nskb, oldskb); | 160 | nf_ct_attach(nskb, oldskb); |
@@ -186,7 +181,7 @@ static unsigned int reject6_target(struct sk_buff **pskb, | |||
186 | { | 181 | { |
187 | const struct ip6t_reject_info *reject = targinfo; | 182 | const struct ip6t_reject_info *reject = targinfo; |
188 | 183 | ||
189 | DEBUGP(KERN_DEBUG "%s: medium point\n", __FUNCTION__); | 184 | pr_debug("%s: medium point\n", __FUNCTION__); |
190 | /* WARNING: This code causes reentry within ip6tables. | 185 | /* WARNING: This code causes reentry within ip6tables. |
191 | This means that the ip6tables jump stack is now crap. We | 186 | This means that the ip6tables jump stack is now crap. We |
192 | must return an absolute verdict. --RR */ | 187 | must return an absolute verdict. --RR */ |
@@ -221,30 +216,30 @@ static unsigned int reject6_target(struct sk_buff **pskb, | |||
221 | return NF_DROP; | 216 | return NF_DROP; |
222 | } | 217 | } |
223 | 218 | ||
224 | static int check(const char *tablename, | 219 | static bool check(const char *tablename, |
225 | const void *entry, | 220 | const void *entry, |
226 | const struct xt_target *target, | 221 | const struct xt_target *target, |
227 | void *targinfo, | 222 | void *targinfo, |
228 | unsigned int hook_mask) | 223 | unsigned int hook_mask) |
229 | { | 224 | { |
230 | const struct ip6t_reject_info *rejinfo = targinfo; | 225 | const struct ip6t_reject_info *rejinfo = targinfo; |
231 | const struct ip6t_entry *e = entry; | 226 | const struct ip6t_entry *e = entry; |
232 | 227 | ||
233 | if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) { | 228 | if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) { |
234 | printk("ip6t_REJECT: ECHOREPLY is not supported.\n"); | 229 | printk("ip6t_REJECT: ECHOREPLY is not supported.\n"); |
235 | return 0; | 230 | return false; |
236 | } else if (rejinfo->with == IP6T_TCP_RESET) { | 231 | } else if (rejinfo->with == IP6T_TCP_RESET) { |
237 | /* Must specify that it's a TCP packet */ | 232 | /* Must specify that it's a TCP packet */ |
238 | if (e->ipv6.proto != IPPROTO_TCP | 233 | if (e->ipv6.proto != IPPROTO_TCP |
239 | || (e->ipv6.invflags & XT_INV_PROTO)) { | 234 | || (e->ipv6.invflags & XT_INV_PROTO)) { |
240 | DEBUGP("ip6t_REJECT: TCP_RESET illegal for non-tcp\n"); | 235 | printk("ip6t_REJECT: TCP_RESET illegal for non-tcp\n"); |
241 | return 0; | 236 | return false; |
242 | } | 237 | } |
243 | } | 238 | } |
244 | return 1; | 239 | return true; |
245 | } | 240 | } |
246 | 241 | ||
247 | static struct xt_target ip6t_reject_reg = { | 242 | static struct xt_target ip6t_reject_reg __read_mostly = { |
248 | .name = "REJECT", | 243 | .name = "REJECT", |
249 | .family = AF_INET6, | 244 | .family = AF_INET6, |
250 | .target = reject6_target, | 245 | .target = reject6_target, |
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c index d3c154371b41..2a25fe25e0e0 100644 --- a/net/ipv6/netfilter/ip6t_ah.c +++ b/net/ipv6/netfilter/ip6t_ah.c | |||
@@ -23,25 +23,20 @@ MODULE_LICENSE("GPL"); | |||
23 | MODULE_DESCRIPTION("IPv6 AH match"); | 23 | MODULE_DESCRIPTION("IPv6 AH match"); |
24 | MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); | 24 | MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); |
25 | 25 | ||
26 | #if 0 | ||
27 | #define DEBUGP printk | ||
28 | #else | ||
29 | #define DEBUGP(format, args...) | ||
30 | #endif | ||
31 | |||
32 | /* Returns 1 if the spi is matched by the range, 0 otherwise */ | 26 | /* Returns 1 if the spi is matched by the range, 0 otherwise */ |
33 | static inline int | 27 | static inline bool |
34 | spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert) | 28 | spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert) |
35 | { | 29 | { |
36 | int r=0; | 30 | bool r; |
37 | DEBUGP("ah spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ', | 31 | |
38 | min,spi,max); | 32 | pr_debug("ah spi_match:%c 0x%x <= 0x%x <= 0x%x", |
33 | invert ? '!' : ' ', min, spi, max); | ||
39 | r = (spi >= min && spi <= max) ^ invert; | 34 | r = (spi >= min && spi <= max) ^ invert; |
40 | DEBUGP(" result %s\n",r? "PASS\n" : "FAILED\n"); | 35 | pr_debug(" result %s\n", r ? "PASS" : "FAILED"); |
41 | return r; | 36 | return r; |
42 | } | 37 | } |
43 | 38 | ||
44 | static int | 39 | static bool |
45 | match(const struct sk_buff *skb, | 40 | match(const struct sk_buff *skb, |
46 | const struct net_device *in, | 41 | const struct net_device *in, |
47 | const struct net_device *out, | 42 | const struct net_device *out, |
@@ -49,9 +44,10 @@ match(const struct sk_buff *skb, | |||
49 | const void *matchinfo, | 44 | const void *matchinfo, |
50 | int offset, | 45 | int offset, |
51 | unsigned int protoff, | 46 | unsigned int protoff, |
52 | int *hotdrop) | 47 | bool *hotdrop) |
53 | { | 48 | { |
54 | struct ip_auth_hdr *ah, _ah; | 49 | struct ip_auth_hdr _ah; |
50 | const struct ip_auth_hdr *ah; | ||
55 | const struct ip6t_ah *ahinfo = matchinfo; | 51 | const struct ip6t_ah *ahinfo = matchinfo; |
56 | unsigned int ptr; | 52 | unsigned int ptr; |
57 | unsigned int hdrlen = 0; | 53 | unsigned int hdrlen = 0; |
@@ -60,40 +56,40 @@ match(const struct sk_buff *skb, | |||
60 | err = ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL); | 56 | err = ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL); |
61 | if (err < 0) { | 57 | if (err < 0) { |
62 | if (err != -ENOENT) | 58 | if (err != -ENOENT) |
63 | *hotdrop = 1; | 59 | *hotdrop = true; |
64 | return 0; | 60 | return false; |
65 | } | 61 | } |
66 | 62 | ||
67 | ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah); | 63 | ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah); |
68 | if (ah == NULL) { | 64 | if (ah == NULL) { |
69 | *hotdrop = 1; | 65 | *hotdrop = true; |
70 | return 0; | 66 | return false; |
71 | } | 67 | } |
72 | 68 | ||
73 | hdrlen = (ah->hdrlen + 2) << 2; | 69 | hdrlen = (ah->hdrlen + 2) << 2; |
74 | 70 | ||
75 | DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen); | 71 | pr_debug("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen); |
76 | DEBUGP("RES %04X ", ah->reserved); | 72 | pr_debug("RES %04X ", ah->reserved); |
77 | DEBUGP("SPI %u %08X\n", ntohl(ah->spi), ntohl(ah->spi)); | 73 | pr_debug("SPI %u %08X\n", ntohl(ah->spi), ntohl(ah->spi)); |
78 | 74 | ||
79 | DEBUGP("IPv6 AH spi %02X ", | 75 | pr_debug("IPv6 AH spi %02X ", |
80 | (spi_match(ahinfo->spis[0], ahinfo->spis[1], | 76 | spi_match(ahinfo->spis[0], ahinfo->spis[1], |
81 | ntohl(ah->spi), | 77 | ntohl(ah->spi), |
82 | !!(ahinfo->invflags & IP6T_AH_INV_SPI)))); | 78 | !!(ahinfo->invflags & IP6T_AH_INV_SPI))); |
83 | DEBUGP("len %02X %04X %02X ", | 79 | pr_debug("len %02X %04X %02X ", |
84 | ahinfo->hdrlen, hdrlen, | 80 | ahinfo->hdrlen, hdrlen, |
85 | (!ahinfo->hdrlen || | 81 | (!ahinfo->hdrlen || |
86 | (ahinfo->hdrlen == hdrlen) ^ | 82 | (ahinfo->hdrlen == hdrlen) ^ |
87 | !!(ahinfo->invflags & IP6T_AH_INV_LEN))); | 83 | !!(ahinfo->invflags & IP6T_AH_INV_LEN))); |
88 | DEBUGP("res %02X %04X %02X\n", | 84 | pr_debug("res %02X %04X %02X\n", |
89 | ahinfo->hdrres, ah->reserved, | 85 | ahinfo->hdrres, ah->reserved, |
90 | !(ahinfo->hdrres && ah->reserved)); | 86 | !(ahinfo->hdrres && ah->reserved)); |
91 | 87 | ||
92 | return (ah != NULL) | 88 | return (ah != NULL) |
93 | && | 89 | && |
94 | (spi_match(ahinfo->spis[0], ahinfo->spis[1], | 90 | spi_match(ahinfo->spis[0], ahinfo->spis[1], |
95 | ntohl(ah->spi), | 91 | ntohl(ah->spi), |
96 | !!(ahinfo->invflags & IP6T_AH_INV_SPI))) | 92 | !!(ahinfo->invflags & IP6T_AH_INV_SPI)) |
97 | && | 93 | && |
98 | (!ahinfo->hdrlen || | 94 | (!ahinfo->hdrlen || |
99 | (ahinfo->hdrlen == hdrlen) ^ | 95 | (ahinfo->hdrlen == hdrlen) ^ |
@@ -103,7 +99,7 @@ match(const struct sk_buff *skb, | |||
103 | } | 99 | } |
104 | 100 | ||
105 | /* Called when user tries to insert an entry of this type. */ | 101 | /* Called when user tries to insert an entry of this type. */ |
106 | static int | 102 | static bool |
107 | checkentry(const char *tablename, | 103 | checkentry(const char *tablename, |
108 | const void *entry, | 104 | const void *entry, |
109 | const struct xt_match *match, | 105 | const struct xt_match *match, |
@@ -113,13 +109,13 @@ checkentry(const char *tablename, | |||
113 | const struct ip6t_ah *ahinfo = matchinfo; | 109 | const struct ip6t_ah *ahinfo = matchinfo; |
114 | 110 | ||
115 | if (ahinfo->invflags & ~IP6T_AH_INV_MASK) { | 111 | if (ahinfo->invflags & ~IP6T_AH_INV_MASK) { |
116 | DEBUGP("ip6t_ah: unknown flags %X\n", ahinfo->invflags); | 112 | pr_debug("ip6t_ah: unknown flags %X\n", ahinfo->invflags); |
117 | return 0; | 113 | return false; |
118 | } | 114 | } |
119 | return 1; | 115 | return true; |
120 | } | 116 | } |
121 | 117 | ||
122 | static struct xt_match ah_match = { | 118 | static struct xt_match ah_match __read_mostly = { |
123 | .name = "ah", | 119 | .name = "ah", |
124 | .family = AF_INET6, | 120 | .family = AF_INET6, |
125 | .match = match, | 121 | .match = match, |
diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c index 0f3dd932f0a6..34ba150bfe5d 100644 --- a/net/ipv6/netfilter/ip6t_eui64.c +++ b/net/ipv6/netfilter/ip6t_eui64.c | |||
@@ -19,7 +19,7 @@ MODULE_DESCRIPTION("IPv6 EUI64 address checking match"); | |||
19 | MODULE_LICENSE("GPL"); | 19 | MODULE_LICENSE("GPL"); |
20 | MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); | 20 | MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); |
21 | 21 | ||
22 | static int | 22 | static bool |
23 | match(const struct sk_buff *skb, | 23 | match(const struct sk_buff *skb, |
24 | const struct net_device *in, | 24 | const struct net_device *in, |
25 | const struct net_device *out, | 25 | const struct net_device *out, |
@@ -27,16 +27,16 @@ match(const struct sk_buff *skb, | |||
27 | const void *matchinfo, | 27 | const void *matchinfo, |
28 | int offset, | 28 | int offset, |
29 | unsigned int protoff, | 29 | unsigned int protoff, |
30 | int *hotdrop) | 30 | bool *hotdrop) |
31 | { | 31 | { |
32 | unsigned char eui64[8]; | 32 | unsigned char eui64[8]; |
33 | int i = 0; | 33 | int i = 0; |
34 | 34 | ||
35 | if (!(skb_mac_header(skb) >= skb->head && | 35 | if (!(skb_mac_header(skb) >= skb->head && |
36 | (skb_mac_header(skb) + ETH_HLEN) <= skb->data) && | 36 | skb_mac_header(skb) + ETH_HLEN <= skb->data) && |
37 | offset != 0) { | 37 | offset != 0) { |
38 | *hotdrop = 1; | 38 | *hotdrop = true; |
39 | return 0; | 39 | return false; |
40 | } | 40 | } |
41 | 41 | ||
42 | memset(eui64, 0, sizeof(eui64)); | 42 | memset(eui64, 0, sizeof(eui64)); |
@@ -50,19 +50,19 @@ match(const struct sk_buff *skb, | |||
50 | eui64[0] |= 0x02; | 50 | eui64[0] |= 0x02; |
51 | 51 | ||
52 | i = 0; | 52 | i = 0; |
53 | while ((ipv6_hdr(skb)->saddr.s6_addr[8 + i] == eui64[i]) | 53 | while (ipv6_hdr(skb)->saddr.s6_addr[8 + i] == eui64[i] |
54 | && (i < 8)) | 54 | && i < 8) |
55 | i++; | 55 | i++; |
56 | 56 | ||
57 | if (i == 8) | 57 | if (i == 8) |
58 | return 1; | 58 | return true; |
59 | } | 59 | } |
60 | } | 60 | } |
61 | 61 | ||
62 | return 0; | 62 | return false; |
63 | } | 63 | } |
64 | 64 | ||
65 | static struct xt_match eui64_match = { | 65 | static struct xt_match eui64_match __read_mostly = { |
66 | .name = "eui64", | 66 | .name = "eui64", |
67 | .family = AF_INET6, | 67 | .family = AF_INET6, |
68 | .match = match, | 68 | .match = match, |
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c index 5a5da71321b6..968aeba02073 100644 --- a/net/ipv6/netfilter/ip6t_frag.c +++ b/net/ipv6/netfilter/ip6t_frag.c | |||
@@ -22,25 +22,19 @@ MODULE_LICENSE("GPL"); | |||
22 | MODULE_DESCRIPTION("IPv6 FRAG match"); | 22 | MODULE_DESCRIPTION("IPv6 FRAG match"); |
23 | MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); | 23 | MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); |
24 | 24 | ||
25 | #if 0 | ||
26 | #define DEBUGP printk | ||
27 | #else | ||
28 | #define DEBUGP(format, args...) | ||
29 | #endif | ||
30 | |||
31 | /* Returns 1 if the id is matched by the range, 0 otherwise */ | 25 | /* Returns 1 if the id is matched by the range, 0 otherwise */ |
32 | static inline int | 26 | static inline bool |
33 | id_match(u_int32_t min, u_int32_t max, u_int32_t id, int invert) | 27 | id_match(u_int32_t min, u_int32_t max, u_int32_t id, bool invert) |
34 | { | 28 | { |
35 | int r = 0; | 29 | bool r; |
36 | DEBUGP("frag id_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ', | 30 | pr_debug("frag id_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ', |
37 | min, id, max); | 31 | min, id, max); |
38 | r = (id >= min && id <= max) ^ invert; | 32 | r = (id >= min && id <= max) ^ invert; |
39 | DEBUGP(" result %s\n", r ? "PASS" : "FAILED"); | 33 | pr_debug(" result %s\n", r ? "PASS" : "FAILED"); |
40 | return r; | 34 | return r; |
41 | } | 35 | } |
42 | 36 | ||
43 | static int | 37 | static bool |
44 | match(const struct sk_buff *skb, | 38 | match(const struct sk_buff *skb, |
45 | const struct net_device *in, | 39 | const struct net_device *in, |
46 | const struct net_device *out, | 40 | const struct net_device *out, |
@@ -48,9 +42,10 @@ match(const struct sk_buff *skb, | |||
48 | const void *matchinfo, | 42 | const void *matchinfo, |
49 | int offset, | 43 | int offset, |
50 | unsigned int protoff, | 44 | unsigned int protoff, |
51 | int *hotdrop) | 45 | bool *hotdrop) |
52 | { | 46 | { |
53 | struct frag_hdr _frag, *fh; | 47 | struct frag_hdr _frag; |
48 | const struct frag_hdr *fh; | ||
54 | const struct ip6t_frag *fraginfo = matchinfo; | 49 | const struct ip6t_frag *fraginfo = matchinfo; |
55 | unsigned int ptr; | 50 | unsigned int ptr; |
56 | int err; | 51 | int err; |
@@ -58,53 +53,53 @@ match(const struct sk_buff *skb, | |||
58 | err = ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL); | 53 | err = ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL); |
59 | if (err < 0) { | 54 | if (err < 0) { |
60 | if (err != -ENOENT) | 55 | if (err != -ENOENT) |
61 | *hotdrop = 1; | 56 | *hotdrop = true; |
62 | return 0; | 57 | return false; |
63 | } | 58 | } |
64 | 59 | ||
65 | fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag); | 60 | fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag); |
66 | if (fh == NULL) { | 61 | if (fh == NULL) { |
67 | *hotdrop = 1; | 62 | *hotdrop = true; |
68 | return 0; | 63 | return false; |
69 | } | 64 | } |
70 | 65 | ||
71 | DEBUGP("INFO %04X ", fh->frag_off); | 66 | pr_debug("INFO %04X ", fh->frag_off); |
72 | DEBUGP("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7); | 67 | pr_debug("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7); |
73 | DEBUGP("RES %02X %04X", fh->reserved, ntohs(fh->frag_off) & 0x6); | 68 | pr_debug("RES %02X %04X", fh->reserved, ntohs(fh->frag_off) & 0x6); |
74 | DEBUGP("MF %04X ", fh->frag_off & htons(IP6_MF)); | 69 | pr_debug("MF %04X ", fh->frag_off & htons(IP6_MF)); |
75 | DEBUGP("ID %u %08X\n", ntohl(fh->identification), | 70 | pr_debug("ID %u %08X\n", ntohl(fh->identification), |
76 | ntohl(fh->identification)); | 71 | ntohl(fh->identification)); |
77 | 72 | ||
78 | DEBUGP("IPv6 FRAG id %02X ", | 73 | pr_debug("IPv6 FRAG id %02X ", |
79 | (id_match(fraginfo->ids[0], fraginfo->ids[1], | 74 | id_match(fraginfo->ids[0], fraginfo->ids[1], |
80 | ntohl(fh->identification), | 75 | ntohl(fh->identification), |
81 | !!(fraginfo->invflags & IP6T_FRAG_INV_IDS)))); | 76 | !!(fraginfo->invflags & IP6T_FRAG_INV_IDS))); |
82 | DEBUGP("res %02X %02X%04X %02X ", | 77 | pr_debug("res %02X %02X%04X %02X ", |
83 | (fraginfo->flags & IP6T_FRAG_RES), fh->reserved, | 78 | fraginfo->flags & IP6T_FRAG_RES, fh->reserved, |
84 | ntohs(fh->frag_off) & 0x6, | 79 | ntohs(fh->frag_off) & 0x6, |
85 | !((fraginfo->flags & IP6T_FRAG_RES) | 80 | !((fraginfo->flags & IP6T_FRAG_RES) |
86 | && (fh->reserved || (ntohs(fh->frag_off) & 0x06)))); | 81 | && (fh->reserved || (ntohs(fh->frag_off) & 0x06)))); |
87 | DEBUGP("first %02X %02X %02X ", | 82 | pr_debug("first %02X %02X %02X ", |
88 | (fraginfo->flags & IP6T_FRAG_FST), | 83 | fraginfo->flags & IP6T_FRAG_FST, |
89 | ntohs(fh->frag_off) & ~0x7, | 84 | ntohs(fh->frag_off) & ~0x7, |
90 | !((fraginfo->flags & IP6T_FRAG_FST) | 85 | !((fraginfo->flags & IP6T_FRAG_FST) |
91 | && (ntohs(fh->frag_off) & ~0x7))); | 86 | && (ntohs(fh->frag_off) & ~0x7))); |
92 | DEBUGP("mf %02X %02X %02X ", | 87 | pr_debug("mf %02X %02X %02X ", |
93 | (fraginfo->flags & IP6T_FRAG_MF), | 88 | fraginfo->flags & IP6T_FRAG_MF, |
94 | ntohs(fh->frag_off) & IP6_MF, | 89 | ntohs(fh->frag_off) & IP6_MF, |
95 | !((fraginfo->flags & IP6T_FRAG_MF) | 90 | !((fraginfo->flags & IP6T_FRAG_MF) |
96 | && !((ntohs(fh->frag_off) & IP6_MF)))); | 91 | && !((ntohs(fh->frag_off) & IP6_MF)))); |
97 | DEBUGP("last %02X %02X %02X\n", | 92 | pr_debug("last %02X %02X %02X\n", |
98 | (fraginfo->flags & IP6T_FRAG_NMF), | 93 | fraginfo->flags & IP6T_FRAG_NMF, |
99 | ntohs(fh->frag_off) & IP6_MF, | 94 | ntohs(fh->frag_off) & IP6_MF, |
100 | !((fraginfo->flags & IP6T_FRAG_NMF) | 95 | !((fraginfo->flags & IP6T_FRAG_NMF) |
101 | && (ntohs(fh->frag_off) & IP6_MF))); | 96 | && (ntohs(fh->frag_off) & IP6_MF))); |
102 | 97 | ||
103 | return (fh != NULL) | 98 | return (fh != NULL) |
104 | && | 99 | && |
105 | (id_match(fraginfo->ids[0], fraginfo->ids[1], | 100 | id_match(fraginfo->ids[0], fraginfo->ids[1], |
106 | ntohl(fh->identification), | 101 | ntohl(fh->identification), |
107 | !!(fraginfo->invflags & IP6T_FRAG_INV_IDS))) | 102 | !!(fraginfo->invflags & IP6T_FRAG_INV_IDS)) |
108 | && | 103 | && |
109 | !((fraginfo->flags & IP6T_FRAG_RES) | 104 | !((fraginfo->flags & IP6T_FRAG_RES) |
110 | && (fh->reserved || (ntohs(fh->frag_off) & 0x6))) | 105 | && (fh->reserved || (ntohs(fh->frag_off) & 0x6))) |
@@ -120,7 +115,7 @@ match(const struct sk_buff *skb, | |||
120 | } | 115 | } |
121 | 116 | ||
122 | /* Called when user tries to insert an entry of this type. */ | 117 | /* Called when user tries to insert an entry of this type. */ |
123 | static int | 118 | static bool |
124 | checkentry(const char *tablename, | 119 | checkentry(const char *tablename, |
125 | const void *ip, | 120 | const void *ip, |
126 | const struct xt_match *match, | 121 | const struct xt_match *match, |
@@ -130,13 +125,13 @@ checkentry(const char *tablename, | |||
130 | const struct ip6t_frag *fraginfo = matchinfo; | 125 | const struct ip6t_frag *fraginfo = matchinfo; |
131 | 126 | ||
132 | if (fraginfo->invflags & ~IP6T_FRAG_INV_MASK) { | 127 | if (fraginfo->invflags & ~IP6T_FRAG_INV_MASK) { |
133 | DEBUGP("ip6t_frag: unknown flags %X\n", fraginfo->invflags); | 128 | pr_debug("ip6t_frag: unknown flags %X\n", fraginfo->invflags); |
134 | return 0; | 129 | return false; |
135 | } | 130 | } |
136 | return 1; | 131 | return true; |
137 | } | 132 | } |
138 | 133 | ||
139 | static struct xt_match frag_match = { | 134 | static struct xt_match frag_match __read_mostly = { |
140 | .name = "frag", | 135 | .name = "frag", |
141 | .family = AF_INET6, | 136 | .family = AF_INET6, |
142 | .match = match, | 137 | .match = match, |
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c index d2373c7cd354..e6ca6018b1ea 100644 --- a/net/ipv6/netfilter/ip6t_hbh.c +++ b/net/ipv6/netfilter/ip6t_hbh.c | |||
@@ -25,12 +25,6 @@ MODULE_DESCRIPTION("IPv6 opts match"); | |||
25 | MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); | 25 | MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); |
26 | MODULE_ALIAS("ip6t_dst"); | 26 | MODULE_ALIAS("ip6t_dst"); |
27 | 27 | ||
28 | #if 0 | ||
29 | #define DEBUGP printk | ||
30 | #else | ||
31 | #define DEBUGP(format, args...) | ||
32 | #endif | ||
33 | |||
34 | /* | 28 | /* |
35 | * (Type & 0xC0) >> 6 | 29 | * (Type & 0xC0) >> 6 |
36 | * 0 -> ignorable | 30 | * 0 -> ignorable |
@@ -47,7 +41,7 @@ MODULE_ALIAS("ip6t_dst"); | |||
47 | * 5 -> RTALERT 2 x x | 41 | * 5 -> RTALERT 2 x x |
48 | */ | 42 | */ |
49 | 43 | ||
50 | static int | 44 | static bool |
51 | match(const struct sk_buff *skb, | 45 | match(const struct sk_buff *skb, |
52 | const struct net_device *in, | 46 | const struct net_device *in, |
53 | const struct net_device *out, | 47 | const struct net_device *out, |
@@ -55,45 +49,48 @@ match(const struct sk_buff *skb, | |||
55 | const void *matchinfo, | 49 | const void *matchinfo, |
56 | int offset, | 50 | int offset, |
57 | unsigned int protoff, | 51 | unsigned int protoff, |
58 | int *hotdrop) | 52 | bool *hotdrop) |
59 | { | 53 | { |
60 | struct ipv6_opt_hdr _optsh, *oh; | 54 | struct ipv6_opt_hdr _optsh; |
55 | const struct ipv6_opt_hdr *oh; | ||
61 | const struct ip6t_opts *optinfo = matchinfo; | 56 | const struct ip6t_opts *optinfo = matchinfo; |
62 | unsigned int temp; | 57 | unsigned int temp; |
63 | unsigned int ptr; | 58 | unsigned int ptr; |
64 | unsigned int hdrlen = 0; | 59 | unsigned int hdrlen = 0; |
65 | unsigned int ret = 0; | 60 | bool ret = false; |
66 | u8 _opttype, *tp = NULL; | 61 | u8 _opttype; |
67 | u8 _optlen, *lp = NULL; | 62 | u8 _optlen; |
63 | const u_int8_t *tp = NULL; | ||
64 | const u_int8_t *lp = NULL; | ||
68 | unsigned int optlen; | 65 | unsigned int optlen; |
69 | int err; | 66 | int err; |
70 | 67 | ||
71 | err = ipv6_find_hdr(skb, &ptr, match->data, NULL); | 68 | err = ipv6_find_hdr(skb, &ptr, match->data, NULL); |
72 | if (err < 0) { | 69 | if (err < 0) { |
73 | if (err != -ENOENT) | 70 | if (err != -ENOENT) |
74 | *hotdrop = 1; | 71 | *hotdrop = true; |
75 | return 0; | 72 | return false; |
76 | } | 73 | } |
77 | 74 | ||
78 | oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); | 75 | oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); |
79 | if (oh == NULL) { | 76 | if (oh == NULL) { |
80 | *hotdrop = 1; | 77 | *hotdrop = true; |
81 | return 0; | 78 | return false; |
82 | } | 79 | } |
83 | 80 | ||
84 | hdrlen = ipv6_optlen(oh); | 81 | hdrlen = ipv6_optlen(oh); |
85 | if (skb->len - ptr < hdrlen) { | 82 | if (skb->len - ptr < hdrlen) { |
86 | /* Packet smaller than it's length field */ | 83 | /* Packet smaller than it's length field */ |
87 | return 0; | 84 | return false; |
88 | } | 85 | } |
89 | 86 | ||
90 | DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); | 87 | pr_debug("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); |
91 | 88 | ||
92 | DEBUGP("len %02X %04X %02X ", | 89 | pr_debug("len %02X %04X %02X ", |
93 | optinfo->hdrlen, hdrlen, | 90 | optinfo->hdrlen, hdrlen, |
94 | (!(optinfo->flags & IP6T_OPTS_LEN) || | 91 | (!(optinfo->flags & IP6T_OPTS_LEN) || |
95 | ((optinfo->hdrlen == hdrlen) ^ | 92 | ((optinfo->hdrlen == hdrlen) ^ |
96 | !!(optinfo->invflags & IP6T_OPTS_INV_LEN)))); | 93 | !!(optinfo->invflags & IP6T_OPTS_INV_LEN)))); |
97 | 94 | ||
98 | ret = (oh != NULL) && | 95 | ret = (oh != NULL) && |
99 | (!(optinfo->flags & IP6T_OPTS_LEN) || | 96 | (!(optinfo->flags & IP6T_OPTS_LEN) || |
@@ -105,10 +102,10 @@ match(const struct sk_buff *skb, | |||
105 | if (!(optinfo->flags & IP6T_OPTS_OPTS)) { | 102 | if (!(optinfo->flags & IP6T_OPTS_OPTS)) { |
106 | return ret; | 103 | return ret; |
107 | } else if (optinfo->flags & IP6T_OPTS_NSTRICT) { | 104 | } else if (optinfo->flags & IP6T_OPTS_NSTRICT) { |
108 | DEBUGP("Not strict - not implemented"); | 105 | pr_debug("Not strict - not implemented"); |
109 | } else { | 106 | } else { |
110 | DEBUGP("Strict "); | 107 | pr_debug("Strict "); |
111 | DEBUGP("#%d ", optinfo->optsnr); | 108 | pr_debug("#%d ", optinfo->optsnr); |
112 | for (temp = 0; temp < optinfo->optsnr; temp++) { | 109 | for (temp = 0; temp < optinfo->optsnr; temp++) { |
113 | /* type field exists ? */ | 110 | /* type field exists ? */ |
114 | if (hdrlen < 1) | 111 | if (hdrlen < 1) |
@@ -120,12 +117,11 @@ match(const struct sk_buff *skb, | |||
120 | 117 | ||
121 | /* Type check */ | 118 | /* Type check */ |
122 | if (*tp != (optinfo->opts[temp] & 0xFF00) >> 8) { | 119 | if (*tp != (optinfo->opts[temp] & 0xFF00) >> 8) { |
123 | DEBUGP("Tbad %02X %02X\n", | 120 | pr_debug("Tbad %02X %02X\n", *tp, |
124 | *tp, | 121 | (optinfo->opts[temp] & 0xFF00) >> 8); |
125 | (optinfo->opts[temp] & 0xFF00) >> 8); | 122 | return false; |
126 | return 0; | ||
127 | } else { | 123 | } else { |
128 | DEBUGP("Tok "); | 124 | pr_debug("Tok "); |
129 | } | 125 | } |
130 | /* Length check */ | 126 | /* Length check */ |
131 | if (*tp) { | 127 | if (*tp) { |
@@ -142,23 +138,23 @@ match(const struct sk_buff *skb, | |||
142 | spec_len = optinfo->opts[temp] & 0x00FF; | 138 | spec_len = optinfo->opts[temp] & 0x00FF; |
143 | 139 | ||
144 | if (spec_len != 0x00FF && spec_len != *lp) { | 140 | if (spec_len != 0x00FF && spec_len != *lp) { |
145 | DEBUGP("Lbad %02X %04X\n", *lp, | 141 | pr_debug("Lbad %02X %04X\n", *lp, |
146 | spec_len); | 142 | spec_len); |
147 | return 0; | 143 | return false; |
148 | } | 144 | } |
149 | DEBUGP("Lok "); | 145 | pr_debug("Lok "); |
150 | optlen = *lp + 2; | 146 | optlen = *lp + 2; |
151 | } else { | 147 | } else { |
152 | DEBUGP("Pad1\n"); | 148 | pr_debug("Pad1\n"); |
153 | optlen = 1; | 149 | optlen = 1; |
154 | } | 150 | } |
155 | 151 | ||
156 | /* Step to the next */ | 152 | /* Step to the next */ |
157 | DEBUGP("len%04X \n", optlen); | 153 | pr_debug("len%04X \n", optlen); |
158 | 154 | ||
159 | if ((ptr > skb->len - optlen || hdrlen < optlen) && | 155 | if ((ptr > skb->len - optlen || hdrlen < optlen) && |
160 | (temp < optinfo->optsnr - 1)) { | 156 | temp < optinfo->optsnr - 1) { |
161 | DEBUGP("new pointer is too large! \n"); | 157 | pr_debug("new pointer is too large! \n"); |
162 | break; | 158 | break; |
163 | } | 159 | } |
164 | ptr += optlen; | 160 | ptr += optlen; |
@@ -167,14 +163,14 @@ match(const struct sk_buff *skb, | |||
167 | if (temp == optinfo->optsnr) | 163 | if (temp == optinfo->optsnr) |
168 | return ret; | 164 | return ret; |
169 | else | 165 | else |
170 | return 0; | 166 | return false; |
171 | } | 167 | } |
172 | 168 | ||
173 | return 0; | 169 | return false; |
174 | } | 170 | } |
175 | 171 | ||
176 | /* Called when user tries to insert an entry of this type. */ | 172 | /* Called when user tries to insert an entry of this type. */ |
177 | static int | 173 | static bool |
178 | checkentry(const char *tablename, | 174 | checkentry(const char *tablename, |
179 | const void *entry, | 175 | const void *entry, |
180 | const struct xt_match *match, | 176 | const struct xt_match *match, |
@@ -184,13 +180,13 @@ checkentry(const char *tablename, | |||
184 | const struct ip6t_opts *optsinfo = matchinfo; | 180 | const struct ip6t_opts *optsinfo = matchinfo; |
185 | 181 | ||
186 | if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) { | 182 | if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) { |
187 | DEBUGP("ip6t_opts: unknown flags %X\n", optsinfo->invflags); | 183 | pr_debug("ip6t_opts: unknown flags %X\n", optsinfo->invflags); |
188 | return 0; | 184 | return false; |
189 | } | 185 | } |
190 | return 1; | 186 | return true; |
191 | } | 187 | } |
192 | 188 | ||
193 | static struct xt_match opts_match[] = { | 189 | static struct xt_match opts_match[] __read_mostly = { |
194 | { | 190 | { |
195 | .name = "hbh", | 191 | .name = "hbh", |
196 | .family = AF_INET6, | 192 | .family = AF_INET6, |
diff --git a/net/ipv6/netfilter/ip6t_hl.c b/net/ipv6/netfilter/ip6t_hl.c index d606c0e6d6fd..ca29ec00dc18 100644 --- a/net/ipv6/netfilter/ip6t_hl.c +++ b/net/ipv6/netfilter/ip6t_hl.c | |||
@@ -19,37 +19,37 @@ MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>"); | |||
19 | MODULE_DESCRIPTION("IP tables Hop Limit matching module"); | 19 | MODULE_DESCRIPTION("IP tables Hop Limit matching module"); |
20 | MODULE_LICENSE("GPL"); | 20 | MODULE_LICENSE("GPL"); |
21 | 21 | ||
22 | static int match(const struct sk_buff *skb, | 22 | static bool match(const struct sk_buff *skb, |
23 | const struct net_device *in, const struct net_device *out, | 23 | const struct net_device *in, const struct net_device *out, |
24 | const struct xt_match *match, const void *matchinfo, | 24 | const struct xt_match *match, const void *matchinfo, |
25 | int offset, unsigned int protoff, int *hotdrop) | 25 | int offset, unsigned int protoff, bool *hotdrop) |
26 | { | 26 | { |
27 | const struct ip6t_hl_info *info = matchinfo; | 27 | const struct ip6t_hl_info *info = matchinfo; |
28 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); | 28 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); |
29 | 29 | ||
30 | switch (info->mode) { | 30 | switch (info->mode) { |
31 | case IP6T_HL_EQ: | 31 | case IP6T_HL_EQ: |
32 | return (ip6h->hop_limit == info->hop_limit); | 32 | return ip6h->hop_limit == info->hop_limit; |
33 | break; | 33 | break; |
34 | case IP6T_HL_NE: | 34 | case IP6T_HL_NE: |
35 | return (!(ip6h->hop_limit == info->hop_limit)); | 35 | return ip6h->hop_limit != info->hop_limit; |
36 | break; | 36 | break; |
37 | case IP6T_HL_LT: | 37 | case IP6T_HL_LT: |
38 | return (ip6h->hop_limit < info->hop_limit); | 38 | return ip6h->hop_limit < info->hop_limit; |
39 | break; | 39 | break; |
40 | case IP6T_HL_GT: | 40 | case IP6T_HL_GT: |
41 | return (ip6h->hop_limit > info->hop_limit); | 41 | return ip6h->hop_limit > info->hop_limit; |
42 | break; | 42 | break; |
43 | default: | 43 | default: |
44 | printk(KERN_WARNING "ip6t_hl: unknown mode %d\n", | 44 | printk(KERN_WARNING "ip6t_hl: unknown mode %d\n", |
45 | info->mode); | 45 | info->mode); |
46 | return 0; | 46 | return false; |
47 | } | 47 | } |
48 | 48 | ||
49 | return 0; | 49 | return false; |
50 | } | 50 | } |
51 | 51 | ||
52 | static struct xt_match hl_match = { | 52 | static struct xt_match hl_match __read_mostly = { |
53 | .name = "hl", | 53 | .name = "hl", |
54 | .family = AF_INET6, | 54 | .family = AF_INET6, |
55 | .match = match, | 55 | .match = match, |
diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c index fd6a0869099b..2c65c2f9a4ab 100644 --- a/net/ipv6/netfilter/ip6t_ipv6header.c +++ b/net/ipv6/netfilter/ip6t_ipv6header.c | |||
@@ -26,7 +26,7 @@ MODULE_LICENSE("GPL"); | |||
26 | MODULE_DESCRIPTION("IPv6 headers match"); | 26 | MODULE_DESCRIPTION("IPv6 headers match"); |
27 | MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); | 27 | MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); |
28 | 28 | ||
29 | static int | 29 | static bool |
30 | ipv6header_match(const struct sk_buff *skb, | 30 | ipv6header_match(const struct sk_buff *skb, |
31 | const struct net_device *in, | 31 | const struct net_device *in, |
32 | const struct net_device *out, | 32 | const struct net_device *out, |
@@ -34,7 +34,7 @@ ipv6header_match(const struct sk_buff *skb, | |||
34 | const void *matchinfo, | 34 | const void *matchinfo, |
35 | int offset, | 35 | int offset, |
36 | unsigned int protoff, | 36 | unsigned int protoff, |
37 | int *hotdrop) | 37 | bool *hotdrop) |
38 | { | 38 | { |
39 | const struct ip6t_ipv6header_info *info = matchinfo; | 39 | const struct ip6t_ipv6header_info *info = matchinfo; |
40 | unsigned int temp; | 40 | unsigned int temp; |
@@ -58,7 +58,7 @@ ipv6header_match(const struct sk_buff *skb, | |||
58 | 58 | ||
59 | /* Is there enough space for the next ext header? */ | 59 | /* Is there enough space for the next ext header? */ |
60 | if (len < (int)sizeof(struct ipv6_opt_hdr)) | 60 | if (len < (int)sizeof(struct ipv6_opt_hdr)) |
61 | return 0; | 61 | return false; |
62 | /* No more exthdr -> evaluate */ | 62 | /* No more exthdr -> evaluate */ |
63 | if (nexthdr == NEXTHDR_NONE) { | 63 | if (nexthdr == NEXTHDR_NONE) { |
64 | temp |= MASK_NONE; | 64 | temp |= MASK_NONE; |
@@ -74,9 +74,9 @@ ipv6header_match(const struct sk_buff *skb, | |||
74 | BUG_ON(hp == NULL); | 74 | BUG_ON(hp == NULL); |
75 | 75 | ||
76 | /* Calculate the header length */ | 76 | /* Calculate the header length */ |
77 | if (nexthdr == NEXTHDR_FRAGMENT) { | 77 | if (nexthdr == NEXTHDR_FRAGMENT) |
78 | hdrlen = 8; | 78 | hdrlen = 8; |
79 | } else if (nexthdr == NEXTHDR_AUTH) | 79 | else if (nexthdr == NEXTHDR_AUTH) |
80 | hdrlen = (hp->hdrlen + 2) << 2; | 80 | hdrlen = (hp->hdrlen + 2) << 2; |
81 | else | 81 | else |
82 | hdrlen = ipv6_optlen(hp); | 82 | hdrlen = ipv6_optlen(hp); |
@@ -99,7 +99,7 @@ ipv6header_match(const struct sk_buff *skb, | |||
99 | temp |= MASK_DSTOPTS; | 99 | temp |= MASK_DSTOPTS; |
100 | break; | 100 | break; |
101 | default: | 101 | default: |
102 | return 0; | 102 | return false; |
103 | break; | 103 | break; |
104 | } | 104 | } |
105 | 105 | ||
@@ -110,7 +110,7 @@ ipv6header_match(const struct sk_buff *skb, | |||
110 | break; | 110 | break; |
111 | } | 111 | } |
112 | 112 | ||
113 | if ((nexthdr != NEXTHDR_NONE) && (nexthdr != NEXTHDR_ESP)) | 113 | if (nexthdr != NEXTHDR_NONE && nexthdr != NEXTHDR_ESP) |
114 | temp |= MASK_PROTO; | 114 | temp |= MASK_PROTO; |
115 | 115 | ||
116 | if (info->modeflag) | 116 | if (info->modeflag) |
@@ -124,7 +124,7 @@ ipv6header_match(const struct sk_buff *skb, | |||
124 | } | 124 | } |
125 | } | 125 | } |
126 | 126 | ||
127 | static int | 127 | static bool |
128 | ipv6header_checkentry(const char *tablename, | 128 | ipv6header_checkentry(const char *tablename, |
129 | const void *ip, | 129 | const void *ip, |
130 | const struct xt_match *match, | 130 | const struct xt_match *match, |
@@ -136,12 +136,12 @@ ipv6header_checkentry(const char *tablename, | |||
136 | /* invflags is 0 or 0xff in hard mode */ | 136 | /* invflags is 0 or 0xff in hard mode */ |
137 | if ((!info->modeflag) && info->invflags != 0x00 && | 137 | if ((!info->modeflag) && info->invflags != 0x00 && |
138 | info->invflags != 0xFF) | 138 | info->invflags != 0xFF) |
139 | return 0; | 139 | return false; |
140 | 140 | ||
141 | return 1; | 141 | return true; |
142 | } | 142 | } |
143 | 143 | ||
144 | static struct xt_match ip6t_ipv6header_match = { | 144 | static struct xt_match ip6t_ipv6header_match __read_mostly = { |
145 | .name = "ipv6header", | 145 | .name = "ipv6header", |
146 | .family = AF_INET6, | 146 | .family = AF_INET6, |
147 | .match = &ipv6header_match, | 147 | .match = &ipv6header_match, |
diff --git a/net/ipv6/netfilter/ip6t_mh.c b/net/ipv6/netfilter/ip6t_mh.c index c2a909893a64..0fa714092dc9 100644 --- a/net/ipv6/netfilter/ip6t_mh.c +++ b/net/ipv6/netfilter/ip6t_mh.c | |||
@@ -31,16 +31,13 @@ MODULE_LICENSE("GPL"); | |||
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | /* Returns 1 if the type is matched by the range, 0 otherwise */ | 33 | /* Returns 1 if the type is matched by the range, 0 otherwise */ |
34 | static inline int | 34 | static inline bool |
35 | type_match(u_int8_t min, u_int8_t max, u_int8_t type, int invert) | 35 | type_match(u_int8_t min, u_int8_t max, u_int8_t type, bool invert) |
36 | { | 36 | { |
37 | int ret; | 37 | return (type >= min && type <= max) ^ invert; |
38 | |||
39 | ret = (type >= min && type <= max) ^ invert; | ||
40 | return ret; | ||
41 | } | 38 | } |
42 | 39 | ||
43 | static int | 40 | static bool |
44 | match(const struct sk_buff *skb, | 41 | match(const struct sk_buff *skb, |
45 | const struct net_device *in, | 42 | const struct net_device *in, |
46 | const struct net_device *out, | 43 | const struct net_device *out, |
@@ -48,29 +45,30 @@ match(const struct sk_buff *skb, | |||
48 | const void *matchinfo, | 45 | const void *matchinfo, |
49 | int offset, | 46 | int offset, |
50 | unsigned int protoff, | 47 | unsigned int protoff, |
51 | int *hotdrop) | 48 | bool *hotdrop) |
52 | { | 49 | { |
53 | struct ip6_mh _mh, *mh; | 50 | struct ip6_mh _mh; |
51 | const struct ip6_mh *mh; | ||
54 | const struct ip6t_mh *mhinfo = matchinfo; | 52 | const struct ip6t_mh *mhinfo = matchinfo; |
55 | 53 | ||
56 | /* Must not be a fragment. */ | 54 | /* Must not be a fragment. */ |
57 | if (offset) | 55 | if (offset) |
58 | return 0; | 56 | return false; |
59 | 57 | ||
60 | mh = skb_header_pointer(skb, protoff, sizeof(_mh), &_mh); | 58 | mh = skb_header_pointer(skb, protoff, sizeof(_mh), &_mh); |
61 | if (mh == NULL) { | 59 | if (mh == NULL) { |
62 | /* We've been asked to examine this packet, and we | 60 | /* We've been asked to examine this packet, and we |
63 | can't. Hence, no choice but to drop. */ | 61 | can't. Hence, no choice but to drop. */ |
64 | duprintf("Dropping evil MH tinygram.\n"); | 62 | duprintf("Dropping evil MH tinygram.\n"); |
65 | *hotdrop = 1; | 63 | *hotdrop = true; |
66 | return 0; | 64 | return false; |
67 | } | 65 | } |
68 | 66 | ||
69 | if (mh->ip6mh_proto != IPPROTO_NONE) { | 67 | if (mh->ip6mh_proto != IPPROTO_NONE) { |
70 | duprintf("Dropping invalid MH Payload Proto: %u\n", | 68 | duprintf("Dropping invalid MH Payload Proto: %u\n", |
71 | mh->ip6mh_proto); | 69 | mh->ip6mh_proto); |
72 | *hotdrop = 1; | 70 | *hotdrop = true; |
73 | return 0; | 71 | return false; |
74 | } | 72 | } |
75 | 73 | ||
76 | return type_match(mhinfo->types[0], mhinfo->types[1], mh->ip6mh_type, | 74 | return type_match(mhinfo->types[0], mhinfo->types[1], mh->ip6mh_type, |
@@ -78,7 +76,7 @@ match(const struct sk_buff *skb, | |||
78 | } | 76 | } |
79 | 77 | ||
80 | /* Called when user tries to insert an entry of this type. */ | 78 | /* Called when user tries to insert an entry of this type. */ |
81 | static int | 79 | static bool |
82 | mh_checkentry(const char *tablename, | 80 | mh_checkentry(const char *tablename, |
83 | const void *entry, | 81 | const void *entry, |
84 | const struct xt_match *match, | 82 | const struct xt_match *match, |
@@ -91,7 +89,7 @@ mh_checkentry(const char *tablename, | |||
91 | return !(mhinfo->invflags & ~IP6T_MH_INV_MASK); | 89 | return !(mhinfo->invflags & ~IP6T_MH_INV_MASK); |
92 | } | 90 | } |
93 | 91 | ||
94 | static struct xt_match mh_match = { | 92 | static struct xt_match mh_match __read_mostly = { |
95 | .name = "mh", | 93 | .name = "mh", |
96 | .family = AF_INET6, | 94 | .family = AF_INET6, |
97 | .checkentry = mh_checkentry, | 95 | .checkentry = mh_checkentry, |
diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c index 43738bba00b5..6036613aef36 100644 --- a/net/ipv6/netfilter/ip6t_owner.c +++ b/net/ipv6/netfilter/ip6t_owner.c | |||
@@ -23,7 +23,7 @@ MODULE_DESCRIPTION("IP6 tables owner matching module"); | |||
23 | MODULE_LICENSE("GPL"); | 23 | MODULE_LICENSE("GPL"); |
24 | 24 | ||
25 | 25 | ||
26 | static int | 26 | static bool |
27 | match(const struct sk_buff *skb, | 27 | match(const struct sk_buff *skb, |
28 | const struct net_device *in, | 28 | const struct net_device *in, |
29 | const struct net_device *out, | 29 | const struct net_device *out, |
@@ -31,29 +31,27 @@ match(const struct sk_buff *skb, | |||
31 | const void *matchinfo, | 31 | const void *matchinfo, |
32 | int offset, | 32 | int offset, |
33 | unsigned int protoff, | 33 | unsigned int protoff, |
34 | int *hotdrop) | 34 | bool *hotdrop) |
35 | { | 35 | { |
36 | const struct ip6t_owner_info *info = matchinfo; | 36 | const struct ip6t_owner_info *info = matchinfo; |
37 | 37 | ||
38 | if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file) | 38 | if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file) |
39 | return 0; | 39 | return false; |
40 | 40 | ||
41 | if (info->match & IP6T_OWNER_UID) { | 41 | if (info->match & IP6T_OWNER_UID) |
42 | if ((skb->sk->sk_socket->file->f_uid != info->uid) ^ | 42 | if ((skb->sk->sk_socket->file->f_uid != info->uid) ^ |
43 | !!(info->invert & IP6T_OWNER_UID)) | 43 | !!(info->invert & IP6T_OWNER_UID)) |
44 | return 0; | 44 | return false; |
45 | } | ||
46 | 45 | ||
47 | if (info->match & IP6T_OWNER_GID) { | 46 | if (info->match & IP6T_OWNER_GID) |
48 | if ((skb->sk->sk_socket->file->f_gid != info->gid) ^ | 47 | if ((skb->sk->sk_socket->file->f_gid != info->gid) ^ |
49 | !!(info->invert & IP6T_OWNER_GID)) | 48 | !!(info->invert & IP6T_OWNER_GID)) |
50 | return 0; | 49 | return false; |
51 | } | ||
52 | 50 | ||
53 | return 1; | 51 | return true; |
54 | } | 52 | } |
55 | 53 | ||
56 | static int | 54 | static bool |
57 | checkentry(const char *tablename, | 55 | checkentry(const char *tablename, |
58 | const void *ip, | 56 | const void *ip, |
59 | const struct xt_match *match, | 57 | const struct xt_match *match, |
@@ -65,12 +63,12 @@ checkentry(const char *tablename, | |||
65 | if (info->match & (IP6T_OWNER_PID | IP6T_OWNER_SID)) { | 63 | if (info->match & (IP6T_OWNER_PID | IP6T_OWNER_SID)) { |
66 | printk("ipt_owner: pid and sid matching " | 64 | printk("ipt_owner: pid and sid matching " |
67 | "not supported anymore\n"); | 65 | "not supported anymore\n"); |
68 | return 0; | 66 | return false; |
69 | } | 67 | } |
70 | return 1; | 68 | return true; |
71 | } | 69 | } |
72 | 70 | ||
73 | static struct xt_match owner_match = { | 71 | static struct xt_match owner_match __read_mostly = { |
74 | .name = "owner", | 72 | .name = "owner", |
75 | .family = AF_INET6, | 73 | .family = AF_INET6, |
76 | .match = match, | 74 | .match = match, |
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c index 81ab00d8c182..357cea703bd9 100644 --- a/net/ipv6/netfilter/ip6t_rt.c +++ b/net/ipv6/netfilter/ip6t_rt.c | |||
@@ -24,25 +24,19 @@ MODULE_LICENSE("GPL"); | |||
24 | MODULE_DESCRIPTION("IPv6 RT match"); | 24 | MODULE_DESCRIPTION("IPv6 RT match"); |
25 | MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); | 25 | MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); |
26 | 26 | ||
27 | #if 0 | ||
28 | #define DEBUGP printk | ||
29 | #else | ||
30 | #define DEBUGP(format, args...) | ||
31 | #endif | ||
32 | |||
33 | /* Returns 1 if the id is matched by the range, 0 otherwise */ | 27 | /* Returns 1 if the id is matched by the range, 0 otherwise */ |
34 | static inline int | 28 | static inline bool |
35 | segsleft_match(u_int32_t min, u_int32_t max, u_int32_t id, int invert) | 29 | segsleft_match(u_int32_t min, u_int32_t max, u_int32_t id, bool invert) |
36 | { | 30 | { |
37 | int r = 0; | 31 | bool r; |
38 | DEBUGP("rt segsleft_match:%c 0x%x <= 0x%x <= 0x%x", | 32 | pr_debug("rt segsleft_match:%c 0x%x <= 0x%x <= 0x%x", |
39 | invert ? '!' : ' ', min, id, max); | 33 | invert ? '!' : ' ', min, id, max); |
40 | r = (id >= min && id <= max) ^ invert; | 34 | r = (id >= min && id <= max) ^ invert; |
41 | DEBUGP(" result %s\n", r ? "PASS" : "FAILED"); | 35 | pr_debug(" result %s\n", r ? "PASS" : "FAILED"); |
42 | return r; | 36 | return r; |
43 | } | 37 | } |
44 | 38 | ||
45 | static int | 39 | static bool |
46 | match(const struct sk_buff *skb, | 40 | match(const struct sk_buff *skb, |
47 | const struct net_device *in, | 41 | const struct net_device *in, |
48 | const struct net_device *out, | 42 | const struct net_device *out, |
@@ -50,59 +44,61 @@ match(const struct sk_buff *skb, | |||
50 | const void *matchinfo, | 44 | const void *matchinfo, |
51 | int offset, | 45 | int offset, |
52 | unsigned int protoff, | 46 | unsigned int protoff, |
53 | int *hotdrop) | 47 | bool *hotdrop) |
54 | { | 48 | { |
55 | struct ipv6_rt_hdr _route, *rh; | 49 | struct ipv6_rt_hdr _route; |
50 | const struct ipv6_rt_hdr *rh; | ||
56 | const struct ip6t_rt *rtinfo = matchinfo; | 51 | const struct ip6t_rt *rtinfo = matchinfo; |
57 | unsigned int temp; | 52 | unsigned int temp; |
58 | unsigned int ptr; | 53 | unsigned int ptr; |
59 | unsigned int hdrlen = 0; | 54 | unsigned int hdrlen = 0; |
60 | unsigned int ret = 0; | 55 | bool ret = false; |
61 | struct in6_addr *ap, _addr; | 56 | struct in6_addr _addr; |
57 | const struct in6_addr *ap; | ||
62 | int err; | 58 | int err; |
63 | 59 | ||
64 | err = ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL); | 60 | err = ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL); |
65 | if (err < 0) { | 61 | if (err < 0) { |
66 | if (err != -ENOENT) | 62 | if (err != -ENOENT) |
67 | *hotdrop = 1; | 63 | *hotdrop = true; |
68 | return 0; | 64 | return false; |
69 | } | 65 | } |
70 | 66 | ||
71 | rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route); | 67 | rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route); |
72 | if (rh == NULL) { | 68 | if (rh == NULL) { |
73 | *hotdrop = 1; | 69 | *hotdrop = true; |
74 | return 0; | 70 | return false; |
75 | } | 71 | } |
76 | 72 | ||
77 | hdrlen = ipv6_optlen(rh); | 73 | hdrlen = ipv6_optlen(rh); |
78 | if (skb->len - ptr < hdrlen) { | 74 | if (skb->len - ptr < hdrlen) { |
79 | /* Pcket smaller than its length field */ | 75 | /* Pcket smaller than its length field */ |
80 | return 0; | 76 | return false; |
81 | } | 77 | } |
82 | 78 | ||
83 | DEBUGP("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen); | 79 | pr_debug("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen); |
84 | DEBUGP("TYPE %04X ", rh->type); | 80 | pr_debug("TYPE %04X ", rh->type); |
85 | DEBUGP("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left); | 81 | pr_debug("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left); |
86 | 82 | ||
87 | DEBUGP("IPv6 RT segsleft %02X ", | 83 | pr_debug("IPv6 RT segsleft %02X ", |
88 | (segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1], | 84 | segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1], |
89 | rh->segments_left, | 85 | rh->segments_left, |
90 | !!(rtinfo->invflags & IP6T_RT_INV_SGS)))); | 86 | !!(rtinfo->invflags & IP6T_RT_INV_SGS))); |
91 | DEBUGP("type %02X %02X %02X ", | 87 | pr_debug("type %02X %02X %02X ", |
92 | rtinfo->rt_type, rh->type, | 88 | rtinfo->rt_type, rh->type, |
93 | (!(rtinfo->flags & IP6T_RT_TYP) || | 89 | (!(rtinfo->flags & IP6T_RT_TYP) || |
94 | ((rtinfo->rt_type == rh->type) ^ | 90 | ((rtinfo->rt_type == rh->type) ^ |
95 | !!(rtinfo->invflags & IP6T_RT_INV_TYP)))); | 91 | !!(rtinfo->invflags & IP6T_RT_INV_TYP)))); |
96 | DEBUGP("len %02X %04X %02X ", | 92 | pr_debug("len %02X %04X %02X ", |
97 | rtinfo->hdrlen, hdrlen, | 93 | rtinfo->hdrlen, hdrlen, |
98 | (!(rtinfo->flags & IP6T_RT_LEN) || | 94 | !(rtinfo->flags & IP6T_RT_LEN) || |
99 | ((rtinfo->hdrlen == hdrlen) ^ | 95 | ((rtinfo->hdrlen == hdrlen) ^ |
100 | !!(rtinfo->invflags & IP6T_RT_INV_LEN)))); | 96 | !!(rtinfo->invflags & IP6T_RT_INV_LEN))); |
101 | DEBUGP("res %02X %02X %02X ", | 97 | pr_debug("res %02X %02X %02X ", |
102 | (rtinfo->flags & IP6T_RT_RES), | 98 | rtinfo->flags & IP6T_RT_RES, |
103 | ((struct rt0_hdr *)rh)->reserved, | 99 | ((const struct rt0_hdr *)rh)->reserved, |
104 | !((rtinfo->flags & IP6T_RT_RES) && | 100 | !((rtinfo->flags & IP6T_RT_RES) && |
105 | (((struct rt0_hdr *)rh)->reserved))); | 101 | (((const struct rt0_hdr *)rh)->reserved))); |
106 | 102 | ||
107 | ret = (rh != NULL) | 103 | ret = (rh != NULL) |
108 | && | 104 | && |
@@ -129,18 +125,18 @@ match(const struct sk_buff *skb, | |||
129 | ret = (*rp == 0); | 125 | ret = (*rp == 0); |
130 | } | 126 | } |
131 | 127 | ||
132 | DEBUGP("#%d ", rtinfo->addrnr); | 128 | pr_debug("#%d ", rtinfo->addrnr); |
133 | if (!(rtinfo->flags & IP6T_RT_FST)) { | 129 | if (!(rtinfo->flags & IP6T_RT_FST)) { |
134 | return ret; | 130 | return ret; |
135 | } else if (rtinfo->flags & IP6T_RT_FST_NSTRICT) { | 131 | } else if (rtinfo->flags & IP6T_RT_FST_NSTRICT) { |
136 | DEBUGP("Not strict "); | 132 | pr_debug("Not strict "); |
137 | if (rtinfo->addrnr > (unsigned int)((hdrlen - 8) / 16)) { | 133 | if (rtinfo->addrnr > (unsigned int)((hdrlen - 8) / 16)) { |
138 | DEBUGP("There isn't enough space\n"); | 134 | pr_debug("There isn't enough space\n"); |
139 | return 0; | 135 | return false; |
140 | } else { | 136 | } else { |
141 | unsigned int i = 0; | 137 | unsigned int i = 0; |
142 | 138 | ||
143 | DEBUGP("#%d ", rtinfo->addrnr); | 139 | pr_debug("#%d ", rtinfo->addrnr); |
144 | for (temp = 0; | 140 | for (temp = 0; |
145 | temp < (unsigned int)((hdrlen - 8) / 16); | 141 | temp < (unsigned int)((hdrlen - 8) / 16); |
146 | temp++) { | 142 | temp++) { |
@@ -154,25 +150,25 @@ match(const struct sk_buff *skb, | |||
154 | BUG_ON(ap == NULL); | 150 | BUG_ON(ap == NULL); |
155 | 151 | ||
156 | if (ipv6_addr_equal(ap, &rtinfo->addrs[i])) { | 152 | if (ipv6_addr_equal(ap, &rtinfo->addrs[i])) { |
157 | DEBUGP("i=%d temp=%d;\n", i, temp); | 153 | pr_debug("i=%d temp=%d;\n", i, temp); |
158 | i++; | 154 | i++; |
159 | } | 155 | } |
160 | if (i == rtinfo->addrnr) | 156 | if (i == rtinfo->addrnr) |
161 | break; | 157 | break; |
162 | } | 158 | } |
163 | DEBUGP("i=%d #%d\n", i, rtinfo->addrnr); | 159 | pr_debug("i=%d #%d\n", i, rtinfo->addrnr); |
164 | if (i == rtinfo->addrnr) | 160 | if (i == rtinfo->addrnr) |
165 | return ret; | 161 | return ret; |
166 | else | 162 | else |
167 | return 0; | 163 | return false; |
168 | } | 164 | } |
169 | } else { | 165 | } else { |
170 | DEBUGP("Strict "); | 166 | pr_debug("Strict "); |
171 | if (rtinfo->addrnr > (unsigned int)((hdrlen - 8) / 16)) { | 167 | if (rtinfo->addrnr > (unsigned int)((hdrlen - 8) / 16)) { |
172 | DEBUGP("There isn't enough space\n"); | 168 | pr_debug("There isn't enough space\n"); |
173 | return 0; | 169 | return false; |
174 | } else { | 170 | } else { |
175 | DEBUGP("#%d ", rtinfo->addrnr); | 171 | pr_debug("#%d ", rtinfo->addrnr); |
176 | for (temp = 0; temp < rtinfo->addrnr; temp++) { | 172 | for (temp = 0; temp < rtinfo->addrnr; temp++) { |
177 | ap = skb_header_pointer(skb, | 173 | ap = skb_header_pointer(skb, |
178 | ptr | 174 | ptr |
@@ -185,20 +181,20 @@ match(const struct sk_buff *skb, | |||
185 | if (!ipv6_addr_equal(ap, &rtinfo->addrs[temp])) | 181 | if (!ipv6_addr_equal(ap, &rtinfo->addrs[temp])) |
186 | break; | 182 | break; |
187 | } | 183 | } |
188 | DEBUGP("temp=%d #%d\n", temp, rtinfo->addrnr); | 184 | pr_debug("temp=%d #%d\n", temp, rtinfo->addrnr); |
189 | if ((temp == rtinfo->addrnr) && | 185 | if (temp == rtinfo->addrnr && |
190 | (temp == (unsigned int)((hdrlen - 8) / 16))) | 186 | temp == (unsigned int)((hdrlen - 8) / 16)) |
191 | return ret; | 187 | return ret; |
192 | else | 188 | else |
193 | return 0; | 189 | return false; |
194 | } | 190 | } |
195 | } | 191 | } |
196 | 192 | ||
197 | return 0; | 193 | return false; |
198 | } | 194 | } |
199 | 195 | ||
200 | /* Called when user tries to insert an entry of this type. */ | 196 | /* Called when user tries to insert an entry of this type. */ |
201 | static int | 197 | static bool |
202 | checkentry(const char *tablename, | 198 | checkentry(const char *tablename, |
203 | const void *entry, | 199 | const void *entry, |
204 | const struct xt_match *match, | 200 | const struct xt_match *match, |
@@ -208,21 +204,21 @@ checkentry(const char *tablename, | |||
208 | const struct ip6t_rt *rtinfo = matchinfo; | 204 | const struct ip6t_rt *rtinfo = matchinfo; |
209 | 205 | ||
210 | if (rtinfo->invflags & ~IP6T_RT_INV_MASK) { | 206 | if (rtinfo->invflags & ~IP6T_RT_INV_MASK) { |
211 | DEBUGP("ip6t_rt: unknown flags %X\n", rtinfo->invflags); | 207 | pr_debug("ip6t_rt: unknown flags %X\n", rtinfo->invflags); |
212 | return 0; | 208 | return false; |
213 | } | 209 | } |
214 | if ((rtinfo->flags & (IP6T_RT_RES | IP6T_RT_FST_MASK)) && | 210 | if ((rtinfo->flags & (IP6T_RT_RES | IP6T_RT_FST_MASK)) && |
215 | (!(rtinfo->flags & IP6T_RT_TYP) || | 211 | (!(rtinfo->flags & IP6T_RT_TYP) || |
216 | (rtinfo->rt_type != 0) || | 212 | (rtinfo->rt_type != 0) || |
217 | (rtinfo->invflags & IP6T_RT_INV_TYP))) { | 213 | (rtinfo->invflags & IP6T_RT_INV_TYP))) { |
218 | DEBUGP("`--rt-type 0' required before `--rt-0-*'"); | 214 | pr_debug("`--rt-type 0' required before `--rt-0-*'"); |
219 | return 0; | 215 | return false; |
220 | } | 216 | } |
221 | 217 | ||
222 | return 1; | 218 | return true; |
223 | } | 219 | } |
224 | 220 | ||
225 | static struct xt_match rt_match = { | 221 | static struct xt_match rt_match __read_mostly = { |
226 | .name = "rt", | 222 | .name = "rt", |
227 | .family = AF_INET6, | 223 | .family = AF_INET6, |
228 | .match = match, | 224 | .match = match, |
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index f2d26495f413..f0a9efa67fb5 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c | |||
@@ -21,12 +21,6 @@ MODULE_DESCRIPTION("ip6tables mangle table"); | |||
21 | (1 << NF_IP6_LOCAL_OUT) | \ | 21 | (1 << NF_IP6_LOCAL_OUT) | \ |
22 | (1 << NF_IP6_POST_ROUTING)) | 22 | (1 << NF_IP6_POST_ROUTING)) |
23 | 23 | ||
24 | #if 0 | ||
25 | #define DEBUGP(x, args...) printk(KERN_DEBUG x, ## args) | ||
26 | #else | ||
27 | #define DEBUGP(x, args...) | ||
28 | #endif | ||
29 | |||
30 | static struct | 24 | static struct |
31 | { | 25 | { |
32 | struct ip6t_replace repl; | 26 | struct ip6t_replace repl; |
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index 0acda45d455d..ec290e4ebdd8 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c | |||
@@ -8,12 +8,6 @@ | |||
8 | 8 | ||
9 | #define RAW_VALID_HOOKS ((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_OUT)) | 9 | #define RAW_VALID_HOOKS ((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_OUT)) |
10 | 10 | ||
11 | #if 0 | ||
12 | #define DEBUGP(x, args...) printk(KERN_DEBUG x, ## args) | ||
13 | #else | ||
14 | #define DEBUGP(x, args...) | ||
15 | #endif | ||
16 | |||
17 | static struct | 11 | static struct |
18 | { | 12 | { |
19 | struct ip6t_replace repl; | 13 | struct ip6t_replace repl; |
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 1b1797f1f33d..36df2218b669 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | |||
@@ -26,12 +26,6 @@ | |||
26 | #include <net/netfilter/nf_conntrack_l3proto.h> | 26 | #include <net/netfilter/nf_conntrack_l3proto.h> |
27 | #include <net/netfilter/nf_conntrack_core.h> | 27 | #include <net/netfilter/nf_conntrack_core.h> |
28 | 28 | ||
29 | #if 0 | ||
30 | #define DEBUGP printk | ||
31 | #else | ||
32 | #define DEBUGP(format, args...) | ||
33 | #endif | ||
34 | |||
35 | static int ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, | 29 | static int ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, |
36 | struct nf_conntrack_tuple *tuple) | 30 | struct nf_conntrack_tuple *tuple) |
37 | { | 31 | { |
@@ -92,7 +86,7 @@ static int ipv6_print_conntrack(struct seq_file *s, | |||
92 | * - Note also special handling of AUTH header. Thanks to IPsec wizards. | 86 | * - Note also special handling of AUTH header. Thanks to IPsec wizards. |
93 | */ | 87 | */ |
94 | 88 | ||
95 | int nf_ct_ipv6_skip_exthdr(struct sk_buff *skb, int start, u8 *nexthdrp, | 89 | int nf_ct_ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, |
96 | int len) | 90 | int len) |
97 | { | 91 | { |
98 | u8 nexthdr = *nexthdrp; | 92 | u8 nexthdr = *nexthdrp; |
@@ -123,22 +117,25 @@ int nf_ct_ipv6_skip_exthdr(struct sk_buff *skb, int start, u8 *nexthdrp, | |||
123 | return start; | 117 | return start; |
124 | } | 118 | } |
125 | 119 | ||
126 | static int | 120 | static int ipv6_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, |
127 | ipv6_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff, | 121 | unsigned int *dataoff, u_int8_t *protonum) |
128 | u_int8_t *protonum) | ||
129 | { | 122 | { |
130 | unsigned int extoff = (u8 *)(ipv6_hdr(*pskb) + 1) - (*pskb)->data; | 123 | unsigned int extoff = nhoff + sizeof(struct ipv6hdr); |
131 | unsigned char pnum = ipv6_hdr(*pskb)->nexthdr; | 124 | unsigned char pnum; |
132 | int protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum, | 125 | int protoff; |
133 | (*pskb)->len - extoff); | 126 | |
127 | if (skb_copy_bits(skb, nhoff + offsetof(struct ipv6hdr, nexthdr), | ||
128 | &pnum, sizeof(pnum)) != 0) { | ||
129 | pr_debug("ip6_conntrack_core: can't get nexthdr\n"); | ||
130 | return -NF_ACCEPT; | ||
131 | } | ||
132 | protoff = nf_ct_ipv6_skip_exthdr(skb, extoff, &pnum, skb->len - extoff); | ||
134 | /* | 133 | /* |
135 | * (protoff == (*pskb)->len) mean that the packet doesn't have no data | 134 | * (protoff == skb->len) mean that the packet doesn't have no data |
136 | * except of IPv6 & ext headers. but it's tracked anyway. - YK | 135 | * except of IPv6 & ext headers. but it's tracked anyway. - YK |
137 | */ | 136 | */ |
138 | if ((protoff < 0) || (protoff > (*pskb)->len)) { | 137 | if ((protoff < 0) || (protoff > skb->len)) { |
139 | DEBUGP("ip6_conntrack_core: can't find proto in pkt\n"); | 138 | pr_debug("ip6_conntrack_core: can't find proto in pkt\n"); |
140 | NF_CT_STAT_INC_ATOMIC(error); | ||
141 | NF_CT_STAT_INC_ATOMIC(invalid); | ||
142 | return -NF_ACCEPT; | 139 | return -NF_ACCEPT; |
143 | } | 140 | } |
144 | 141 | ||
@@ -147,11 +144,6 @@ ipv6_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff, | |||
147 | return NF_ACCEPT; | 144 | return NF_ACCEPT; |
148 | } | 145 | } |
149 | 146 | ||
150 | static u_int32_t ipv6_get_features(const struct nf_conntrack_tuple *tuple) | ||
151 | { | ||
152 | return NF_CT_F_BASIC; | ||
153 | } | ||
154 | |||
155 | static unsigned int ipv6_confirm(unsigned int hooknum, | 147 | static unsigned int ipv6_confirm(unsigned int hooknum, |
156 | struct sk_buff **pskb, | 148 | struct sk_buff **pskb, |
157 | const struct net_device *in, | 149 | const struct net_device *in, |
@@ -183,7 +175,7 @@ static unsigned int ipv6_confirm(unsigned int hooknum, | |||
183 | protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum, | 175 | protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum, |
184 | (*pskb)->len - extoff); | 176 | (*pskb)->len - extoff); |
185 | if (protoff > (*pskb)->len || pnum == NEXTHDR_FRAGMENT) { | 177 | if (protoff > (*pskb)->len || pnum == NEXTHDR_FRAGMENT) { |
186 | DEBUGP("proto header not found\n"); | 178 | pr_debug("proto header not found\n"); |
187 | return NF_ACCEPT; | 179 | return NF_ACCEPT; |
188 | } | 180 | } |
189 | 181 | ||
@@ -381,14 +373,14 @@ static int ipv6_nfattr_to_tuple(struct nfattr *tb[], | |||
381 | } | 373 | } |
382 | #endif | 374 | #endif |
383 | 375 | ||
384 | struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 = { | 376 | struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = { |
385 | .l3proto = PF_INET6, | 377 | .l3proto = PF_INET6, |
386 | .name = "ipv6", | 378 | .name = "ipv6", |
387 | .pkt_to_tuple = ipv6_pkt_to_tuple, | 379 | .pkt_to_tuple = ipv6_pkt_to_tuple, |
388 | .invert_tuple = ipv6_invert_tuple, | 380 | .invert_tuple = ipv6_invert_tuple, |
389 | .print_tuple = ipv6_print_tuple, | 381 | .print_tuple = ipv6_print_tuple, |
390 | .print_conntrack = ipv6_print_conntrack, | 382 | .print_conntrack = ipv6_print_conntrack, |
391 | .prepare = ipv6_prepare, | 383 | .get_l4proto = ipv6_get_l4proto, |
392 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 384 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
393 | .tuple_to_nfattr = ipv6_tuple_to_nfattr, | 385 | .tuple_to_nfattr = ipv6_tuple_to_nfattr, |
394 | .nfattr_to_tuple = ipv6_nfattr_to_tuple, | 386 | .nfattr_to_tuple = ipv6_nfattr_to_tuple, |
@@ -397,7 +389,6 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 = { | |||
397 | .ctl_table_path = nf_net_netfilter_sysctl_path, | 389 | .ctl_table_path = nf_net_netfilter_sysctl_path, |
398 | .ctl_table = nf_ct_ipv6_sysctl_table, | 390 | .ctl_table = nf_ct_ipv6_sysctl_table, |
399 | #endif | 391 | #endif |
400 | .get_features = ipv6_get_features, | ||
401 | .me = THIS_MODULE, | 392 | .me = THIS_MODULE, |
402 | }; | 393 | }; |
403 | 394 | ||
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 8814b95b2326..ab154fb90018 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | |||
@@ -27,12 +27,6 @@ | |||
27 | 27 | ||
28 | static unsigned long nf_ct_icmpv6_timeout __read_mostly = 30*HZ; | 28 | static unsigned long nf_ct_icmpv6_timeout __read_mostly = 30*HZ; |
29 | 29 | ||
30 | #if 0 | ||
31 | #define DEBUGP printk | ||
32 | #else | ||
33 | #define DEBUGP(format, args...) | ||
34 | #endif | ||
35 | |||
36 | static int icmpv6_pkt_to_tuple(const struct sk_buff *skb, | 30 | static int icmpv6_pkt_to_tuple(const struct sk_buff *skb, |
37 | unsigned int dataoff, | 31 | unsigned int dataoff, |
38 | struct nf_conntrack_tuple *tuple) | 32 | struct nf_conntrack_tuple *tuple) |
@@ -125,8 +119,8 @@ static int icmpv6_new(struct nf_conn *conntrack, | |||
125 | 119 | ||
126 | if (type < 0 || type >= sizeof(valid_new) || !valid_new[type]) { | 120 | if (type < 0 || type >= sizeof(valid_new) || !valid_new[type]) { |
127 | /* Can't create a new ICMPv6 `conn' with this. */ | 121 | /* Can't create a new ICMPv6 `conn' with this. */ |
128 | DEBUGP("icmpv6: can't create new conn with type %u\n", | 122 | pr_debug("icmpv6: can't create new conn with type %u\n", |
129 | type + 128); | 123 | type + 128); |
130 | NF_CT_DUMP_TUPLE(&conntrack->tuplehash[0].tuple); | 124 | NF_CT_DUMP_TUPLE(&conntrack->tuplehash[0].tuple); |
131 | return 0; | 125 | return 0; |
132 | } | 126 | } |
@@ -142,60 +136,36 @@ icmpv6_error_message(struct sk_buff *skb, | |||
142 | { | 136 | { |
143 | struct nf_conntrack_tuple intuple, origtuple; | 137 | struct nf_conntrack_tuple intuple, origtuple; |
144 | struct nf_conntrack_tuple_hash *h; | 138 | struct nf_conntrack_tuple_hash *h; |
145 | struct icmp6hdr _hdr, *hp; | ||
146 | unsigned int inip6off; | ||
147 | struct nf_conntrack_l4proto *inproto; | 139 | struct nf_conntrack_l4proto *inproto; |
148 | u_int8_t inprotonum; | ||
149 | unsigned int inprotoff; | ||
150 | 140 | ||
151 | NF_CT_ASSERT(skb->nfct == NULL); | 141 | NF_CT_ASSERT(skb->nfct == NULL); |
152 | 142 | ||
153 | hp = skb_header_pointer(skb, icmp6off, sizeof(_hdr), &_hdr); | 143 | /* Are they talking about one of our connections? */ |
154 | if (hp == NULL) { | 144 | if (!nf_ct_get_tuplepr(skb, |
155 | DEBUGP("icmpv6_error: Can't get ICMPv6 hdr.\n"); | 145 | skb_network_offset(skb) |
156 | return -NF_ACCEPT; | 146 | + sizeof(struct ipv6hdr) |
157 | } | 147 | + sizeof(struct icmp6hdr), |
158 | 148 | PF_INET6, &origtuple)) { | |
159 | inip6off = icmp6off + sizeof(_hdr); | 149 | pr_debug("icmpv6_error: Can't get tuple\n"); |
160 | if (skb_copy_bits(skb, inip6off+offsetof(struct ipv6hdr, nexthdr), | ||
161 | &inprotonum, sizeof(inprotonum)) != 0) { | ||
162 | DEBUGP("icmpv6_error: Can't get nexthdr in inner IPv6 header.\n"); | ||
163 | return -NF_ACCEPT; | ||
164 | } | ||
165 | inprotoff = nf_ct_ipv6_skip_exthdr(skb, | ||
166 | inip6off + sizeof(struct ipv6hdr), | ||
167 | &inprotonum, | ||
168 | skb->len - inip6off | ||
169 | - sizeof(struct ipv6hdr)); | ||
170 | |||
171 | if ((inprotoff > skb->len) || (inprotonum == NEXTHDR_FRAGMENT)) { | ||
172 | DEBUGP("icmpv6_error: Can't get protocol header in ICMPv6 payload.\n"); | ||
173 | return -NF_ACCEPT; | 150 | return -NF_ACCEPT; |
174 | } | 151 | } |
175 | 152 | ||
176 | /* rcu_read_lock()ed by nf_hook_slow */ | 153 | /* rcu_read_lock()ed by nf_hook_slow */ |
177 | inproto = __nf_ct_l4proto_find(PF_INET6, inprotonum); | 154 | inproto = __nf_ct_l4proto_find(PF_INET6, origtuple.dst.protonum); |
178 | |||
179 | /* Are they talking about one of our connections? */ | ||
180 | if (!nf_ct_get_tuple(skb, inip6off, inprotoff, PF_INET6, inprotonum, | ||
181 | &origtuple, &nf_conntrack_l3proto_ipv6, inproto)) { | ||
182 | DEBUGP("icmpv6_error: Can't get tuple\n"); | ||
183 | return -NF_ACCEPT; | ||
184 | } | ||
185 | 155 | ||
186 | /* Ordinarily, we'd expect the inverted tupleproto, but it's | 156 | /* Ordinarily, we'd expect the inverted tupleproto, but it's |
187 | been preserved inside the ICMP. */ | 157 | been preserved inside the ICMP. */ |
188 | if (!nf_ct_invert_tuple(&intuple, &origtuple, | 158 | if (!nf_ct_invert_tuple(&intuple, &origtuple, |
189 | &nf_conntrack_l3proto_ipv6, inproto)) { | 159 | &nf_conntrack_l3proto_ipv6, inproto)) { |
190 | DEBUGP("icmpv6_error: Can't invert tuple\n"); | 160 | pr_debug("icmpv6_error: Can't invert tuple\n"); |
191 | return -NF_ACCEPT; | 161 | return -NF_ACCEPT; |
192 | } | 162 | } |
193 | 163 | ||
194 | *ctinfo = IP_CT_RELATED; | 164 | *ctinfo = IP_CT_RELATED; |
195 | 165 | ||
196 | h = nf_conntrack_find_get(&intuple, NULL); | 166 | h = nf_conntrack_find_get(&intuple); |
197 | if (!h) { | 167 | if (!h) { |
198 | DEBUGP("icmpv6_error: no match\n"); | 168 | pr_debug("icmpv6_error: no match\n"); |
199 | return -NF_ACCEPT; | 169 | return -NF_ACCEPT; |
200 | } else { | 170 | } else { |
201 | if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) | 171 | if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) |
@@ -306,7 +276,7 @@ static struct ctl_table icmpv6_sysctl_table[] = { | |||
306 | }; | 276 | }; |
307 | #endif /* CONFIG_SYSCTL */ | 277 | #endif /* CONFIG_SYSCTL */ |
308 | 278 | ||
309 | struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 = | 279 | struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly = |
310 | { | 280 | { |
311 | .l3proto = PF_INET6, | 281 | .l3proto = PF_INET6, |
312 | .l4proto = IPPROTO_ICMPV6, | 282 | .l4proto = IPPROTO_ICMPV6, |
@@ -327,5 +297,3 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 = | |||
327 | .ctl_table = icmpv6_sysctl_table, | 297 | .ctl_table = icmpv6_sysctl_table, |
328 | #endif | 298 | #endif |
329 | }; | 299 | }; |
330 | |||
331 | EXPORT_SYMBOL(nf_conntrack_l4proto_icmpv6); | ||
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 347ab7608231..25442a8c1ba8 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -44,12 +44,6 @@ | |||
44 | #include <linux/kernel.h> | 44 | #include <linux/kernel.h> |
45 | #include <linux/module.h> | 45 | #include <linux/module.h> |
46 | 46 | ||
47 | #if 0 | ||
48 | #define DEBUGP printk | ||
49 | #else | ||
50 | #define DEBUGP(format, args...) | ||
51 | #endif | ||
52 | |||
53 | #define NF_CT_FRAG6_HIGH_THRESH 262144 /* == 256*1024 */ | 47 | #define NF_CT_FRAG6_HIGH_THRESH 262144 /* == 256*1024 */ |
54 | #define NF_CT_FRAG6_LOW_THRESH 196608 /* == 192*1024 */ | 48 | #define NF_CT_FRAG6_LOW_THRESH 196608 /* == 192*1024 */ |
55 | #define NF_CT_FRAG6_TIMEOUT IPV6_FRAG_TIMEOUT | 49 | #define NF_CT_FRAG6_TIMEOUT IPV6_FRAG_TIMEOUT |
@@ -343,7 +337,7 @@ nf_ct_frag6_create(unsigned int hash, __be32 id, struct in6_addr *src, str | |||
343 | struct nf_ct_frag6_queue *fq; | 337 | struct nf_ct_frag6_queue *fq; |
344 | 338 | ||
345 | if ((fq = frag_alloc_queue()) == NULL) { | 339 | if ((fq = frag_alloc_queue()) == NULL) { |
346 | DEBUGP("Can't alloc new queue\n"); | 340 | pr_debug("Can't alloc new queue\n"); |
347 | goto oom; | 341 | goto oom; |
348 | } | 342 | } |
349 | 343 | ||
@@ -393,7 +387,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
393 | int offset, end; | 387 | int offset, end; |
394 | 388 | ||
395 | if (fq->last_in & COMPLETE) { | 389 | if (fq->last_in & COMPLETE) { |
396 | DEBUGP("Allready completed\n"); | 390 | pr_debug("Allready completed\n"); |
397 | goto err; | 391 | goto err; |
398 | } | 392 | } |
399 | 393 | ||
@@ -402,7 +396,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
402 | ((u8 *)(fhdr + 1) - (u8 *)(ipv6_hdr(skb) + 1))); | 396 | ((u8 *)(fhdr + 1) - (u8 *)(ipv6_hdr(skb) + 1))); |
403 | 397 | ||
404 | if ((unsigned int)end > IPV6_MAXPLEN) { | 398 | if ((unsigned int)end > IPV6_MAXPLEN) { |
405 | DEBUGP("offset is too large.\n"); | 399 | pr_debug("offset is too large.\n"); |
406 | return -1; | 400 | return -1; |
407 | } | 401 | } |
408 | 402 | ||
@@ -420,7 +414,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
420 | */ | 414 | */ |
421 | if (end < fq->len || | 415 | if (end < fq->len || |
422 | ((fq->last_in & LAST_IN) && end != fq->len)) { | 416 | ((fq->last_in & LAST_IN) && end != fq->len)) { |
423 | DEBUGP("already received last fragment\n"); | 417 | pr_debug("already received last fragment\n"); |
424 | goto err; | 418 | goto err; |
425 | } | 419 | } |
426 | fq->last_in |= LAST_IN; | 420 | fq->last_in |= LAST_IN; |
@@ -433,13 +427,13 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
433 | /* RFC2460 says always send parameter problem in | 427 | /* RFC2460 says always send parameter problem in |
434 | * this case. -DaveM | 428 | * this case. -DaveM |
435 | */ | 429 | */ |
436 | DEBUGP("the end of this fragment is not rounded to 8 bytes.\n"); | 430 | pr_debug("end of fragment not rounded to 8 bytes.\n"); |
437 | return -1; | 431 | return -1; |
438 | } | 432 | } |
439 | if (end > fq->len) { | 433 | if (end > fq->len) { |
440 | /* Some bits beyond end -> corruption. */ | 434 | /* Some bits beyond end -> corruption. */ |
441 | if (fq->last_in & LAST_IN) { | 435 | if (fq->last_in & LAST_IN) { |
442 | DEBUGP("last packet already reached.\n"); | 436 | pr_debug("last packet already reached.\n"); |
443 | goto err; | 437 | goto err; |
444 | } | 438 | } |
445 | fq->len = end; | 439 | fq->len = end; |
@@ -451,11 +445,11 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
451 | 445 | ||
452 | /* Point into the IP datagram 'data' part. */ | 446 | /* Point into the IP datagram 'data' part. */ |
453 | if (!pskb_pull(skb, (u8 *) (fhdr + 1) - skb->data)) { | 447 | if (!pskb_pull(skb, (u8 *) (fhdr + 1) - skb->data)) { |
454 | DEBUGP("queue: message is too short.\n"); | 448 | pr_debug("queue: message is too short.\n"); |
455 | goto err; | 449 | goto err; |
456 | } | 450 | } |
457 | if (pskb_trim_rcsum(skb, end - offset)) { | 451 | if (pskb_trim_rcsum(skb, end - offset)) { |
458 | DEBUGP("Can't trim\n"); | 452 | pr_debug("Can't trim\n"); |
459 | goto err; | 453 | goto err; |
460 | } | 454 | } |
461 | 455 | ||
@@ -480,11 +474,11 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
480 | if (i > 0) { | 474 | if (i > 0) { |
481 | offset += i; | 475 | offset += i; |
482 | if (end <= offset) { | 476 | if (end <= offset) { |
483 | DEBUGP("overlap\n"); | 477 | pr_debug("overlap\n"); |
484 | goto err; | 478 | goto err; |
485 | } | 479 | } |
486 | if (!pskb_pull(skb, i)) { | 480 | if (!pskb_pull(skb, i)) { |
487 | DEBUGP("Can't pull\n"); | 481 | pr_debug("Can't pull\n"); |
488 | goto err; | 482 | goto err; |
489 | } | 483 | } |
490 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) | 484 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) |
@@ -503,7 +497,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
503 | /* Eat head of the next overlapped fragment | 497 | /* Eat head of the next overlapped fragment |
504 | * and leave the loop. The next ones cannot overlap. | 498 | * and leave the loop. The next ones cannot overlap. |
505 | */ | 499 | */ |
506 | DEBUGP("Eat head of the overlapped parts.: %d", i); | 500 | pr_debug("Eat head of the overlapped parts.: %d", i); |
507 | if (!pskb_pull(next, i)) | 501 | if (!pskb_pull(next, i)) |
508 | goto err; | 502 | goto err; |
509 | 503 | ||
@@ -586,13 +580,13 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | |||
586 | sizeof(struct ipv6hdr) + fq->len - | 580 | sizeof(struct ipv6hdr) + fq->len - |
587 | sizeof(struct frag_hdr)); | 581 | sizeof(struct frag_hdr)); |
588 | if (payload_len > IPV6_MAXPLEN) { | 582 | if (payload_len > IPV6_MAXPLEN) { |
589 | DEBUGP("payload len is too large.\n"); | 583 | pr_debug("payload len is too large.\n"); |
590 | goto out_oversize; | 584 | goto out_oversize; |
591 | } | 585 | } |
592 | 586 | ||
593 | /* Head of list must not be cloned. */ | 587 | /* Head of list must not be cloned. */ |
594 | if (skb_cloned(head) && pskb_expand_head(head, 0, 0, GFP_ATOMIC)) { | 588 | if (skb_cloned(head) && pskb_expand_head(head, 0, 0, GFP_ATOMIC)) { |
595 | DEBUGP("skb is cloned but can't expand head"); | 589 | pr_debug("skb is cloned but can't expand head"); |
596 | goto out_oom; | 590 | goto out_oom; |
597 | } | 591 | } |
598 | 592 | ||
@@ -604,7 +598,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | |||
604 | int i, plen = 0; | 598 | int i, plen = 0; |
605 | 599 | ||
606 | if ((clone = alloc_skb(0, GFP_ATOMIC)) == NULL) { | 600 | if ((clone = alloc_skb(0, GFP_ATOMIC)) == NULL) { |
607 | DEBUGP("Can't alloc skb\n"); | 601 | pr_debug("Can't alloc skb\n"); |
608 | goto out_oom; | 602 | goto out_oom; |
609 | } | 603 | } |
610 | clone->next = head->next; | 604 | clone->next = head->next; |
@@ -719,11 +713,11 @@ find_prev_fhdr(struct sk_buff *skb, u8 *prevhdrp, int *prevhoff, int *fhoff) | |||
719 | return -1; | 713 | return -1; |
720 | } | 714 | } |
721 | if (len < (int)sizeof(struct ipv6_opt_hdr)) { | 715 | if (len < (int)sizeof(struct ipv6_opt_hdr)) { |
722 | DEBUGP("too short\n"); | 716 | pr_debug("too short\n"); |
723 | return -1; | 717 | return -1; |
724 | } | 718 | } |
725 | if (nexthdr == NEXTHDR_NONE) { | 719 | if (nexthdr == NEXTHDR_NONE) { |
726 | DEBUGP("next header is none\n"); | 720 | pr_debug("next header is none\n"); |
727 | return -1; | 721 | return -1; |
728 | } | 722 | } |
729 | if (skb_copy_bits(skb, start, &hdr, sizeof(hdr))) | 723 | if (skb_copy_bits(skb, start, &hdr, sizeof(hdr))) |
@@ -764,7 +758,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) | |||
764 | 758 | ||
765 | /* Jumbo payload inhibits frag. header */ | 759 | /* Jumbo payload inhibits frag. header */ |
766 | if (ipv6_hdr(skb)->payload_len == 0) { | 760 | if (ipv6_hdr(skb)->payload_len == 0) { |
767 | DEBUGP("payload len = 0\n"); | 761 | pr_debug("payload len = 0\n"); |
768 | return skb; | 762 | return skb; |
769 | } | 763 | } |
770 | 764 | ||
@@ -773,14 +767,14 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) | |||
773 | 767 | ||
774 | clone = skb_clone(skb, GFP_ATOMIC); | 768 | clone = skb_clone(skb, GFP_ATOMIC); |
775 | if (clone == NULL) { | 769 | if (clone == NULL) { |
776 | DEBUGP("Can't clone skb\n"); | 770 | pr_debug("Can't clone skb\n"); |
777 | return skb; | 771 | return skb; |
778 | } | 772 | } |
779 | 773 | ||
780 | NFCT_FRAG6_CB(clone)->orig = skb; | 774 | NFCT_FRAG6_CB(clone)->orig = skb; |
781 | 775 | ||
782 | if (!pskb_may_pull(clone, fhoff + sizeof(*fhdr))) { | 776 | if (!pskb_may_pull(clone, fhoff + sizeof(*fhdr))) { |
783 | DEBUGP("message is too short.\n"); | 777 | pr_debug("message is too short.\n"); |
784 | goto ret_orig; | 778 | goto ret_orig; |
785 | } | 779 | } |
786 | 780 | ||
@@ -789,7 +783,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) | |||
789 | fhdr = (struct frag_hdr *)skb_transport_header(clone); | 783 | fhdr = (struct frag_hdr *)skb_transport_header(clone); |
790 | 784 | ||
791 | if (!(fhdr->frag_off & htons(0xFFF9))) { | 785 | if (!(fhdr->frag_off & htons(0xFFF9))) { |
792 | DEBUGP("Invalid fragment offset\n"); | 786 | pr_debug("Invalid fragment offset\n"); |
793 | /* It is not a fragmented frame */ | 787 | /* It is not a fragmented frame */ |
794 | goto ret_orig; | 788 | goto ret_orig; |
795 | } | 789 | } |
@@ -799,7 +793,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) | |||
799 | 793 | ||
800 | fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr); | 794 | fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr); |
801 | if (fq == NULL) { | 795 | if (fq == NULL) { |
802 | DEBUGP("Can't find and can't create new queue\n"); | 796 | pr_debug("Can't find and can't create new queue\n"); |
803 | goto ret_orig; | 797 | goto ret_orig; |
804 | } | 798 | } |
805 | 799 | ||
@@ -807,7 +801,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) | |||
807 | 801 | ||
808 | if (nf_ct_frag6_queue(fq, clone, fhdr, nhoff) < 0) { | 802 | if (nf_ct_frag6_queue(fq, clone, fhdr, nhoff) < 0) { |
809 | spin_unlock(&fq->lock); | 803 | spin_unlock(&fq->lock); |
810 | DEBUGP("Can't insert skb to queue\n"); | 804 | pr_debug("Can't insert skb to queue\n"); |
811 | fq_put(fq, NULL); | 805 | fq_put(fq, NULL); |
812 | goto ret_orig; | 806 | goto ret_orig; |
813 | } | 807 | } |
@@ -815,7 +809,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) | |||
815 | if (fq->last_in == (FIRST_IN|LAST_IN) && fq->meat == fq->len) { | 809 | if (fq->last_in == (FIRST_IN|LAST_IN) && fq->meat == fq->len) { |
816 | ret_skb = nf_ct_frag6_reasm(fq, dev); | 810 | ret_skb = nf_ct_frag6_reasm(fq, dev); |
817 | if (ret_skb == NULL) | 811 | if (ret_skb == NULL) |
818 | DEBUGP("Can't reassemble fragmented packets\n"); | 812 | pr_debug("Can't reassemble fragmented packets\n"); |
819 | } | 813 | } |
820 | spin_unlock(&fq->lock); | 814 | spin_unlock(&fq->lock); |
821 | 815 | ||
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index a58459a76684..e27383d855de 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -49,7 +49,7 @@ | |||
49 | #include <net/udp.h> | 49 | #include <net/udp.h> |
50 | #include <net/inet_common.h> | 50 | #include <net/inet_common.h> |
51 | #include <net/tcp_states.h> | 51 | #include <net/tcp_states.h> |
52 | #ifdef CONFIG_IPV6_MIP6 | 52 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
53 | #include <net/mip6.h> | 53 | #include <net/mip6.h> |
54 | #endif | 54 | #endif |
55 | 55 | ||
@@ -137,6 +137,28 @@ static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb) | |||
137 | return 0; | 137 | return 0; |
138 | } | 138 | } |
139 | 139 | ||
140 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | ||
141 | static int (*mh_filter)(struct sock *sock, struct sk_buff *skb); | ||
142 | |||
143 | int rawv6_mh_filter_register(int (*filter)(struct sock *sock, | ||
144 | struct sk_buff *skb)) | ||
145 | { | ||
146 | rcu_assign_pointer(mh_filter, filter); | ||
147 | return 0; | ||
148 | } | ||
149 | EXPORT_SYMBOL(rawv6_mh_filter_register); | ||
150 | |||
151 | int rawv6_mh_filter_unregister(int (*filter)(struct sock *sock, | ||
152 | struct sk_buff *skb)) | ||
153 | { | ||
154 | rcu_assign_pointer(mh_filter, NULL); | ||
155 | synchronize_rcu(); | ||
156 | return 0; | ||
157 | } | ||
158 | EXPORT_SYMBOL(rawv6_mh_filter_unregister); | ||
159 | |||
160 | #endif | ||
161 | |||
140 | /* | 162 | /* |
141 | * demultiplex raw sockets. | 163 | * demultiplex raw sockets. |
142 | * (should consider queueing the skb in the sock receive_queue | 164 | * (should consider queueing the skb in the sock receive_queue |
@@ -178,16 +200,22 @@ int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) | |||
178 | case IPPROTO_ICMPV6: | 200 | case IPPROTO_ICMPV6: |
179 | filtered = icmpv6_filter(sk, skb); | 201 | filtered = icmpv6_filter(sk, skb); |
180 | break; | 202 | break; |
181 | #ifdef CONFIG_IPV6_MIP6 | 203 | |
204 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | ||
182 | case IPPROTO_MH: | 205 | case IPPROTO_MH: |
206 | { | ||
183 | /* XXX: To validate MH only once for each packet, | 207 | /* XXX: To validate MH only once for each packet, |
184 | * this is placed here. It should be after checking | 208 | * this is placed here. It should be after checking |
185 | * xfrm policy, however it doesn't. The checking xfrm | 209 | * xfrm policy, however it doesn't. The checking xfrm |
186 | * policy is placed in rawv6_rcv() because it is | 210 | * policy is placed in rawv6_rcv() because it is |
187 | * required for each socket. | 211 | * required for each socket. |
188 | */ | 212 | */ |
189 | filtered = mip6_mh_filter(sk, skb); | 213 | int (*filter)(struct sock *sock, struct sk_buff *skb); |
214 | |||
215 | filter = rcu_dereference(mh_filter); | ||
216 | filtered = filter ? filter(sk, skb) : 0; | ||
190 | break; | 217 | break; |
218 | } | ||
191 | #endif | 219 | #endif |
192 | default: | 220 | default: |
193 | filtered = 0; | 221 | filtered = 0; |
@@ -611,9 +639,7 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) | |||
611 | struct iovec *iov; | 639 | struct iovec *iov; |
612 | u8 __user *type = NULL; | 640 | u8 __user *type = NULL; |
613 | u8 __user *code = NULL; | 641 | u8 __user *code = NULL; |
614 | #ifdef CONFIG_IPV6_MIP6 | ||
615 | u8 len = 0; | 642 | u8 len = 0; |
616 | #endif | ||
617 | int probed = 0; | 643 | int probed = 0; |
618 | int i; | 644 | int i; |
619 | 645 | ||
@@ -646,7 +672,6 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) | |||
646 | probed = 1; | 672 | probed = 1; |
647 | } | 673 | } |
648 | break; | 674 | break; |
649 | #ifdef CONFIG_IPV6_MIP6 | ||
650 | case IPPROTO_MH: | 675 | case IPPROTO_MH: |
651 | if (iov->iov_base && iov->iov_len < 1) | 676 | if (iov->iov_base && iov->iov_len < 1) |
652 | break; | 677 | break; |
@@ -660,7 +685,6 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) | |||
660 | len += iov->iov_len; | 685 | len += iov->iov_len; |
661 | 686 | ||
662 | break; | 687 | break; |
663 | #endif | ||
664 | default: | 688 | default: |
665 | probed = 1; | 689 | probed = 1; |
666 | break; | 690 | break; |
@@ -1256,7 +1280,7 @@ static int raw6_seq_show(struct seq_file *seq, void *v) | |||
1256 | return 0; | 1280 | return 0; |
1257 | } | 1281 | } |
1258 | 1282 | ||
1259 | static struct seq_operations raw6_seq_ops = { | 1283 | static const struct seq_operations raw6_seq_ops = { |
1260 | .start = raw6_seq_start, | 1284 | .start = raw6_seq_start, |
1261 | .next = raw6_seq_next, | 1285 | .next = raw6_seq_next, |
1262 | .stop = raw6_seq_stop, | 1286 | .stop = raw6_seq_stop, |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 1efa95a99f45..eb20bb690abd 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -532,7 +532,8 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
532 | */ | 532 | */ |
533 | max_headroom = LL_RESERVED_SPACE(tdev)+sizeof(struct iphdr); | 533 | max_headroom = LL_RESERVED_SPACE(tdev)+sizeof(struct iphdr); |
534 | 534 | ||
535 | if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) { | 535 | if (skb_headroom(skb) < max_headroom || skb_shared(skb) || |
536 | (skb_cloned(skb) && !skb_clone_writable(skb, 0))) { | ||
536 | struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); | 537 | struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); |
537 | if (!new_skb) { | 538 | if (!new_skb) { |
538 | ip_rt_put(rt); | 539 | ip_rt_put(rt); |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 193d9d60bb7a..d67fb1ef751e 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -484,17 +484,6 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
484 | 484 | ||
485 | if (dst == NULL) { | 485 | if (dst == NULL) { |
486 | opt = np->opt; | 486 | opt = np->opt; |
487 | if (opt == NULL && | ||
488 | np->rxopt.bits.osrcrt == 2 && | ||
489 | treq->pktopts) { | ||
490 | struct sk_buff *pktopts = treq->pktopts; | ||
491 | struct inet6_skb_parm *rxopt = IP6CB(pktopts); | ||
492 | if (rxopt->srcrt) | ||
493 | opt = ipv6_invert_rthdr(sk, | ||
494 | (struct ipv6_rt_hdr *)(skb_network_header(pktopts) + | ||
495 | rxopt->srcrt)); | ||
496 | } | ||
497 | |||
498 | if (opt && opt->srcrt) { | 487 | if (opt && opt->srcrt) { |
499 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; | 488 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; |
500 | ipv6_addr_copy(&final, &fl.fl6_dst); | 489 | ipv6_addr_copy(&final, &fl.fl6_dst); |
@@ -1391,15 +1380,6 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1391 | if (sk_acceptq_is_full(sk)) | 1380 | if (sk_acceptq_is_full(sk)) |
1392 | goto out_overflow; | 1381 | goto out_overflow; |
1393 | 1382 | ||
1394 | if (np->rxopt.bits.osrcrt == 2 && | ||
1395 | opt == NULL && treq->pktopts) { | ||
1396 | struct inet6_skb_parm *rxopt = IP6CB(treq->pktopts); | ||
1397 | if (rxopt->srcrt) | ||
1398 | opt = ipv6_invert_rthdr(sk, | ||
1399 | (struct ipv6_rt_hdr *)(skb_network_header(treq->pktopts) + | ||
1400 | rxopt->srcrt)); | ||
1401 | } | ||
1402 | |||
1403 | if (dst == NULL) { | 1383 | if (dst == NULL) { |
1404 | struct in6_addr *final_p = NULL, final; | 1384 | struct in6_addr *final_p = NULL, final; |
1405 | struct flowi fl; | 1385 | struct flowi fl; |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 1faa2ea80afc..3ec0c4770ee3 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include <net/ip.h> | 18 | #include <net/ip.h> |
19 | #include <net/ipv6.h> | 19 | #include <net/ipv6.h> |
20 | #include <net/ip6_route.h> | 20 | #include <net/ip6_route.h> |
21 | #ifdef CONFIG_IPV6_MIP6 | 21 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
22 | #include <net/mip6.h> | 22 | #include <net/mip6.h> |
23 | #endif | 23 | #endif |
24 | 24 | ||
@@ -318,7 +318,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl) | |||
318 | fl->proto = nexthdr; | 318 | fl->proto = nexthdr; |
319 | return; | 319 | return; |
320 | 320 | ||
321 | #ifdef CONFIG_IPV6_MIP6 | 321 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
322 | case IPPROTO_MH: | 322 | case IPPROTO_MH: |
323 | if (pskb_may_pull(skb, nh + offset + 3 - skb->data)) { | 323 | if (pskb_may_pull(skb, nh + offset + 3 - skb->data)) { |
324 | struct ip6_mh *mh; | 324 | struct ip6_mh *mh; |
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index baa461b9f74e..cdadb4847469 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
@@ -65,7 +65,7 @@ __xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n) | |||
65 | goto end; | 65 | goto end; |
66 | 66 | ||
67 | /* Rule 2: select MIPv6 RO or inbound trigger */ | 67 | /* Rule 2: select MIPv6 RO or inbound trigger */ |
68 | #ifdef CONFIG_IPV6_MIP6 | 68 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
69 | for (i = 0; i < n; i++) { | 69 | for (i = 0; i < n; i++) { |
70 | if (src[i] && | 70 | if (src[i] && |
71 | (src[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION || | 71 | (src[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION || |
@@ -130,7 +130,7 @@ __xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n) | |||
130 | goto end; | 130 | goto end; |
131 | 131 | ||
132 | /* Rule 2: select MIPv6 RO or inbound trigger */ | 132 | /* Rule 2: select MIPv6 RO or inbound trigger */ |
133 | #ifdef CONFIG_IPV6_MIP6 | 133 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
134 | for (i = 0; i < n; i++) { | 134 | for (i = 0; i < n; i++) { |
135 | if (src[i] && | 135 | if (src[i] && |
136 | (src[i]->mode == XFRM_MODE_ROUTEOPTIMIZATION || | 136 | (src[i]->mode == XFRM_MODE_ROUTEOPTIMIZATION || |
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 5502cc948dfb..6f87dd568ded 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c | |||
@@ -379,3 +379,4 @@ static void __exit xfrm6_tunnel_fini(void) | |||
379 | module_init(xfrm6_tunnel_init); | 379 | module_init(xfrm6_tunnel_init); |
380 | module_exit(xfrm6_tunnel_fini); | 380 | module_exit(xfrm6_tunnel_fini); |
381 | MODULE_LICENSE("GPL"); | 381 | MODULE_LICENSE("GPL"); |
382 | MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_IPV6); | ||
diff --git a/net/ipx/ipx_proc.c b/net/ipx/ipx_proc.c index db32ac8e79bd..4226e71ae1e3 100644 --- a/net/ipx/ipx_proc.c +++ b/net/ipx/ipx_proc.c | |||
@@ -286,21 +286,21 @@ out: | |||
286 | return 0; | 286 | return 0; |
287 | } | 287 | } |
288 | 288 | ||
289 | static struct seq_operations ipx_seq_interface_ops = { | 289 | static const struct seq_operations ipx_seq_interface_ops = { |
290 | .start = ipx_seq_interface_start, | 290 | .start = ipx_seq_interface_start, |
291 | .next = ipx_seq_interface_next, | 291 | .next = ipx_seq_interface_next, |
292 | .stop = ipx_seq_interface_stop, | 292 | .stop = ipx_seq_interface_stop, |
293 | .show = ipx_seq_interface_show, | 293 | .show = ipx_seq_interface_show, |
294 | }; | 294 | }; |
295 | 295 | ||
296 | static struct seq_operations ipx_seq_route_ops = { | 296 | static const struct seq_operations ipx_seq_route_ops = { |
297 | .start = ipx_seq_route_start, | 297 | .start = ipx_seq_route_start, |
298 | .next = ipx_seq_route_next, | 298 | .next = ipx_seq_route_next, |
299 | .stop = ipx_seq_route_stop, | 299 | .stop = ipx_seq_route_stop, |
300 | .show = ipx_seq_route_show, | 300 | .show = ipx_seq_route_show, |
301 | }; | 301 | }; |
302 | 302 | ||
303 | static struct seq_operations ipx_seq_socket_ops = { | 303 | static const struct seq_operations ipx_seq_socket_ops = { |
304 | .start = ipx_seq_socket_start, | 304 | .start = ipx_seq_socket_start, |
305 | .next = ipx_seq_socket_next, | 305 | .next = ipx_seq_socket_next, |
306 | .stop = ipx_seq_interface_stop, | 306 | .stop = ipx_seq_interface_stop, |
diff --git a/net/irda/Makefile b/net/irda/Makefile index d1366c2a39cb..187f6c563a4b 100644 --- a/net/irda/Makefile +++ b/net/irda/Makefile | |||
@@ -10,6 +10,6 @@ obj-$(CONFIG_IRCOMM) += ircomm/ | |||
10 | irda-y := iriap.o iriap_event.o irlmp.o irlmp_event.o irlmp_frame.o \ | 10 | irda-y := iriap.o iriap_event.o irlmp.o irlmp_event.o irlmp_frame.o \ |
11 | irlap.o irlap_event.o irlap_frame.o timer.o qos.o irqueue.o \ | 11 | irlap.o irlap_event.o irlap_frame.o timer.o qos.o irqueue.o \ |
12 | irttp.o irda_device.o irias_object.o wrapper.o af_irda.o \ | 12 | irttp.o irda_device.o irias_object.o wrapper.o af_irda.o \ |
13 | discovery.o parameters.o irmod.o | 13 | discovery.o parameters.o irnetlink.o irmod.o |
14 | irda-$(CONFIG_PROC_FS) += irproc.o | 14 | irda-$(CONFIG_PROC_FS) += irproc.o |
15 | irda-$(CONFIG_SYSCTL) += irsysctl.o | 15 | irda-$(CONFIG_SYSCTL) += irsysctl.o |
diff --git a/net/irda/discovery.c b/net/irda/discovery.c index f09734128674..af0cea721d2a 100644 --- a/net/irda/discovery.c +++ b/net/irda/discovery.c | |||
@@ -395,7 +395,7 @@ static int discovery_seq_show(struct seq_file *seq, void *v) | |||
395 | return 0; | 395 | return 0; |
396 | } | 396 | } |
397 | 397 | ||
398 | static struct seq_operations discovery_seq_ops = { | 398 | static const struct seq_operations discovery_seq_ops = { |
399 | .start = discovery_seq_start, | 399 | .start = discovery_seq_start, |
400 | .next = discovery_seq_next, | 400 | .next = discovery_seq_next, |
401 | .stop = discovery_seq_stop, | 401 | .stop = discovery_seq_stop, |
diff --git a/net/irda/ircomm/ircomm_core.c b/net/irda/ircomm/ircomm_core.c index 4749f8f55391..2d63fa8e1556 100644 --- a/net/irda/ircomm/ircomm_core.c +++ b/net/irda/ircomm/ircomm_core.c | |||
@@ -562,7 +562,7 @@ static int ircomm_seq_show(struct seq_file *seq, void *v) | |||
562 | return 0; | 562 | return 0; |
563 | } | 563 | } |
564 | 564 | ||
565 | static struct seq_operations ircomm_seq_ops = { | 565 | static const struct seq_operations ircomm_seq_ops = { |
566 | .start = ircomm_seq_start, | 566 | .start = ircomm_seq_start, |
567 | .next = ircomm_seq_next, | 567 | .next = ircomm_seq_next, |
568 | .stop = ircomm_seq_stop, | 568 | .stop = ircomm_seq_stop, |
diff --git a/net/irda/iriap.c b/net/irda/iriap.c index 915d9384f36a..774eb707940c 100644 --- a/net/irda/iriap.c +++ b/net/irda/iriap.c | |||
@@ -1066,7 +1066,7 @@ static int irias_seq_show(struct seq_file *seq, void *v) | |||
1066 | return 0; | 1066 | return 0; |
1067 | } | 1067 | } |
1068 | 1068 | ||
1069 | static struct seq_operations irias_seq_ops = { | 1069 | static const struct seq_operations irias_seq_ops = { |
1070 | .start = irias_seq_start, | 1070 | .start = irias_seq_start, |
1071 | .next = irias_seq_next, | 1071 | .next = irias_seq_next, |
1072 | .stop = irias_seq_stop, | 1072 | .stop = irias_seq_stop, |
diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c index ed69773b0f8e..f5778ef3ccc7 100644 --- a/net/irda/irlan/irlan_common.c +++ b/net/irda/irlan/irlan_common.c | |||
@@ -1217,7 +1217,7 @@ static int irlan_seq_show(struct seq_file *seq, void *v) | |||
1217 | return 0; | 1217 | return 0; |
1218 | } | 1218 | } |
1219 | 1219 | ||
1220 | static struct seq_operations irlan_seq_ops = { | 1220 | static const struct seq_operations irlan_seq_ops = { |
1221 | .start = irlan_seq_start, | 1221 | .start = irlan_seq_start, |
1222 | .next = irlan_seq_next, | 1222 | .next = irlan_seq_next, |
1223 | .stop = irlan_seq_stop, | 1223 | .stop = irlan_seq_stop, |
diff --git a/net/irda/irlap.c b/net/irda/irlap.c index d93ebd11431e..2fc9f518f89d 100644 --- a/net/irda/irlap.c +++ b/net/irda/irlap.c | |||
@@ -1210,7 +1210,7 @@ static int irlap_seq_show(struct seq_file *seq, void *v) | |||
1210 | return 0; | 1210 | return 0; |
1211 | } | 1211 | } |
1212 | 1212 | ||
1213 | static struct seq_operations irlap_seq_ops = { | 1213 | static const struct seq_operations irlap_seq_ops = { |
1214 | .start = irlap_seq_start, | 1214 | .start = irlap_seq_start, |
1215 | .next = irlap_seq_next, | 1215 | .next = irlap_seq_next, |
1216 | .stop = irlap_seq_stop, | 1216 | .stop = irlap_seq_stop, |
diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c index 3013c49ab975..25a3444a9234 100644 --- a/net/irda/irlap_frame.c +++ b/net/irda/irlap_frame.c | |||
@@ -101,6 +101,13 @@ void irlap_queue_xmit(struct irlap_cb *self, struct sk_buff *skb) | |||
101 | 101 | ||
102 | irlap_insert_info(self, skb); | 102 | irlap_insert_info(self, skb); |
103 | 103 | ||
104 | if (unlikely(self->mode & IRDA_MODE_MONITOR)) { | ||
105 | IRDA_DEBUG(3, "%s(): %s is in monitor mode\n", __FUNCTION__, | ||
106 | self->netdev->name); | ||
107 | dev_kfree_skb(skb); | ||
108 | return; | ||
109 | } | ||
110 | |||
104 | dev_queue_xmit(skb); | 111 | dev_queue_xmit(skb); |
105 | } | 112 | } |
106 | 113 | ||
diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c index 9df0461b6d18..24a5e3f23778 100644 --- a/net/irda/irlmp.c +++ b/net/irda/irlmp.c | |||
@@ -1994,7 +1994,7 @@ static int irlmp_seq_show(struct seq_file *seq, void *v) | |||
1994 | return 0; | 1994 | return 0; |
1995 | } | 1995 | } |
1996 | 1996 | ||
1997 | static struct seq_operations irlmp_seq_ops = { | 1997 | static const struct seq_operations irlmp_seq_ops = { |
1998 | .start = irlmp_seq_start, | 1998 | .start = irlmp_seq_start, |
1999 | .next = irlmp_seq_next, | 1999 | .next = irlmp_seq_next, |
2000 | .stop = irlmp_seq_stop, | 2000 | .stop = irlmp_seq_stop, |
diff --git a/net/irda/irmod.c b/net/irda/irmod.c index c7fad2c5b9f3..1900937b3328 100644 --- a/net/irda/irmod.c +++ b/net/irda/irmod.c | |||
@@ -88,16 +88,23 @@ EXPORT_SYMBOL(irda_notify_init); | |||
88 | */ | 88 | */ |
89 | static int __init irda_init(void) | 89 | static int __init irda_init(void) |
90 | { | 90 | { |
91 | int ret = 0; | ||
92 | |||
91 | IRDA_DEBUG(0, "%s()\n", __FUNCTION__); | 93 | IRDA_DEBUG(0, "%s()\n", __FUNCTION__); |
92 | 94 | ||
93 | /* Lower layer of the stack */ | 95 | /* Lower layer of the stack */ |
94 | irlmp_init(); | 96 | irlmp_init(); |
95 | irlap_init(); | 97 | irlap_init(); |
96 | 98 | ||
99 | /* Driver/dongle support */ | ||
100 | irda_device_init(); | ||
101 | |||
97 | /* Higher layers of the stack */ | 102 | /* Higher layers of the stack */ |
98 | iriap_init(); | 103 | iriap_init(); |
99 | irttp_init(); | 104 | irttp_init(); |
100 | irsock_init(); | 105 | ret = irsock_init(); |
106 | if (ret < 0) | ||
107 | goto out_err_1; | ||
101 | 108 | ||
102 | /* Add IrDA packet type (Start receiving packets) */ | 109 | /* Add IrDA packet type (Start receiving packets) */ |
103 | dev_add_pack(&irda_packet_type); | 110 | dev_add_pack(&irda_packet_type); |
@@ -107,13 +114,44 @@ static int __init irda_init(void) | |||
107 | irda_proc_register(); | 114 | irda_proc_register(); |
108 | #endif | 115 | #endif |
109 | #ifdef CONFIG_SYSCTL | 116 | #ifdef CONFIG_SYSCTL |
110 | irda_sysctl_register(); | 117 | ret = irda_sysctl_register(); |
118 | if (ret < 0) | ||
119 | goto out_err_2; | ||
111 | #endif | 120 | #endif |
112 | 121 | ||
113 | /* Driver/dongle support */ | 122 | ret = irda_nl_register(); |
114 | irda_device_init(); | 123 | if (ret < 0) |
124 | goto out_err_3; | ||
115 | 125 | ||
116 | return 0; | 126 | return 0; |
127 | |||
128 | out_err_3: | ||
129 | #ifdef CONFIG_SYSCTL | ||
130 | irda_sysctl_unregister(); | ||
131 | #endif | ||
132 | out_err_2: | ||
133 | #ifdef CONFIG_PROC_FS | ||
134 | irda_proc_unregister(); | ||
135 | #endif | ||
136 | |||
137 | /* Remove IrDA packet type (stop receiving packets) */ | ||
138 | dev_remove_pack(&irda_packet_type); | ||
139 | |||
140 | /* Remove higher layers */ | ||
141 | irsock_cleanup(); | ||
142 | out_err_1: | ||
143 | irttp_cleanup(); | ||
144 | iriap_cleanup(); | ||
145 | |||
146 | /* Remove lower layers */ | ||
147 | irda_device_cleanup(); | ||
148 | irlap_cleanup(); /* Must be done before irlmp_cleanup()! DB */ | ||
149 | |||
150 | /* Remove middle layer */ | ||
151 | irlmp_cleanup(); | ||
152 | |||
153 | |||
154 | return ret; | ||
117 | } | 155 | } |
118 | 156 | ||
119 | /* | 157 | /* |
@@ -125,6 +163,8 @@ static int __init irda_init(void) | |||
125 | static void __exit irda_cleanup(void) | 163 | static void __exit irda_cleanup(void) |
126 | { | 164 | { |
127 | /* Remove External APIs */ | 165 | /* Remove External APIs */ |
166 | irda_nl_unregister(); | ||
167 | |||
128 | #ifdef CONFIG_SYSCTL | 168 | #ifdef CONFIG_SYSCTL |
129 | irda_sysctl_unregister(); | 169 | irda_sysctl_unregister(); |
130 | #endif | 170 | #endif |
diff --git a/net/irda/irnetlink.c b/net/irda/irnetlink.c new file mode 100644 index 000000000000..db716580e1ae --- /dev/null +++ b/net/irda/irnetlink.c | |||
@@ -0,0 +1,170 @@ | |||
1 | /* | ||
2 | * IrDA netlink layer, for stack configuration. | ||
3 | * | ||
4 | * Copyright (c) 2007 Samuel Ortiz <samuel@sortiz> | ||
5 | * | ||
6 | * Partly based on the 802.11 nelink implementation | ||
7 | * (see net/wireless/nl80211.c) which is: | ||
8 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/socket.h> | ||
17 | #include <linux/irda.h> | ||
18 | #include <net/sock.h> | ||
19 | #include <net/irda/irda.h> | ||
20 | #include <net/irda/irlap.h> | ||
21 | #include <net/genetlink.h> | ||
22 | |||
23 | |||
24 | |||
25 | static struct genl_family irda_nl_family = { | ||
26 | .id = GENL_ID_GENERATE, | ||
27 | .name = IRDA_NL_NAME, | ||
28 | .hdrsize = 0, | ||
29 | .version = IRDA_NL_VERSION, | ||
30 | .maxattr = IRDA_NL_CMD_MAX, | ||
31 | }; | ||
32 | |||
33 | static struct net_device * ifname_to_netdev(struct genl_info *info) | ||
34 | { | ||
35 | char * ifname; | ||
36 | |||
37 | if (!info->attrs[IRDA_NL_ATTR_IFNAME]) | ||
38 | return NULL; | ||
39 | |||
40 | ifname = nla_data(info->attrs[IRDA_NL_ATTR_IFNAME]); | ||
41 | |||
42 | IRDA_DEBUG(5, "%s(): Looking for %s\n", __FUNCTION__, ifname); | ||
43 | |||
44 | return dev_get_by_name(ifname); | ||
45 | } | ||
46 | |||
47 | static int irda_nl_set_mode(struct sk_buff *skb, struct genl_info *info) | ||
48 | { | ||
49 | struct net_device * dev; | ||
50 | struct irlap_cb * irlap; | ||
51 | u32 mode; | ||
52 | |||
53 | if (!info->attrs[IRDA_NL_ATTR_MODE]) | ||
54 | return -EINVAL; | ||
55 | |||
56 | mode = nla_get_u32(info->attrs[IRDA_NL_ATTR_MODE]); | ||
57 | |||
58 | IRDA_DEBUG(5, "%s(): Switching to mode: %d\n", __FUNCTION__, mode); | ||
59 | |||
60 | dev = ifname_to_netdev(info); | ||
61 | if (!dev) | ||
62 | return -ENODEV; | ||
63 | |||
64 | irlap = (struct irlap_cb *)dev->atalk_ptr; | ||
65 | if (!irlap) { | ||
66 | dev_put(dev); | ||
67 | return -ENODEV; | ||
68 | } | ||
69 | |||
70 | irlap->mode = mode; | ||
71 | |||
72 | dev_put(dev); | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static int irda_nl_get_mode(struct sk_buff *skb, struct genl_info *info) | ||
78 | { | ||
79 | struct net_device * dev; | ||
80 | struct irlap_cb * irlap; | ||
81 | struct sk_buff *msg; | ||
82 | void *hdr; | ||
83 | int ret = -ENOBUFS; | ||
84 | |||
85 | dev = ifname_to_netdev(info); | ||
86 | if (!dev) | ||
87 | return -ENODEV; | ||
88 | |||
89 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
90 | if (!msg) { | ||
91 | dev_put(dev); | ||
92 | return -ENOMEM; | ||
93 | } | ||
94 | |||
95 | irlap = (struct irlap_cb *)dev->atalk_ptr; | ||
96 | if (!irlap) { | ||
97 | ret = -ENODEV; | ||
98 | goto err_out; | ||
99 | } | ||
100 | |||
101 | hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, | ||
102 | &irda_nl_family, 0, IRDA_NL_CMD_GET_MODE); | ||
103 | if (IS_ERR(hdr)) { | ||
104 | ret = PTR_ERR(hdr); | ||
105 | goto err_out; | ||
106 | } | ||
107 | |||
108 | if(nla_put_string(msg, IRDA_NL_ATTR_IFNAME, | ||
109 | dev->name)); | ||
110 | goto err_out; | ||
111 | |||
112 | if(nla_put_u32(msg, IRDA_NL_ATTR_MODE, irlap->mode)) | ||
113 | goto err_out; | ||
114 | |||
115 | genlmsg_end(msg, hdr); | ||
116 | |||
117 | return genlmsg_unicast(msg, info->snd_pid); | ||
118 | |||
119 | err_out: | ||
120 | nlmsg_free(msg); | ||
121 | dev_put(dev); | ||
122 | |||
123 | return ret; | ||
124 | } | ||
125 | |||
126 | static struct nla_policy irda_nl_policy[IRDA_NL_ATTR_MAX + 1] = { | ||
127 | [IRDA_NL_ATTR_IFNAME] = { .type = NLA_NUL_STRING, | ||
128 | .len = IFNAMSIZ-1 }, | ||
129 | [IRDA_NL_ATTR_MODE] = { .type = NLA_U32 }, | ||
130 | }; | ||
131 | |||
132 | static struct genl_ops irda_nl_ops[] = { | ||
133 | { | ||
134 | .cmd = IRDA_NL_CMD_SET_MODE, | ||
135 | .doit = irda_nl_set_mode, | ||
136 | .policy = irda_nl_policy, | ||
137 | .flags = GENL_ADMIN_PERM, | ||
138 | }, | ||
139 | { | ||
140 | .cmd = IRDA_NL_CMD_GET_MODE, | ||
141 | .doit = irda_nl_get_mode, | ||
142 | .policy = irda_nl_policy, | ||
143 | /* can be retrieved by unprivileged users */ | ||
144 | }, | ||
145 | |||
146 | }; | ||
147 | |||
148 | int irda_nl_register(void) | ||
149 | { | ||
150 | int err, i; | ||
151 | |||
152 | err = genl_register_family(&irda_nl_family); | ||
153 | if (err) | ||
154 | return err; | ||
155 | |||
156 | for (i = 0; i < ARRAY_SIZE(irda_nl_ops); i++) { | ||
157 | err = genl_register_ops(&irda_nl_family, &irda_nl_ops[i]); | ||
158 | if (err) | ||
159 | goto err_out; | ||
160 | } | ||
161 | return 0; | ||
162 | err_out: | ||
163 | genl_unregister_family(&irda_nl_family); | ||
164 | return err; | ||
165 | } | ||
166 | |||
167 | void irda_nl_unregister(void) | ||
168 | { | ||
169 | genl_unregister_family(&irda_nl_family); | ||
170 | } | ||
diff --git a/net/irda/irttp.c b/net/irda/irttp.c index 7069e4a58257..7f50832a2cd5 100644 --- a/net/irda/irttp.c +++ b/net/irda/irttp.c | |||
@@ -369,6 +369,20 @@ static int irttp_param_max_sdu_size(void *instance, irda_param_t *param, | |||
369 | /* Everything is happily mixed up. Waiting for next clean up - Jean II */ | 369 | /* Everything is happily mixed up. Waiting for next clean up - Jean II */ |
370 | 370 | ||
371 | /* | 371 | /* |
372 | * Initialization, that has to be done on new tsap | ||
373 | * instance allocation and on duplication | ||
374 | */ | ||
375 | static void irttp_init_tsap(struct tsap_cb *tsap) | ||
376 | { | ||
377 | spin_lock_init(&tsap->lock); | ||
378 | init_timer(&tsap->todo_timer); | ||
379 | |||
380 | skb_queue_head_init(&tsap->rx_queue); | ||
381 | skb_queue_head_init(&tsap->tx_queue); | ||
382 | skb_queue_head_init(&tsap->rx_fragments); | ||
383 | } | ||
384 | |||
385 | /* | ||
372 | * Function irttp_open_tsap (stsap, notify) | 386 | * Function irttp_open_tsap (stsap, notify) |
373 | * | 387 | * |
374 | * Create TSAP connection endpoint, | 388 | * Create TSAP connection endpoint, |
@@ -395,10 +409,11 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify) | |||
395 | IRDA_DEBUG(0, "%s(), unable to kmalloc!\n", __FUNCTION__); | 409 | IRDA_DEBUG(0, "%s(), unable to kmalloc!\n", __FUNCTION__); |
396 | return NULL; | 410 | return NULL; |
397 | } | 411 | } |
398 | spin_lock_init(&self->lock); | 412 | |
413 | /* Initialize internal objects */ | ||
414 | irttp_init_tsap(self); | ||
399 | 415 | ||
400 | /* Initialise todo timer */ | 416 | /* Initialise todo timer */ |
401 | init_timer(&self->todo_timer); | ||
402 | self->todo_timer.data = (unsigned long) self; | 417 | self->todo_timer.data = (unsigned long) self; |
403 | self->todo_timer.function = &irttp_todo_expired; | 418 | self->todo_timer.function = &irttp_todo_expired; |
404 | 419 | ||
@@ -418,9 +433,6 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify) | |||
418 | self->magic = TTP_TSAP_MAGIC; | 433 | self->magic = TTP_TSAP_MAGIC; |
419 | self->connected = FALSE; | 434 | self->connected = FALSE; |
420 | 435 | ||
421 | skb_queue_head_init(&self->rx_queue); | ||
422 | skb_queue_head_init(&self->tx_queue); | ||
423 | skb_queue_head_init(&self->rx_fragments); | ||
424 | /* | 436 | /* |
425 | * Create LSAP at IrLMP layer | 437 | * Create LSAP at IrLMP layer |
426 | */ | 438 | */ |
@@ -1455,12 +1467,9 @@ struct tsap_cb *irttp_dup(struct tsap_cb *orig, void *instance) | |||
1455 | 1467 | ||
1456 | /* Not everything should be copied */ | 1468 | /* Not everything should be copied */ |
1457 | new->notify.instance = instance; | 1469 | new->notify.instance = instance; |
1458 | spin_lock_init(&new->lock); | ||
1459 | init_timer(&new->todo_timer); | ||
1460 | 1470 | ||
1461 | skb_queue_head_init(&new->rx_queue); | 1471 | /* Initialize internal objects */ |
1462 | skb_queue_head_init(&new->tx_queue); | 1472 | irttp_init_tsap(new); |
1463 | skb_queue_head_init(&new->rx_fragments); | ||
1464 | 1473 | ||
1465 | /* This is locked */ | 1474 | /* This is locked */ |
1466 | hashbin_insert(irttp->tsaps, (irda_queue_t *) new, (long) new, NULL); | 1475 | hashbin_insert(irttp->tsaps, (irda_queue_t *) new, (long) new, NULL); |
@@ -1866,7 +1875,7 @@ static int irttp_seq_show(struct seq_file *seq, void *v) | |||
1866 | return 0; | 1875 | return 0; |
1867 | } | 1876 | } |
1868 | 1877 | ||
1869 | static struct seq_operations irttp_seq_ops = { | 1878 | static const struct seq_operations irttp_seq_ops = { |
1870 | .start = irttp_seq_start, | 1879 | .start = irttp_seq_start, |
1871 | .next = irttp_seq_next, | 1880 | .next = irttp_seq_next, |
1872 | .stop = irttp_seq_stop, | 1881 | .stop = irttp_seq_stop, |
diff --git a/net/iucv/Kconfig b/net/iucv/Kconfig index f8fcc3d10327..16ce9cd4f39e 100644 --- a/net/iucv/Kconfig +++ b/net/iucv/Kconfig | |||
@@ -1,13 +1,13 @@ | |||
1 | config IUCV | 1 | config IUCV |
2 | tristate "IUCV support (VM only)" | 2 | tristate "IUCV support (S390 - z/VM only)" |
3 | depends on S390 | 3 | depends on S390 |
4 | help | 4 | help |
5 | Select this option if you want to use inter-user communication under | 5 | Select this option if you want to use inter-user communication |
6 | VM or VIF sockets. If you run on z/VM, say "Y" to enable a fast | 6 | under VM or VIF. If you run on z/VM, say "Y" to enable a fast |
7 | communication link between VM guests. | 7 | communication link between VM guests. |
8 | 8 | ||
9 | config AFIUCV | 9 | config AFIUCV |
10 | tristate "AF_IUCV support (VM only)" | 10 | tristate "AF_IUCV support (S390 - z/VM only)" |
11 | depends on IUCV | 11 | depends on IUCV |
12 | help | 12 | help |
13 | Select this option if you want to use inter-user communication under | 13 | Select this option if you want to use inter-user communication under |
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index d9e9ddb8eac5..53ae14c35f70 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
@@ -219,6 +219,7 @@ static struct sock *iucv_sock_alloc(struct socket *sock, int proto, gfp_t prio) | |||
219 | 219 | ||
220 | sock_init_data(sock, sk); | 220 | sock_init_data(sock, sk); |
221 | INIT_LIST_HEAD(&iucv_sk(sk)->accept_q); | 221 | INIT_LIST_HEAD(&iucv_sk(sk)->accept_q); |
222 | spin_lock_init(&iucv_sk(sk)->accept_q_lock); | ||
222 | skb_queue_head_init(&iucv_sk(sk)->send_skb_q); | 223 | skb_queue_head_init(&iucv_sk(sk)->send_skb_q); |
223 | skb_queue_head_init(&iucv_sk(sk)->backlog_skb_q); | 224 | skb_queue_head_init(&iucv_sk(sk)->backlog_skb_q); |
224 | iucv_sk(sk)->send_tag = 0; | 225 | iucv_sk(sk)->send_tag = 0; |
@@ -274,15 +275,25 @@ void iucv_sock_unlink(struct iucv_sock_list *l, struct sock *sk) | |||
274 | 275 | ||
275 | void iucv_accept_enqueue(struct sock *parent, struct sock *sk) | 276 | void iucv_accept_enqueue(struct sock *parent, struct sock *sk) |
276 | { | 277 | { |
278 | unsigned long flags; | ||
279 | struct iucv_sock *par = iucv_sk(parent); | ||
280 | |||
277 | sock_hold(sk); | 281 | sock_hold(sk); |
278 | list_add_tail(&iucv_sk(sk)->accept_q, &iucv_sk(parent)->accept_q); | 282 | spin_lock_irqsave(&par->accept_q_lock, flags); |
283 | list_add_tail(&iucv_sk(sk)->accept_q, &par->accept_q); | ||
284 | spin_unlock_irqrestore(&par->accept_q_lock, flags); | ||
279 | iucv_sk(sk)->parent = parent; | 285 | iucv_sk(sk)->parent = parent; |
280 | parent->sk_ack_backlog++; | 286 | parent->sk_ack_backlog++; |
281 | } | 287 | } |
282 | 288 | ||
283 | void iucv_accept_unlink(struct sock *sk) | 289 | void iucv_accept_unlink(struct sock *sk) |
284 | { | 290 | { |
291 | unsigned long flags; | ||
292 | struct iucv_sock *par = iucv_sk(iucv_sk(sk)->parent); | ||
293 | |||
294 | spin_lock_irqsave(&par->accept_q_lock, flags); | ||
285 | list_del_init(&iucv_sk(sk)->accept_q); | 295 | list_del_init(&iucv_sk(sk)->accept_q); |
296 | spin_unlock_irqrestore(&par->accept_q_lock, flags); | ||
286 | iucv_sk(sk)->parent->sk_ack_backlog--; | 297 | iucv_sk(sk)->parent->sk_ack_backlog--; |
287 | iucv_sk(sk)->parent = NULL; | 298 | iucv_sk(sk)->parent = NULL; |
288 | sock_put(sk); | 299 | sock_put(sk); |
@@ -298,8 +309,8 @@ struct sock *iucv_accept_dequeue(struct sock *parent, struct socket *newsock) | |||
298 | lock_sock(sk); | 309 | lock_sock(sk); |
299 | 310 | ||
300 | if (sk->sk_state == IUCV_CLOSED) { | 311 | if (sk->sk_state == IUCV_CLOSED) { |
301 | release_sock(sk); | ||
302 | iucv_accept_unlink(sk); | 312 | iucv_accept_unlink(sk); |
313 | release_sock(sk); | ||
303 | continue; | 314 | continue; |
304 | } | 315 | } |
305 | 316 | ||
@@ -879,6 +890,7 @@ static int iucv_callback_connreq(struct iucv_path *path, | |||
879 | /* Find out if this path belongs to af_iucv. */ | 890 | /* Find out if this path belongs to af_iucv. */ |
880 | read_lock(&iucv_sk_list.lock); | 891 | read_lock(&iucv_sk_list.lock); |
881 | iucv = NULL; | 892 | iucv = NULL; |
893 | sk = NULL; | ||
882 | sk_for_each(sk, node, &iucv_sk_list.head) | 894 | sk_for_each(sk, node, &iucv_sk_list.head) |
883 | if (sk->sk_state == IUCV_LISTEN && | 895 | if (sk->sk_state == IUCV_LISTEN && |
884 | !memcmp(&iucv_sk(sk)->src_name, src_name, 8)) { | 896 | !memcmp(&iucv_sk(sk)->src_name, src_name, 8)) { |
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index b7333061016d..ad5150b8dfa9 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c | |||
@@ -1494,7 +1494,10 @@ static void iucv_tasklet_fn(unsigned long ignored) | |||
1494 | struct iucv_irq_list *p, *n; | 1494 | struct iucv_irq_list *p, *n; |
1495 | 1495 | ||
1496 | /* Serialize tasklet, iucv_path_sever and iucv_path_connect. */ | 1496 | /* Serialize tasklet, iucv_path_sever and iucv_path_connect. */ |
1497 | spin_lock(&iucv_table_lock); | 1497 | if (!spin_trylock(&iucv_table_lock)) { |
1498 | tasklet_schedule(&iucv_tasklet); | ||
1499 | return; | ||
1500 | } | ||
1498 | iucv_active_cpu = smp_processor_id(); | 1501 | iucv_active_cpu = smp_processor_id(); |
1499 | 1502 | ||
1500 | spin_lock_irq(&iucv_queue_lock); | 1503 | spin_lock_irq(&iucv_queue_lock); |
diff --git a/net/llc/llc_proc.c b/net/llc/llc_proc.c index 3ab9d9f8b17f..49be6c902c83 100644 --- a/net/llc/llc_proc.c +++ b/net/llc/llc_proc.c | |||
@@ -184,14 +184,14 @@ out: | |||
184 | return 0; | 184 | return 0; |
185 | } | 185 | } |
186 | 186 | ||
187 | static struct seq_operations llc_seq_socket_ops = { | 187 | static const struct seq_operations llc_seq_socket_ops = { |
188 | .start = llc_seq_start, | 188 | .start = llc_seq_start, |
189 | .next = llc_seq_next, | 189 | .next = llc_seq_next, |
190 | .stop = llc_seq_stop, | 190 | .stop = llc_seq_stop, |
191 | .show = llc_seq_socket_show, | 191 | .show = llc_seq_socket_show, |
192 | }; | 192 | }; |
193 | 193 | ||
194 | static struct seq_operations llc_seq_core_ops = { | 194 | static const struct seq_operations llc_seq_core_ops = { |
195 | .start = llc_seq_start, | 195 | .start = llc_seq_start, |
196 | .next = llc_seq_next, | 196 | .next = llc_seq_next, |
197 | .stop = llc_seq_stop, | 197 | .stop = llc_seq_stop, |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 9e3964638bad..a3e01d76d503 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -118,7 +118,7 @@ static ssize_t ieee80211_if_fmt_flags( | |||
118 | sdata->u.sta.authenticated ? "AUTH\n" : "", | 118 | sdata->u.sta.authenticated ? "AUTH\n" : "", |
119 | sdata->u.sta.associated ? "ASSOC\n" : "", | 119 | sdata->u.sta.associated ? "ASSOC\n" : "", |
120 | sdata->u.sta.probereq_poll ? "PROBEREQ POLL\n" : "", | 120 | sdata->u.sta.probereq_poll ? "PROBEREQ POLL\n" : "", |
121 | sdata->u.sta.use_protection ? "CTS prot\n" : ""); | 121 | sdata->use_protection ? "CTS prot\n" : ""); |
122 | } | 122 | } |
123 | __IEEE80211_IF_FILE(flags); | 123 | __IEEE80211_IF_FILE(flags); |
124 | 124 | ||
diff --git a/net/mac80211/hostapd_ioctl.h b/net/mac80211/hostapd_ioctl.h index 34fa128e9872..52da513f060a 100644 --- a/net/mac80211/hostapd_ioctl.h +++ b/net/mac80211/hostapd_ioctl.h | |||
@@ -26,24 +26,16 @@ | |||
26 | * mess shall be deleted completely. */ | 26 | * mess shall be deleted completely. */ |
27 | enum { | 27 | enum { |
28 | PRISM2_PARAM_IEEE_802_1X = 23, | 28 | PRISM2_PARAM_IEEE_802_1X = 23, |
29 | PRISM2_PARAM_ANTSEL_TX = 24, | ||
30 | PRISM2_PARAM_ANTSEL_RX = 25, | ||
31 | 29 | ||
32 | /* Instant802 additions */ | 30 | /* Instant802 additions */ |
33 | PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES = 1001, | 31 | PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES = 1001, |
34 | PRISM2_PARAM_DROP_UNENCRYPTED = 1002, | ||
35 | PRISM2_PARAM_PREAMBLE = 1003, | 32 | PRISM2_PARAM_PREAMBLE = 1003, |
36 | PRISM2_PARAM_SHORT_SLOT_TIME = 1006, | 33 | PRISM2_PARAM_SHORT_SLOT_TIME = 1006, |
37 | PRISM2_PARAM_NEXT_MODE = 1008, | 34 | PRISM2_PARAM_NEXT_MODE = 1008, |
38 | PRISM2_PARAM_CLEAR_KEYS = 1009, | ||
39 | PRISM2_PARAM_RADIO_ENABLED = 1010, | 35 | PRISM2_PARAM_RADIO_ENABLED = 1010, |
40 | PRISM2_PARAM_ANTENNA_MODE = 1013, | 36 | PRISM2_PARAM_ANTENNA_MODE = 1013, |
41 | PRISM2_PARAM_STAT_TIME = 1016, | 37 | PRISM2_PARAM_STAT_TIME = 1016, |
42 | PRISM2_PARAM_STA_ANTENNA_SEL = 1017, | 38 | PRISM2_PARAM_STA_ANTENNA_SEL = 1017, |
43 | PRISM2_PARAM_FORCE_UNICAST_RATE = 1018, | ||
44 | PRISM2_PARAM_RATE_CTRL_NUM_UP = 1019, | ||
45 | PRISM2_PARAM_RATE_CTRL_NUM_DOWN = 1020, | ||
46 | PRISM2_PARAM_MAX_RATECTRL_RATE = 1021, | ||
47 | PRISM2_PARAM_TX_POWER_REDUCTION = 1022, | 39 | PRISM2_PARAM_TX_POWER_REDUCTION = 1022, |
48 | PRISM2_PARAM_KEY_TX_RX_THRESHOLD = 1024, | 40 | PRISM2_PARAM_KEY_TX_RX_THRESHOLD = 1024, |
49 | PRISM2_PARAM_DEFAULT_WEP_ONLY = 1026, | 41 | PRISM2_PARAM_DEFAULT_WEP_ONLY = 1026, |
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index 4e84f24fd439..2ddf4ef4065e 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/compiler.h> | 24 | #include <linux/compiler.h> |
25 | #include <linux/bitmap.h> | 25 | #include <linux/bitmap.h> |
26 | #include <net/cfg80211.h> | 26 | #include <net/cfg80211.h> |
27 | #include <asm/unaligned.h> | ||
27 | 28 | ||
28 | #include "ieee80211_common.h" | 29 | #include "ieee80211_common.h" |
29 | #include "ieee80211_i.h" | 30 | #include "ieee80211_i.h" |
@@ -56,6 +57,17 @@ static const unsigned char eapol_header[] = | |||
56 | { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e }; | 57 | { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e }; |
57 | 58 | ||
58 | 59 | ||
60 | /* | ||
61 | * For seeing transmitted packets on monitor interfaces | ||
62 | * we have a radiotap header too. | ||
63 | */ | ||
64 | struct ieee80211_tx_status_rtap_hdr { | ||
65 | struct ieee80211_radiotap_header hdr; | ||
66 | __le16 tx_flags; | ||
67 | u8 data_retries; | ||
68 | } __attribute__ ((packed)); | ||
69 | |||
70 | |||
59 | static inline void ieee80211_include_sequence(struct ieee80211_sub_if_data *sdata, | 71 | static inline void ieee80211_include_sequence(struct ieee80211_sub_if_data *sdata, |
60 | struct ieee80211_hdr *hdr) | 72 | struct ieee80211_hdr *hdr) |
61 | { | 73 | { |
@@ -430,7 +442,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_txrx_data *tx) | |||
430 | if (!tx->u.tx.rate) | 442 | if (!tx->u.tx.rate) |
431 | return TXRX_DROP; | 443 | return TXRX_DROP; |
432 | if (tx->u.tx.mode->mode == MODE_IEEE80211G && | 444 | if (tx->u.tx.mode->mode == MODE_IEEE80211G && |
433 | tx->local->cts_protect_erp_frames && tx->fragmented && | 445 | tx->sdata->use_protection && tx->fragmented && |
434 | extra.nonerp) { | 446 | extra.nonerp) { |
435 | tx->u.tx.last_frag_rate = tx->u.tx.rate; | 447 | tx->u.tx.last_frag_rate = tx->u.tx.rate; |
436 | tx->u.tx.probe_last_frag = extra.probe ? 1 : 0; | 448 | tx->u.tx.probe_last_frag = extra.probe ? 1 : 0; |
@@ -528,7 +540,7 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx) | |||
528 | /* reserve enough extra head and tail room for possible | 540 | /* reserve enough extra head and tail room for possible |
529 | * encryption */ | 541 | * encryption */ |
530 | frag = frags[i] = | 542 | frag = frags[i] = |
531 | dev_alloc_skb(tx->local->hw.extra_tx_headroom + | 543 | dev_alloc_skb(tx->local->tx_headroom + |
532 | frag_threshold + | 544 | frag_threshold + |
533 | IEEE80211_ENCRYPT_HEADROOM + | 545 | IEEE80211_ENCRYPT_HEADROOM + |
534 | IEEE80211_ENCRYPT_TAILROOM); | 546 | IEEE80211_ENCRYPT_TAILROOM); |
@@ -537,8 +549,8 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx) | |||
537 | /* Make sure that all fragments use the same priority so | 549 | /* Make sure that all fragments use the same priority so |
538 | * that they end up using the same TX queue */ | 550 | * that they end up using the same TX queue */ |
539 | frag->priority = first->priority; | 551 | frag->priority = first->priority; |
540 | skb_reserve(frag, tx->local->hw.extra_tx_headroom + | 552 | skb_reserve(frag, tx->local->tx_headroom + |
541 | IEEE80211_ENCRYPT_HEADROOM); | 553 | IEEE80211_ENCRYPT_HEADROOM); |
542 | fhdr = (struct ieee80211_hdr *) skb_put(frag, hdrlen); | 554 | fhdr = (struct ieee80211_hdr *) skb_put(frag, hdrlen); |
543 | memcpy(fhdr, first->data, hdrlen); | 555 | memcpy(fhdr, first->data, hdrlen); |
544 | if (i == num_fragm - 2) | 556 | if (i == num_fragm - 2) |
@@ -856,8 +868,7 @@ ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx) | |||
856 | * for the frame. */ | 868 | * for the frame. */ |
857 | if (mode->mode == MODE_IEEE80211G && | 869 | if (mode->mode == MODE_IEEE80211G && |
858 | (tx->u.tx.rate->flags & IEEE80211_RATE_ERP) && | 870 | (tx->u.tx.rate->flags & IEEE80211_RATE_ERP) && |
859 | tx->u.tx.unicast && | 871 | tx->u.tx.unicast && tx->sdata->use_protection && |
860 | tx->local->cts_protect_erp_frames && | ||
861 | !(control->flags & IEEE80211_TXCTL_USE_RTS_CTS)) | 872 | !(control->flags & IEEE80211_TXCTL_USE_RTS_CTS)) |
862 | control->flags |= IEEE80211_TXCTL_USE_CTS_PROTECT; | 873 | control->flags |= IEEE80211_TXCTL_USE_CTS_PROTECT; |
863 | 874 | ||
@@ -1118,7 +1129,138 @@ ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) | |||
1118 | } | 1129 | } |
1119 | 1130 | ||
1120 | 1131 | ||
1121 | static void inline | 1132 | /* |
1133 | * deal with packet injection down monitor interface | ||
1134 | * with Radiotap Header -- only called for monitor mode interface | ||
1135 | */ | ||
1136 | |||
1137 | static ieee80211_txrx_result | ||
1138 | __ieee80211_parse_tx_radiotap( | ||
1139 | struct ieee80211_txrx_data *tx, | ||
1140 | struct sk_buff *skb, struct ieee80211_tx_control *control) | ||
1141 | { | ||
1142 | /* | ||
1143 | * this is the moment to interpret and discard the radiotap header that | ||
1144 | * must be at the start of the packet injected in Monitor mode | ||
1145 | * | ||
1146 | * Need to take some care with endian-ness since radiotap | ||
1147 | * args are little-endian | ||
1148 | */ | ||
1149 | |||
1150 | struct ieee80211_radiotap_iterator iterator; | ||
1151 | struct ieee80211_radiotap_header *rthdr = | ||
1152 | (struct ieee80211_radiotap_header *) skb->data; | ||
1153 | struct ieee80211_hw_mode *mode = tx->local->hw.conf.mode; | ||
1154 | int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len); | ||
1155 | |||
1156 | /* | ||
1157 | * default control situation for all injected packets | ||
1158 | * FIXME: this does not suit all usage cases, expand to allow control | ||
1159 | */ | ||
1160 | |||
1161 | control->retry_limit = 1; /* no retry */ | ||
1162 | control->key_idx = -1; /* no encryption key */ | ||
1163 | control->flags &= ~(IEEE80211_TXCTL_USE_RTS_CTS | | ||
1164 | IEEE80211_TXCTL_USE_CTS_PROTECT); | ||
1165 | control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT | | ||
1166 | IEEE80211_TXCTL_NO_ACK; | ||
1167 | control->antenna_sel_tx = 0; /* default to default antenna */ | ||
1168 | |||
1169 | /* | ||
1170 | * for every radiotap entry that is present | ||
1171 | * (ieee80211_radiotap_iterator_next returns -ENOENT when no more | ||
1172 | * entries present, or -EINVAL on error) | ||
1173 | */ | ||
1174 | |||
1175 | while (!ret) { | ||
1176 | int i, target_rate; | ||
1177 | |||
1178 | ret = ieee80211_radiotap_iterator_next(&iterator); | ||
1179 | |||
1180 | if (ret) | ||
1181 | continue; | ||
1182 | |||
1183 | /* see if this argument is something we can use */ | ||
1184 | switch (iterator.this_arg_index) { | ||
1185 | /* | ||
1186 | * You must take care when dereferencing iterator.this_arg | ||
1187 | * for multibyte types... the pointer is not aligned. Use | ||
1188 | * get_unaligned((type *)iterator.this_arg) to dereference | ||
1189 | * iterator.this_arg for type "type" safely on all arches. | ||
1190 | */ | ||
1191 | case IEEE80211_RADIOTAP_RATE: | ||
1192 | /* | ||
1193 | * radiotap rate u8 is in 500kbps units eg, 0x02=1Mbps | ||
1194 | * ieee80211 rate int is in 100kbps units eg, 0x0a=1Mbps | ||
1195 | */ | ||
1196 | target_rate = (*iterator.this_arg) * 5; | ||
1197 | for (i = 0; i < mode->num_rates; i++) { | ||
1198 | struct ieee80211_rate *r = &mode->rates[i]; | ||
1199 | |||
1200 | if (r->rate > target_rate) | ||
1201 | continue; | ||
1202 | |||
1203 | control->rate = r; | ||
1204 | |||
1205 | if (r->flags & IEEE80211_RATE_PREAMBLE2) | ||
1206 | control->tx_rate = r->val2; | ||
1207 | else | ||
1208 | control->tx_rate = r->val; | ||
1209 | |||
1210 | /* end on exact match */ | ||
1211 | if (r->rate == target_rate) | ||
1212 | i = mode->num_rates; | ||
1213 | } | ||
1214 | break; | ||
1215 | |||
1216 | case IEEE80211_RADIOTAP_ANTENNA: | ||
1217 | /* | ||
1218 | * radiotap uses 0 for 1st ant, mac80211 is 1 for | ||
1219 | * 1st ant | ||
1220 | */ | ||
1221 | control->antenna_sel_tx = (*iterator.this_arg) + 1; | ||
1222 | break; | ||
1223 | |||
1224 | case IEEE80211_RADIOTAP_DBM_TX_POWER: | ||
1225 | control->power_level = *iterator.this_arg; | ||
1226 | break; | ||
1227 | |||
1228 | case IEEE80211_RADIOTAP_FLAGS: | ||
1229 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) { | ||
1230 | /* | ||
1231 | * this indicates that the skb we have been | ||
1232 | * handed has the 32-bit FCS CRC at the end... | ||
1233 | * we should react to that by snipping it off | ||
1234 | * because it will be recomputed and added | ||
1235 | * on transmission | ||
1236 | */ | ||
1237 | if (skb->len < (iterator.max_length + FCS_LEN)) | ||
1238 | return TXRX_DROP; | ||
1239 | |||
1240 | skb_trim(skb, skb->len - FCS_LEN); | ||
1241 | } | ||
1242 | break; | ||
1243 | |||
1244 | default: | ||
1245 | break; | ||
1246 | } | ||
1247 | } | ||
1248 | |||
1249 | if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */ | ||
1250 | return TXRX_DROP; | ||
1251 | |||
1252 | /* | ||
1253 | * remove the radiotap header | ||
1254 | * iterator->max_length was sanity-checked against | ||
1255 | * skb->len by iterator init | ||
1256 | */ | ||
1257 | skb_pull(skb, iterator.max_length); | ||
1258 | |||
1259 | return TXRX_CONTINUE; | ||
1260 | } | ||
1261 | |||
1262 | |||
1263 | static ieee80211_txrx_result inline | ||
1122 | __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, | 1264 | __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, |
1123 | struct sk_buff *skb, | 1265 | struct sk_buff *skb, |
1124 | struct net_device *dev, | 1266 | struct net_device *dev, |
@@ -1126,6 +1268,9 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, | |||
1126 | { | 1268 | { |
1127 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1269 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1128 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1270 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
1271 | struct ieee80211_sub_if_data *sdata; | ||
1272 | ieee80211_txrx_result res = TXRX_CONTINUE; | ||
1273 | |||
1129 | int hdrlen; | 1274 | int hdrlen; |
1130 | 1275 | ||
1131 | memset(tx, 0, sizeof(*tx)); | 1276 | memset(tx, 0, sizeof(*tx)); |
@@ -1135,7 +1280,32 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, | |||
1135 | tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1280 | tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1136 | tx->sta = sta_info_get(local, hdr->addr1); | 1281 | tx->sta = sta_info_get(local, hdr->addr1); |
1137 | tx->fc = le16_to_cpu(hdr->frame_control); | 1282 | tx->fc = le16_to_cpu(hdr->frame_control); |
1283 | |||
1284 | /* | ||
1285 | * set defaults for things that can be set by | ||
1286 | * injected radiotap headers | ||
1287 | */ | ||
1138 | control->power_level = local->hw.conf.power_level; | 1288 | control->power_level = local->hw.conf.power_level; |
1289 | control->antenna_sel_tx = local->hw.conf.antenna_sel_tx; | ||
1290 | if (local->sta_antenna_sel != STA_ANTENNA_SEL_AUTO && tx->sta) | ||
1291 | control->antenna_sel_tx = tx->sta->antenna_sel_tx; | ||
1292 | |||
1293 | /* process and remove the injection radiotap header */ | ||
1294 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1295 | if (unlikely(sdata->type == IEEE80211_IF_TYPE_MNTR)) { | ||
1296 | if (__ieee80211_parse_tx_radiotap(tx, skb, control) == | ||
1297 | TXRX_DROP) { | ||
1298 | return TXRX_DROP; | ||
1299 | } | ||
1300 | /* | ||
1301 | * we removed the radiotap header after this point, | ||
1302 | * we filled control with what we could use | ||
1303 | * set to the actual ieee header now | ||
1304 | */ | ||
1305 | hdr = (struct ieee80211_hdr *) skb->data; | ||
1306 | res = TXRX_QUEUED; /* indication it was monitor packet */ | ||
1307 | } | ||
1308 | |||
1139 | tx->u.tx.control = control; | 1309 | tx->u.tx.control = control; |
1140 | tx->u.tx.unicast = !is_multicast_ether_addr(hdr->addr1); | 1310 | tx->u.tx.unicast = !is_multicast_ether_addr(hdr->addr1); |
1141 | if (is_multicast_ether_addr(hdr->addr1)) | 1311 | if (is_multicast_ether_addr(hdr->addr1)) |
@@ -1152,9 +1322,6 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, | |||
1152 | control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK; | 1322 | control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK; |
1153 | tx->sta->clear_dst_mask = 0; | 1323 | tx->sta->clear_dst_mask = 0; |
1154 | } | 1324 | } |
1155 | control->antenna_sel_tx = local->hw.conf.antenna_sel_tx; | ||
1156 | if (local->sta_antenna_sel != STA_ANTENNA_SEL_AUTO && tx->sta) | ||
1157 | control->antenna_sel_tx = tx->sta->antenna_sel_tx; | ||
1158 | hdrlen = ieee80211_get_hdrlen(tx->fc); | 1325 | hdrlen = ieee80211_get_hdrlen(tx->fc); |
1159 | if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) { | 1326 | if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) { |
1160 | u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)]; | 1327 | u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)]; |
@@ -1162,6 +1329,7 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, | |||
1162 | } | 1329 | } |
1163 | control->flags |= IEEE80211_TXCTL_FIRST_FRAGMENT; | 1330 | control->flags |= IEEE80211_TXCTL_FIRST_FRAGMENT; |
1164 | 1331 | ||
1332 | return res; | ||
1165 | } | 1333 | } |
1166 | 1334 | ||
1167 | static int inline is_ieee80211_device(struct net_device *dev, | 1335 | static int inline is_ieee80211_device(struct net_device *dev, |
@@ -1274,7 +1442,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb, | |||
1274 | struct sta_info *sta; | 1442 | struct sta_info *sta; |
1275 | ieee80211_tx_handler *handler; | 1443 | ieee80211_tx_handler *handler; |
1276 | struct ieee80211_txrx_data tx; | 1444 | struct ieee80211_txrx_data tx; |
1277 | ieee80211_txrx_result res = TXRX_DROP; | 1445 | ieee80211_txrx_result res = TXRX_DROP, res_prepare; |
1278 | int ret, i; | 1446 | int ret, i; |
1279 | 1447 | ||
1280 | WARN_ON(__ieee80211_queue_pending(local, control->queue)); | 1448 | WARN_ON(__ieee80211_queue_pending(local, control->queue)); |
@@ -1284,15 +1452,26 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb, | |||
1284 | return 0; | 1452 | return 0; |
1285 | } | 1453 | } |
1286 | 1454 | ||
1287 | __ieee80211_tx_prepare(&tx, skb, dev, control); | 1455 | res_prepare = __ieee80211_tx_prepare(&tx, skb, dev, control); |
1456 | |||
1457 | if (res_prepare == TXRX_DROP) { | ||
1458 | dev_kfree_skb(skb); | ||
1459 | return 0; | ||
1460 | } | ||
1461 | |||
1288 | sta = tx.sta; | 1462 | sta = tx.sta; |
1289 | tx.u.tx.mgmt_interface = mgmt; | 1463 | tx.u.tx.mgmt_interface = mgmt; |
1290 | tx.u.tx.mode = local->hw.conf.mode; | 1464 | tx.u.tx.mode = local->hw.conf.mode; |
1291 | 1465 | ||
1292 | for (handler = local->tx_handlers; *handler != NULL; handler++) { | 1466 | if (res_prepare == TXRX_QUEUED) { /* if it was an injected packet */ |
1293 | res = (*handler)(&tx); | 1467 | res = TXRX_CONTINUE; |
1294 | if (res != TXRX_CONTINUE) | 1468 | } else { |
1295 | break; | 1469 | for (handler = local->tx_handlers; *handler != NULL; |
1470 | handler++) { | ||
1471 | res = (*handler)(&tx); | ||
1472 | if (res != TXRX_CONTINUE) | ||
1473 | break; | ||
1474 | } | ||
1296 | } | 1475 | } |
1297 | 1476 | ||
1298 | skb = tx.skb; /* handlers are allowed to change skb */ | 1477 | skb = tx.skb; /* handlers are allowed to change skb */ |
@@ -1467,8 +1646,7 @@ static int ieee80211_master_start_xmit(struct sk_buff *skb, | |||
1467 | } | 1646 | } |
1468 | osdata = IEEE80211_DEV_TO_SUB_IF(odev); | 1647 | osdata = IEEE80211_DEV_TO_SUB_IF(odev); |
1469 | 1648 | ||
1470 | headroom = osdata->local->hw.extra_tx_headroom + | 1649 | headroom = osdata->local->tx_headroom + IEEE80211_ENCRYPT_HEADROOM; |
1471 | IEEE80211_ENCRYPT_HEADROOM; | ||
1472 | if (skb_headroom(skb) < headroom) { | 1650 | if (skb_headroom(skb) < headroom) { |
1473 | if (pskb_expand_head(skb, headroom, 0, GFP_ATOMIC)) { | 1651 | if (pskb_expand_head(skb, headroom, 0, GFP_ATOMIC)) { |
1474 | dev_kfree_skb(skb); | 1652 | dev_kfree_skb(skb); |
@@ -1494,6 +1672,56 @@ static int ieee80211_master_start_xmit(struct sk_buff *skb, | |||
1494 | } | 1672 | } |
1495 | 1673 | ||
1496 | 1674 | ||
1675 | int ieee80211_monitor_start_xmit(struct sk_buff *skb, | ||
1676 | struct net_device *dev) | ||
1677 | { | ||
1678 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1679 | struct ieee80211_tx_packet_data *pkt_data; | ||
1680 | struct ieee80211_radiotap_header *prthdr = | ||
1681 | (struct ieee80211_radiotap_header *)skb->data; | ||
1682 | u16 len; | ||
1683 | |||
1684 | /* | ||
1685 | * there must be a radiotap header at the | ||
1686 | * start in this case | ||
1687 | */ | ||
1688 | if (unlikely(prthdr->it_version)) { | ||
1689 | /* only version 0 is supported */ | ||
1690 | dev_kfree_skb(skb); | ||
1691 | return NETDEV_TX_OK; | ||
1692 | } | ||
1693 | |||
1694 | skb->dev = local->mdev; | ||
1695 | |||
1696 | pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; | ||
1697 | memset(pkt_data, 0, sizeof(*pkt_data)); | ||
1698 | pkt_data->ifindex = dev->ifindex; | ||
1699 | pkt_data->mgmt_iface = 0; | ||
1700 | pkt_data->do_not_encrypt = 1; | ||
1701 | |||
1702 | /* above needed because we set skb device to master */ | ||
1703 | |||
1704 | /* | ||
1705 | * fix up the pointers accounting for the radiotap | ||
1706 | * header still being in there. We are being given | ||
1707 | * a precooked IEEE80211 header so no need for | ||
1708 | * normal processing | ||
1709 | */ | ||
1710 | len = le16_to_cpu(get_unaligned(&prthdr->it_len)); | ||
1711 | skb_set_mac_header(skb, len); | ||
1712 | skb_set_network_header(skb, len + sizeof(struct ieee80211_hdr)); | ||
1713 | skb_set_transport_header(skb, len + sizeof(struct ieee80211_hdr)); | ||
1714 | |||
1715 | /* | ||
1716 | * pass the radiotap header up to | ||
1717 | * the next stage intact | ||
1718 | */ | ||
1719 | dev_queue_xmit(skb); | ||
1720 | |||
1721 | return NETDEV_TX_OK; | ||
1722 | } | ||
1723 | |||
1724 | |||
1497 | /** | 1725 | /** |
1498 | * ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type | 1726 | * ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type |
1499 | * subinterfaces (wlan#, WDS, and VLAN interfaces) | 1727 | * subinterfaces (wlan#, WDS, and VLAN interfaces) |
@@ -1509,8 +1737,8 @@ static int ieee80211_master_start_xmit(struct sk_buff *skb, | |||
1509 | * encapsulated packet will then be passed to master interface, wlan#.11, for | 1737 | * encapsulated packet will then be passed to master interface, wlan#.11, for |
1510 | * transmission (through low-level driver). | 1738 | * transmission (through low-level driver). |
1511 | */ | 1739 | */ |
1512 | static int ieee80211_subif_start_xmit(struct sk_buff *skb, | 1740 | int ieee80211_subif_start_xmit(struct sk_buff *skb, |
1513 | struct net_device *dev) | 1741 | struct net_device *dev) |
1514 | { | 1742 | { |
1515 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1743 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1516 | struct ieee80211_tx_packet_data *pkt_data; | 1744 | struct ieee80211_tx_packet_data *pkt_data; |
@@ -1619,7 +1847,7 @@ static int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1619 | * build in headroom in __dev_alloc_skb() (linux/skbuff.h) and | 1847 | * build in headroom in __dev_alloc_skb() (linux/skbuff.h) and |
1620 | * alloc_skb() (net/core/skbuff.c) | 1848 | * alloc_skb() (net/core/skbuff.c) |
1621 | */ | 1849 | */ |
1622 | head_need = hdrlen + encaps_len + local->hw.extra_tx_headroom; | 1850 | head_need = hdrlen + encaps_len + local->tx_headroom; |
1623 | head_need -= skb_headroom(skb); | 1851 | head_need -= skb_headroom(skb); |
1624 | 1852 | ||
1625 | /* We are going to modify skb data, so make a copy of it if happens to | 1853 | /* We are going to modify skb data, so make a copy of it if happens to |
@@ -1658,7 +1886,7 @@ static int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1658 | 1886 | ||
1659 | pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; | 1887 | pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; |
1660 | memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data)); | 1888 | memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data)); |
1661 | pkt_data->ifindex = sdata->dev->ifindex; | 1889 | pkt_data->ifindex = dev->ifindex; |
1662 | pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT); | 1890 | pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT); |
1663 | pkt_data->do_not_encrypt = no_encrypt; | 1891 | pkt_data->do_not_encrypt = no_encrypt; |
1664 | 1892 | ||
@@ -1706,9 +1934,9 @@ ieee80211_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1706 | return 0; | 1934 | return 0; |
1707 | } | 1935 | } |
1708 | 1936 | ||
1709 | if (skb_headroom(skb) < sdata->local->hw.extra_tx_headroom) { | 1937 | if (skb_headroom(skb) < sdata->local->tx_headroom) { |
1710 | if (pskb_expand_head(skb, | 1938 | if (pskb_expand_head(skb, sdata->local->tx_headroom, |
1711 | sdata->local->hw.extra_tx_headroom, 0, GFP_ATOMIC)) { | 1939 | 0, GFP_ATOMIC)) { |
1712 | dev_kfree_skb(skb); | 1940 | dev_kfree_skb(skb); |
1713 | return 0; | 1941 | return 0; |
1714 | } | 1942 | } |
@@ -1847,12 +2075,12 @@ struct sk_buff * ieee80211_beacon_get(struct ieee80211_hw *hw, int if_id, | |||
1847 | bh_len = ap->beacon_head_len; | 2075 | bh_len = ap->beacon_head_len; |
1848 | bt_len = ap->beacon_tail_len; | 2076 | bt_len = ap->beacon_tail_len; |
1849 | 2077 | ||
1850 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | 2078 | skb = dev_alloc_skb(local->tx_headroom + |
1851 | bh_len + bt_len + 256 /* maximum TIM len */); | 2079 | bh_len + bt_len + 256 /* maximum TIM len */); |
1852 | if (!skb) | 2080 | if (!skb) |
1853 | return NULL; | 2081 | return NULL; |
1854 | 2082 | ||
1855 | skb_reserve(skb, local->hw.extra_tx_headroom); | 2083 | skb_reserve(skb, local->tx_headroom); |
1856 | memcpy(skb_put(skb, bh_len), b_head, bh_len); | 2084 | memcpy(skb_put(skb, bh_len), b_head, bh_len); |
1857 | 2085 | ||
1858 | ieee80211_include_sequence(sdata, (struct ieee80211_hdr *)skb->data); | 2086 | ieee80211_include_sequence(sdata, (struct ieee80211_hdr *)skb->data); |
@@ -2376,8 +2604,7 @@ static void ieee80211_start_hard_monitor(struct ieee80211_local *local) | |||
2376 | struct ieee80211_if_init_conf conf; | 2604 | struct ieee80211_if_init_conf conf; |
2377 | 2605 | ||
2378 | if (local->open_count && local->open_count == local->monitors && | 2606 | if (local->open_count && local->open_count == local->monitors && |
2379 | !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) && | 2607 | !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER)) { |
2380 | local->ops->add_interface) { | ||
2381 | conf.if_id = -1; | 2608 | conf.if_id = -1; |
2382 | conf.type = IEEE80211_IF_TYPE_MNTR; | 2609 | conf.type = IEEE80211_IF_TYPE_MNTR; |
2383 | conf.mac_addr = NULL; | 2610 | conf.mac_addr = NULL; |
@@ -2420,21 +2647,14 @@ static int ieee80211_open(struct net_device *dev) | |||
2420 | } | 2647 | } |
2421 | ieee80211_start_soft_monitor(local); | 2648 | ieee80211_start_soft_monitor(local); |
2422 | 2649 | ||
2423 | if (local->ops->add_interface) { | 2650 | conf.if_id = dev->ifindex; |
2424 | conf.if_id = dev->ifindex; | 2651 | conf.type = sdata->type; |
2425 | conf.type = sdata->type; | 2652 | conf.mac_addr = dev->dev_addr; |
2426 | conf.mac_addr = dev->dev_addr; | 2653 | res = local->ops->add_interface(local_to_hw(local), &conf); |
2427 | res = local->ops->add_interface(local_to_hw(local), &conf); | 2654 | if (res) { |
2428 | if (res) { | 2655 | if (sdata->type == IEEE80211_IF_TYPE_MNTR) |
2429 | if (sdata->type == IEEE80211_IF_TYPE_MNTR) | 2656 | ieee80211_start_hard_monitor(local); |
2430 | ieee80211_start_hard_monitor(local); | 2657 | return res; |
2431 | return res; | ||
2432 | } | ||
2433 | } else { | ||
2434 | if (sdata->type != IEEE80211_IF_TYPE_STA) | ||
2435 | return -EOPNOTSUPP; | ||
2436 | if (local->open_count > 0) | ||
2437 | return -ENOBUFS; | ||
2438 | } | 2658 | } |
2439 | 2659 | ||
2440 | if (local->open_count == 0) { | 2660 | if (local->open_count == 0) { |
@@ -2941,34 +3161,6 @@ int ieee80211_radar_status(struct ieee80211_hw *hw, int channel, | |||
2941 | } | 3161 | } |
2942 | EXPORT_SYMBOL(ieee80211_radar_status); | 3162 | EXPORT_SYMBOL(ieee80211_radar_status); |
2943 | 3163 | ||
2944 | int ieee80211_set_aid_for_sta(struct ieee80211_hw *hw, u8 *peer_address, | ||
2945 | u16 aid) | ||
2946 | { | ||
2947 | struct sk_buff *skb; | ||
2948 | struct ieee80211_msg_set_aid_for_sta *msg; | ||
2949 | struct ieee80211_local *local = hw_to_local(hw); | ||
2950 | |||
2951 | /* unlikely because if this event only happens for APs, | ||
2952 | * which require an open ap device. */ | ||
2953 | if (unlikely(!local->apdev)) | ||
2954 | return 0; | ||
2955 | |||
2956 | skb = dev_alloc_skb(sizeof(struct ieee80211_frame_info) + | ||
2957 | sizeof(struct ieee80211_msg_set_aid_for_sta)); | ||
2958 | |||
2959 | if (!skb) | ||
2960 | return -ENOMEM; | ||
2961 | skb_reserve(skb, sizeof(struct ieee80211_frame_info)); | ||
2962 | |||
2963 | msg = (struct ieee80211_msg_set_aid_for_sta *) | ||
2964 | skb_put(skb, sizeof(struct ieee80211_msg_set_aid_for_sta)); | ||
2965 | memcpy(msg->sta_address, peer_address, ETH_ALEN); | ||
2966 | msg->aid = aid; | ||
2967 | |||
2968 | ieee80211_rx_mgmt(local, skb, NULL, ieee80211_msg_set_aid_for_sta); | ||
2969 | return 0; | ||
2970 | } | ||
2971 | EXPORT_SYMBOL(ieee80211_set_aid_for_sta); | ||
2972 | 3164 | ||
2973 | static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta) | 3165 | static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta) |
2974 | { | 3166 | { |
@@ -4284,6 +4476,9 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
4284 | struct ieee80211_local *local = hw_to_local(hw); | 4476 | struct ieee80211_local *local = hw_to_local(hw); |
4285 | u16 frag, type; | 4477 | u16 frag, type; |
4286 | u32 msg_type; | 4478 | u32 msg_type; |
4479 | struct ieee80211_tx_status_rtap_hdr *rthdr; | ||
4480 | struct ieee80211_sub_if_data *sdata; | ||
4481 | int monitors; | ||
4287 | 4482 | ||
4288 | if (!status) { | 4483 | if (!status) { |
4289 | printk(KERN_ERR | 4484 | printk(KERN_ERR |
@@ -4395,27 +4590,100 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
4395 | local->dot11FailedCount++; | 4590 | local->dot11FailedCount++; |
4396 | } | 4591 | } |
4397 | 4592 | ||
4398 | if (!(status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS) | 4593 | msg_type = (status->flags & IEEE80211_TX_STATUS_ACK) ? |
4399 | || unlikely(!local->apdev)) { | 4594 | ieee80211_msg_tx_callback_ack : ieee80211_msg_tx_callback_fail; |
4595 | |||
4596 | /* this was a transmitted frame, but now we want to reuse it */ | ||
4597 | skb_orphan(skb); | ||
4598 | |||
4599 | if ((status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS) && | ||
4600 | local->apdev) { | ||
4601 | if (local->monitors) { | ||
4602 | skb2 = skb_clone(skb, GFP_ATOMIC); | ||
4603 | } else { | ||
4604 | skb2 = skb; | ||
4605 | skb = NULL; | ||
4606 | } | ||
4607 | |||
4608 | if (skb2) | ||
4609 | /* Send frame to hostapd */ | ||
4610 | ieee80211_rx_mgmt(local, skb2, NULL, msg_type); | ||
4611 | |||
4612 | if (!skb) | ||
4613 | return; | ||
4614 | } | ||
4615 | |||
4616 | if (!local->monitors) { | ||
4400 | dev_kfree_skb(skb); | 4617 | dev_kfree_skb(skb); |
4401 | return; | 4618 | return; |
4402 | } | 4619 | } |
4403 | 4620 | ||
4404 | msg_type = (status->flags & IEEE80211_TX_STATUS_ACK) ? | 4621 | /* send frame to monitor interfaces now */ |
4405 | ieee80211_msg_tx_callback_ack : ieee80211_msg_tx_callback_fail; | ||
4406 | 4622 | ||
4407 | /* skb was the original skb used for TX. Clone it and give the clone | 4623 | if (skb_headroom(skb) < sizeof(*rthdr)) { |
4408 | * to netif_rx(). Free original skb. */ | 4624 | printk(KERN_ERR "ieee80211_tx_status: headroom too small\n"); |
4409 | skb2 = skb_copy(skb, GFP_ATOMIC); | ||
4410 | if (!skb2) { | ||
4411 | dev_kfree_skb(skb); | 4625 | dev_kfree_skb(skb); |
4412 | return; | 4626 | return; |
4413 | } | 4627 | } |
4414 | dev_kfree_skb(skb); | ||
4415 | skb = skb2; | ||
4416 | 4628 | ||
4417 | /* Send frame to hostapd */ | 4629 | rthdr = (struct ieee80211_tx_status_rtap_hdr*) |
4418 | ieee80211_rx_mgmt(local, skb, NULL, msg_type); | 4630 | skb_push(skb, sizeof(*rthdr)); |
4631 | |||
4632 | memset(rthdr, 0, sizeof(*rthdr)); | ||
4633 | rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr)); | ||
4634 | rthdr->hdr.it_present = | ||
4635 | cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) | | ||
4636 | (1 << IEEE80211_RADIOTAP_DATA_RETRIES)); | ||
4637 | |||
4638 | if (!(status->flags & IEEE80211_TX_STATUS_ACK) && | ||
4639 | !is_multicast_ether_addr(hdr->addr1)) | ||
4640 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); | ||
4641 | |||
4642 | if ((status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) && | ||
4643 | (status->control.flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) | ||
4644 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS); | ||
4645 | else if (status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) | ||
4646 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS); | ||
4647 | |||
4648 | rthdr->data_retries = status->retry_count; | ||
4649 | |||
4650 | read_lock(&local->sub_if_lock); | ||
4651 | monitors = local->monitors; | ||
4652 | list_for_each_entry(sdata, &local->sub_if_list, list) { | ||
4653 | /* | ||
4654 | * Using the monitors counter is possibly racy, but | ||
4655 | * if the value is wrong we simply either clone the skb | ||
4656 | * once too much or forget sending it to one monitor iface | ||
4657 | * The latter case isn't nice but fixing the race is much | ||
4658 | * more complicated. | ||
4659 | */ | ||
4660 | if (!monitors || !skb) | ||
4661 | goto out; | ||
4662 | |||
4663 | if (sdata->type == IEEE80211_IF_TYPE_MNTR) { | ||
4664 | if (!netif_running(sdata->dev)) | ||
4665 | continue; | ||
4666 | monitors--; | ||
4667 | if (monitors) | ||
4668 | skb2 = skb_clone(skb, GFP_KERNEL); | ||
4669 | else | ||
4670 | skb2 = NULL; | ||
4671 | skb->dev = sdata->dev; | ||
4672 | /* XXX: is this sufficient for BPF? */ | ||
4673 | skb_set_mac_header(skb, 0); | ||
4674 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
4675 | skb->pkt_type = PACKET_OTHERHOST; | ||
4676 | skb->protocol = htons(ETH_P_802_2); | ||
4677 | memset(skb->cb, 0, sizeof(skb->cb)); | ||
4678 | netif_rx(skb); | ||
4679 | skb = skb2; | ||
4680 | break; | ||
4681 | } | ||
4682 | } | ||
4683 | out: | ||
4684 | read_unlock(&local->sub_if_lock); | ||
4685 | if (skb) | ||
4686 | dev_kfree_skb(skb); | ||
4419 | } | 4687 | } |
4420 | EXPORT_SYMBOL(ieee80211_tx_status); | 4688 | EXPORT_SYMBOL(ieee80211_tx_status); |
4421 | 4689 | ||
@@ -4619,6 +4887,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
4619 | ((sizeof(struct ieee80211_local) + | 4887 | ((sizeof(struct ieee80211_local) + |
4620 | NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); | 4888 | NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); |
4621 | 4889 | ||
4890 | BUG_ON(!ops->tx); | ||
4891 | BUG_ON(!ops->config); | ||
4892 | BUG_ON(!ops->add_interface); | ||
4622 | local->ops = ops; | 4893 | local->ops = ops; |
4623 | 4894 | ||
4624 | /* for now, mdev needs sub_if_data :/ */ | 4895 | /* for now, mdev needs sub_if_data :/ */ |
@@ -4647,8 +4918,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
4647 | local->short_retry_limit = 7; | 4918 | local->short_retry_limit = 7; |
4648 | local->long_retry_limit = 4; | 4919 | local->long_retry_limit = 4; |
4649 | local->hw.conf.radio_enabled = 1; | 4920 | local->hw.conf.radio_enabled = 1; |
4650 | local->rate_ctrl_num_up = RATE_CONTROL_NUM_UP; | ||
4651 | local->rate_ctrl_num_down = RATE_CONTROL_NUM_DOWN; | ||
4652 | 4921 | ||
4653 | local->enabled_modes = (unsigned int) -1; | 4922 | local->enabled_modes = (unsigned int) -1; |
4654 | 4923 | ||
@@ -4712,6 +4981,14 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
4712 | goto fail_workqueue; | 4981 | goto fail_workqueue; |
4713 | } | 4982 | } |
4714 | 4983 | ||
4984 | /* | ||
4985 | * The hardware needs headroom for sending the frame, | ||
4986 | * and we need some headroom for passing the frame to monitor | ||
4987 | * interfaces, but never both at the same time. | ||
4988 | */ | ||
4989 | local->tx_headroom = max(local->hw.extra_tx_headroom, | ||
4990 | sizeof(struct ieee80211_tx_status_rtap_hdr)); | ||
4991 | |||
4715 | debugfs_hw_add(local); | 4992 | debugfs_hw_add(local); |
4716 | 4993 | ||
4717 | local->hw.conf.beacon_int = 1000; | 4994 | local->hw.conf.beacon_int = 1000; |
diff --git a/net/mac80211/ieee80211_common.h b/net/mac80211/ieee80211_common.h index b9a73e7f5f75..77c6afb7f6a8 100644 --- a/net/mac80211/ieee80211_common.h +++ b/net/mac80211/ieee80211_common.h | |||
@@ -47,21 +47,16 @@ enum ieee80211_msg_type { | |||
47 | ieee80211_msg_normal = 0, | 47 | ieee80211_msg_normal = 0, |
48 | ieee80211_msg_tx_callback_ack = 1, | 48 | ieee80211_msg_tx_callback_ack = 1, |
49 | ieee80211_msg_tx_callback_fail = 2, | 49 | ieee80211_msg_tx_callback_fail = 2, |
50 | ieee80211_msg_passive_scan = 3, | 50 | /* hole at 3, was ieee80211_msg_passive_scan but unused */ |
51 | ieee80211_msg_wep_frame_unknown_key = 4, | 51 | ieee80211_msg_wep_frame_unknown_key = 4, |
52 | ieee80211_msg_michael_mic_failure = 5, | 52 | ieee80211_msg_michael_mic_failure = 5, |
53 | /* hole at 6, was monitor but never sent to userspace */ | 53 | /* hole at 6, was monitor but never sent to userspace */ |
54 | ieee80211_msg_sta_not_assoc = 7, | 54 | ieee80211_msg_sta_not_assoc = 7, |
55 | ieee80211_msg_set_aid_for_sta = 8 /* used by Intersil MVC driver */, | 55 | /* 8 was ieee80211_msg_set_aid_for_sta */ |
56 | ieee80211_msg_key_threshold_notification = 9, | 56 | ieee80211_msg_key_threshold_notification = 9, |
57 | ieee80211_msg_radar = 11, | 57 | ieee80211_msg_radar = 11, |
58 | }; | 58 | }; |
59 | 59 | ||
60 | struct ieee80211_msg_set_aid_for_sta { | ||
61 | char sta_address[ETH_ALEN]; | ||
62 | u16 aid; | ||
63 | }; | ||
64 | |||
65 | struct ieee80211_msg_key_notification { | 60 | struct ieee80211_msg_key_notification { |
66 | int tx_rx_count; | 61 | int tx_rx_count; |
67 | char ifname[IFNAMSIZ]; | 62 | char ifname[IFNAMSIZ]; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index af4d14d0b969..055a2a912185 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -99,6 +99,12 @@ struct ieee80211_sta_bss { | |||
99 | int probe_resp; | 99 | int probe_resp; |
100 | unsigned long last_update; | 100 | unsigned long last_update; |
101 | 101 | ||
102 | /* during assocation, we save an ERP value from a probe response so | ||
103 | * that we can feed ERP info to the driver when handling the | ||
104 | * association completes. these fields probably won't be up-to-date | ||
105 | * otherwise, you probably don't want to use them. */ | ||
106 | int has_erp_value; | ||
107 | u8 erp_value; | ||
102 | }; | 108 | }; |
103 | 109 | ||
104 | 110 | ||
@@ -235,7 +241,6 @@ struct ieee80211_if_sta { | |||
235 | unsigned int authenticated:1; | 241 | unsigned int authenticated:1; |
236 | unsigned int associated:1; | 242 | unsigned int associated:1; |
237 | unsigned int probereq_poll:1; | 243 | unsigned int probereq_poll:1; |
238 | unsigned int use_protection:1; | ||
239 | unsigned int create_ibss:1; | 244 | unsigned int create_ibss:1; |
240 | unsigned int mixed_cell:1; | 245 | unsigned int mixed_cell:1; |
241 | unsigned int wmm_enabled:1; | 246 | unsigned int wmm_enabled:1; |
@@ -278,6 +283,7 @@ struct ieee80211_sub_if_data { | |||
278 | int mc_count; | 283 | int mc_count; |
279 | unsigned int allmulti:1; | 284 | unsigned int allmulti:1; |
280 | unsigned int promisc:1; | 285 | unsigned int promisc:1; |
286 | unsigned int use_protection:1; /* CTS protect ERP frames */ | ||
281 | 287 | ||
282 | struct net_device_stats stats; | 288 | struct net_device_stats stats; |
283 | int drop_unencrypted; | 289 | int drop_unencrypted; |
@@ -392,6 +398,7 @@ struct ieee80211_local { | |||
392 | int monitors; | 398 | int monitors; |
393 | struct iw_statistics wstats; | 399 | struct iw_statistics wstats; |
394 | u8 wstats_flags; | 400 | u8 wstats_flags; |
401 | int tx_headroom; /* required headroom for hardware/radiotap */ | ||
395 | 402 | ||
396 | enum { | 403 | enum { |
397 | IEEE80211_DEV_UNINITIALIZED = 0, | 404 | IEEE80211_DEV_UNINITIALIZED = 0, |
@@ -437,7 +444,6 @@ struct ieee80211_local { | |||
437 | int *basic_rates[NUM_IEEE80211_MODES]; | 444 | int *basic_rates[NUM_IEEE80211_MODES]; |
438 | 445 | ||
439 | int rts_threshold; | 446 | int rts_threshold; |
440 | int cts_protect_erp_frames; | ||
441 | int fragmentation_threshold; | 447 | int fragmentation_threshold; |
442 | int short_retry_limit; /* dot11ShortRetryLimit */ | 448 | int short_retry_limit; /* dot11ShortRetryLimit */ |
443 | int long_retry_limit; /* dot11LongRetryLimit */ | 449 | int long_retry_limit; /* dot11LongRetryLimit */ |
@@ -513,8 +519,6 @@ struct ieee80211_local { | |||
513 | STA_ANTENNA_SEL_SW_CTRL_DEBUG = 2 | 519 | STA_ANTENNA_SEL_SW_CTRL_DEBUG = 2 |
514 | } sta_antenna_sel; | 520 | } sta_antenna_sel; |
515 | 521 | ||
516 | int rate_ctrl_num_up, rate_ctrl_num_down; | ||
517 | |||
518 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | 522 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS |
519 | /* TX/RX handler statistics */ | 523 | /* TX/RX handler statistics */ |
520 | unsigned int tx_handlers_drop; | 524 | unsigned int tx_handlers_drop; |
@@ -719,6 +723,8 @@ void ieee80211_prepare_rates(struct ieee80211_local *local, | |||
719 | struct ieee80211_hw_mode *mode); | 723 | struct ieee80211_hw_mode *mode); |
720 | void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx); | 724 | void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx); |
721 | int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr); | 725 | int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr); |
726 | int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); | ||
727 | int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); | ||
722 | void ieee80211_if_setup(struct net_device *dev); | 728 | void ieee80211_if_setup(struct net_device *dev); |
723 | void ieee80211_if_mgmt_setup(struct net_device *dev); | 729 | void ieee80211_if_mgmt_setup(struct net_device *dev); |
724 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, | 730 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, |
diff --git a/net/mac80211/ieee80211_iface.c b/net/mac80211/ieee80211_iface.c index cf0f32e8c2a2..8532a5ccdd1e 100644 --- a/net/mac80211/ieee80211_iface.c +++ b/net/mac80211/ieee80211_iface.c | |||
@@ -157,6 +157,8 @@ void ieee80211_if_set_type(struct net_device *dev, int type) | |||
157 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 157 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
158 | int oldtype = sdata->type; | 158 | int oldtype = sdata->type; |
159 | 159 | ||
160 | dev->hard_start_xmit = ieee80211_subif_start_xmit; | ||
161 | |||
160 | sdata->type = type; | 162 | sdata->type = type; |
161 | switch (type) { | 163 | switch (type) { |
162 | case IEEE80211_IF_TYPE_WDS: | 164 | case IEEE80211_IF_TYPE_WDS: |
@@ -196,6 +198,7 @@ void ieee80211_if_set_type(struct net_device *dev, int type) | |||
196 | } | 198 | } |
197 | case IEEE80211_IF_TYPE_MNTR: | 199 | case IEEE80211_IF_TYPE_MNTR: |
198 | dev->type = ARPHRD_IEEE80211_RADIOTAP; | 200 | dev->type = ARPHRD_IEEE80211_RADIOTAP; |
201 | dev->hard_start_xmit = ieee80211_monitor_start_xmit; | ||
199 | break; | 202 | break; |
200 | default: | 203 | default: |
201 | printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x", | 204 | printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x", |
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c index 352f03bd8a3a..5918dd079e12 100644 --- a/net/mac80211/ieee80211_ioctl.c +++ b/net/mac80211/ieee80211_ioctl.c | |||
@@ -345,6 +345,8 @@ static int ieee80211_ioctl_giwrange(struct net_device *dev, | |||
345 | { | 345 | { |
346 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 346 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
347 | struct iw_range *range = (struct iw_range *) extra; | 347 | struct iw_range *range = (struct iw_range *) extra; |
348 | struct ieee80211_hw_mode *mode = NULL; | ||
349 | int c = 0; | ||
348 | 350 | ||
349 | data->length = sizeof(struct iw_range); | 351 | data->length = sizeof(struct iw_range); |
350 | memset(range, 0, sizeof(struct iw_range)); | 352 | memset(range, 0, sizeof(struct iw_range)); |
@@ -378,6 +380,29 @@ static int ieee80211_ioctl_giwrange(struct net_device *dev, | |||
378 | range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | | 380 | range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | |
379 | IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; | 381 | IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; |
380 | 382 | ||
383 | list_for_each_entry(mode, &local->modes_list, list) { | ||
384 | int i = 0; | ||
385 | |||
386 | if (!(local->enabled_modes & (1 << mode->mode)) || | ||
387 | (local->hw_modes & local->enabled_modes & | ||
388 | (1 << MODE_IEEE80211G) && mode->mode == MODE_IEEE80211B)) | ||
389 | continue; | ||
390 | |||
391 | while (i < mode->num_channels && c < IW_MAX_FREQUENCIES) { | ||
392 | struct ieee80211_channel *chan = &mode->channels[i]; | ||
393 | |||
394 | if (chan->flag & IEEE80211_CHAN_W_SCAN) { | ||
395 | range->freq[c].i = chan->chan; | ||
396 | range->freq[c].m = chan->freq * 100000; | ||
397 | range->freq[c].e = 1; | ||
398 | c++; | ||
399 | } | ||
400 | i++; | ||
401 | } | ||
402 | } | ||
403 | range->num_channels = c; | ||
404 | range->num_frequency = c; | ||
405 | |||
381 | IW_EVENT_CAPA_SET_KERNEL(range->event_capa); | 406 | IW_EVENT_CAPA_SET_KERNEL(range->event_capa); |
382 | IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY); | 407 | IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY); |
383 | IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP); | 408 | IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP); |
@@ -838,6 +863,67 @@ static int ieee80211_ioctl_giwscan(struct net_device *dev, | |||
838 | } | 863 | } |
839 | 864 | ||
840 | 865 | ||
866 | static int ieee80211_ioctl_siwrate(struct net_device *dev, | ||
867 | struct iw_request_info *info, | ||
868 | struct iw_param *rate, char *extra) | ||
869 | { | ||
870 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
871 | struct ieee80211_hw_mode *mode; | ||
872 | int i; | ||
873 | u32 target_rate = rate->value / 100000; | ||
874 | struct ieee80211_sub_if_data *sdata; | ||
875 | |||
876 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
877 | if (!sdata->bss) | ||
878 | return -ENODEV; | ||
879 | mode = local->oper_hw_mode; | ||
880 | /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates | ||
881 | * target_rate = X, rate->fixed = 1 means only rate X | ||
882 | * target_rate = X, rate->fixed = 0 means all rates <= X */ | ||
883 | sdata->bss->max_ratectrl_rateidx = -1; | ||
884 | sdata->bss->force_unicast_rateidx = -1; | ||
885 | if (rate->value < 0) | ||
886 | return 0; | ||
887 | for (i=0; i< mode->num_rates; i++) { | ||
888 | struct ieee80211_rate *rates = &mode->rates[i]; | ||
889 | int this_rate = rates->rate; | ||
890 | |||
891 | if (mode->mode == MODE_ATHEROS_TURBO || | ||
892 | mode->mode == MODE_ATHEROS_TURBOG) | ||
893 | this_rate *= 2; | ||
894 | if (target_rate == this_rate) { | ||
895 | sdata->bss->max_ratectrl_rateidx = i; | ||
896 | if (rate->fixed) | ||
897 | sdata->bss->force_unicast_rateidx = i; | ||
898 | break; | ||
899 | } | ||
900 | } | ||
901 | return 0; | ||
902 | } | ||
903 | |||
904 | static int ieee80211_ioctl_giwrate(struct net_device *dev, | ||
905 | struct iw_request_info *info, | ||
906 | struct iw_param *rate, char *extra) | ||
907 | { | ||
908 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
909 | struct sta_info *sta; | ||
910 | struct ieee80211_sub_if_data *sdata; | ||
911 | |||
912 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
913 | if (sdata->type == IEEE80211_IF_TYPE_STA) | ||
914 | sta = sta_info_get(local, sdata->u.sta.bssid); | ||
915 | else | ||
916 | return -EOPNOTSUPP; | ||
917 | if (!sta) | ||
918 | return -ENODEV; | ||
919 | if (sta->txrate < local->oper_hw_mode->num_rates) | ||
920 | rate->value = local->oper_hw_mode->rates[sta->txrate].rate * 100000; | ||
921 | else | ||
922 | rate->value = 0; | ||
923 | sta_info_put(sta); | ||
924 | return 0; | ||
925 | } | ||
926 | |||
841 | static int ieee80211_ioctl_siwrts(struct net_device *dev, | 927 | static int ieee80211_ioctl_siwrts(struct net_device *dev, |
842 | struct iw_request_info *info, | 928 | struct iw_request_info *info, |
843 | struct iw_param *rts, char *extra) | 929 | struct iw_param *rts, char *extra) |
@@ -970,118 +1056,6 @@ static int ieee80211_ioctl_giwretry(struct net_device *dev, | |||
970 | return 0; | 1056 | return 0; |
971 | } | 1057 | } |
972 | 1058 | ||
973 | static int ieee80211_ioctl_clear_keys(struct net_device *dev) | ||
974 | { | ||
975 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
976 | struct ieee80211_key_conf key; | ||
977 | int i; | ||
978 | u8 addr[ETH_ALEN]; | ||
979 | struct ieee80211_key_conf *keyconf; | ||
980 | struct ieee80211_sub_if_data *sdata; | ||
981 | struct sta_info *sta; | ||
982 | |||
983 | memset(addr, 0xff, ETH_ALEN); | ||
984 | read_lock(&local->sub_if_lock); | ||
985 | list_for_each_entry(sdata, &local->sub_if_list, list) { | ||
986 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | ||
987 | keyconf = NULL; | ||
988 | if (sdata->keys[i] && | ||
989 | !sdata->keys[i]->force_sw_encrypt && | ||
990 | local->ops->set_key && | ||
991 | (keyconf = ieee80211_key_data2conf(local, | ||
992 | sdata->keys[i]))) | ||
993 | local->ops->set_key(local_to_hw(local), | ||
994 | DISABLE_KEY, addr, | ||
995 | keyconf, 0); | ||
996 | kfree(keyconf); | ||
997 | ieee80211_key_free(sdata->keys[i]); | ||
998 | sdata->keys[i] = NULL; | ||
999 | } | ||
1000 | sdata->default_key = NULL; | ||
1001 | } | ||
1002 | read_unlock(&local->sub_if_lock); | ||
1003 | |||
1004 | spin_lock_bh(&local->sta_lock); | ||
1005 | list_for_each_entry(sta, &local->sta_list, list) { | ||
1006 | keyconf = NULL; | ||
1007 | if (sta->key && !sta->key->force_sw_encrypt && | ||
1008 | local->ops->set_key && | ||
1009 | (keyconf = ieee80211_key_data2conf(local, sta->key))) | ||
1010 | local->ops->set_key(local_to_hw(local), DISABLE_KEY, | ||
1011 | sta->addr, keyconf, sta->aid); | ||
1012 | kfree(keyconf); | ||
1013 | ieee80211_key_free(sta->key); | ||
1014 | sta->key = NULL; | ||
1015 | } | ||
1016 | spin_unlock_bh(&local->sta_lock); | ||
1017 | |||
1018 | memset(&key, 0, sizeof(key)); | ||
1019 | if (local->ops->set_key && | ||
1020 | local->ops->set_key(local_to_hw(local), REMOVE_ALL_KEYS, | ||
1021 | NULL, &key, 0)) | ||
1022 | printk(KERN_DEBUG "%s: failed to remove hwaccel keys\n", | ||
1023 | dev->name); | ||
1024 | |||
1025 | return 0; | ||
1026 | } | ||
1027 | |||
1028 | |||
1029 | static int | ||
1030 | ieee80211_ioctl_force_unicast_rate(struct net_device *dev, | ||
1031 | struct ieee80211_sub_if_data *sdata, | ||
1032 | int rate) | ||
1033 | { | ||
1034 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1035 | struct ieee80211_hw_mode *mode; | ||
1036 | int i; | ||
1037 | |||
1038 | if (sdata->type != IEEE80211_IF_TYPE_AP) | ||
1039 | return -ENOENT; | ||
1040 | |||
1041 | if (rate == 0) { | ||
1042 | sdata->u.ap.force_unicast_rateidx = -1; | ||
1043 | return 0; | ||
1044 | } | ||
1045 | |||
1046 | mode = local->oper_hw_mode; | ||
1047 | for (i = 0; i < mode->num_rates; i++) { | ||
1048 | if (mode->rates[i].rate == rate) { | ||
1049 | sdata->u.ap.force_unicast_rateidx = i; | ||
1050 | return 0; | ||
1051 | } | ||
1052 | } | ||
1053 | return -EINVAL; | ||
1054 | } | ||
1055 | |||
1056 | |||
1057 | static int | ||
1058 | ieee80211_ioctl_max_ratectrl_rate(struct net_device *dev, | ||
1059 | struct ieee80211_sub_if_data *sdata, | ||
1060 | int rate) | ||
1061 | { | ||
1062 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1063 | struct ieee80211_hw_mode *mode; | ||
1064 | int i; | ||
1065 | |||
1066 | if (sdata->type != IEEE80211_IF_TYPE_AP) | ||
1067 | return -ENOENT; | ||
1068 | |||
1069 | if (rate == 0) { | ||
1070 | sdata->u.ap.max_ratectrl_rateidx = -1; | ||
1071 | return 0; | ||
1072 | } | ||
1073 | |||
1074 | mode = local->oper_hw_mode; | ||
1075 | for (i = 0; i < mode->num_rates; i++) { | ||
1076 | if (mode->rates[i].rate == rate) { | ||
1077 | sdata->u.ap.max_ratectrl_rateidx = i; | ||
1078 | return 0; | ||
1079 | } | ||
1080 | } | ||
1081 | return -EINVAL; | ||
1082 | } | ||
1083 | |||
1084 | |||
1085 | static void ieee80211_key_enable_hwaccel(struct ieee80211_local *local, | 1059 | static void ieee80211_key_enable_hwaccel(struct ieee80211_local *local, |
1086 | struct ieee80211_key *key) | 1060 | struct ieee80211_key *key) |
1087 | { | 1061 | { |
@@ -1205,24 +1179,11 @@ static int ieee80211_ioctl_prism2_param(struct net_device *dev, | |||
1205 | sdata->ieee802_1x = value; | 1179 | sdata->ieee802_1x = value; |
1206 | break; | 1180 | break; |
1207 | 1181 | ||
1208 | case PRISM2_PARAM_ANTSEL_TX: | ||
1209 | local->hw.conf.antenna_sel_tx = value; | ||
1210 | if (ieee80211_hw_config(local)) | ||
1211 | ret = -EINVAL; | ||
1212 | break; | ||
1213 | |||
1214 | case PRISM2_PARAM_ANTSEL_RX: | ||
1215 | local->hw.conf.antenna_sel_rx = value; | ||
1216 | if (ieee80211_hw_config(local)) | ||
1217 | ret = -EINVAL; | ||
1218 | break; | ||
1219 | |||
1220 | case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES: | 1182 | case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES: |
1221 | local->cts_protect_erp_frames = value; | 1183 | if (sdata->type != IEEE80211_IF_TYPE_AP) |
1222 | break; | 1184 | ret = -ENOENT; |
1223 | 1185 | else | |
1224 | case PRISM2_PARAM_DROP_UNENCRYPTED: | 1186 | sdata->use_protection = value; |
1225 | sdata->drop_unencrypted = value; | ||
1226 | break; | 1187 | break; |
1227 | 1188 | ||
1228 | case PRISM2_PARAM_PREAMBLE: | 1189 | case PRISM2_PARAM_PREAMBLE: |
@@ -1251,10 +1212,6 @@ static int ieee80211_ioctl_prism2_param(struct net_device *dev, | |||
1251 | local->next_mode = value; | 1212 | local->next_mode = value; |
1252 | break; | 1213 | break; |
1253 | 1214 | ||
1254 | case PRISM2_PARAM_CLEAR_KEYS: | ||
1255 | ret = ieee80211_ioctl_clear_keys(dev); | ||
1256 | break; | ||
1257 | |||
1258 | case PRISM2_PARAM_RADIO_ENABLED: | 1215 | case PRISM2_PARAM_RADIO_ENABLED: |
1259 | ret = ieee80211_ioctl_set_radio_enabled(dev, value); | 1216 | ret = ieee80211_ioctl_set_radio_enabled(dev, value); |
1260 | break; | 1217 | break; |
@@ -1269,22 +1226,6 @@ static int ieee80211_ioctl_prism2_param(struct net_device *dev, | |||
1269 | local->sta_antenna_sel = value; | 1226 | local->sta_antenna_sel = value; |
1270 | break; | 1227 | break; |
1271 | 1228 | ||
1272 | case PRISM2_PARAM_FORCE_UNICAST_RATE: | ||
1273 | ret = ieee80211_ioctl_force_unicast_rate(dev, sdata, value); | ||
1274 | break; | ||
1275 | |||
1276 | case PRISM2_PARAM_MAX_RATECTRL_RATE: | ||
1277 | ret = ieee80211_ioctl_max_ratectrl_rate(dev, sdata, value); | ||
1278 | break; | ||
1279 | |||
1280 | case PRISM2_PARAM_RATE_CTRL_NUM_UP: | ||
1281 | local->rate_ctrl_num_up = value; | ||
1282 | break; | ||
1283 | |||
1284 | case PRISM2_PARAM_RATE_CTRL_NUM_DOWN: | ||
1285 | local->rate_ctrl_num_down = value; | ||
1286 | break; | ||
1287 | |||
1288 | case PRISM2_PARAM_TX_POWER_REDUCTION: | 1229 | case PRISM2_PARAM_TX_POWER_REDUCTION: |
1289 | if (value < 0) | 1230 | if (value < 0) |
1290 | ret = -EINVAL; | 1231 | ret = -EINVAL; |
@@ -1364,20 +1305,8 @@ static int ieee80211_ioctl_get_prism2_param(struct net_device *dev, | |||
1364 | *param = sdata->ieee802_1x; | 1305 | *param = sdata->ieee802_1x; |
1365 | break; | 1306 | break; |
1366 | 1307 | ||
1367 | case PRISM2_PARAM_ANTSEL_TX: | ||
1368 | *param = local->hw.conf.antenna_sel_tx; | ||
1369 | break; | ||
1370 | |||
1371 | case PRISM2_PARAM_ANTSEL_RX: | ||
1372 | *param = local->hw.conf.antenna_sel_rx; | ||
1373 | break; | ||
1374 | |||
1375 | case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES: | 1308 | case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES: |
1376 | *param = local->cts_protect_erp_frames; | 1309 | *param = sdata->use_protection; |
1377 | break; | ||
1378 | |||
1379 | case PRISM2_PARAM_DROP_UNENCRYPTED: | ||
1380 | *param = sdata->drop_unencrypted; | ||
1381 | break; | 1310 | break; |
1382 | 1311 | ||
1383 | case PRISM2_PARAM_PREAMBLE: | 1312 | case PRISM2_PARAM_PREAMBLE: |
@@ -1403,14 +1332,6 @@ static int ieee80211_ioctl_get_prism2_param(struct net_device *dev, | |||
1403 | *param = local->sta_antenna_sel; | 1332 | *param = local->sta_antenna_sel; |
1404 | break; | 1333 | break; |
1405 | 1334 | ||
1406 | case PRISM2_PARAM_RATE_CTRL_NUM_UP: | ||
1407 | *param = local->rate_ctrl_num_up; | ||
1408 | break; | ||
1409 | |||
1410 | case PRISM2_PARAM_RATE_CTRL_NUM_DOWN: | ||
1411 | *param = local->rate_ctrl_num_down; | ||
1412 | break; | ||
1413 | |||
1414 | case PRISM2_PARAM_TX_POWER_REDUCTION: | 1335 | case PRISM2_PARAM_TX_POWER_REDUCTION: |
1415 | *param = local->hw.conf.tx_power_reduction; | 1336 | *param = local->hw.conf.tx_power_reduction; |
1416 | break; | 1337 | break; |
@@ -1778,8 +1699,8 @@ static const iw_handler ieee80211_handler[] = | |||
1778 | (iw_handler) NULL, /* SIOCGIWNICKN */ | 1699 | (iw_handler) NULL, /* SIOCGIWNICKN */ |
1779 | (iw_handler) NULL, /* -- hole -- */ | 1700 | (iw_handler) NULL, /* -- hole -- */ |
1780 | (iw_handler) NULL, /* -- hole -- */ | 1701 | (iw_handler) NULL, /* -- hole -- */ |
1781 | (iw_handler) NULL, /* SIOCSIWRATE */ | 1702 | (iw_handler) ieee80211_ioctl_siwrate, /* SIOCSIWRATE */ |
1782 | (iw_handler) NULL, /* SIOCGIWRATE */ | 1703 | (iw_handler) ieee80211_ioctl_giwrate, /* SIOCGIWRATE */ |
1783 | (iw_handler) ieee80211_ioctl_siwrts, /* SIOCSIWRTS */ | 1704 | (iw_handler) ieee80211_ioctl_siwrts, /* SIOCSIWRTS */ |
1784 | (iw_handler) ieee80211_ioctl_giwrts, /* SIOCGIWRTS */ | 1705 | (iw_handler) ieee80211_ioctl_giwrts, /* SIOCGIWRTS */ |
1785 | (iw_handler) ieee80211_ioctl_siwfrag, /* SIOCSIWFRAG */ | 1706 | (iw_handler) ieee80211_ioctl_siwfrag, /* SIOCSIWFRAG */ |
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index 91b545c144c1..ba2bf8f0a347 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c | |||
@@ -76,33 +76,36 @@ static int ieee80211_sta_config_auth(struct net_device *dev, | |||
76 | 76 | ||
77 | /* Parsed Information Elements */ | 77 | /* Parsed Information Elements */ |
78 | struct ieee802_11_elems { | 78 | struct ieee802_11_elems { |
79 | /* pointers to IEs */ | ||
79 | u8 *ssid; | 80 | u8 *ssid; |
80 | u8 ssid_len; | ||
81 | u8 *supp_rates; | 81 | u8 *supp_rates; |
82 | u8 supp_rates_len; | ||
83 | u8 *fh_params; | 82 | u8 *fh_params; |
84 | u8 fh_params_len; | ||
85 | u8 *ds_params; | 83 | u8 *ds_params; |
86 | u8 ds_params_len; | ||
87 | u8 *cf_params; | 84 | u8 *cf_params; |
88 | u8 cf_params_len; | ||
89 | u8 *tim; | 85 | u8 *tim; |
90 | u8 tim_len; | ||
91 | u8 *ibss_params; | 86 | u8 *ibss_params; |
92 | u8 ibss_params_len; | ||
93 | u8 *challenge; | 87 | u8 *challenge; |
94 | u8 challenge_len; | ||
95 | u8 *wpa; | 88 | u8 *wpa; |
96 | u8 wpa_len; | ||
97 | u8 *rsn; | 89 | u8 *rsn; |
98 | u8 rsn_len; | ||
99 | u8 *erp_info; | 90 | u8 *erp_info; |
100 | u8 erp_info_len; | ||
101 | u8 *ext_supp_rates; | 91 | u8 *ext_supp_rates; |
102 | u8 ext_supp_rates_len; | ||
103 | u8 *wmm_info; | 92 | u8 *wmm_info; |
104 | u8 wmm_info_len; | ||
105 | u8 *wmm_param; | 93 | u8 *wmm_param; |
94 | |||
95 | /* length of them, respectively */ | ||
96 | u8 ssid_len; | ||
97 | u8 supp_rates_len; | ||
98 | u8 fh_params_len; | ||
99 | u8 ds_params_len; | ||
100 | u8 cf_params_len; | ||
101 | u8 tim_len; | ||
102 | u8 ibss_params_len; | ||
103 | u8 challenge_len; | ||
104 | u8 wpa_len; | ||
105 | u8 rsn_len; | ||
106 | u8 erp_info_len; | ||
107 | u8 ext_supp_rates_len; | ||
108 | u8 wmm_info_len; | ||
106 | u8 wmm_param_len; | 109 | u8 wmm_param_len; |
107 | }; | 110 | }; |
108 | 111 | ||
@@ -311,6 +314,25 @@ static void ieee80211_sta_wmm_params(struct net_device *dev, | |||
311 | } | 314 | } |
312 | 315 | ||
313 | 316 | ||
317 | static void ieee80211_handle_erp_ie(struct net_device *dev, u8 erp_value) | ||
318 | { | ||
319 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
320 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
321 | int use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0; | ||
322 | |||
323 | if (use_protection != sdata->use_protection) { | ||
324 | if (net_ratelimit()) { | ||
325 | printk(KERN_DEBUG "%s: CTS protection %s (BSSID=" | ||
326 | MAC_FMT ")\n", | ||
327 | dev->name, | ||
328 | use_protection ? "enabled" : "disabled", | ||
329 | MAC_ARG(ifsta->bssid)); | ||
330 | } | ||
331 | sdata->use_protection = use_protection; | ||
332 | } | ||
333 | } | ||
334 | |||
335 | |||
314 | static void ieee80211_sta_send_associnfo(struct net_device *dev, | 336 | static void ieee80211_sta_send_associnfo(struct net_device *dev, |
315 | struct ieee80211_if_sta *ifsta) | 337 | struct ieee80211_if_sta *ifsta) |
316 | { | 338 | { |
@@ -366,6 +388,7 @@ static void ieee80211_set_associated(struct net_device *dev, | |||
366 | struct ieee80211_if_sta *ifsta, int assoc) | 388 | struct ieee80211_if_sta *ifsta, int assoc) |
367 | { | 389 | { |
368 | union iwreq_data wrqu; | 390 | union iwreq_data wrqu; |
391 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
369 | 392 | ||
370 | if (ifsta->associated == assoc) | 393 | if (ifsta->associated == assoc) |
371 | return; | 394 | return; |
@@ -374,9 +397,18 @@ static void ieee80211_set_associated(struct net_device *dev, | |||
374 | 397 | ||
375 | if (assoc) { | 398 | if (assoc) { |
376 | struct ieee80211_sub_if_data *sdata; | 399 | struct ieee80211_sub_if_data *sdata; |
400 | struct ieee80211_sta_bss *bss; | ||
377 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 401 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
378 | if (sdata->type != IEEE80211_IF_TYPE_STA) | 402 | if (sdata->type != IEEE80211_IF_TYPE_STA) |
379 | return; | 403 | return; |
404 | |||
405 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid); | ||
406 | if (bss) { | ||
407 | if (bss->has_erp_value) | ||
408 | ieee80211_handle_erp_ie(dev, bss->erp_value); | ||
409 | ieee80211_rx_bss_put(dev, bss); | ||
410 | } | ||
411 | |||
380 | netif_carrier_on(dev); | 412 | netif_carrier_on(dev); |
381 | ifsta->prev_bssid_set = 1; | 413 | ifsta->prev_bssid_set = 1; |
382 | memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); | 414 | memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); |
@@ -384,6 +416,7 @@ static void ieee80211_set_associated(struct net_device *dev, | |||
384 | ieee80211_sta_send_associnfo(dev, ifsta); | 416 | ieee80211_sta_send_associnfo(dev, ifsta); |
385 | } else { | 417 | } else { |
386 | netif_carrier_off(dev); | 418 | netif_carrier_off(dev); |
419 | sdata->use_protection = 0; | ||
387 | memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); | 420 | memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); |
388 | } | 421 | } |
389 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | 422 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; |
@@ -1174,6 +1207,18 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, | |||
1174 | return; | 1207 | return; |
1175 | } | 1208 | } |
1176 | 1209 | ||
1210 | /* it probably doesn't, but if the frame includes an ERP value then | ||
1211 | * update our stored copy */ | ||
1212 | if (elems.erp_info && elems.erp_info_len >= 1) { | ||
1213 | struct ieee80211_sta_bss *bss | ||
1214 | = ieee80211_rx_bss_get(dev, ifsta->bssid); | ||
1215 | if (bss) { | ||
1216 | bss->erp_value = elems.erp_info[0]; | ||
1217 | bss->has_erp_value = 1; | ||
1218 | ieee80211_rx_bss_put(dev, bss); | ||
1219 | } | ||
1220 | } | ||
1221 | |||
1177 | printk(KERN_DEBUG "%s: associated\n", dev->name); | 1222 | printk(KERN_DEBUG "%s: associated\n", dev->name); |
1178 | ifsta->aid = aid; | 1223 | ifsta->aid = aid; |
1179 | ifsta->ap_capab = capab_info; | 1224 | ifsta->ap_capab = capab_info; |
@@ -1496,6 +1541,12 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
1496 | return; | 1541 | return; |
1497 | } | 1542 | } |
1498 | 1543 | ||
1544 | /* save the ERP value so that it is available at association time */ | ||
1545 | if (elems.erp_info && elems.erp_info_len >= 1) { | ||
1546 | bss->erp_value = elems.erp_info[0]; | ||
1547 | bss->has_erp_value = 1; | ||
1548 | } | ||
1549 | |||
1499 | bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); | 1550 | bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); |
1500 | bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); | 1551 | bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); |
1501 | if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) { | 1552 | if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) { |
@@ -1611,10 +1662,8 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, | |||
1611 | size_t len, | 1662 | size_t len, |
1612 | struct ieee80211_rx_status *rx_status) | 1663 | struct ieee80211_rx_status *rx_status) |
1613 | { | 1664 | { |
1614 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1615 | struct ieee80211_sub_if_data *sdata; | 1665 | struct ieee80211_sub_if_data *sdata; |
1616 | struct ieee80211_if_sta *ifsta; | 1666 | struct ieee80211_if_sta *ifsta; |
1617 | int use_protection; | ||
1618 | size_t baselen; | 1667 | size_t baselen; |
1619 | struct ieee802_11_elems elems; | 1668 | struct ieee802_11_elems elems; |
1620 | 1669 | ||
@@ -1638,23 +1687,8 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, | |||
1638 | &elems) == ParseFailed) | 1687 | &elems) == ParseFailed) |
1639 | return; | 1688 | return; |
1640 | 1689 | ||
1641 | use_protection = 0; | 1690 | if (elems.erp_info && elems.erp_info_len >= 1) |
1642 | if (elems.erp_info && elems.erp_info_len >= 1) { | 1691 | ieee80211_handle_erp_ie(dev, elems.erp_info[0]); |
1643 | use_protection = | ||
1644 | (elems.erp_info[0] & ERP_INFO_USE_PROTECTION) != 0; | ||
1645 | } | ||
1646 | |||
1647 | if (use_protection != !!ifsta->use_protection) { | ||
1648 | if (net_ratelimit()) { | ||
1649 | printk(KERN_DEBUG "%s: CTS protection %s (BSSID=" | ||
1650 | MAC_FMT ")\n", | ||
1651 | dev->name, | ||
1652 | use_protection ? "enabled" : "disabled", | ||
1653 | MAC_ARG(ifsta->bssid)); | ||
1654 | } | ||
1655 | ifsta->use_protection = use_protection ? 1 : 0; | ||
1656 | local->cts_protect_erp_frames = use_protection; | ||
1657 | } | ||
1658 | 1692 | ||
1659 | if (elems.wmm_param && ifsta->wmm_enabled) { | 1693 | if (elems.wmm_param && ifsta->wmm_enabled) { |
1660 | ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, | 1694 | ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, |
diff --git a/net/mac80211/rc80211_simple.c b/net/mac80211/rc80211_simple.c index 2048cfd1ca70..f6780d63b342 100644 --- a/net/mac80211/rc80211_simple.c +++ b/net/mac80211/rc80211_simple.c | |||
@@ -187,9 +187,13 @@ static void rate_control_simple_tx_status(void *priv, struct net_device *dev, | |||
187 | } | 187 | } |
188 | #endif | 188 | #endif |
189 | 189 | ||
190 | if (per_failed > local->rate_ctrl_num_down) { | 190 | /* |
191 | * XXX: Make these configurable once we have an | ||
192 | * interface to the rate control algorithms | ||
193 | */ | ||
194 | if (per_failed > RATE_CONTROL_NUM_DOWN) { | ||
191 | rate_control_rate_dec(local, sta); | 195 | rate_control_rate_dec(local, sta); |
192 | } else if (per_failed < local->rate_ctrl_num_up) { | 196 | } else if (per_failed < RATE_CONTROL_NUM_UP) { |
193 | rate_control_rate_inc(local, sta); | 197 | rate_control_rate_inc(local, sta); |
194 | } | 198 | } |
195 | srctrl->tx_avg_rate_sum += status->control.rate->rate; | 199 | srctrl->tx_avg_rate_sum += status->control.rate->rate; |
@@ -283,14 +287,16 @@ static void rate_control_simple_rate_init(void *priv, void *priv_sta, | |||
283 | int i; | 287 | int i; |
284 | sta->txrate = 0; | 288 | sta->txrate = 0; |
285 | mode = local->oper_hw_mode; | 289 | mode = local->oper_hw_mode; |
286 | /* TODO: what is a good starting rate for STA? About middle? Maybe not | 290 | /* TODO: This routine should consider using RSSI from previous packets |
287 | * the lowest or the highest rate.. Could consider using RSSI from | 291 | * as we need to have IEEE 802.1X auth succeed immediately after assoc.. |
288 | * previous packets? Need to have IEEE 802.1X auth succeed immediately | 292 | * Until that method is implemented, we will use the lowest supported rate |
289 | * after assoc.. */ | 293 | * as a workaround, */ |
290 | for (i = 0; i < mode->num_rates; i++) { | 294 | for (i = 0; i < mode->num_rates; i++) { |
291 | if ((sta->supp_rates & BIT(i)) && | 295 | if ((sta->supp_rates & BIT(i)) && |
292 | (mode->rates[i].flags & IEEE80211_RATE_SUPPORTED)) | 296 | (mode->rates[i].flags & IEEE80211_RATE_SUPPORTED)) { |
293 | sta->txrate = i; | 297 | sta->txrate = i; |
298 | break; | ||
299 | } | ||
294 | } | 300 | } |
295 | } | 301 | } |
296 | 302 | ||
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index a567dae8e5fd..3ac39f1ec775 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -102,6 +102,16 @@ config NF_CT_PROTO_SCTP | |||
102 | If you want to compile it as a module, say M here and read | 102 | If you want to compile it as a module, say M here and read |
103 | <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. | 103 | <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. |
104 | 104 | ||
105 | config NF_CT_PROTO_UDPLITE | ||
106 | tristate 'UDP-Lite protocol connection tracking support (EXPERIMENTAL)' | ||
107 | depends on EXPERIMENTAL && NF_CONNTRACK | ||
108 | help | ||
109 | With this option enabled, the layer 3 independent connection | ||
110 | tracking code will be able to do state tracking on UDP-Lite | ||
111 | connections. | ||
112 | |||
113 | To compile it as a module, choose M here. If unsure, say N. | ||
114 | |||
105 | config NF_CONNTRACK_AMANDA | 115 | config NF_CONNTRACK_AMANDA |
106 | tristate "Amanda backup protocol support" | 116 | tristate "Amanda backup protocol support" |
107 | depends on NF_CONNTRACK | 117 | depends on NF_CONNTRACK |
@@ -343,6 +353,18 @@ config NETFILTER_XT_TARGET_NOTRACK | |||
343 | If you want to compile it as a module, say M here and read | 353 | If you want to compile it as a module, say M here and read |
344 | <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. | 354 | <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. |
345 | 355 | ||
356 | config NETFILTER_XT_TARGET_TRACE | ||
357 | tristate '"TRACE" target support' | ||
358 | depends on NETFILTER_XTABLES | ||
359 | depends on IP_NF_RAW || IP6_NF_RAW | ||
360 | help | ||
361 | The TRACE target allows you to mark packets so that the kernel | ||
362 | will log every rule which match the packets as those traverse | ||
363 | the tables, chains, rules. | ||
364 | |||
365 | If you want to compile it as a module, say M here and read | ||
366 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
367 | |||
346 | config NETFILTER_XT_TARGET_SECMARK | 368 | config NETFILTER_XT_TARGET_SECMARK |
347 | tristate '"SECMARK" target support' | 369 | tristate '"SECMARK" target support' |
348 | depends on NETFILTER_XTABLES && NETWORK_SECMARK | 370 | depends on NETFILTER_XTABLES && NETWORK_SECMARK |
@@ -411,6 +433,13 @@ config NETFILTER_XT_MATCH_CONNBYTES | |||
411 | If you want to compile it as a module, say M here and read | 433 | If you want to compile it as a module, say M here and read |
412 | <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. | 434 | <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. |
413 | 435 | ||
436 | config NETFILTER_XT_MATCH_CONNLIMIT | ||
437 | tristate '"connlimit" match support"' | ||
438 | depends on NETFILTER_XTABLES | ||
439 | ---help--- | ||
440 | This match allows you to match against the number of parallel | ||
441 | connections to a server per client IP address (or address block). | ||
442 | |||
414 | config NETFILTER_XT_MATCH_CONNMARK | 443 | config NETFILTER_XT_MATCH_CONNMARK |
415 | tristate '"connmark" connection mark match support' | 444 | tristate '"connmark" connection mark match support' |
416 | depends on NETFILTER_XTABLES | 445 | depends on NETFILTER_XTABLES |
@@ -635,6 +664,19 @@ config NETFILTER_XT_MATCH_TCPMSS | |||
635 | 664 | ||
636 | To compile it as a module, choose M here. If unsure, say N. | 665 | To compile it as a module, choose M here. If unsure, say N. |
637 | 666 | ||
667 | config NETFILTER_XT_MATCH_U32 | ||
668 | tristate '"u32" match support' | ||
669 | depends on NETFILTER_XTABLES | ||
670 | ---help--- | ||
671 | u32 allows you to extract quantities of up to 4 bytes from a packet, | ||
672 | AND them with specified masks, shift them by specified amounts and | ||
673 | test whether the results are in any of a set of specified ranges. | ||
674 | The specification of what to extract is general enough to skip over | ||
675 | headers with lengths stored in the packet, as in IP or TCP header | ||
676 | lengths. | ||
677 | |||
678 | Details and examples are in the kernel module source. | ||
679 | |||
638 | config NETFILTER_XT_MATCH_HASHLIMIT | 680 | config NETFILTER_XT_MATCH_HASHLIMIT |
639 | tristate '"hashlimit" match support' | 681 | tristate '"hashlimit" match support' |
640 | depends on NETFILTER_XTABLES && (IP6_NF_IPTABLES || IP6_NF_IPTABLES=n) | 682 | depends on NETFILTER_XTABLES && (IP6_NF_IPTABLES || IP6_NF_IPTABLES=n) |
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index b2b5c7566b26..0c054bf27973 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o | 1 | netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o |
2 | 2 | ||
3 | nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o | 3 | nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o nf_conntrack_extend.o |
4 | nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o | 4 | nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o |
5 | 5 | ||
6 | obj-$(CONFIG_NETFILTER) = netfilter.o | 6 | obj-$(CONFIG_NETFILTER) = netfilter.o |
@@ -16,6 +16,7 @@ obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o | |||
16 | # SCTP protocol connection tracking | 16 | # SCTP protocol connection tracking |
17 | obj-$(CONFIG_NF_CT_PROTO_GRE) += nf_conntrack_proto_gre.o | 17 | obj-$(CONFIG_NF_CT_PROTO_GRE) += nf_conntrack_proto_gre.o |
18 | obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o | 18 | obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o |
19 | obj-$(CONFIG_NF_CT_PROTO_UDPLITE) += nf_conntrack_proto_udplite.o | ||
19 | 20 | ||
20 | # netlink interface for nf_conntrack | 21 | # netlink interface for nf_conntrack |
21 | obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o | 22 | obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o |
@@ -44,6 +45,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o | |||
44 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o | 45 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o |
45 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o | 46 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o |
46 | obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o | 47 | obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o |
48 | obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o | ||
47 | obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o | 49 | obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o |
48 | obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o | 50 | obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o |
49 | obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o | 51 | obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o |
@@ -51,6 +53,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o | |||
51 | # matches | 53 | # matches |
52 | obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o | 54 | obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o |
53 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o | 55 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o |
56 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNLIMIT) += xt_connlimit.o | ||
54 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o | 57 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o |
55 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o | 58 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o |
56 | obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o | 59 | obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o |
@@ -72,4 +75,5 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o | |||
72 | obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o | 75 | obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o |
73 | obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o | 76 | obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o |
74 | obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o | 77 | obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o |
78 | obj-$(CONFIG_NETFILTER_XT_MATCH_U32) += xt_u32.o | ||
75 | obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o | 79 | obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o |
diff --git a/net/netfilter/core.c b/net/netfilter/core.c index a84478ee2ded..381a77cf0c9e 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c | |||
@@ -203,7 +203,9 @@ int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len) | |||
203 | return 0; | 203 | return 0; |
204 | 204 | ||
205 | /* Not exclusive use of packet? Must copy. */ | 205 | /* Not exclusive use of packet? Must copy. */ |
206 | if (skb_shared(*pskb) || skb_cloned(*pskb)) | 206 | if (skb_cloned(*pskb) && !skb_clone_writable(*pskb, writable_len)) |
207 | goto copy_skb; | ||
208 | if (skb_shared(*pskb)) | ||
207 | goto copy_skb; | 209 | goto copy_skb; |
208 | 210 | ||
209 | return pskb_may_pull(*pskb, writable_len); | 211 | return pskb_may_pull(*pskb, writable_len); |
@@ -229,13 +231,13 @@ void nf_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb, | |||
229 | { | 231 | { |
230 | __be32 diff[] = { ~from, to }; | 232 | __be32 diff[] = { ~from, to }; |
231 | if (skb->ip_summed != CHECKSUM_PARTIAL) { | 233 | if (skb->ip_summed != CHECKSUM_PARTIAL) { |
232 | *sum = csum_fold(csum_partial((char *)diff, sizeof(diff), | 234 | *sum = csum_fold(csum_partial(diff, sizeof(diff), |
233 | ~csum_unfold(*sum))); | 235 | ~csum_unfold(*sum))); |
234 | if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr) | 236 | if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr) |
235 | skb->csum = ~csum_partial((char *)diff, sizeof(diff), | 237 | skb->csum = ~csum_partial(diff, sizeof(diff), |
236 | ~skb->csum); | 238 | ~skb->csum); |
237 | } else if (pseudohdr) | 239 | } else if (pseudohdr) |
238 | *sum = ~csum_fold(csum_partial((char *)diff, sizeof(diff), | 240 | *sum = ~csum_fold(csum_partial(diff, sizeof(diff), |
239 | csum_unfold(*sum))); | 241 | csum_unfold(*sum))); |
240 | } | 242 | } |
241 | EXPORT_SYMBOL(nf_proto_csum_replace4); | 243 | EXPORT_SYMBOL(nf_proto_csum_replace4); |
diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c index 0568f2e86b59..e42ab230ad88 100644 --- a/net/netfilter/nf_conntrack_amanda.c +++ b/net/netfilter/nf_conntrack_amanda.c | |||
@@ -142,23 +142,22 @@ static int amanda_help(struct sk_buff **pskb, | |||
142 | if (port == 0 || len > 5) | 142 | if (port == 0 || len > 5) |
143 | break; | 143 | break; |
144 | 144 | ||
145 | exp = nf_conntrack_expect_alloc(ct); | 145 | exp = nf_ct_expect_alloc(ct); |
146 | if (exp == NULL) { | 146 | if (exp == NULL) { |
147 | ret = NF_DROP; | 147 | ret = NF_DROP; |
148 | goto out; | 148 | goto out; |
149 | } | 149 | } |
150 | tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; | 150 | tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; |
151 | nf_conntrack_expect_init(exp, family, | 151 | nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3, |
152 | &tuple->src.u3, &tuple->dst.u3, | 152 | IPPROTO_TCP, NULL, &port); |
153 | IPPROTO_TCP, NULL, &port); | ||
154 | 153 | ||
155 | nf_nat_amanda = rcu_dereference(nf_nat_amanda_hook); | 154 | nf_nat_amanda = rcu_dereference(nf_nat_amanda_hook); |
156 | if (nf_nat_amanda && ct->status & IPS_NAT_MASK) | 155 | if (nf_nat_amanda && ct->status & IPS_NAT_MASK) |
157 | ret = nf_nat_amanda(pskb, ctinfo, off - dataoff, | 156 | ret = nf_nat_amanda(pskb, ctinfo, off - dataoff, |
158 | len, exp); | 157 | len, exp); |
159 | else if (nf_conntrack_expect_related(exp) != 0) | 158 | else if (nf_ct_expect_related(exp) != 0) |
160 | ret = NF_DROP; | 159 | ret = NF_DROP; |
161 | nf_conntrack_expect_put(exp); | 160 | nf_ct_expect_put(exp); |
162 | } | 161 | } |
163 | 162 | ||
164 | out: | 163 | out: |
@@ -175,9 +174,6 @@ static struct nf_conntrack_helper amanda_helper[2] __read_mostly = { | |||
175 | .tuple.src.l3num = AF_INET, | 174 | .tuple.src.l3num = AF_INET, |
176 | .tuple.src.u.udp.port = __constant_htons(10080), | 175 | .tuple.src.u.udp.port = __constant_htons(10080), |
177 | .tuple.dst.protonum = IPPROTO_UDP, | 176 | .tuple.dst.protonum = IPPROTO_UDP, |
178 | .mask.src.l3num = 0xFFFF, | ||
179 | .mask.src.u.udp.port = __constant_htons(0xFFFF), | ||
180 | .mask.dst.protonum = 0xFF, | ||
181 | }, | 177 | }, |
182 | { | 178 | { |
183 | .name = "amanda", | 179 | .name = "amanda", |
@@ -188,9 +184,6 @@ static struct nf_conntrack_helper amanda_helper[2] __read_mostly = { | |||
188 | .tuple.src.l3num = AF_INET6, | 184 | .tuple.src.l3num = AF_INET6, |
189 | .tuple.src.u.udp.port = __constant_htons(10080), | 185 | .tuple.src.u.udp.port = __constant_htons(10080), |
190 | .tuple.dst.protonum = IPPROTO_UDP, | 186 | .tuple.dst.protonum = IPPROTO_UDP, |
191 | .mask.src.l3num = 0xFFFF, | ||
192 | .mask.src.u.udp.port = __constant_htons(0xFFFF), | ||
193 | .mask.dst.protonum = 0xFF, | ||
194 | }, | 187 | }, |
195 | }; | 188 | }; |
196 | 189 | ||
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 7a15e30356f2..8cce814f6bee 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -36,15 +36,10 @@ | |||
36 | #include <net/netfilter/nf_conntrack_expect.h> | 36 | #include <net/netfilter/nf_conntrack_expect.h> |
37 | #include <net/netfilter/nf_conntrack_helper.h> | 37 | #include <net/netfilter/nf_conntrack_helper.h> |
38 | #include <net/netfilter/nf_conntrack_core.h> | 38 | #include <net/netfilter/nf_conntrack_core.h> |
39 | #include <net/netfilter/nf_conntrack_extend.h> | ||
39 | 40 | ||
40 | #define NF_CONNTRACK_VERSION "0.5.0" | 41 | #define NF_CONNTRACK_VERSION "0.5.0" |
41 | 42 | ||
42 | #if 0 | ||
43 | #define DEBUGP printk | ||
44 | #else | ||
45 | #define DEBUGP(format, args...) | ||
46 | #endif | ||
47 | |||
48 | DEFINE_RWLOCK(nf_conntrack_lock); | 43 | DEFINE_RWLOCK(nf_conntrack_lock); |
49 | EXPORT_SYMBOL_GPL(nf_conntrack_lock); | 44 | EXPORT_SYMBOL_GPL(nf_conntrack_lock); |
50 | 45 | ||
@@ -52,57 +47,27 @@ EXPORT_SYMBOL_GPL(nf_conntrack_lock); | |||
52 | atomic_t nf_conntrack_count = ATOMIC_INIT(0); | 47 | atomic_t nf_conntrack_count = ATOMIC_INIT(0); |
53 | EXPORT_SYMBOL_GPL(nf_conntrack_count); | 48 | EXPORT_SYMBOL_GPL(nf_conntrack_count); |
54 | 49 | ||
55 | void (*nf_conntrack_destroyed)(struct nf_conn *conntrack); | ||
56 | EXPORT_SYMBOL_GPL(nf_conntrack_destroyed); | ||
57 | |||
58 | unsigned int nf_conntrack_htable_size __read_mostly; | 50 | unsigned int nf_conntrack_htable_size __read_mostly; |
59 | EXPORT_SYMBOL_GPL(nf_conntrack_htable_size); | 51 | EXPORT_SYMBOL_GPL(nf_conntrack_htable_size); |
60 | 52 | ||
61 | int nf_conntrack_max __read_mostly; | 53 | int nf_conntrack_max __read_mostly; |
62 | EXPORT_SYMBOL_GPL(nf_conntrack_max); | 54 | EXPORT_SYMBOL_GPL(nf_conntrack_max); |
63 | 55 | ||
64 | struct list_head *nf_conntrack_hash __read_mostly; | 56 | struct hlist_head *nf_conntrack_hash __read_mostly; |
65 | EXPORT_SYMBOL_GPL(nf_conntrack_hash); | 57 | EXPORT_SYMBOL_GPL(nf_conntrack_hash); |
66 | 58 | ||
67 | struct nf_conn nf_conntrack_untracked __read_mostly; | 59 | struct nf_conn nf_conntrack_untracked __read_mostly; |
68 | EXPORT_SYMBOL_GPL(nf_conntrack_untracked); | 60 | EXPORT_SYMBOL_GPL(nf_conntrack_untracked); |
69 | 61 | ||
70 | unsigned int nf_ct_log_invalid __read_mostly; | 62 | unsigned int nf_ct_log_invalid __read_mostly; |
71 | LIST_HEAD(unconfirmed); | 63 | HLIST_HEAD(unconfirmed); |
72 | static int nf_conntrack_vmalloc __read_mostly; | 64 | static int nf_conntrack_vmalloc __read_mostly; |
73 | 65 | static struct kmem_cache *nf_conntrack_cachep __read_mostly; | |
74 | static unsigned int nf_conntrack_next_id; | 66 | static unsigned int nf_conntrack_next_id; |
75 | 67 | ||
76 | DEFINE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat); | 68 | DEFINE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat); |
77 | EXPORT_PER_CPU_SYMBOL(nf_conntrack_stat); | 69 | EXPORT_PER_CPU_SYMBOL(nf_conntrack_stat); |
78 | 70 | ||
79 | /* | ||
80 | * This scheme offers various size of "struct nf_conn" dependent on | ||
81 | * features(helper, nat, ...) | ||
82 | */ | ||
83 | |||
84 | #define NF_CT_FEATURES_NAMELEN 256 | ||
85 | static struct { | ||
86 | /* name of slab cache. printed in /proc/slabinfo */ | ||
87 | char *name; | ||
88 | |||
89 | /* size of slab cache */ | ||
90 | size_t size; | ||
91 | |||
92 | /* slab cache pointer */ | ||
93 | struct kmem_cache *cachep; | ||
94 | |||
95 | /* allocated slab cache + modules which uses this slab cache */ | ||
96 | int use; | ||
97 | |||
98 | } nf_ct_cache[NF_CT_F_NUM]; | ||
99 | |||
100 | /* protect members of nf_ct_cache except of "use" */ | ||
101 | DEFINE_RWLOCK(nf_ct_cache_lock); | ||
102 | |||
103 | /* This avoids calling kmem_cache_create() with same name simultaneously */ | ||
104 | static DEFINE_MUTEX(nf_ct_cache_mutex); | ||
105 | |||
106 | static int nf_conntrack_hash_rnd_initted; | 71 | static int nf_conntrack_hash_rnd_initted; |
107 | static unsigned int nf_conntrack_hash_rnd; | 72 | static unsigned int nf_conntrack_hash_rnd; |
108 | 73 | ||
@@ -125,122 +90,6 @@ static inline u_int32_t hash_conntrack(const struct nf_conntrack_tuple *tuple) | |||
125 | nf_conntrack_hash_rnd); | 90 | nf_conntrack_hash_rnd); |
126 | } | 91 | } |
127 | 92 | ||
128 | int nf_conntrack_register_cache(u_int32_t features, const char *name, | ||
129 | size_t size) | ||
130 | { | ||
131 | int ret = 0; | ||
132 | char *cache_name; | ||
133 | struct kmem_cache *cachep; | ||
134 | |||
135 | DEBUGP("nf_conntrack_register_cache: features=0x%x, name=%s, size=%d\n", | ||
136 | features, name, size); | ||
137 | |||
138 | if (features < NF_CT_F_BASIC || features >= NF_CT_F_NUM) { | ||
139 | DEBUGP("nf_conntrack_register_cache: invalid features.: 0x%x\n", | ||
140 | features); | ||
141 | return -EINVAL; | ||
142 | } | ||
143 | |||
144 | mutex_lock(&nf_ct_cache_mutex); | ||
145 | |||
146 | write_lock_bh(&nf_ct_cache_lock); | ||
147 | /* e.g: multiple helpers are loaded */ | ||
148 | if (nf_ct_cache[features].use > 0) { | ||
149 | DEBUGP("nf_conntrack_register_cache: already resisterd.\n"); | ||
150 | if ((!strncmp(nf_ct_cache[features].name, name, | ||
151 | NF_CT_FEATURES_NAMELEN)) | ||
152 | && nf_ct_cache[features].size == size) { | ||
153 | DEBUGP("nf_conntrack_register_cache: reusing.\n"); | ||
154 | nf_ct_cache[features].use++; | ||
155 | ret = 0; | ||
156 | } else | ||
157 | ret = -EBUSY; | ||
158 | |||
159 | write_unlock_bh(&nf_ct_cache_lock); | ||
160 | mutex_unlock(&nf_ct_cache_mutex); | ||
161 | return ret; | ||
162 | } | ||
163 | write_unlock_bh(&nf_ct_cache_lock); | ||
164 | |||
165 | /* | ||
166 | * The memory space for name of slab cache must be alive until | ||
167 | * cache is destroyed. | ||
168 | */ | ||
169 | cache_name = kmalloc(sizeof(char)*NF_CT_FEATURES_NAMELEN, GFP_ATOMIC); | ||
170 | if (cache_name == NULL) { | ||
171 | DEBUGP("nf_conntrack_register_cache: can't alloc cache_name\n"); | ||
172 | ret = -ENOMEM; | ||
173 | goto out_up_mutex; | ||
174 | } | ||
175 | |||
176 | if (strlcpy(cache_name, name, NF_CT_FEATURES_NAMELEN) | ||
177 | >= NF_CT_FEATURES_NAMELEN) { | ||
178 | printk("nf_conntrack_register_cache: name too long\n"); | ||
179 | ret = -EINVAL; | ||
180 | goto out_free_name; | ||
181 | } | ||
182 | |||
183 | cachep = kmem_cache_create(cache_name, size, 0, 0, | ||
184 | NULL, NULL); | ||
185 | if (!cachep) { | ||
186 | printk("nf_conntrack_register_cache: Can't create slab cache " | ||
187 | "for the features = 0x%x\n", features); | ||
188 | ret = -ENOMEM; | ||
189 | goto out_free_name; | ||
190 | } | ||
191 | |||
192 | write_lock_bh(&nf_ct_cache_lock); | ||
193 | nf_ct_cache[features].use = 1; | ||
194 | nf_ct_cache[features].size = size; | ||
195 | nf_ct_cache[features].cachep = cachep; | ||
196 | nf_ct_cache[features].name = cache_name; | ||
197 | write_unlock_bh(&nf_ct_cache_lock); | ||
198 | |||
199 | goto out_up_mutex; | ||
200 | |||
201 | out_free_name: | ||
202 | kfree(cache_name); | ||
203 | out_up_mutex: | ||
204 | mutex_unlock(&nf_ct_cache_mutex); | ||
205 | return ret; | ||
206 | } | ||
207 | EXPORT_SYMBOL_GPL(nf_conntrack_register_cache); | ||
208 | |||
209 | /* FIXME: In the current, only nf_conntrack_cleanup() can call this function. */ | ||
210 | void nf_conntrack_unregister_cache(u_int32_t features) | ||
211 | { | ||
212 | struct kmem_cache *cachep; | ||
213 | char *name; | ||
214 | |||
215 | /* | ||
216 | * This assures that kmem_cache_create() isn't called before destroying | ||
217 | * slab cache. | ||
218 | */ | ||
219 | DEBUGP("nf_conntrack_unregister_cache: 0x%04x\n", features); | ||
220 | mutex_lock(&nf_ct_cache_mutex); | ||
221 | |||
222 | write_lock_bh(&nf_ct_cache_lock); | ||
223 | if (--nf_ct_cache[features].use > 0) { | ||
224 | write_unlock_bh(&nf_ct_cache_lock); | ||
225 | mutex_unlock(&nf_ct_cache_mutex); | ||
226 | return; | ||
227 | } | ||
228 | cachep = nf_ct_cache[features].cachep; | ||
229 | name = nf_ct_cache[features].name; | ||
230 | nf_ct_cache[features].cachep = NULL; | ||
231 | nf_ct_cache[features].name = NULL; | ||
232 | nf_ct_cache[features].size = 0; | ||
233 | write_unlock_bh(&nf_ct_cache_lock); | ||
234 | |||
235 | synchronize_net(); | ||
236 | |||
237 | kmem_cache_destroy(cachep); | ||
238 | kfree(name); | ||
239 | |||
240 | mutex_unlock(&nf_ct_cache_mutex); | ||
241 | } | ||
242 | EXPORT_SYMBOL_GPL(nf_conntrack_unregister_cache); | ||
243 | |||
244 | int | 93 | int |
245 | nf_ct_get_tuple(const struct sk_buff *skb, | 94 | nf_ct_get_tuple(const struct sk_buff *skb, |
246 | unsigned int nhoff, | 95 | unsigned int nhoff, |
@@ -264,6 +113,36 @@ nf_ct_get_tuple(const struct sk_buff *skb, | |||
264 | } | 113 | } |
265 | EXPORT_SYMBOL_GPL(nf_ct_get_tuple); | 114 | EXPORT_SYMBOL_GPL(nf_ct_get_tuple); |
266 | 115 | ||
116 | int nf_ct_get_tuplepr(const struct sk_buff *skb, | ||
117 | unsigned int nhoff, | ||
118 | u_int16_t l3num, | ||
119 | struct nf_conntrack_tuple *tuple) | ||
120 | { | ||
121 | struct nf_conntrack_l3proto *l3proto; | ||
122 | struct nf_conntrack_l4proto *l4proto; | ||
123 | unsigned int protoff; | ||
124 | u_int8_t protonum; | ||
125 | int ret; | ||
126 | |||
127 | rcu_read_lock(); | ||
128 | |||
129 | l3proto = __nf_ct_l3proto_find(l3num); | ||
130 | ret = l3proto->get_l4proto(skb, nhoff, &protoff, &protonum); | ||
131 | if (ret != NF_ACCEPT) { | ||
132 | rcu_read_unlock(); | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | l4proto = __nf_ct_l4proto_find(l3num, protonum); | ||
137 | |||
138 | ret = nf_ct_get_tuple(skb, nhoff, protoff, l3num, protonum, tuple, | ||
139 | l3proto, l4proto); | ||
140 | |||
141 | rcu_read_unlock(); | ||
142 | return ret; | ||
143 | } | ||
144 | EXPORT_SYMBOL_GPL(nf_ct_get_tuplepr); | ||
145 | |||
267 | int | 146 | int |
268 | nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, | 147 | nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, |
269 | const struct nf_conntrack_tuple *orig, | 148 | const struct nf_conntrack_tuple *orig, |
@@ -286,9 +165,9 @@ EXPORT_SYMBOL_GPL(nf_ct_invert_tuple); | |||
286 | static void | 165 | static void |
287 | clean_from_lists(struct nf_conn *ct) | 166 | clean_from_lists(struct nf_conn *ct) |
288 | { | 167 | { |
289 | DEBUGP("clean_from_lists(%p)\n", ct); | 168 | pr_debug("clean_from_lists(%p)\n", ct); |
290 | list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list); | 169 | hlist_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode); |
291 | list_del(&ct->tuplehash[IP_CT_DIR_REPLY].list); | 170 | hlist_del(&ct->tuplehash[IP_CT_DIR_REPLY].hnode); |
292 | 171 | ||
293 | /* Destroy all pending expectations */ | 172 | /* Destroy all pending expectations */ |
294 | nf_ct_remove_expectations(ct); | 173 | nf_ct_remove_expectations(ct); |
@@ -299,9 +178,8 @@ destroy_conntrack(struct nf_conntrack *nfct) | |||
299 | { | 178 | { |
300 | struct nf_conn *ct = (struct nf_conn *)nfct; | 179 | struct nf_conn *ct = (struct nf_conn *)nfct; |
301 | struct nf_conntrack_l4proto *l4proto; | 180 | struct nf_conntrack_l4proto *l4proto; |
302 | typeof(nf_conntrack_destroyed) destroyed; | ||
303 | 181 | ||
304 | DEBUGP("destroy_conntrack(%p)\n", ct); | 182 | pr_debug("destroy_conntrack(%p)\n", ct); |
305 | NF_CT_ASSERT(atomic_read(&nfct->use) == 0); | 183 | NF_CT_ASSERT(atomic_read(&nfct->use) == 0); |
306 | NF_CT_ASSERT(!timer_pending(&ct->timeout)); | 184 | NF_CT_ASSERT(!timer_pending(&ct->timeout)); |
307 | 185 | ||
@@ -317,9 +195,7 @@ destroy_conntrack(struct nf_conntrack *nfct) | |||
317 | if (l4proto && l4proto->destroy) | 195 | if (l4proto && l4proto->destroy) |
318 | l4proto->destroy(ct); | 196 | l4proto->destroy(ct); |
319 | 197 | ||
320 | destroyed = rcu_dereference(nf_conntrack_destroyed); | 198 | nf_ct_ext_destroy(ct); |
321 | if (destroyed) | ||
322 | destroyed(ct); | ||
323 | 199 | ||
324 | rcu_read_unlock(); | 200 | rcu_read_unlock(); |
325 | 201 | ||
@@ -332,8 +208,8 @@ destroy_conntrack(struct nf_conntrack *nfct) | |||
332 | 208 | ||
333 | /* We overload first tuple to link into unconfirmed list. */ | 209 | /* We overload first tuple to link into unconfirmed list. */ |
334 | if (!nf_ct_is_confirmed(ct)) { | 210 | if (!nf_ct_is_confirmed(ct)) { |
335 | BUG_ON(list_empty(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list)); | 211 | BUG_ON(hlist_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode)); |
336 | list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list); | 212 | hlist_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode); |
337 | } | 213 | } |
338 | 214 | ||
339 | NF_CT_STAT_INC(delete); | 215 | NF_CT_STAT_INC(delete); |
@@ -342,7 +218,7 @@ destroy_conntrack(struct nf_conntrack *nfct) | |||
342 | if (ct->master) | 218 | if (ct->master) |
343 | nf_ct_put(ct->master); | 219 | nf_ct_put(ct->master); |
344 | 220 | ||
345 | DEBUGP("destroy_conntrack: returning ct=%p to slab\n", ct); | 221 | pr_debug("destroy_conntrack: returning ct=%p to slab\n", ct); |
346 | nf_conntrack_free(ct); | 222 | nf_conntrack_free(ct); |
347 | } | 223 | } |
348 | 224 | ||
@@ -374,9 +250,10 @@ __nf_conntrack_find(const struct nf_conntrack_tuple *tuple, | |||
374 | const struct nf_conn *ignored_conntrack) | 250 | const struct nf_conn *ignored_conntrack) |
375 | { | 251 | { |
376 | struct nf_conntrack_tuple_hash *h; | 252 | struct nf_conntrack_tuple_hash *h; |
253 | struct hlist_node *n; | ||
377 | unsigned int hash = hash_conntrack(tuple); | 254 | unsigned int hash = hash_conntrack(tuple); |
378 | 255 | ||
379 | list_for_each_entry(h, &nf_conntrack_hash[hash], list) { | 256 | hlist_for_each_entry(h, n, &nf_conntrack_hash[hash], hnode) { |
380 | if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack && | 257 | if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack && |
381 | nf_ct_tuple_equal(tuple, &h->tuple)) { | 258 | nf_ct_tuple_equal(tuple, &h->tuple)) { |
382 | NF_CT_STAT_INC(found); | 259 | NF_CT_STAT_INC(found); |
@@ -391,13 +268,12 @@ EXPORT_SYMBOL_GPL(__nf_conntrack_find); | |||
391 | 268 | ||
392 | /* Find a connection corresponding to a tuple. */ | 269 | /* Find a connection corresponding to a tuple. */ |
393 | struct nf_conntrack_tuple_hash * | 270 | struct nf_conntrack_tuple_hash * |
394 | nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple, | 271 | nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple) |
395 | const struct nf_conn *ignored_conntrack) | ||
396 | { | 272 | { |
397 | struct nf_conntrack_tuple_hash *h; | 273 | struct nf_conntrack_tuple_hash *h; |
398 | 274 | ||
399 | read_lock_bh(&nf_conntrack_lock); | 275 | read_lock_bh(&nf_conntrack_lock); |
400 | h = __nf_conntrack_find(tuple, ignored_conntrack); | 276 | h = __nf_conntrack_find(tuple, NULL); |
401 | if (h) | 277 | if (h) |
402 | atomic_inc(&nf_ct_tuplehash_to_ctrack(h)->ct_general.use); | 278 | atomic_inc(&nf_ct_tuplehash_to_ctrack(h)->ct_general.use); |
403 | read_unlock_bh(&nf_conntrack_lock); | 279 | read_unlock_bh(&nf_conntrack_lock); |
@@ -411,10 +287,10 @@ static void __nf_conntrack_hash_insert(struct nf_conn *ct, | |||
411 | unsigned int repl_hash) | 287 | unsigned int repl_hash) |
412 | { | 288 | { |
413 | ct->id = ++nf_conntrack_next_id; | 289 | ct->id = ++nf_conntrack_next_id; |
414 | list_add(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list, | 290 | hlist_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode, |
415 | &nf_conntrack_hash[hash]); | 291 | &nf_conntrack_hash[hash]); |
416 | list_add(&ct->tuplehash[IP_CT_DIR_REPLY].list, | 292 | hlist_add_head(&ct->tuplehash[IP_CT_DIR_REPLY].hnode, |
417 | &nf_conntrack_hash[repl_hash]); | 293 | &nf_conntrack_hash[repl_hash]); |
418 | } | 294 | } |
419 | 295 | ||
420 | void nf_conntrack_hash_insert(struct nf_conn *ct) | 296 | void nf_conntrack_hash_insert(struct nf_conn *ct) |
@@ -438,6 +314,7 @@ __nf_conntrack_confirm(struct sk_buff **pskb) | |||
438 | struct nf_conntrack_tuple_hash *h; | 314 | struct nf_conntrack_tuple_hash *h; |
439 | struct nf_conn *ct; | 315 | struct nf_conn *ct; |
440 | struct nf_conn_help *help; | 316 | struct nf_conn_help *help; |
317 | struct hlist_node *n; | ||
441 | enum ip_conntrack_info ctinfo; | 318 | enum ip_conntrack_info ctinfo; |
442 | 319 | ||
443 | ct = nf_ct_get(*pskb, &ctinfo); | 320 | ct = nf_ct_get(*pskb, &ctinfo); |
@@ -460,24 +337,24 @@ __nf_conntrack_confirm(struct sk_buff **pskb) | |||
460 | /* No external references means noone else could have | 337 | /* No external references means noone else could have |
461 | confirmed us. */ | 338 | confirmed us. */ |
462 | NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); | 339 | NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); |
463 | DEBUGP("Confirming conntrack %p\n", ct); | 340 | pr_debug("Confirming conntrack %p\n", ct); |
464 | 341 | ||
465 | write_lock_bh(&nf_conntrack_lock); | 342 | write_lock_bh(&nf_conntrack_lock); |
466 | 343 | ||
467 | /* See if there's one in the list already, including reverse: | 344 | /* See if there's one in the list already, including reverse: |
468 | NAT could have grabbed it without realizing, since we're | 345 | NAT could have grabbed it without realizing, since we're |
469 | not in the hash. If there is, we lost race. */ | 346 | not in the hash. If there is, we lost race. */ |
470 | list_for_each_entry(h, &nf_conntrack_hash[hash], list) | 347 | hlist_for_each_entry(h, n, &nf_conntrack_hash[hash], hnode) |
471 | if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, | 348 | if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, |
472 | &h->tuple)) | 349 | &h->tuple)) |
473 | goto out; | 350 | goto out; |
474 | list_for_each_entry(h, &nf_conntrack_hash[repl_hash], list) | 351 | hlist_for_each_entry(h, n, &nf_conntrack_hash[repl_hash], hnode) |
475 | if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple, | 352 | if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple, |
476 | &h->tuple)) | 353 | &h->tuple)) |
477 | goto out; | 354 | goto out; |
478 | 355 | ||
479 | /* Remove from unconfirmed list */ | 356 | /* Remove from unconfirmed list */ |
480 | list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list); | 357 | hlist_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode); |
481 | 358 | ||
482 | __nf_conntrack_hash_insert(ct, hash, repl_hash); | 359 | __nf_conntrack_hash_insert(ct, hash, repl_hash); |
483 | /* Timer relative to confirmation time, not original | 360 | /* Timer relative to confirmation time, not original |
@@ -524,24 +401,33 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, | |||
524 | } | 401 | } |
525 | EXPORT_SYMBOL_GPL(nf_conntrack_tuple_taken); | 402 | EXPORT_SYMBOL_GPL(nf_conntrack_tuple_taken); |
526 | 403 | ||
404 | #define NF_CT_EVICTION_RANGE 8 | ||
405 | |||
527 | /* There's a small race here where we may free a just-assured | 406 | /* There's a small race here where we may free a just-assured |
528 | connection. Too bad: we're in trouble anyway. */ | 407 | connection. Too bad: we're in trouble anyway. */ |
529 | static int early_drop(struct list_head *chain) | 408 | static int early_drop(unsigned int hash) |
530 | { | 409 | { |
531 | /* Traverse backwards: gives us oldest, which is roughly LRU */ | 410 | /* Use oldest entry, which is roughly LRU */ |
532 | struct nf_conntrack_tuple_hash *h; | 411 | struct nf_conntrack_tuple_hash *h; |
533 | struct nf_conn *ct = NULL, *tmp; | 412 | struct nf_conn *ct = NULL, *tmp; |
413 | struct hlist_node *n; | ||
414 | unsigned int i, cnt = 0; | ||
534 | int dropped = 0; | 415 | int dropped = 0; |
535 | 416 | ||
536 | read_lock_bh(&nf_conntrack_lock); | 417 | read_lock_bh(&nf_conntrack_lock); |
537 | list_for_each_entry_reverse(h, chain, list) { | 418 | for (i = 0; i < nf_conntrack_htable_size; i++) { |
538 | tmp = nf_ct_tuplehash_to_ctrack(h); | 419 | hlist_for_each_entry(h, n, &nf_conntrack_hash[hash], hnode) { |
539 | if (!test_bit(IPS_ASSURED_BIT, &tmp->status)) { | 420 | tmp = nf_ct_tuplehash_to_ctrack(h); |
540 | ct = tmp; | 421 | if (!test_bit(IPS_ASSURED_BIT, &tmp->status)) |
541 | atomic_inc(&ct->ct_general.use); | 422 | ct = tmp; |
542 | break; | 423 | cnt++; |
543 | } | 424 | } |
425 | if (ct || cnt >= NF_CT_EVICTION_RANGE) | ||
426 | break; | ||
427 | hash = (hash + 1) % nf_conntrack_htable_size; | ||
544 | } | 428 | } |
429 | if (ct) | ||
430 | atomic_inc(&ct->ct_general.use); | ||
545 | read_unlock_bh(&nf_conntrack_lock); | 431 | read_unlock_bh(&nf_conntrack_lock); |
546 | 432 | ||
547 | if (!ct) | 433 | if (!ct) |
@@ -556,14 +442,10 @@ static int early_drop(struct list_head *chain) | |||
556 | return dropped; | 442 | return dropped; |
557 | } | 443 | } |
558 | 444 | ||
559 | static struct nf_conn * | 445 | struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, |
560 | __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, | 446 | const struct nf_conntrack_tuple *repl) |
561 | const struct nf_conntrack_tuple *repl, | ||
562 | const struct nf_conntrack_l3proto *l3proto, | ||
563 | u_int32_t features) | ||
564 | { | 447 | { |
565 | struct nf_conn *conntrack = NULL; | 448 | struct nf_conn *conntrack = NULL; |
566 | struct nf_conntrack_helper *helper; | ||
567 | 449 | ||
568 | if (unlikely(!nf_conntrack_hash_rnd_initted)) { | 450 | if (unlikely(!nf_conntrack_hash_rnd_initted)) { |
569 | get_random_bytes(&nf_conntrack_hash_rnd, 4); | 451 | get_random_bytes(&nf_conntrack_hash_rnd, 4); |
@@ -576,8 +458,7 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, | |||
576 | if (nf_conntrack_max | 458 | if (nf_conntrack_max |
577 | && atomic_read(&nf_conntrack_count) > nf_conntrack_max) { | 459 | && atomic_read(&nf_conntrack_count) > nf_conntrack_max) { |
578 | unsigned int hash = hash_conntrack(orig); | 460 | unsigned int hash = hash_conntrack(orig); |
579 | /* Try dropping from this hash chain. */ | 461 | if (!early_drop(hash)) { |
580 | if (!early_drop(&nf_conntrack_hash[hash])) { | ||
581 | atomic_dec(&nf_conntrack_count); | 462 | atomic_dec(&nf_conntrack_count); |
582 | if (net_ratelimit()) | 463 | if (net_ratelimit()) |
583 | printk(KERN_WARNING | 464 | printk(KERN_WARNING |
@@ -587,72 +468,28 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, | |||
587 | } | 468 | } |
588 | } | 469 | } |
589 | 470 | ||
590 | /* find features needed by this conntrack. */ | 471 | conntrack = kmem_cache_zalloc(nf_conntrack_cachep, GFP_ATOMIC); |
591 | features |= l3proto->get_features(orig); | ||
592 | |||
593 | /* FIXME: protect helper list per RCU */ | ||
594 | read_lock_bh(&nf_conntrack_lock); | ||
595 | helper = __nf_ct_helper_find(repl); | ||
596 | /* NAT might want to assign a helper later */ | ||
597 | if (helper || features & NF_CT_F_NAT) | ||
598 | features |= NF_CT_F_HELP; | ||
599 | read_unlock_bh(&nf_conntrack_lock); | ||
600 | |||
601 | DEBUGP("nf_conntrack_alloc: features=0x%x\n", features); | ||
602 | |||
603 | read_lock_bh(&nf_ct_cache_lock); | ||
604 | |||
605 | if (unlikely(!nf_ct_cache[features].use)) { | ||
606 | DEBUGP("nf_conntrack_alloc: not supported features = 0x%x\n", | ||
607 | features); | ||
608 | goto out; | ||
609 | } | ||
610 | |||
611 | conntrack = kmem_cache_alloc(nf_ct_cache[features].cachep, GFP_ATOMIC); | ||
612 | if (conntrack == NULL) { | 472 | if (conntrack == NULL) { |
613 | DEBUGP("nf_conntrack_alloc: Can't alloc conntrack from cache\n"); | 473 | pr_debug("nf_conntrack_alloc: Can't alloc conntrack.\n"); |
614 | goto out; | 474 | atomic_dec(&nf_conntrack_count); |
475 | return ERR_PTR(-ENOMEM); | ||
615 | } | 476 | } |
616 | 477 | ||
617 | memset(conntrack, 0, nf_ct_cache[features].size); | ||
618 | conntrack->features = features; | ||
619 | atomic_set(&conntrack->ct_general.use, 1); | 478 | atomic_set(&conntrack->ct_general.use, 1); |
620 | conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig; | 479 | conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig; |
621 | conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *repl; | 480 | conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *repl; |
622 | /* Don't set timer yet: wait for confirmation */ | 481 | /* Don't set timer yet: wait for confirmation */ |
623 | setup_timer(&conntrack->timeout, death_by_timeout, | 482 | setup_timer(&conntrack->timeout, death_by_timeout, |
624 | (unsigned long)conntrack); | 483 | (unsigned long)conntrack); |
625 | read_unlock_bh(&nf_ct_cache_lock); | ||
626 | 484 | ||
627 | return conntrack; | 485 | return conntrack; |
628 | out: | ||
629 | read_unlock_bh(&nf_ct_cache_lock); | ||
630 | atomic_dec(&nf_conntrack_count); | ||
631 | return conntrack; | ||
632 | } | ||
633 | |||
634 | struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, | ||
635 | const struct nf_conntrack_tuple *repl) | ||
636 | { | ||
637 | struct nf_conntrack_l3proto *l3proto; | ||
638 | struct nf_conn *ct; | ||
639 | |||
640 | rcu_read_lock(); | ||
641 | l3proto = __nf_ct_l3proto_find(orig->src.l3num); | ||
642 | ct = __nf_conntrack_alloc(orig, repl, l3proto, 0); | ||
643 | rcu_read_unlock(); | ||
644 | |||
645 | return ct; | ||
646 | } | 486 | } |
647 | EXPORT_SYMBOL_GPL(nf_conntrack_alloc); | 487 | EXPORT_SYMBOL_GPL(nf_conntrack_alloc); |
648 | 488 | ||
649 | void nf_conntrack_free(struct nf_conn *conntrack) | 489 | void nf_conntrack_free(struct nf_conn *conntrack) |
650 | { | 490 | { |
651 | u_int32_t features = conntrack->features; | 491 | nf_ct_ext_free(conntrack); |
652 | NF_CT_ASSERT(features >= NF_CT_F_BASIC && features < NF_CT_F_NUM); | 492 | kmem_cache_free(nf_conntrack_cachep, conntrack); |
653 | DEBUGP("nf_conntrack_free: features = 0x%x, conntrack=%p\n", features, | ||
654 | conntrack); | ||
655 | kmem_cache_free(nf_ct_cache[features].cachep, conntrack); | ||
656 | atomic_dec(&nf_conntrack_count); | 493 | atomic_dec(&nf_conntrack_count); |
657 | } | 494 | } |
658 | EXPORT_SYMBOL_GPL(nf_conntrack_free); | 495 | EXPORT_SYMBOL_GPL(nf_conntrack_free); |
@@ -670,43 +507,38 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, | |||
670 | struct nf_conn_help *help; | 507 | struct nf_conn_help *help; |
671 | struct nf_conntrack_tuple repl_tuple; | 508 | struct nf_conntrack_tuple repl_tuple; |
672 | struct nf_conntrack_expect *exp; | 509 | struct nf_conntrack_expect *exp; |
673 | u_int32_t features = 0; | ||
674 | 510 | ||
675 | if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) { | 511 | if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) { |
676 | DEBUGP("Can't invert tuple.\n"); | 512 | pr_debug("Can't invert tuple.\n"); |
677 | return NULL; | 513 | return NULL; |
678 | } | 514 | } |
679 | 515 | ||
680 | read_lock_bh(&nf_conntrack_lock); | 516 | conntrack = nf_conntrack_alloc(tuple, &repl_tuple); |
681 | exp = __nf_conntrack_expect_find(tuple); | ||
682 | if (exp && exp->helper) | ||
683 | features = NF_CT_F_HELP; | ||
684 | read_unlock_bh(&nf_conntrack_lock); | ||
685 | |||
686 | conntrack = __nf_conntrack_alloc(tuple, &repl_tuple, l3proto, features); | ||
687 | if (conntrack == NULL || IS_ERR(conntrack)) { | 517 | if (conntrack == NULL || IS_ERR(conntrack)) { |
688 | DEBUGP("Can't allocate conntrack.\n"); | 518 | pr_debug("Can't allocate conntrack.\n"); |
689 | return (struct nf_conntrack_tuple_hash *)conntrack; | 519 | return (struct nf_conntrack_tuple_hash *)conntrack; |
690 | } | 520 | } |
691 | 521 | ||
692 | if (!l4proto->new(conntrack, skb, dataoff)) { | 522 | if (!l4proto->new(conntrack, skb, dataoff)) { |
693 | nf_conntrack_free(conntrack); | 523 | nf_conntrack_free(conntrack); |
694 | DEBUGP("init conntrack: can't track with proto module\n"); | 524 | pr_debug("init conntrack: can't track with proto module\n"); |
695 | return NULL; | 525 | return NULL; |
696 | } | 526 | } |
697 | 527 | ||
698 | write_lock_bh(&nf_conntrack_lock); | 528 | write_lock_bh(&nf_conntrack_lock); |
699 | exp = find_expectation(tuple); | 529 | exp = nf_ct_find_expectation(tuple); |
700 | |||
701 | help = nfct_help(conntrack); | ||
702 | if (exp) { | 530 | if (exp) { |
703 | DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n", | 531 | pr_debug("conntrack: expectation arrives ct=%p exp=%p\n", |
704 | conntrack, exp); | 532 | conntrack, exp); |
705 | /* Welcome, Mr. Bond. We've been expecting you... */ | 533 | /* Welcome, Mr. Bond. We've been expecting you... */ |
706 | __set_bit(IPS_EXPECTED_BIT, &conntrack->status); | 534 | __set_bit(IPS_EXPECTED_BIT, &conntrack->status); |
707 | conntrack->master = exp->master; | 535 | conntrack->master = exp->master; |
708 | if (exp->helper) | 536 | if (exp->helper) { |
709 | rcu_assign_pointer(help->helper, exp->helper); | 537 | help = nf_ct_helper_ext_add(conntrack, GFP_ATOMIC); |
538 | if (help) | ||
539 | rcu_assign_pointer(help->helper, exp->helper); | ||
540 | } | ||
541 | |||
710 | #ifdef CONFIG_NF_CONNTRACK_MARK | 542 | #ifdef CONFIG_NF_CONNTRACK_MARK |
711 | conntrack->mark = exp->master->mark; | 543 | conntrack->mark = exp->master->mark; |
712 | #endif | 544 | #endif |
@@ -716,23 +548,27 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, | |||
716 | nf_conntrack_get(&conntrack->master->ct_general); | 548 | nf_conntrack_get(&conntrack->master->ct_general); |
717 | NF_CT_STAT_INC(expect_new); | 549 | NF_CT_STAT_INC(expect_new); |
718 | } else { | 550 | } else { |
719 | if (help) { | 551 | struct nf_conntrack_helper *helper; |
720 | /* not in hash table yet, so not strictly necessary */ | 552 | |
721 | rcu_assign_pointer(help->helper, | 553 | helper = __nf_ct_helper_find(&repl_tuple); |
722 | __nf_ct_helper_find(&repl_tuple)); | 554 | if (helper) { |
555 | help = nf_ct_helper_ext_add(conntrack, GFP_ATOMIC); | ||
556 | if (help) | ||
557 | rcu_assign_pointer(help->helper, helper); | ||
723 | } | 558 | } |
724 | NF_CT_STAT_INC(new); | 559 | NF_CT_STAT_INC(new); |
725 | } | 560 | } |
726 | 561 | ||
727 | /* Overload tuple linked list to put us in unconfirmed list. */ | 562 | /* Overload tuple linked list to put us in unconfirmed list. */ |
728 | list_add(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list, &unconfirmed); | 563 | hlist_add_head(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].hnode, |
564 | &unconfirmed); | ||
729 | 565 | ||
730 | write_unlock_bh(&nf_conntrack_lock); | 566 | write_unlock_bh(&nf_conntrack_lock); |
731 | 567 | ||
732 | if (exp) { | 568 | if (exp) { |
733 | if (exp->expectfn) | 569 | if (exp->expectfn) |
734 | exp->expectfn(conntrack, exp); | 570 | exp->expectfn(conntrack, exp); |
735 | nf_conntrack_expect_put(exp); | 571 | nf_ct_expect_put(exp); |
736 | } | 572 | } |
737 | 573 | ||
738 | return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL]; | 574 | return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL]; |
@@ -756,12 +592,12 @@ resolve_normal_ct(struct sk_buff *skb, | |||
756 | if (!nf_ct_get_tuple(skb, skb_network_offset(skb), | 592 | if (!nf_ct_get_tuple(skb, skb_network_offset(skb), |
757 | dataoff, l3num, protonum, &tuple, l3proto, | 593 | dataoff, l3num, protonum, &tuple, l3proto, |
758 | l4proto)) { | 594 | l4proto)) { |
759 | DEBUGP("resolve_normal_ct: Can't get tuple\n"); | 595 | pr_debug("resolve_normal_ct: Can't get tuple\n"); |
760 | return NULL; | 596 | return NULL; |
761 | } | 597 | } |
762 | 598 | ||
763 | /* look for tuple match */ | 599 | /* look for tuple match */ |
764 | h = nf_conntrack_find_get(&tuple, NULL); | 600 | h = nf_conntrack_find_get(&tuple); |
765 | if (!h) { | 601 | if (!h) { |
766 | h = init_conntrack(&tuple, l3proto, l4proto, skb, dataoff); | 602 | h = init_conntrack(&tuple, l3proto, l4proto, skb, dataoff); |
767 | if (!h) | 603 | if (!h) |
@@ -779,13 +615,14 @@ resolve_normal_ct(struct sk_buff *skb, | |||
779 | } else { | 615 | } else { |
780 | /* Once we've had two way comms, always ESTABLISHED. */ | 616 | /* Once we've had two way comms, always ESTABLISHED. */ |
781 | if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { | 617 | if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { |
782 | DEBUGP("nf_conntrack_in: normal packet for %p\n", ct); | 618 | pr_debug("nf_conntrack_in: normal packet for %p\n", ct); |
783 | *ctinfo = IP_CT_ESTABLISHED; | 619 | *ctinfo = IP_CT_ESTABLISHED; |
784 | } else if (test_bit(IPS_EXPECTED_BIT, &ct->status)) { | 620 | } else if (test_bit(IPS_EXPECTED_BIT, &ct->status)) { |
785 | DEBUGP("nf_conntrack_in: related packet for %p\n", ct); | 621 | pr_debug("nf_conntrack_in: related packet for %p\n", |
622 | ct); | ||
786 | *ctinfo = IP_CT_RELATED; | 623 | *ctinfo = IP_CT_RELATED; |
787 | } else { | 624 | } else { |
788 | DEBUGP("nf_conntrack_in: new packet for %p\n", ct); | 625 | pr_debug("nf_conntrack_in: new packet for %p\n", ct); |
789 | *ctinfo = IP_CT_NEW; | 626 | *ctinfo = IP_CT_NEW; |
790 | } | 627 | } |
791 | *set_reply = 0; | 628 | *set_reply = 0; |
@@ -815,9 +652,12 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb) | |||
815 | 652 | ||
816 | /* rcu_read_lock()ed by nf_hook_slow */ | 653 | /* rcu_read_lock()ed by nf_hook_slow */ |
817 | l3proto = __nf_ct_l3proto_find((u_int16_t)pf); | 654 | l3proto = __nf_ct_l3proto_find((u_int16_t)pf); |
818 | 655 | ret = l3proto->get_l4proto(*pskb, skb_network_offset(*pskb), | |
819 | if ((ret = l3proto->prepare(pskb, hooknum, &dataoff, &protonum)) <= 0) { | 656 | &dataoff, &protonum); |
820 | DEBUGP("not prepared to track yet or error occured\n"); | 657 | if (ret <= 0) { |
658 | pr_debug("not prepared to track yet or error occured\n"); | ||
659 | NF_CT_STAT_INC_ATOMIC(error); | ||
660 | NF_CT_STAT_INC_ATOMIC(invalid); | ||
821 | return -ret; | 661 | return -ret; |
822 | } | 662 | } |
823 | 663 | ||
@@ -853,7 +693,7 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb) | |||
853 | if (ret < 0) { | 693 | if (ret < 0) { |
854 | /* Invalid: inverse of the return code tells | 694 | /* Invalid: inverse of the return code tells |
855 | * the netfilter core what to do */ | 695 | * the netfilter core what to do */ |
856 | DEBUGP("nf_conntrack_in: Can't track with proto module\n"); | 696 | pr_debug("nf_conntrack_in: Can't track with proto module\n"); |
857 | nf_conntrack_put((*pskb)->nfct); | 697 | nf_conntrack_put((*pskb)->nfct); |
858 | (*pskb)->nfct = NULL; | 698 | (*pskb)->nfct = NULL; |
859 | NF_CT_STAT_INC_ATOMIC(invalid); | 699 | NF_CT_STAT_INC_ATOMIC(invalid); |
@@ -888,23 +728,36 @@ void nf_conntrack_alter_reply(struct nf_conn *ct, | |||
888 | const struct nf_conntrack_tuple *newreply) | 728 | const struct nf_conntrack_tuple *newreply) |
889 | { | 729 | { |
890 | struct nf_conn_help *help = nfct_help(ct); | 730 | struct nf_conn_help *help = nfct_help(ct); |
731 | struct nf_conntrack_helper *helper; | ||
891 | 732 | ||
892 | write_lock_bh(&nf_conntrack_lock); | 733 | write_lock_bh(&nf_conntrack_lock); |
893 | /* Should be unconfirmed, so not in hash table yet */ | 734 | /* Should be unconfirmed, so not in hash table yet */ |
894 | NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); | 735 | NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); |
895 | 736 | ||
896 | DEBUGP("Altering reply tuple of %p to ", ct); | 737 | pr_debug("Altering reply tuple of %p to ", ct); |
897 | NF_CT_DUMP_TUPLE(newreply); | 738 | NF_CT_DUMP_TUPLE(newreply); |
898 | 739 | ||
899 | ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply; | 740 | ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply; |
900 | if (!ct->master && help && help->expecting == 0) { | 741 | if (ct->master || (help && help->expecting != 0)) |
901 | struct nf_conntrack_helper *helper; | 742 | goto out; |
902 | helper = __nf_ct_helper_find(newreply); | 743 | |
903 | if (helper) | 744 | helper = __nf_ct_helper_find(newreply); |
904 | memset(&help->help, 0, sizeof(help->help)); | 745 | if (helper == NULL) { |
905 | /* not in hash table yet, so not strictly necessary */ | 746 | if (help) |
906 | rcu_assign_pointer(help->helper, helper); | 747 | rcu_assign_pointer(help->helper, NULL); |
748 | goto out; | ||
907 | } | 749 | } |
750 | |||
751 | if (help == NULL) { | ||
752 | help = nf_ct_helper_ext_add(ct, GFP_ATOMIC); | ||
753 | if (help == NULL) | ||
754 | goto out; | ||
755 | } else { | ||
756 | memset(&help->help, 0, sizeof(help->help)); | ||
757 | } | ||
758 | |||
759 | rcu_assign_pointer(help->helper, helper); | ||
760 | out: | ||
908 | write_unlock_bh(&nf_conntrack_lock); | 761 | write_unlock_bh(&nf_conntrack_lock); |
909 | } | 762 | } |
910 | EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply); | 763 | EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply); |
@@ -1048,16 +901,17 @@ get_next_corpse(int (*iter)(struct nf_conn *i, void *data), | |||
1048 | { | 901 | { |
1049 | struct nf_conntrack_tuple_hash *h; | 902 | struct nf_conntrack_tuple_hash *h; |
1050 | struct nf_conn *ct; | 903 | struct nf_conn *ct; |
904 | struct hlist_node *n; | ||
1051 | 905 | ||
1052 | write_lock_bh(&nf_conntrack_lock); | 906 | write_lock_bh(&nf_conntrack_lock); |
1053 | for (; *bucket < nf_conntrack_htable_size; (*bucket)++) { | 907 | for (; *bucket < nf_conntrack_htable_size; (*bucket)++) { |
1054 | list_for_each_entry(h, &nf_conntrack_hash[*bucket], list) { | 908 | hlist_for_each_entry(h, n, &nf_conntrack_hash[*bucket], hnode) { |
1055 | ct = nf_ct_tuplehash_to_ctrack(h); | 909 | ct = nf_ct_tuplehash_to_ctrack(h); |
1056 | if (iter(ct, data)) | 910 | if (iter(ct, data)) |
1057 | goto found; | 911 | goto found; |
1058 | } | 912 | } |
1059 | } | 913 | } |
1060 | list_for_each_entry(h, &unconfirmed, list) { | 914 | hlist_for_each_entry(h, n, &unconfirmed, hnode) { |
1061 | ct = nf_ct_tuplehash_to_ctrack(h); | 915 | ct = nf_ct_tuplehash_to_ctrack(h); |
1062 | if (iter(ct, data)) | 916 | if (iter(ct, data)) |
1063 | set_bit(IPS_DYING_BIT, &ct->status); | 917 | set_bit(IPS_DYING_BIT, &ct->status); |
@@ -1092,14 +946,15 @@ static int kill_all(struct nf_conn *i, void *data) | |||
1092 | return 1; | 946 | return 1; |
1093 | } | 947 | } |
1094 | 948 | ||
1095 | static void free_conntrack_hash(struct list_head *hash, int vmalloced, int size) | 949 | void nf_ct_free_hashtable(struct hlist_head *hash, int vmalloced, int size) |
1096 | { | 950 | { |
1097 | if (vmalloced) | 951 | if (vmalloced) |
1098 | vfree(hash); | 952 | vfree(hash); |
1099 | else | 953 | else |
1100 | free_pages((unsigned long)hash, | 954 | free_pages((unsigned long)hash, |
1101 | get_order(sizeof(struct list_head) * size)); | 955 | get_order(sizeof(struct hlist_head) * size)); |
1102 | } | 956 | } |
957 | EXPORT_SYMBOL_GPL(nf_ct_free_hashtable); | ||
1103 | 958 | ||
1104 | void nf_conntrack_flush(void) | 959 | void nf_conntrack_flush(void) |
1105 | { | 960 | { |
@@ -1111,8 +966,6 @@ EXPORT_SYMBOL_GPL(nf_conntrack_flush); | |||
1111 | supposed to kill the mall. */ | 966 | supposed to kill the mall. */ |
1112 | void nf_conntrack_cleanup(void) | 967 | void nf_conntrack_cleanup(void) |
1113 | { | 968 | { |
1114 | int i; | ||
1115 | |||
1116 | rcu_assign_pointer(ip_ct_attach, NULL); | 969 | rcu_assign_pointer(ip_ct_attach, NULL); |
1117 | 970 | ||
1118 | /* This makes sure all current packets have passed through | 971 | /* This makes sure all current packets have passed through |
@@ -1133,49 +986,46 @@ void nf_conntrack_cleanup(void) | |||
1133 | 986 | ||
1134 | rcu_assign_pointer(nf_ct_destroy, NULL); | 987 | rcu_assign_pointer(nf_ct_destroy, NULL); |
1135 | 988 | ||
1136 | for (i = 0; i < NF_CT_F_NUM; i++) { | 989 | kmem_cache_destroy(nf_conntrack_cachep); |
1137 | if (nf_ct_cache[i].use == 0) | 990 | nf_ct_free_hashtable(nf_conntrack_hash, nf_conntrack_vmalloc, |
1138 | continue; | 991 | nf_conntrack_htable_size); |
1139 | |||
1140 | NF_CT_ASSERT(nf_ct_cache[i].use == 1); | ||
1141 | nf_ct_cache[i].use = 1; | ||
1142 | nf_conntrack_unregister_cache(i); | ||
1143 | } | ||
1144 | kmem_cache_destroy(nf_conntrack_expect_cachep); | ||
1145 | free_conntrack_hash(nf_conntrack_hash, nf_conntrack_vmalloc, | ||
1146 | nf_conntrack_htable_size); | ||
1147 | 992 | ||
1148 | nf_conntrack_proto_fini(); | 993 | nf_conntrack_proto_fini(); |
994 | nf_conntrack_helper_fini(); | ||
995 | nf_conntrack_expect_fini(); | ||
1149 | } | 996 | } |
1150 | 997 | ||
1151 | static struct list_head *alloc_hashtable(int size, int *vmalloced) | 998 | struct hlist_head *nf_ct_alloc_hashtable(int *sizep, int *vmalloced) |
1152 | { | 999 | { |
1153 | struct list_head *hash; | 1000 | struct hlist_head *hash; |
1154 | unsigned int i; | 1001 | unsigned int size, i; |
1155 | 1002 | ||
1156 | *vmalloced = 0; | 1003 | *vmalloced = 0; |
1004 | |||
1005 | size = *sizep = roundup(*sizep, PAGE_SIZE / sizeof(struct hlist_head)); | ||
1157 | hash = (void*)__get_free_pages(GFP_KERNEL, | 1006 | hash = (void*)__get_free_pages(GFP_KERNEL, |
1158 | get_order(sizeof(struct list_head) | 1007 | get_order(sizeof(struct hlist_head) |
1159 | * size)); | 1008 | * size)); |
1160 | if (!hash) { | 1009 | if (!hash) { |
1161 | *vmalloced = 1; | 1010 | *vmalloced = 1; |
1162 | printk(KERN_WARNING "nf_conntrack: falling back to vmalloc.\n"); | 1011 | printk(KERN_WARNING "nf_conntrack: falling back to vmalloc.\n"); |
1163 | hash = vmalloc(sizeof(struct list_head) * size); | 1012 | hash = vmalloc(sizeof(struct hlist_head) * size); |
1164 | } | 1013 | } |
1165 | 1014 | ||
1166 | if (hash) | 1015 | if (hash) |
1167 | for (i = 0; i < size; i++) | 1016 | for (i = 0; i < size; i++) |
1168 | INIT_LIST_HEAD(&hash[i]); | 1017 | INIT_HLIST_HEAD(&hash[i]); |
1169 | 1018 | ||
1170 | return hash; | 1019 | return hash; |
1171 | } | 1020 | } |
1021 | EXPORT_SYMBOL_GPL(nf_ct_alloc_hashtable); | ||
1172 | 1022 | ||
1173 | int set_hashsize(const char *val, struct kernel_param *kp) | 1023 | int set_hashsize(const char *val, struct kernel_param *kp) |
1174 | { | 1024 | { |
1175 | int i, bucket, hashsize, vmalloced; | 1025 | int i, bucket, hashsize, vmalloced; |
1176 | int old_vmalloced, old_size; | 1026 | int old_vmalloced, old_size; |
1177 | int rnd; | 1027 | int rnd; |
1178 | struct list_head *hash, *old_hash; | 1028 | struct hlist_head *hash, *old_hash; |
1179 | struct nf_conntrack_tuple_hash *h; | 1029 | struct nf_conntrack_tuple_hash *h; |
1180 | 1030 | ||
1181 | /* On boot, we can set this without any fancy locking. */ | 1031 | /* On boot, we can set this without any fancy locking. */ |
@@ -1186,7 +1036,7 @@ int set_hashsize(const char *val, struct kernel_param *kp) | |||
1186 | if (!hashsize) | 1036 | if (!hashsize) |
1187 | return -EINVAL; | 1037 | return -EINVAL; |
1188 | 1038 | ||
1189 | hash = alloc_hashtable(hashsize, &vmalloced); | 1039 | hash = nf_ct_alloc_hashtable(&hashsize, &vmalloced); |
1190 | if (!hash) | 1040 | if (!hash) |
1191 | return -ENOMEM; | 1041 | return -ENOMEM; |
1192 | 1042 | ||
@@ -1196,12 +1046,12 @@ int set_hashsize(const char *val, struct kernel_param *kp) | |||
1196 | 1046 | ||
1197 | write_lock_bh(&nf_conntrack_lock); | 1047 | write_lock_bh(&nf_conntrack_lock); |
1198 | for (i = 0; i < nf_conntrack_htable_size; i++) { | 1048 | for (i = 0; i < nf_conntrack_htable_size; i++) { |
1199 | while (!list_empty(&nf_conntrack_hash[i])) { | 1049 | while (!hlist_empty(&nf_conntrack_hash[i])) { |
1200 | h = list_entry(nf_conntrack_hash[i].next, | 1050 | h = hlist_entry(nf_conntrack_hash[i].first, |
1201 | struct nf_conntrack_tuple_hash, list); | 1051 | struct nf_conntrack_tuple_hash, hnode); |
1202 | list_del(&h->list); | 1052 | hlist_del(&h->hnode); |
1203 | bucket = __hash_conntrack(&h->tuple, hashsize, rnd); | 1053 | bucket = __hash_conntrack(&h->tuple, hashsize, rnd); |
1204 | list_add_tail(&h->list, &hash[bucket]); | 1054 | hlist_add_head(&h->hnode, &hash[bucket]); |
1205 | } | 1055 | } |
1206 | } | 1056 | } |
1207 | old_size = nf_conntrack_htable_size; | 1057 | old_size = nf_conntrack_htable_size; |
@@ -1214,7 +1064,7 @@ int set_hashsize(const char *val, struct kernel_param *kp) | |||
1214 | nf_conntrack_hash_rnd = rnd; | 1064 | nf_conntrack_hash_rnd = rnd; |
1215 | write_unlock_bh(&nf_conntrack_lock); | 1065 | write_unlock_bh(&nf_conntrack_lock); |
1216 | 1066 | ||
1217 | free_conntrack_hash(old_hash, old_vmalloced, old_size); | 1067 | nf_ct_free_hashtable(old_hash, old_vmalloced, old_size); |
1218 | return 0; | 1068 | return 0; |
1219 | } | 1069 | } |
1220 | 1070 | ||
@@ -1223,50 +1073,58 @@ module_param_call(hashsize, set_hashsize, param_get_uint, | |||
1223 | 1073 | ||
1224 | int __init nf_conntrack_init(void) | 1074 | int __init nf_conntrack_init(void) |
1225 | { | 1075 | { |
1076 | int max_factor = 8; | ||
1226 | int ret; | 1077 | int ret; |
1227 | 1078 | ||
1228 | /* Idea from tcp.c: use 1/16384 of memory. On i386: 32MB | 1079 | /* Idea from tcp.c: use 1/16384 of memory. On i386: 32MB |
1229 | * machine has 256 buckets. >= 1GB machines have 8192 buckets. */ | 1080 | * machine has 512 buckets. >= 1GB machines have 16384 buckets. */ |
1230 | if (!nf_conntrack_htable_size) { | 1081 | if (!nf_conntrack_htable_size) { |
1231 | nf_conntrack_htable_size | 1082 | nf_conntrack_htable_size |
1232 | = (((num_physpages << PAGE_SHIFT) / 16384) | 1083 | = (((num_physpages << PAGE_SHIFT) / 16384) |
1233 | / sizeof(struct list_head)); | 1084 | / sizeof(struct hlist_head)); |
1234 | if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE)) | 1085 | if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE)) |
1235 | nf_conntrack_htable_size = 8192; | 1086 | nf_conntrack_htable_size = 16384; |
1236 | if (nf_conntrack_htable_size < 16) | 1087 | if (nf_conntrack_htable_size < 32) |
1237 | nf_conntrack_htable_size = 16; | 1088 | nf_conntrack_htable_size = 32; |
1089 | |||
1090 | /* Use a max. factor of four by default to get the same max as | ||
1091 | * with the old struct list_heads. When a table size is given | ||
1092 | * we use the old value of 8 to avoid reducing the max. | ||
1093 | * entries. */ | ||
1094 | max_factor = 4; | ||
1238 | } | 1095 | } |
1239 | nf_conntrack_max = 8 * nf_conntrack_htable_size; | 1096 | nf_conntrack_hash = nf_ct_alloc_hashtable(&nf_conntrack_htable_size, |
1240 | 1097 | &nf_conntrack_vmalloc); | |
1241 | printk("nf_conntrack version %s (%u buckets, %d max)\n", | ||
1242 | NF_CONNTRACK_VERSION, nf_conntrack_htable_size, | ||
1243 | nf_conntrack_max); | ||
1244 | |||
1245 | nf_conntrack_hash = alloc_hashtable(nf_conntrack_htable_size, | ||
1246 | &nf_conntrack_vmalloc); | ||
1247 | if (!nf_conntrack_hash) { | 1098 | if (!nf_conntrack_hash) { |
1248 | printk(KERN_ERR "Unable to create nf_conntrack_hash\n"); | 1099 | printk(KERN_ERR "Unable to create nf_conntrack_hash\n"); |
1249 | goto err_out; | 1100 | goto err_out; |
1250 | } | 1101 | } |
1251 | 1102 | ||
1252 | ret = nf_conntrack_register_cache(NF_CT_F_BASIC, "nf_conntrack:basic", | 1103 | nf_conntrack_max = max_factor * nf_conntrack_htable_size; |
1253 | sizeof(struct nf_conn)); | 1104 | |
1254 | if (ret < 0) { | 1105 | printk("nf_conntrack version %s (%u buckets, %d max)\n", |
1106 | NF_CONNTRACK_VERSION, nf_conntrack_htable_size, | ||
1107 | nf_conntrack_max); | ||
1108 | |||
1109 | nf_conntrack_cachep = kmem_cache_create("nf_conntrack", | ||
1110 | sizeof(struct nf_conn), | ||
1111 | 0, 0, NULL, NULL); | ||
1112 | if (!nf_conntrack_cachep) { | ||
1255 | printk(KERN_ERR "Unable to create nf_conn slab cache\n"); | 1113 | printk(KERN_ERR "Unable to create nf_conn slab cache\n"); |
1256 | goto err_free_hash; | 1114 | goto err_free_hash; |
1257 | } | 1115 | } |
1258 | 1116 | ||
1259 | nf_conntrack_expect_cachep = kmem_cache_create("nf_conntrack_expect", | 1117 | ret = nf_conntrack_proto_init(); |
1260 | sizeof(struct nf_conntrack_expect), | 1118 | if (ret < 0) |
1261 | 0, 0, NULL, NULL); | ||
1262 | if (!nf_conntrack_expect_cachep) { | ||
1263 | printk(KERN_ERR "Unable to create nf_expect slab cache\n"); | ||
1264 | goto err_free_conntrack_slab; | 1119 | goto err_free_conntrack_slab; |
1265 | } | ||
1266 | 1120 | ||
1267 | ret = nf_conntrack_proto_init(); | 1121 | ret = nf_conntrack_expect_init(); |
1122 | if (ret < 0) | ||
1123 | goto out_fini_proto; | ||
1124 | |||
1125 | ret = nf_conntrack_helper_init(); | ||
1268 | if (ret < 0) | 1126 | if (ret < 0) |
1269 | goto out_free_expect_slab; | 1127 | goto out_fini_expect; |
1270 | 1128 | ||
1271 | /* For use by REJECT target */ | 1129 | /* For use by REJECT target */ |
1272 | rcu_assign_pointer(ip_ct_attach, __nf_conntrack_attach); | 1130 | rcu_assign_pointer(ip_ct_attach, __nf_conntrack_attach); |
@@ -1280,13 +1138,15 @@ int __init nf_conntrack_init(void) | |||
1280 | 1138 | ||
1281 | return ret; | 1139 | return ret; |
1282 | 1140 | ||
1283 | out_free_expect_slab: | 1141 | out_fini_expect: |
1284 | kmem_cache_destroy(nf_conntrack_expect_cachep); | 1142 | nf_conntrack_expect_fini(); |
1143 | out_fini_proto: | ||
1144 | nf_conntrack_proto_fini(); | ||
1285 | err_free_conntrack_slab: | 1145 | err_free_conntrack_slab: |
1286 | nf_conntrack_unregister_cache(NF_CT_F_BASIC); | 1146 | kmem_cache_destroy(nf_conntrack_cachep); |
1287 | err_free_hash: | 1147 | err_free_hash: |
1288 | free_conntrack_hash(nf_conntrack_hash, nf_conntrack_vmalloc, | 1148 | nf_ct_free_hashtable(nf_conntrack_hash, nf_conntrack_vmalloc, |
1289 | nf_conntrack_htable_size); | 1149 | nf_conntrack_htable_size); |
1290 | err_out: | 1150 | err_out: |
1291 | return -ENOMEM; | 1151 | return -ENOMEM; |
1292 | } | 1152 | } |
diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c index 6bd421df2dbc..83c41ac3505b 100644 --- a/net/netfilter/nf_conntrack_ecache.c +++ b/net/netfilter/nf_conntrack_ecache.c | |||
@@ -26,8 +26,8 @@ | |||
26 | ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain); | 26 | ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain); |
27 | EXPORT_SYMBOL_GPL(nf_conntrack_chain); | 27 | EXPORT_SYMBOL_GPL(nf_conntrack_chain); |
28 | 28 | ||
29 | ATOMIC_NOTIFIER_HEAD(nf_conntrack_expect_chain); | 29 | ATOMIC_NOTIFIER_HEAD(nf_ct_expect_chain); |
30 | EXPORT_SYMBOL_GPL(nf_conntrack_expect_chain); | 30 | EXPORT_SYMBOL_GPL(nf_ct_expect_chain); |
31 | 31 | ||
32 | DEFINE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache); | 32 | DEFINE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache); |
33 | EXPORT_PER_CPU_SYMBOL_GPL(nf_conntrack_ecache); | 33 | EXPORT_PER_CPU_SYMBOL_GPL(nf_conntrack_ecache); |
@@ -103,14 +103,14 @@ int nf_conntrack_unregister_notifier(struct notifier_block *nb) | |||
103 | } | 103 | } |
104 | EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier); | 104 | EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier); |
105 | 105 | ||
106 | int nf_conntrack_expect_register_notifier(struct notifier_block *nb) | 106 | int nf_ct_expect_register_notifier(struct notifier_block *nb) |
107 | { | 107 | { |
108 | return atomic_notifier_chain_register(&nf_conntrack_expect_chain, nb); | 108 | return atomic_notifier_chain_register(&nf_ct_expect_chain, nb); |
109 | } | 109 | } |
110 | EXPORT_SYMBOL_GPL(nf_conntrack_expect_register_notifier); | 110 | EXPORT_SYMBOL_GPL(nf_ct_expect_register_notifier); |
111 | 111 | ||
112 | int nf_conntrack_expect_unregister_notifier(struct notifier_block *nb) | 112 | int nf_ct_expect_unregister_notifier(struct notifier_block *nb) |
113 | { | 113 | { |
114 | return atomic_notifier_chain_unregister(&nf_conntrack_expect_chain, nb); | 114 | return atomic_notifier_chain_unregister(&nf_ct_expect_chain, nb); |
115 | } | 115 | } |
116 | EXPORT_SYMBOL_GPL(nf_conntrack_expect_unregister_notifier); | 116 | EXPORT_SYMBOL_GPL(nf_ct_expect_unregister_notifier); |
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 504fb6c083f9..2191fe008f60 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/err.h> | 19 | #include <linux/err.h> |
20 | #include <linux/percpu.h> | 20 | #include <linux/percpu.h> |
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/jhash.h> | ||
22 | 23 | ||
23 | #include <net/netfilter/nf_conntrack.h> | 24 | #include <net/netfilter/nf_conntrack.h> |
24 | #include <net/netfilter/nf_conntrack_core.h> | 25 | #include <net/netfilter/nf_conntrack_core.h> |
@@ -26,11 +27,20 @@ | |||
26 | #include <net/netfilter/nf_conntrack_helper.h> | 27 | #include <net/netfilter/nf_conntrack_helper.h> |
27 | #include <net/netfilter/nf_conntrack_tuple.h> | 28 | #include <net/netfilter/nf_conntrack_tuple.h> |
28 | 29 | ||
29 | LIST_HEAD(nf_conntrack_expect_list); | 30 | struct hlist_head *nf_ct_expect_hash __read_mostly; |
30 | EXPORT_SYMBOL_GPL(nf_conntrack_expect_list); | 31 | EXPORT_SYMBOL_GPL(nf_ct_expect_hash); |
31 | 32 | ||
32 | struct kmem_cache *nf_conntrack_expect_cachep __read_mostly; | 33 | unsigned int nf_ct_expect_hsize __read_mostly; |
33 | static unsigned int nf_conntrack_expect_next_id; | 34 | EXPORT_SYMBOL_GPL(nf_ct_expect_hsize); |
35 | |||
36 | static unsigned int nf_ct_expect_hash_rnd __read_mostly; | ||
37 | static unsigned int nf_ct_expect_count; | ||
38 | unsigned int nf_ct_expect_max __read_mostly; | ||
39 | static int nf_ct_expect_hash_rnd_initted __read_mostly; | ||
40 | static int nf_ct_expect_vmalloc; | ||
41 | |||
42 | static struct kmem_cache *nf_ct_expect_cachep __read_mostly; | ||
43 | static unsigned int nf_ct_expect_next_id; | ||
34 | 44 | ||
35 | /* nf_conntrack_expect helper functions */ | 45 | /* nf_conntrack_expect helper functions */ |
36 | void nf_ct_unlink_expect(struct nf_conntrack_expect *exp) | 46 | void nf_ct_unlink_expect(struct nf_conntrack_expect *exp) |
@@ -40,60 +50,83 @@ void nf_ct_unlink_expect(struct nf_conntrack_expect *exp) | |||
40 | NF_CT_ASSERT(master_help); | 50 | NF_CT_ASSERT(master_help); |
41 | NF_CT_ASSERT(!timer_pending(&exp->timeout)); | 51 | NF_CT_ASSERT(!timer_pending(&exp->timeout)); |
42 | 52 | ||
43 | list_del(&exp->list); | 53 | hlist_del(&exp->hnode); |
44 | NF_CT_STAT_INC(expect_delete); | 54 | nf_ct_expect_count--; |
55 | |||
56 | hlist_del(&exp->lnode); | ||
45 | master_help->expecting--; | 57 | master_help->expecting--; |
46 | nf_conntrack_expect_put(exp); | 58 | nf_ct_expect_put(exp); |
59 | |||
60 | NF_CT_STAT_INC(expect_delete); | ||
47 | } | 61 | } |
48 | EXPORT_SYMBOL_GPL(nf_ct_unlink_expect); | 62 | EXPORT_SYMBOL_GPL(nf_ct_unlink_expect); |
49 | 63 | ||
50 | static void expectation_timed_out(unsigned long ul_expect) | 64 | static void nf_ct_expectation_timed_out(unsigned long ul_expect) |
51 | { | 65 | { |
52 | struct nf_conntrack_expect *exp = (void *)ul_expect; | 66 | struct nf_conntrack_expect *exp = (void *)ul_expect; |
53 | 67 | ||
54 | write_lock_bh(&nf_conntrack_lock); | 68 | write_lock_bh(&nf_conntrack_lock); |
55 | nf_ct_unlink_expect(exp); | 69 | nf_ct_unlink_expect(exp); |
56 | write_unlock_bh(&nf_conntrack_lock); | 70 | write_unlock_bh(&nf_conntrack_lock); |
57 | nf_conntrack_expect_put(exp); | 71 | nf_ct_expect_put(exp); |
72 | } | ||
73 | |||
74 | static unsigned int nf_ct_expect_dst_hash(const struct nf_conntrack_tuple *tuple) | ||
75 | { | ||
76 | if (unlikely(!nf_ct_expect_hash_rnd_initted)) { | ||
77 | get_random_bytes(&nf_ct_expect_hash_rnd, 4); | ||
78 | nf_ct_expect_hash_rnd_initted = 1; | ||
79 | } | ||
80 | |||
81 | return jhash2(tuple->dst.u3.all, ARRAY_SIZE(tuple->dst.u3.all), | ||
82 | (((tuple->dst.protonum ^ tuple->src.l3num) << 16) | | ||
83 | tuple->dst.u.all) ^ nf_ct_expect_hash_rnd) % | ||
84 | nf_ct_expect_hsize; | ||
58 | } | 85 | } |
59 | 86 | ||
60 | struct nf_conntrack_expect * | 87 | struct nf_conntrack_expect * |
61 | __nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple) | 88 | __nf_ct_expect_find(const struct nf_conntrack_tuple *tuple) |
62 | { | 89 | { |
63 | struct nf_conntrack_expect *i; | 90 | struct nf_conntrack_expect *i; |
91 | struct hlist_node *n; | ||
92 | unsigned int h; | ||
93 | |||
94 | if (!nf_ct_expect_count) | ||
95 | return NULL; | ||
64 | 96 | ||
65 | list_for_each_entry(i, &nf_conntrack_expect_list, list) { | 97 | h = nf_ct_expect_dst_hash(tuple); |
98 | hlist_for_each_entry(i, n, &nf_ct_expect_hash[h], hnode) { | ||
66 | if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) | 99 | if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) |
67 | return i; | 100 | return i; |
68 | } | 101 | } |
69 | return NULL; | 102 | return NULL; |
70 | } | 103 | } |
71 | EXPORT_SYMBOL_GPL(__nf_conntrack_expect_find); | 104 | EXPORT_SYMBOL_GPL(__nf_ct_expect_find); |
72 | 105 | ||
73 | /* Just find a expectation corresponding to a tuple. */ | 106 | /* Just find a expectation corresponding to a tuple. */ |
74 | struct nf_conntrack_expect * | 107 | struct nf_conntrack_expect * |
75 | nf_conntrack_expect_find_get(const struct nf_conntrack_tuple *tuple) | 108 | nf_ct_expect_find_get(const struct nf_conntrack_tuple *tuple) |
76 | { | 109 | { |
77 | struct nf_conntrack_expect *i; | 110 | struct nf_conntrack_expect *i; |
78 | 111 | ||
79 | read_lock_bh(&nf_conntrack_lock); | 112 | read_lock_bh(&nf_conntrack_lock); |
80 | i = __nf_conntrack_expect_find(tuple); | 113 | i = __nf_ct_expect_find(tuple); |
81 | if (i) | 114 | if (i) |
82 | atomic_inc(&i->use); | 115 | atomic_inc(&i->use); |
83 | read_unlock_bh(&nf_conntrack_lock); | 116 | read_unlock_bh(&nf_conntrack_lock); |
84 | 117 | ||
85 | return i; | 118 | return i; |
86 | } | 119 | } |
87 | EXPORT_SYMBOL_GPL(nf_conntrack_expect_find_get); | 120 | EXPORT_SYMBOL_GPL(nf_ct_expect_find_get); |
88 | 121 | ||
89 | /* If an expectation for this connection is found, it gets delete from | 122 | /* If an expectation for this connection is found, it gets delete from |
90 | * global list then returned. */ | 123 | * global list then returned. */ |
91 | struct nf_conntrack_expect * | 124 | struct nf_conntrack_expect * |
92 | find_expectation(const struct nf_conntrack_tuple *tuple) | 125 | nf_ct_find_expectation(const struct nf_conntrack_tuple *tuple) |
93 | { | 126 | { |
94 | struct nf_conntrack_expect *exp; | 127 | struct nf_conntrack_expect *exp; |
95 | 128 | ||
96 | exp = __nf_conntrack_expect_find(tuple); | 129 | exp = __nf_ct_expect_find(tuple); |
97 | if (!exp) | 130 | if (!exp) |
98 | return NULL; | 131 | return NULL; |
99 | 132 | ||
@@ -119,17 +152,18 @@ find_expectation(const struct nf_conntrack_tuple *tuple) | |||
119 | /* delete all expectations for this conntrack */ | 152 | /* delete all expectations for this conntrack */ |
120 | void nf_ct_remove_expectations(struct nf_conn *ct) | 153 | void nf_ct_remove_expectations(struct nf_conn *ct) |
121 | { | 154 | { |
122 | struct nf_conntrack_expect *i, *tmp; | ||
123 | struct nf_conn_help *help = nfct_help(ct); | 155 | struct nf_conn_help *help = nfct_help(ct); |
156 | struct nf_conntrack_expect *exp; | ||
157 | struct hlist_node *n, *next; | ||
124 | 158 | ||
125 | /* Optimization: most connection never expect any others. */ | 159 | /* Optimization: most connection never expect any others. */ |
126 | if (!help || help->expecting == 0) | 160 | if (!help || help->expecting == 0) |
127 | return; | 161 | return; |
128 | 162 | ||
129 | list_for_each_entry_safe(i, tmp, &nf_conntrack_expect_list, list) { | 163 | hlist_for_each_entry_safe(exp, n, next, &help->expectations, lnode) { |
130 | if (i->master == ct && del_timer(&i->timeout)) { | 164 | if (del_timer(&exp->timeout)) { |
131 | nf_ct_unlink_expect(i); | 165 | nf_ct_unlink_expect(exp); |
132 | nf_conntrack_expect_put(i); | 166 | nf_ct_expect_put(exp); |
133 | } | 167 | } |
134 | } | 168 | } |
135 | } | 169 | } |
@@ -141,25 +175,16 @@ static inline int expect_clash(const struct nf_conntrack_expect *a, | |||
141 | { | 175 | { |
142 | /* Part covered by intersection of masks must be unequal, | 176 | /* Part covered by intersection of masks must be unequal, |
143 | otherwise they clash */ | 177 | otherwise they clash */ |
144 | struct nf_conntrack_tuple intersect_mask; | 178 | struct nf_conntrack_tuple_mask intersect_mask; |
145 | int count; | 179 | int count; |
146 | 180 | ||
147 | intersect_mask.src.l3num = a->mask.src.l3num & b->mask.src.l3num; | ||
148 | intersect_mask.src.u.all = a->mask.src.u.all & b->mask.src.u.all; | 181 | intersect_mask.src.u.all = a->mask.src.u.all & b->mask.src.u.all; |
149 | intersect_mask.dst.u.all = a->mask.dst.u.all & b->mask.dst.u.all; | ||
150 | intersect_mask.dst.protonum = a->mask.dst.protonum | ||
151 | & b->mask.dst.protonum; | ||
152 | 182 | ||
153 | for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){ | 183 | for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){ |
154 | intersect_mask.src.u3.all[count] = | 184 | intersect_mask.src.u3.all[count] = |
155 | a->mask.src.u3.all[count] & b->mask.src.u3.all[count]; | 185 | a->mask.src.u3.all[count] & b->mask.src.u3.all[count]; |
156 | } | 186 | } |
157 | 187 | ||
158 | for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){ | ||
159 | intersect_mask.dst.u3.all[count] = | ||
160 | a->mask.dst.u3.all[count] & b->mask.dst.u3.all[count]; | ||
161 | } | ||
162 | |||
163 | return nf_ct_tuple_mask_cmp(&a->tuple, &b->tuple, &intersect_mask); | 188 | return nf_ct_tuple_mask_cmp(&a->tuple, &b->tuple, &intersect_mask); |
164 | } | 189 | } |
165 | 190 | ||
@@ -168,36 +193,29 @@ static inline int expect_matches(const struct nf_conntrack_expect *a, | |||
168 | { | 193 | { |
169 | return a->master == b->master | 194 | return a->master == b->master |
170 | && nf_ct_tuple_equal(&a->tuple, &b->tuple) | 195 | && nf_ct_tuple_equal(&a->tuple, &b->tuple) |
171 | && nf_ct_tuple_equal(&a->mask, &b->mask); | 196 | && nf_ct_tuple_mask_equal(&a->mask, &b->mask); |
172 | } | 197 | } |
173 | 198 | ||
174 | /* Generally a bad idea to call this: could have matched already. */ | 199 | /* Generally a bad idea to call this: could have matched already. */ |
175 | void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp) | 200 | void nf_ct_unexpect_related(struct nf_conntrack_expect *exp) |
176 | { | 201 | { |
177 | struct nf_conntrack_expect *i; | ||
178 | |||
179 | write_lock_bh(&nf_conntrack_lock); | 202 | write_lock_bh(&nf_conntrack_lock); |
180 | /* choose the oldest expectation to evict */ | 203 | if (del_timer(&exp->timeout)) { |
181 | list_for_each_entry_reverse(i, &nf_conntrack_expect_list, list) { | 204 | nf_ct_unlink_expect(exp); |
182 | if (expect_matches(i, exp) && del_timer(&i->timeout)) { | 205 | nf_ct_expect_put(exp); |
183 | nf_ct_unlink_expect(i); | ||
184 | write_unlock_bh(&nf_conntrack_lock); | ||
185 | nf_conntrack_expect_put(i); | ||
186 | return; | ||
187 | } | ||
188 | } | 206 | } |
189 | write_unlock_bh(&nf_conntrack_lock); | 207 | write_unlock_bh(&nf_conntrack_lock); |
190 | } | 208 | } |
191 | EXPORT_SYMBOL_GPL(nf_conntrack_unexpect_related); | 209 | EXPORT_SYMBOL_GPL(nf_ct_unexpect_related); |
192 | 210 | ||
193 | /* We don't increase the master conntrack refcount for non-fulfilled | 211 | /* We don't increase the master conntrack refcount for non-fulfilled |
194 | * conntracks. During the conntrack destruction, the expectations are | 212 | * conntracks. During the conntrack destruction, the expectations are |
195 | * always killed before the conntrack itself */ | 213 | * always killed before the conntrack itself */ |
196 | struct nf_conntrack_expect *nf_conntrack_expect_alloc(struct nf_conn *me) | 214 | struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me) |
197 | { | 215 | { |
198 | struct nf_conntrack_expect *new; | 216 | struct nf_conntrack_expect *new; |
199 | 217 | ||
200 | new = kmem_cache_alloc(nf_conntrack_expect_cachep, GFP_ATOMIC); | 218 | new = kmem_cache_alloc(nf_ct_expect_cachep, GFP_ATOMIC); |
201 | if (!new) | 219 | if (!new) |
202 | return NULL; | 220 | return NULL; |
203 | 221 | ||
@@ -205,12 +223,12 @@ struct nf_conntrack_expect *nf_conntrack_expect_alloc(struct nf_conn *me) | |||
205 | atomic_set(&new->use, 1); | 223 | atomic_set(&new->use, 1); |
206 | return new; | 224 | return new; |
207 | } | 225 | } |
208 | EXPORT_SYMBOL_GPL(nf_conntrack_expect_alloc); | 226 | EXPORT_SYMBOL_GPL(nf_ct_expect_alloc); |
209 | 227 | ||
210 | void nf_conntrack_expect_init(struct nf_conntrack_expect *exp, int family, | 228 | void nf_ct_expect_init(struct nf_conntrack_expect *exp, int family, |
211 | union nf_conntrack_address *saddr, | 229 | union nf_conntrack_address *saddr, |
212 | union nf_conntrack_address *daddr, | 230 | union nf_conntrack_address *daddr, |
213 | u_int8_t proto, __be16 *src, __be16 *dst) | 231 | u_int8_t proto, __be16 *src, __be16 *dst) |
214 | { | 232 | { |
215 | int len; | 233 | int len; |
216 | 234 | ||
@@ -224,8 +242,6 @@ void nf_conntrack_expect_init(struct nf_conntrack_expect *exp, int family, | |||
224 | exp->helper = NULL; | 242 | exp->helper = NULL; |
225 | exp->tuple.src.l3num = family; | 243 | exp->tuple.src.l3num = family; |
226 | exp->tuple.dst.protonum = proto; | 244 | exp->tuple.dst.protonum = proto; |
227 | exp->mask.src.l3num = 0xFFFF; | ||
228 | exp->mask.dst.protonum = 0xFF; | ||
229 | 245 | ||
230 | if (saddr) { | 246 | if (saddr) { |
231 | memcpy(&exp->tuple.src.u3, saddr, len); | 247 | memcpy(&exp->tuple.src.u3, saddr, len); |
@@ -242,21 +258,6 @@ void nf_conntrack_expect_init(struct nf_conntrack_expect *exp, int family, | |||
242 | memset(&exp->mask.src.u3, 0x00, sizeof(exp->mask.src.u3)); | 258 | memset(&exp->mask.src.u3, 0x00, sizeof(exp->mask.src.u3)); |
243 | } | 259 | } |
244 | 260 | ||
245 | if (daddr) { | ||
246 | memcpy(&exp->tuple.dst.u3, daddr, len); | ||
247 | if (sizeof(exp->tuple.dst.u3) > len) | ||
248 | /* address needs to be cleared for nf_ct_tuple_equal */ | ||
249 | memset((void *)&exp->tuple.dst.u3 + len, 0x00, | ||
250 | sizeof(exp->tuple.dst.u3) - len); | ||
251 | memset(&exp->mask.dst.u3, 0xFF, len); | ||
252 | if (sizeof(exp->mask.dst.u3) > len) | ||
253 | memset((void *)&exp->mask.dst.u3 + len, 0x00, | ||
254 | sizeof(exp->mask.dst.u3) - len); | ||
255 | } else { | ||
256 | memset(&exp->tuple.dst.u3, 0x00, sizeof(exp->tuple.dst.u3)); | ||
257 | memset(&exp->mask.dst.u3, 0x00, sizeof(exp->mask.dst.u3)); | ||
258 | } | ||
259 | |||
260 | if (src) { | 261 | if (src) { |
261 | exp->tuple.src.u.all = (__force u16)*src; | 262 | exp->tuple.src.u.all = (__force u16)*src; |
262 | exp->mask.src.u.all = 0xFFFF; | 263 | exp->mask.src.u.all = 0xFFFF; |
@@ -265,36 +266,42 @@ void nf_conntrack_expect_init(struct nf_conntrack_expect *exp, int family, | |||
265 | exp->mask.src.u.all = 0; | 266 | exp->mask.src.u.all = 0; |
266 | } | 267 | } |
267 | 268 | ||
268 | if (dst) { | 269 | memcpy(&exp->tuple.dst.u3, daddr, len); |
269 | exp->tuple.dst.u.all = (__force u16)*dst; | 270 | if (sizeof(exp->tuple.dst.u3) > len) |
270 | exp->mask.dst.u.all = 0xFFFF; | 271 | /* address needs to be cleared for nf_ct_tuple_equal */ |
271 | } else { | 272 | memset((void *)&exp->tuple.dst.u3 + len, 0x00, |
272 | exp->tuple.dst.u.all = 0; | 273 | sizeof(exp->tuple.dst.u3) - len); |
273 | exp->mask.dst.u.all = 0; | 274 | |
274 | } | 275 | exp->tuple.dst.u.all = (__force u16)*dst; |
275 | } | 276 | } |
276 | EXPORT_SYMBOL_GPL(nf_conntrack_expect_init); | 277 | EXPORT_SYMBOL_GPL(nf_ct_expect_init); |
277 | 278 | ||
278 | void nf_conntrack_expect_put(struct nf_conntrack_expect *exp) | 279 | void nf_ct_expect_put(struct nf_conntrack_expect *exp) |
279 | { | 280 | { |
280 | if (atomic_dec_and_test(&exp->use)) | 281 | if (atomic_dec_and_test(&exp->use)) |
281 | kmem_cache_free(nf_conntrack_expect_cachep, exp); | 282 | kmem_cache_free(nf_ct_expect_cachep, exp); |
282 | } | 283 | } |
283 | EXPORT_SYMBOL_GPL(nf_conntrack_expect_put); | 284 | EXPORT_SYMBOL_GPL(nf_ct_expect_put); |
284 | 285 | ||
285 | static void nf_conntrack_expect_insert(struct nf_conntrack_expect *exp) | 286 | static void nf_ct_expect_insert(struct nf_conntrack_expect *exp) |
286 | { | 287 | { |
287 | struct nf_conn_help *master_help = nfct_help(exp->master); | 288 | struct nf_conn_help *master_help = nfct_help(exp->master); |
289 | unsigned int h = nf_ct_expect_dst_hash(&exp->tuple); | ||
288 | 290 | ||
289 | atomic_inc(&exp->use); | 291 | atomic_inc(&exp->use); |
292 | |||
293 | hlist_add_head(&exp->lnode, &master_help->expectations); | ||
290 | master_help->expecting++; | 294 | master_help->expecting++; |
291 | list_add(&exp->list, &nf_conntrack_expect_list); | ||
292 | 295 | ||
293 | setup_timer(&exp->timeout, expectation_timed_out, (unsigned long)exp); | 296 | hlist_add_head(&exp->hnode, &nf_ct_expect_hash[h]); |
297 | nf_ct_expect_count++; | ||
298 | |||
299 | setup_timer(&exp->timeout, nf_ct_expectation_timed_out, | ||
300 | (unsigned long)exp); | ||
294 | exp->timeout.expires = jiffies + master_help->helper->timeout * HZ; | 301 | exp->timeout.expires = jiffies + master_help->helper->timeout * HZ; |
295 | add_timer(&exp->timeout); | 302 | add_timer(&exp->timeout); |
296 | 303 | ||
297 | exp->id = ++nf_conntrack_expect_next_id; | 304 | exp->id = ++nf_ct_expect_next_id; |
298 | atomic_inc(&exp->use); | 305 | atomic_inc(&exp->use); |
299 | NF_CT_STAT_INC(expect_create); | 306 | NF_CT_STAT_INC(expect_create); |
300 | } | 307 | } |
@@ -302,16 +309,16 @@ static void nf_conntrack_expect_insert(struct nf_conntrack_expect *exp) | |||
302 | /* Race with expectations being used means we could have none to find; OK. */ | 309 | /* Race with expectations being used means we could have none to find; OK. */ |
303 | static void evict_oldest_expect(struct nf_conn *master) | 310 | static void evict_oldest_expect(struct nf_conn *master) |
304 | { | 311 | { |
305 | struct nf_conntrack_expect *i; | 312 | struct nf_conn_help *master_help = nfct_help(master); |
313 | struct nf_conntrack_expect *exp = NULL; | ||
314 | struct hlist_node *n; | ||
306 | 315 | ||
307 | list_for_each_entry_reverse(i, &nf_conntrack_expect_list, list) { | 316 | hlist_for_each_entry(exp, n, &master_help->expectations, lnode) |
308 | if (i->master == master) { | 317 | ; /* nothing */ |
309 | if (del_timer(&i->timeout)) { | 318 | |
310 | nf_ct_unlink_expect(i); | 319 | if (exp && del_timer(&exp->timeout)) { |
311 | nf_conntrack_expect_put(i); | 320 | nf_ct_unlink_expect(exp); |
312 | } | 321 | nf_ct_expect_put(exp); |
313 | break; | ||
314 | } | ||
315 | } | 322 | } |
316 | } | 323 | } |
317 | 324 | ||
@@ -327,11 +334,13 @@ static inline int refresh_timer(struct nf_conntrack_expect *i) | |||
327 | return 1; | 334 | return 1; |
328 | } | 335 | } |
329 | 336 | ||
330 | int nf_conntrack_expect_related(struct nf_conntrack_expect *expect) | 337 | int nf_ct_expect_related(struct nf_conntrack_expect *expect) |
331 | { | 338 | { |
332 | struct nf_conntrack_expect *i; | 339 | struct nf_conntrack_expect *i; |
333 | struct nf_conn *master = expect->master; | 340 | struct nf_conn *master = expect->master; |
334 | struct nf_conn_help *master_help = nfct_help(master); | 341 | struct nf_conn_help *master_help = nfct_help(master); |
342 | struct hlist_node *n; | ||
343 | unsigned int h; | ||
335 | int ret; | 344 | int ret; |
336 | 345 | ||
337 | NF_CT_ASSERT(master_help); | 346 | NF_CT_ASSERT(master_help); |
@@ -341,7 +350,8 @@ int nf_conntrack_expect_related(struct nf_conntrack_expect *expect) | |||
341 | ret = -ESHUTDOWN; | 350 | ret = -ESHUTDOWN; |
342 | goto out; | 351 | goto out; |
343 | } | 352 | } |
344 | list_for_each_entry(i, &nf_conntrack_expect_list, list) { | 353 | h = nf_ct_expect_dst_hash(&expect->tuple); |
354 | hlist_for_each_entry(i, n, &nf_ct_expect_hash[h], hnode) { | ||
345 | if (expect_matches(i, expect)) { | 355 | if (expect_matches(i, expect)) { |
346 | /* Refresh timer: if it's dying, ignore.. */ | 356 | /* Refresh timer: if it's dying, ignore.. */ |
347 | if (refresh_timer(i)) { | 357 | if (refresh_timer(i)) { |
@@ -358,57 +368,86 @@ int nf_conntrack_expect_related(struct nf_conntrack_expect *expect) | |||
358 | master_help->expecting >= master_help->helper->max_expected) | 368 | master_help->expecting >= master_help->helper->max_expected) |
359 | evict_oldest_expect(master); | 369 | evict_oldest_expect(master); |
360 | 370 | ||
361 | nf_conntrack_expect_insert(expect); | 371 | if (nf_ct_expect_count >= nf_ct_expect_max) { |
362 | nf_conntrack_expect_event(IPEXP_NEW, expect); | 372 | if (net_ratelimit()) |
373 | printk(KERN_WARNING | ||
374 | "nf_conntrack: expectation table full"); | ||
375 | ret = -EMFILE; | ||
376 | goto out; | ||
377 | } | ||
378 | |||
379 | nf_ct_expect_insert(expect); | ||
380 | nf_ct_expect_event(IPEXP_NEW, expect); | ||
363 | ret = 0; | 381 | ret = 0; |
364 | out: | 382 | out: |
365 | write_unlock_bh(&nf_conntrack_lock); | 383 | write_unlock_bh(&nf_conntrack_lock); |
366 | return ret; | 384 | return ret; |
367 | } | 385 | } |
368 | EXPORT_SYMBOL_GPL(nf_conntrack_expect_related); | 386 | EXPORT_SYMBOL_GPL(nf_ct_expect_related); |
369 | 387 | ||
370 | #ifdef CONFIG_PROC_FS | 388 | #ifdef CONFIG_PROC_FS |
371 | static void *exp_seq_start(struct seq_file *s, loff_t *pos) | 389 | struct ct_expect_iter_state { |
390 | unsigned int bucket; | ||
391 | }; | ||
392 | |||
393 | static struct hlist_node *ct_expect_get_first(struct seq_file *seq) | ||
372 | { | 394 | { |
373 | struct list_head *e = &nf_conntrack_expect_list; | 395 | struct ct_expect_iter_state *st = seq->private; |
374 | loff_t i; | ||
375 | 396 | ||
376 | /* strange seq_file api calls stop even if we fail, | 397 | for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) { |
377 | * thus we need to grab lock since stop unlocks */ | 398 | if (!hlist_empty(&nf_ct_expect_hash[st->bucket])) |
378 | read_lock_bh(&nf_conntrack_lock); | 399 | return nf_ct_expect_hash[st->bucket].first; |
400 | } | ||
401 | return NULL; | ||
402 | } | ||
379 | 403 | ||
380 | if (list_empty(e)) | 404 | static struct hlist_node *ct_expect_get_next(struct seq_file *seq, |
381 | return NULL; | 405 | struct hlist_node *head) |
406 | { | ||
407 | struct ct_expect_iter_state *st = seq->private; | ||
382 | 408 | ||
383 | for (i = 0; i <= *pos; i++) { | 409 | head = head->next; |
384 | e = e->next; | 410 | while (head == NULL) { |
385 | if (e == &nf_conntrack_expect_list) | 411 | if (++st->bucket >= nf_ct_expect_hsize) |
386 | return NULL; | 412 | return NULL; |
413 | head = nf_ct_expect_hash[st->bucket].first; | ||
387 | } | 414 | } |
388 | return e; | 415 | return head; |
389 | } | 416 | } |
390 | 417 | ||
391 | static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos) | 418 | static struct hlist_node *ct_expect_get_idx(struct seq_file *seq, loff_t pos) |
392 | { | 419 | { |
393 | struct list_head *e = v; | 420 | struct hlist_node *head = ct_expect_get_first(seq); |
394 | 421 | ||
395 | ++*pos; | 422 | if (head) |
396 | e = e->next; | 423 | while (pos && (head = ct_expect_get_next(seq, head))) |
424 | pos--; | ||
425 | return pos ? NULL : head; | ||
426 | } | ||
397 | 427 | ||
398 | if (e == &nf_conntrack_expect_list) | 428 | static void *exp_seq_start(struct seq_file *seq, loff_t *pos) |
399 | return NULL; | 429 | { |
430 | read_lock_bh(&nf_conntrack_lock); | ||
431 | return ct_expect_get_idx(seq, *pos); | ||
432 | } | ||
400 | 433 | ||
401 | return e; | 434 | static void *exp_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
435 | { | ||
436 | (*pos)++; | ||
437 | return ct_expect_get_next(seq, v); | ||
402 | } | 438 | } |
403 | 439 | ||
404 | static void exp_seq_stop(struct seq_file *s, void *v) | 440 | static void exp_seq_stop(struct seq_file *seq, void *v) |
405 | { | 441 | { |
406 | read_unlock_bh(&nf_conntrack_lock); | 442 | read_unlock_bh(&nf_conntrack_lock); |
407 | } | 443 | } |
408 | 444 | ||
409 | static int exp_seq_show(struct seq_file *s, void *v) | 445 | static int exp_seq_show(struct seq_file *s, void *v) |
410 | { | 446 | { |
411 | struct nf_conntrack_expect *expect = v; | 447 | struct nf_conntrack_expect *expect; |
448 | struct hlist_node *n = v; | ||
449 | |||
450 | expect = hlist_entry(n, struct nf_conntrack_expect, hnode); | ||
412 | 451 | ||
413 | if (expect->timeout.function) | 452 | if (expect->timeout.function) |
414 | seq_printf(s, "%ld ", timer_pending(&expect->timeout) | 453 | seq_printf(s, "%ld ", timer_pending(&expect->timeout) |
@@ -425,7 +464,7 @@ static int exp_seq_show(struct seq_file *s, void *v) | |||
425 | return seq_putc(s, '\n'); | 464 | return seq_putc(s, '\n'); |
426 | } | 465 | } |
427 | 466 | ||
428 | static struct seq_operations exp_seq_ops = { | 467 | static const struct seq_operations exp_seq_ops = { |
429 | .start = exp_seq_start, | 468 | .start = exp_seq_start, |
430 | .next = exp_seq_next, | 469 | .next = exp_seq_next, |
431 | .stop = exp_seq_stop, | 470 | .stop = exp_seq_stop, |
@@ -434,14 +473,96 @@ static struct seq_operations exp_seq_ops = { | |||
434 | 473 | ||
435 | static int exp_open(struct inode *inode, struct file *file) | 474 | static int exp_open(struct inode *inode, struct file *file) |
436 | { | 475 | { |
437 | return seq_open(file, &exp_seq_ops); | 476 | struct seq_file *seq; |
477 | struct ct_expect_iter_state *st; | ||
478 | int ret; | ||
479 | |||
480 | st = kmalloc(sizeof(struct ct_expect_iter_state), GFP_KERNEL); | ||
481 | if (st == NULL) | ||
482 | return -ENOMEM; | ||
483 | ret = seq_open(file, &exp_seq_ops); | ||
484 | if (ret) | ||
485 | goto out_free; | ||
486 | seq = file->private_data; | ||
487 | seq->private = st; | ||
488 | memset(st, 0, sizeof(struct ct_expect_iter_state)); | ||
489 | return ret; | ||
490 | out_free: | ||
491 | kfree(st); | ||
492 | return ret; | ||
438 | } | 493 | } |
439 | 494 | ||
440 | const struct file_operations exp_file_ops = { | 495 | static const struct file_operations exp_file_ops = { |
441 | .owner = THIS_MODULE, | 496 | .owner = THIS_MODULE, |
442 | .open = exp_open, | 497 | .open = exp_open, |
443 | .read = seq_read, | 498 | .read = seq_read, |
444 | .llseek = seq_lseek, | 499 | .llseek = seq_lseek, |
445 | .release = seq_release | 500 | .release = seq_release_private, |
446 | }; | 501 | }; |
447 | #endif /* CONFIG_PROC_FS */ | 502 | #endif /* CONFIG_PROC_FS */ |
503 | |||
504 | static int __init exp_proc_init(void) | ||
505 | { | ||
506 | #ifdef CONFIG_PROC_FS | ||
507 | struct proc_dir_entry *proc; | ||
508 | |||
509 | proc = proc_net_fops_create("nf_conntrack_expect", 0440, &exp_file_ops); | ||
510 | if (!proc) | ||
511 | return -ENOMEM; | ||
512 | #endif /* CONFIG_PROC_FS */ | ||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | static void exp_proc_remove(void) | ||
517 | { | ||
518 | #ifdef CONFIG_PROC_FS | ||
519 | proc_net_remove("nf_conntrack_expect"); | ||
520 | #endif /* CONFIG_PROC_FS */ | ||
521 | } | ||
522 | |||
523 | module_param_named(expect_hashsize, nf_ct_expect_hsize, uint, 0600); | ||
524 | |||
525 | int __init nf_conntrack_expect_init(void) | ||
526 | { | ||
527 | int err = -ENOMEM; | ||
528 | |||
529 | if (!nf_ct_expect_hsize) { | ||
530 | nf_ct_expect_hsize = nf_conntrack_htable_size / 256; | ||
531 | if (!nf_ct_expect_hsize) | ||
532 | nf_ct_expect_hsize = 1; | ||
533 | } | ||
534 | nf_ct_expect_max = nf_ct_expect_hsize * 4; | ||
535 | |||
536 | nf_ct_expect_hash = nf_ct_alloc_hashtable(&nf_ct_expect_hsize, | ||
537 | &nf_ct_expect_vmalloc); | ||
538 | if (nf_ct_expect_hash == NULL) | ||
539 | goto err1; | ||
540 | |||
541 | nf_ct_expect_cachep = kmem_cache_create("nf_conntrack_expect", | ||
542 | sizeof(struct nf_conntrack_expect), | ||
543 | 0, 0, NULL, NULL); | ||
544 | if (!nf_ct_expect_cachep) | ||
545 | goto err2; | ||
546 | |||
547 | err = exp_proc_init(); | ||
548 | if (err < 0) | ||
549 | goto err3; | ||
550 | |||
551 | return 0; | ||
552 | |||
553 | err3: | ||
554 | nf_ct_free_hashtable(nf_ct_expect_hash, nf_ct_expect_vmalloc, | ||
555 | nf_ct_expect_hsize); | ||
556 | err2: | ||
557 | kmem_cache_destroy(nf_ct_expect_cachep); | ||
558 | err1: | ||
559 | return err; | ||
560 | } | ||
561 | |||
562 | void nf_conntrack_expect_fini(void) | ||
563 | { | ||
564 | exp_proc_remove(); | ||
565 | kmem_cache_destroy(nf_ct_expect_cachep); | ||
566 | nf_ct_free_hashtable(nf_ct_expect_hash, nf_ct_expect_vmalloc, | ||
567 | nf_ct_expect_hsize); | ||
568 | } | ||
diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c new file mode 100644 index 000000000000..a1a65a1313b3 --- /dev/null +++ b/net/netfilter/nf_conntrack_extend.c | |||
@@ -0,0 +1,195 @@ | |||
1 | /* Structure dynamic extension infrastructure | ||
2 | * Copyright (C) 2004 Rusty Russell IBM Corporation | ||
3 | * Copyright (C) 2007 Netfilter Core Team <coreteam@netfilter.org> | ||
4 | * Copyright (C) 2007 USAGI/WIDE Project <http://www.linux-ipv6.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/mutex.h> | ||
14 | #include <linux/rcupdate.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/skbuff.h> | ||
17 | #include <net/netfilter/nf_conntrack_extend.h> | ||
18 | |||
19 | static struct nf_ct_ext_type *nf_ct_ext_types[NF_CT_EXT_NUM]; | ||
20 | static DEFINE_MUTEX(nf_ct_ext_type_mutex); | ||
21 | |||
22 | /* Horrible trick to figure out smallest amount worth kmallocing. */ | ||
23 | #define CACHE(x) (x) + 0 * | ||
24 | enum { | ||
25 | NF_CT_EXT_MIN_SIZE = | ||
26 | #include <linux/kmalloc_sizes.h> | ||
27 | 1 }; | ||
28 | #undef CACHE | ||
29 | |||
30 | void __nf_ct_ext_destroy(struct nf_conn *ct) | ||
31 | { | ||
32 | unsigned int i; | ||
33 | struct nf_ct_ext_type *t; | ||
34 | |||
35 | for (i = 0; i < NF_CT_EXT_NUM; i++) { | ||
36 | if (!nf_ct_ext_exist(ct, i)) | ||
37 | continue; | ||
38 | |||
39 | rcu_read_lock(); | ||
40 | t = rcu_dereference(nf_ct_ext_types[i]); | ||
41 | |||
42 | /* Here the nf_ct_ext_type might have been unregisterd. | ||
43 | * I.e., it has responsible to cleanup private | ||
44 | * area in all conntracks when it is unregisterd. | ||
45 | */ | ||
46 | if (t && t->destroy) | ||
47 | t->destroy(ct); | ||
48 | rcu_read_unlock(); | ||
49 | } | ||
50 | } | ||
51 | EXPORT_SYMBOL(__nf_ct_ext_destroy); | ||
52 | |||
53 | static void * | ||
54 | nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id, gfp_t gfp) | ||
55 | { | ||
56 | unsigned int off, len, real_len; | ||
57 | struct nf_ct_ext_type *t; | ||
58 | |||
59 | rcu_read_lock(); | ||
60 | t = rcu_dereference(nf_ct_ext_types[id]); | ||
61 | BUG_ON(t == NULL); | ||
62 | off = ALIGN(sizeof(struct nf_ct_ext), t->align); | ||
63 | len = off + t->len; | ||
64 | real_len = t->alloc_size; | ||
65 | rcu_read_unlock(); | ||
66 | |||
67 | *ext = kzalloc(real_len, gfp); | ||
68 | if (!*ext) | ||
69 | return NULL; | ||
70 | |||
71 | (*ext)->offset[id] = off; | ||
72 | (*ext)->len = len; | ||
73 | (*ext)->real_len = real_len; | ||
74 | |||
75 | return (void *)(*ext) + off; | ||
76 | } | ||
77 | |||
78 | void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp) | ||
79 | { | ||
80 | struct nf_ct_ext *new; | ||
81 | int i, newlen, newoff; | ||
82 | struct nf_ct_ext_type *t; | ||
83 | |||
84 | if (!ct->ext) | ||
85 | return nf_ct_ext_create(&ct->ext, id, gfp); | ||
86 | |||
87 | if (nf_ct_ext_exist(ct, id)) | ||
88 | return NULL; | ||
89 | |||
90 | rcu_read_lock(); | ||
91 | t = rcu_dereference(nf_ct_ext_types[id]); | ||
92 | BUG_ON(t == NULL); | ||
93 | |||
94 | newoff = ALIGN(ct->ext->len, t->align); | ||
95 | newlen = newoff + t->len; | ||
96 | rcu_read_unlock(); | ||
97 | |||
98 | if (newlen >= ct->ext->real_len) { | ||
99 | new = kmalloc(newlen, gfp); | ||
100 | if (!new) | ||
101 | return NULL; | ||
102 | |||
103 | memcpy(new, ct->ext, ct->ext->len); | ||
104 | |||
105 | for (i = 0; i < NF_CT_EXT_NUM; i++) { | ||
106 | if (!nf_ct_ext_exist(ct, i)) | ||
107 | continue; | ||
108 | |||
109 | rcu_read_lock(); | ||
110 | t = rcu_dereference(nf_ct_ext_types[i]); | ||
111 | if (t && t->move) | ||
112 | t->move(ct, ct->ext + ct->ext->offset[id]); | ||
113 | rcu_read_unlock(); | ||
114 | } | ||
115 | kfree(ct->ext); | ||
116 | new->real_len = newlen; | ||
117 | ct->ext = new; | ||
118 | } | ||
119 | |||
120 | ct->ext->offset[id] = newoff; | ||
121 | ct->ext->len = newlen; | ||
122 | memset((void *)ct->ext + newoff, 0, newlen - newoff); | ||
123 | return (void *)ct->ext + newoff; | ||
124 | } | ||
125 | EXPORT_SYMBOL(__nf_ct_ext_add); | ||
126 | |||
127 | static void update_alloc_size(struct nf_ct_ext_type *type) | ||
128 | { | ||
129 | int i, j; | ||
130 | struct nf_ct_ext_type *t1, *t2; | ||
131 | enum nf_ct_ext_id min = 0, max = NF_CT_EXT_NUM - 1; | ||
132 | |||
133 | /* unnecessary to update all types */ | ||
134 | if ((type->flags & NF_CT_EXT_F_PREALLOC) == 0) { | ||
135 | min = type->id; | ||
136 | max = type->id; | ||
137 | } | ||
138 | |||
139 | /* This assumes that extended areas in conntrack for the types | ||
140 | whose NF_CT_EXT_F_PREALLOC bit set are allocated in order */ | ||
141 | for (i = min; i <= max; i++) { | ||
142 | t1 = nf_ct_ext_types[i]; | ||
143 | if (!t1) | ||
144 | continue; | ||
145 | |||
146 | t1->alloc_size = sizeof(struct nf_ct_ext) | ||
147 | + ALIGN(sizeof(struct nf_ct_ext), t1->align) | ||
148 | + t1->len; | ||
149 | for (j = 0; j < NF_CT_EXT_NUM; j++) { | ||
150 | t2 = nf_ct_ext_types[j]; | ||
151 | if (t2 == NULL || t2 == t1 || | ||
152 | (t2->flags & NF_CT_EXT_F_PREALLOC) == 0) | ||
153 | continue; | ||
154 | |||
155 | t1->alloc_size = ALIGN(t1->alloc_size, t2->align) | ||
156 | + t2->len; | ||
157 | } | ||
158 | if (t1->alloc_size < NF_CT_EXT_MIN_SIZE) | ||
159 | t1->alloc_size = NF_CT_EXT_MIN_SIZE; | ||
160 | } | ||
161 | } | ||
162 | |||
163 | /* This MUST be called in process context. */ | ||
164 | int nf_ct_extend_register(struct nf_ct_ext_type *type) | ||
165 | { | ||
166 | int ret = 0; | ||
167 | |||
168 | mutex_lock(&nf_ct_ext_type_mutex); | ||
169 | if (nf_ct_ext_types[type->id]) { | ||
170 | ret = -EBUSY; | ||
171 | goto out; | ||
172 | } | ||
173 | |||
174 | /* This ensures that nf_ct_ext_create() can allocate enough area | ||
175 | before updating alloc_size */ | ||
176 | type->alloc_size = ALIGN(sizeof(struct nf_ct_ext), type->align) | ||
177 | + type->len; | ||
178 | rcu_assign_pointer(nf_ct_ext_types[type->id], type); | ||
179 | update_alloc_size(type); | ||
180 | out: | ||
181 | mutex_unlock(&nf_ct_ext_type_mutex); | ||
182 | return ret; | ||
183 | } | ||
184 | EXPORT_SYMBOL_GPL(nf_ct_extend_register); | ||
185 | |||
186 | /* This MUST be called in process context. */ | ||
187 | void nf_ct_extend_unregister(struct nf_ct_ext_type *type) | ||
188 | { | ||
189 | mutex_lock(&nf_ct_ext_type_mutex); | ||
190 | rcu_assign_pointer(nf_ct_ext_types[type->id], NULL); | ||
191 | update_alloc_size(type); | ||
192 | mutex_unlock(&nf_ct_ext_type_mutex); | ||
193 | synchronize_rcu(); | ||
194 | } | ||
195 | EXPORT_SYMBOL_GPL(nf_ct_extend_unregister); | ||
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index 82db2aa53bfc..c763ee74ea02 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c | |||
@@ -51,12 +51,6 @@ unsigned int (*nf_nat_ftp_hook)(struct sk_buff **pskb, | |||
51 | struct nf_conntrack_expect *exp); | 51 | struct nf_conntrack_expect *exp); |
52 | EXPORT_SYMBOL_GPL(nf_nat_ftp_hook); | 52 | EXPORT_SYMBOL_GPL(nf_nat_ftp_hook); |
53 | 53 | ||
54 | #if 0 | ||
55 | #define DEBUGP printk | ||
56 | #else | ||
57 | #define DEBUGP(format, args...) | ||
58 | #endif | ||
59 | |||
60 | static int try_rfc959(const char *, size_t, struct nf_conntrack_man *, char); | 54 | static int try_rfc959(const char *, size_t, struct nf_conntrack_man *, char); |
61 | static int try_eprt(const char *, size_t, struct nf_conntrack_man *, char); | 55 | static int try_eprt(const char *, size_t, struct nf_conntrack_man *, char); |
62 | static int try_epsv_response(const char *, size_t, struct nf_conntrack_man *, | 56 | static int try_epsv_response(const char *, size_t, struct nf_conntrack_man *, |
@@ -138,13 +132,13 @@ static int try_number(const char *data, size_t dlen, u_int32_t array[], | |||
138 | if (*data == term && i == array_size - 1) | 132 | if (*data == term && i == array_size - 1) |
139 | return len; | 133 | return len; |
140 | 134 | ||
141 | DEBUGP("Char %u (got %u nums) `%u' unexpected\n", | 135 | pr_debug("Char %u (got %u nums) `%u' unexpected\n", |
142 | len, i, *data); | 136 | len, i, *data); |
143 | return 0; | 137 | return 0; |
144 | } | 138 | } |
145 | } | 139 | } |
146 | DEBUGP("Failed to fill %u numbers separated by %c\n", array_size, sep); | 140 | pr_debug("Failed to fill %u numbers separated by %c\n", |
147 | 141 | array_size, sep); | |
148 | return 0; | 142 | return 0; |
149 | } | 143 | } |
150 | 144 | ||
@@ -178,13 +172,13 @@ static int get_port(const char *data, int start, size_t dlen, char delim, | |||
178 | if (tmp_port == 0) | 172 | if (tmp_port == 0) |
179 | break; | 173 | break; |
180 | *port = htons(tmp_port); | 174 | *port = htons(tmp_port); |
181 | DEBUGP("get_port: return %d\n", tmp_port); | 175 | pr_debug("get_port: return %d\n", tmp_port); |
182 | return i + 1; | 176 | return i + 1; |
183 | } | 177 | } |
184 | else if (data[i] >= '0' && data[i] <= '9') | 178 | else if (data[i] >= '0' && data[i] <= '9') |
185 | tmp_port = tmp_port*10 + data[i] - '0'; | 179 | tmp_port = tmp_port*10 + data[i] - '0'; |
186 | else { /* Some other crap */ | 180 | else { /* Some other crap */ |
187 | DEBUGP("get_port: invalid char.\n"); | 181 | pr_debug("get_port: invalid char.\n"); |
188 | break; | 182 | break; |
189 | } | 183 | } |
190 | } | 184 | } |
@@ -201,22 +195,22 @@ static int try_eprt(const char *data, size_t dlen, struct nf_conntrack_man *cmd, | |||
201 | /* First character is delimiter, then "1" for IPv4 or "2" for IPv6, | 195 | /* First character is delimiter, then "1" for IPv4 or "2" for IPv6, |
202 | then delimiter again. */ | 196 | then delimiter again. */ |
203 | if (dlen <= 3) { | 197 | if (dlen <= 3) { |
204 | DEBUGP("EPRT: too short\n"); | 198 | pr_debug("EPRT: too short\n"); |
205 | return 0; | 199 | return 0; |
206 | } | 200 | } |
207 | delim = data[0]; | 201 | delim = data[0]; |
208 | if (isdigit(delim) || delim < 33 || delim > 126 || data[2] != delim) { | 202 | if (isdigit(delim) || delim < 33 || delim > 126 || data[2] != delim) { |
209 | DEBUGP("try_eprt: invalid delimitter.\n"); | 203 | pr_debug("try_eprt: invalid delimitter.\n"); |
210 | return 0; | 204 | return 0; |
211 | } | 205 | } |
212 | 206 | ||
213 | if ((cmd->l3num == PF_INET && data[1] != '1') || | 207 | if ((cmd->l3num == PF_INET && data[1] != '1') || |
214 | (cmd->l3num == PF_INET6 && data[1] != '2')) { | 208 | (cmd->l3num == PF_INET6 && data[1] != '2')) { |
215 | DEBUGP("EPRT: invalid protocol number.\n"); | 209 | pr_debug("EPRT: invalid protocol number.\n"); |
216 | return 0; | 210 | return 0; |
217 | } | 211 | } |
218 | 212 | ||
219 | DEBUGP("EPRT: Got %c%c%c\n", delim, data[1], delim); | 213 | pr_debug("EPRT: Got %c%c%c\n", delim, data[1], delim); |
220 | 214 | ||
221 | if (data[1] == '1') { | 215 | if (data[1] == '1') { |
222 | u_int32_t array[4]; | 216 | u_int32_t array[4]; |
@@ -234,7 +228,7 @@ static int try_eprt(const char *data, size_t dlen, struct nf_conntrack_man *cmd, | |||
234 | 228 | ||
235 | if (length == 0) | 229 | if (length == 0) |
236 | return 0; | 230 | return 0; |
237 | DEBUGP("EPRT: Got IP address!\n"); | 231 | pr_debug("EPRT: Got IP address!\n"); |
238 | /* Start offset includes initial "|1|", and trailing delimiter */ | 232 | /* Start offset includes initial "|1|", and trailing delimiter */ |
239 | return get_port(data, 3 + length + 1, dlen, delim, &cmd->u.tcp.port); | 233 | return get_port(data, 3 + length + 1, dlen, delim, &cmd->u.tcp.port); |
240 | } | 234 | } |
@@ -267,7 +261,7 @@ static int find_pattern(const char *data, size_t dlen, | |||
267 | { | 261 | { |
268 | size_t i; | 262 | size_t i; |
269 | 263 | ||
270 | DEBUGP("find_pattern `%s': dlen = %u\n", pattern, dlen); | 264 | pr_debug("find_pattern `%s': dlen = %Zu\n", pattern, dlen); |
271 | if (dlen == 0) | 265 | if (dlen == 0) |
272 | return 0; | 266 | return 0; |
273 | 267 | ||
@@ -282,17 +276,17 @@ static int find_pattern(const char *data, size_t dlen, | |||
282 | #if 0 | 276 | #if 0 |
283 | size_t i; | 277 | size_t i; |
284 | 278 | ||
285 | DEBUGP("ftp: string mismatch\n"); | 279 | pr_debug("ftp: string mismatch\n"); |
286 | for (i = 0; i < plen; i++) { | 280 | for (i = 0; i < plen; i++) { |
287 | DEBUGP("ftp:char %u `%c'(%u) vs `%c'(%u)\n", | 281 | pr_debug("ftp:char %u `%c'(%u) vs `%c'(%u)\n", |
288 | i, data[i], data[i], | 282 | i, data[i], data[i], |
289 | pattern[i], pattern[i]); | 283 | pattern[i], pattern[i]); |
290 | } | 284 | } |
291 | #endif | 285 | #endif |
292 | return 0; | 286 | return 0; |
293 | } | 287 | } |
294 | 288 | ||
295 | DEBUGP("Pattern matches!\n"); | 289 | pr_debug("Pattern matches!\n"); |
296 | /* Now we've found the constant string, try to skip | 290 | /* Now we've found the constant string, try to skip |
297 | to the 'skip' character */ | 291 | to the 'skip' character */ |
298 | for (i = plen; data[i] != skip; i++) | 292 | for (i = plen; data[i] != skip; i++) |
@@ -301,14 +295,14 @@ static int find_pattern(const char *data, size_t dlen, | |||
301 | /* Skip over the last character */ | 295 | /* Skip over the last character */ |
302 | i++; | 296 | i++; |
303 | 297 | ||
304 | DEBUGP("Skipped up to `%c'!\n", skip); | 298 | pr_debug("Skipped up to `%c'!\n", skip); |
305 | 299 | ||
306 | *numoff = i; | 300 | *numoff = i; |
307 | *numlen = getnum(data + i, dlen - i, cmd, term); | 301 | *numlen = getnum(data + i, dlen - i, cmd, term); |
308 | if (!*numlen) | 302 | if (!*numlen) |
309 | return -1; | 303 | return -1; |
310 | 304 | ||
311 | DEBUGP("Match succeeded!\n"); | 305 | pr_debug("Match succeeded!\n"); |
312 | return 1; | 306 | return 1; |
313 | } | 307 | } |
314 | 308 | ||
@@ -364,6 +358,7 @@ static int help(struct sk_buff **pskb, | |||
364 | unsigned int matchlen, matchoff; | 358 | unsigned int matchlen, matchoff; |
365 | struct nf_ct_ftp_master *ct_ftp_info = &nfct_help(ct)->help.ct_ftp_info; | 359 | struct nf_ct_ftp_master *ct_ftp_info = &nfct_help(ct)->help.ct_ftp_info; |
366 | struct nf_conntrack_expect *exp; | 360 | struct nf_conntrack_expect *exp; |
361 | union nf_conntrack_address *daddr; | ||
367 | struct nf_conntrack_man cmd = {}; | 362 | struct nf_conntrack_man cmd = {}; |
368 | unsigned int i; | 363 | unsigned int i; |
369 | int found = 0, ends_in_nl; | 364 | int found = 0, ends_in_nl; |
@@ -372,7 +367,7 @@ static int help(struct sk_buff **pskb, | |||
372 | /* Until there's been traffic both ways, don't look in packets. */ | 367 | /* Until there's been traffic both ways, don't look in packets. */ |
373 | if (ctinfo != IP_CT_ESTABLISHED | 368 | if (ctinfo != IP_CT_ESTABLISHED |
374 | && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) { | 369 | && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) { |
375 | DEBUGP("ftp: Conntrackinfo = %u\n", ctinfo); | 370 | pr_debug("ftp: Conntrackinfo = %u\n", ctinfo); |
376 | return NF_ACCEPT; | 371 | return NF_ACCEPT; |
377 | } | 372 | } |
378 | 373 | ||
@@ -383,8 +378,8 @@ static int help(struct sk_buff **pskb, | |||
383 | dataoff = protoff + th->doff * 4; | 378 | dataoff = protoff + th->doff * 4; |
384 | /* No data? */ | 379 | /* No data? */ |
385 | if (dataoff >= (*pskb)->len) { | 380 | if (dataoff >= (*pskb)->len) { |
386 | DEBUGP("ftp: dataoff(%u) >= skblen(%u)\n", dataoff, | 381 | pr_debug("ftp: dataoff(%u) >= skblen(%u)\n", dataoff, |
387 | (*pskb)->len); | 382 | (*pskb)->len); |
388 | return NF_ACCEPT; | 383 | return NF_ACCEPT; |
389 | } | 384 | } |
390 | datalen = (*pskb)->len - dataoff; | 385 | datalen = (*pskb)->len - dataoff; |
@@ -399,11 +394,11 @@ static int help(struct sk_buff **pskb, | |||
399 | /* Look up to see if we're just after a \n. */ | 394 | /* Look up to see if we're just after a \n. */ |
400 | if (!find_nl_seq(ntohl(th->seq), ct_ftp_info, dir)) { | 395 | if (!find_nl_seq(ntohl(th->seq), ct_ftp_info, dir)) { |
401 | /* Now if this ends in \n, update ftp info. */ | 396 | /* Now if this ends in \n, update ftp info. */ |
402 | DEBUGP("nf_conntrack_ftp_help: wrong seq pos %s(%u) or %s(%u)\n", | 397 | pr_debug("nf_conntrack_ftp: wrong seq pos %s(%u) or %s(%u)\n", |
403 | ct_ftp_info->seq_aft_nl_num[dir] > 0 ? "" : "(UNSET)", | 398 | ct_ftp_info->seq_aft_nl_num[dir] > 0 ? "" : "(UNSET)", |
404 | ct_ftp_info->seq_aft_nl[dir][0], | 399 | ct_ftp_info->seq_aft_nl[dir][0], |
405 | ct_ftp_info->seq_aft_nl_num[dir] > 1 ? "" : "(UNSET)", | 400 | ct_ftp_info->seq_aft_nl_num[dir] > 1 ? "" : "(UNSET)", |
406 | ct_ftp_info->seq_aft_nl[dir][1]); | 401 | ct_ftp_info->seq_aft_nl[dir][1]); |
407 | ret = NF_ACCEPT; | 402 | ret = NF_ACCEPT; |
408 | goto out_update_nl; | 403 | goto out_update_nl; |
409 | } | 404 | } |
@@ -441,11 +436,11 @@ static int help(struct sk_buff **pskb, | |||
441 | goto out_update_nl; | 436 | goto out_update_nl; |
442 | } | 437 | } |
443 | 438 | ||
444 | DEBUGP("conntrack_ftp: match `%.*s' (%u bytes at %u)\n", | 439 | pr_debug("conntrack_ftp: match `%.*s' (%u bytes at %u)\n", |
445 | (int)matchlen, fb_ptr + matchoff, | 440 | matchlen, fb_ptr + matchoff, |
446 | matchlen, ntohl(th->seq) + matchoff); | 441 | matchlen, ntohl(th->seq) + matchoff); |
447 | 442 | ||
448 | exp = nf_conntrack_expect_alloc(ct); | 443 | exp = nf_ct_expect_alloc(ct); |
449 | if (exp == NULL) { | 444 | if (exp == NULL) { |
450 | ret = NF_DROP; | 445 | ret = NF_DROP; |
451 | goto out; | 446 | goto out; |
@@ -454,7 +449,7 @@ static int help(struct sk_buff **pskb, | |||
454 | /* We refer to the reverse direction ("!dir") tuples here, | 449 | /* We refer to the reverse direction ("!dir") tuples here, |
455 | * because we're expecting something in the other direction. | 450 | * because we're expecting something in the other direction. |
456 | * Doesn't matter unless NAT is happening. */ | 451 | * Doesn't matter unless NAT is happening. */ |
457 | exp->tuple.dst.u3 = ct->tuplehash[!dir].tuple.dst.u3; | 452 | daddr = &ct->tuplehash[!dir].tuple.dst.u3; |
458 | 453 | ||
459 | /* Update the ftp info */ | 454 | /* Update the ftp info */ |
460 | if ((cmd.l3num == ct->tuplehash[dir].tuple.src.l3num) && | 455 | if ((cmd.l3num == ct->tuplehash[dir].tuple.src.l3num) && |
@@ -465,14 +460,16 @@ static int help(struct sk_buff **pskb, | |||
465 | different IP address. Simply don't record it for | 460 | different IP address. Simply don't record it for |
466 | NAT. */ | 461 | NAT. */ |
467 | if (cmd.l3num == PF_INET) { | 462 | if (cmd.l3num == PF_INET) { |
468 | DEBUGP("conntrack_ftp: NOT RECORDING: " NIPQUAD_FMT " != " NIPQUAD_FMT "\n", | 463 | pr_debug("conntrack_ftp: NOT RECORDING: " NIPQUAD_FMT |
469 | NIPQUAD(cmd.u3.ip), | 464 | " != " NIPQUAD_FMT "\n", |
470 | NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip)); | 465 | NIPQUAD(cmd.u3.ip), |
466 | NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip)); | ||
471 | } else { | 467 | } else { |
472 | DEBUGP("conntrack_ftp: NOT RECORDING: " NIP6_FMT " != " NIP6_FMT "\n", | 468 | pr_debug("conntrack_ftp: NOT RECORDING: " NIP6_FMT |
473 | NIP6(*((struct in6_addr *)cmd.u3.ip6)), | 469 | " != " NIP6_FMT "\n", |
474 | NIP6(*((struct in6_addr *)ct->tuplehash[dir] | 470 | NIP6(*((struct in6_addr *)cmd.u3.ip6)), |
475 | .tuple.src.u3.ip6))); | 471 | NIP6(*((struct in6_addr *) |
472 | ct->tuplehash[dir].tuple.src.u3.ip6))); | ||
476 | } | 473 | } |
477 | 474 | ||
478 | /* Thanks to Cristiano Lincoln Mattos | 475 | /* Thanks to Cristiano Lincoln Mattos |
@@ -483,37 +480,12 @@ static int help(struct sk_buff **pskb, | |||
483 | ret = NF_ACCEPT; | 480 | ret = NF_ACCEPT; |
484 | goto out_put_expect; | 481 | goto out_put_expect; |
485 | } | 482 | } |
486 | memcpy(&exp->tuple.dst.u3, &cmd.u3.all, | 483 | daddr = &cmd.u3; |
487 | sizeof(exp->tuple.dst.u3)); | ||
488 | } | ||
489 | |||
490 | exp->tuple.src.u3 = ct->tuplehash[!dir].tuple.src.u3; | ||
491 | exp->tuple.src.l3num = cmd.l3num; | ||
492 | exp->tuple.src.u.tcp.port = 0; | ||
493 | exp->tuple.dst.u.tcp.port = cmd.u.tcp.port; | ||
494 | exp->tuple.dst.protonum = IPPROTO_TCP; | ||
495 | |||
496 | exp->mask = (struct nf_conntrack_tuple) | ||
497 | { .src = { .l3num = 0xFFFF, | ||
498 | .u = { .tcp = { 0 }}, | ||
499 | }, | ||
500 | .dst = { .protonum = 0xFF, | ||
501 | .u = { .tcp = { __constant_htons(0xFFFF) }}, | ||
502 | }, | ||
503 | }; | ||
504 | if (cmd.l3num == PF_INET) { | ||
505 | exp->mask.src.u3.ip = htonl(0xFFFFFFFF); | ||
506 | exp->mask.dst.u3.ip = htonl(0xFFFFFFFF); | ||
507 | } else { | ||
508 | memset(exp->mask.src.u3.ip6, 0xFF, | ||
509 | sizeof(exp->mask.src.u3.ip6)); | ||
510 | memset(exp->mask.dst.u3.ip6, 0xFF, | ||
511 | sizeof(exp->mask.src.u3.ip6)); | ||
512 | } | 484 | } |
513 | 485 | ||
514 | exp->expectfn = NULL; | 486 | nf_ct_expect_init(exp, cmd.l3num, |
515 | exp->helper = NULL; | 487 | &ct->tuplehash[!dir].tuple.src.u3, daddr, |
516 | exp->flags = 0; | 488 | IPPROTO_TCP, NULL, &cmd.u.tcp.port); |
517 | 489 | ||
518 | /* Now, NAT might want to mangle the packet, and register the | 490 | /* Now, NAT might want to mangle the packet, and register the |
519 | * (possibly changed) expectation itself. */ | 491 | * (possibly changed) expectation itself. */ |
@@ -523,14 +495,14 @@ static int help(struct sk_buff **pskb, | |||
523 | matchoff, matchlen, exp); | 495 | matchoff, matchlen, exp); |
524 | else { | 496 | else { |
525 | /* Can't expect this? Best to drop packet now. */ | 497 | /* Can't expect this? Best to drop packet now. */ |
526 | if (nf_conntrack_expect_related(exp) != 0) | 498 | if (nf_ct_expect_related(exp) != 0) |
527 | ret = NF_DROP; | 499 | ret = NF_DROP; |
528 | else | 500 | else |
529 | ret = NF_ACCEPT; | 501 | ret = NF_ACCEPT; |
530 | } | 502 | } |
531 | 503 | ||
532 | out_put_expect: | 504 | out_put_expect: |
533 | nf_conntrack_expect_put(exp); | 505 | nf_ct_expect_put(exp); |
534 | 506 | ||
535 | out_update_nl: | 507 | out_update_nl: |
536 | /* Now if this ends in \n, update ftp info. Seq may have been | 508 | /* Now if this ends in \n, update ftp info. Seq may have been |
@@ -542,8 +514,8 @@ out_update_nl: | |||
542 | return ret; | 514 | return ret; |
543 | } | 515 | } |
544 | 516 | ||
545 | static struct nf_conntrack_helper ftp[MAX_PORTS][2]; | 517 | static struct nf_conntrack_helper ftp[MAX_PORTS][2] __read_mostly; |
546 | static char ftp_names[MAX_PORTS][2][sizeof("ftp-65535")]; | 518 | static char ftp_names[MAX_PORTS][2][sizeof("ftp-65535")] __read_mostly; |
547 | 519 | ||
548 | /* don't make this __exit, since it's called from __init ! */ | 520 | /* don't make this __exit, since it's called from __init ! */ |
549 | static void nf_conntrack_ftp_fini(void) | 521 | static void nf_conntrack_ftp_fini(void) |
@@ -554,9 +526,9 @@ static void nf_conntrack_ftp_fini(void) | |||
554 | if (ftp[i][j].me == NULL) | 526 | if (ftp[i][j].me == NULL) |
555 | continue; | 527 | continue; |
556 | 528 | ||
557 | DEBUGP("nf_ct_ftp: unregistering helper for pf: %d " | 529 | pr_debug("nf_ct_ftp: unregistering helper for pf: %d " |
558 | "port: %d\n", | 530 | "port: %d\n", |
559 | ftp[i][j].tuple.src.l3num, ports[i]); | 531 | ftp[i][j].tuple.src.l3num, ports[i]); |
560 | nf_conntrack_helper_unregister(&ftp[i][j]); | 532 | nf_conntrack_helper_unregister(&ftp[i][j]); |
561 | } | 533 | } |
562 | } | 534 | } |
@@ -584,9 +556,6 @@ static int __init nf_conntrack_ftp_init(void) | |||
584 | for (j = 0; j < 2; j++) { | 556 | for (j = 0; j < 2; j++) { |
585 | ftp[i][j].tuple.src.u.tcp.port = htons(ports[i]); | 557 | ftp[i][j].tuple.src.u.tcp.port = htons(ports[i]); |
586 | ftp[i][j].tuple.dst.protonum = IPPROTO_TCP; | 558 | ftp[i][j].tuple.dst.protonum = IPPROTO_TCP; |
587 | ftp[i][j].mask.src.l3num = 0xFFFF; | ||
588 | ftp[i][j].mask.src.u.tcp.port = htons(0xFFFF); | ||
589 | ftp[i][j].mask.dst.protonum = 0xFF; | ||
590 | ftp[i][j].max_expected = 1; | 559 | ftp[i][j].max_expected = 1; |
591 | ftp[i][j].timeout = 5 * 60; /* 5 Minutes */ | 560 | ftp[i][j].timeout = 5 * 60; /* 5 Minutes */ |
592 | ftp[i][j].me = THIS_MODULE; | 561 | ftp[i][j].me = THIS_MODULE; |
@@ -598,9 +567,9 @@ static int __init nf_conntrack_ftp_init(void) | |||
598 | sprintf(tmpname, "ftp-%d", ports[i]); | 567 | sprintf(tmpname, "ftp-%d", ports[i]); |
599 | ftp[i][j].name = tmpname; | 568 | ftp[i][j].name = tmpname; |
600 | 569 | ||
601 | DEBUGP("nf_ct_ftp: registering helper for pf: %d " | 570 | pr_debug("nf_ct_ftp: registering helper for pf: %d " |
602 | "port: %d\n", | 571 | "port: %d\n", |
603 | ftp[i][j].tuple.src.l3num, ports[i]); | 572 | ftp[i][j].tuple.src.l3num, ports[i]); |
604 | ret = nf_conntrack_helper_register(&ftp[i][j]); | 573 | ret = nf_conntrack_helper_register(&ftp[i][j]); |
605 | if (ret) { | 574 | if (ret) { |
606 | printk("nf_ct_ftp: failed to register helper " | 575 | printk("nf_ct_ftp: failed to register helper " |
diff --git a/net/netfilter/nf_conntrack_h323_asn1.c b/net/netfilter/nf_conntrack_h323_asn1.c index 6b7eaa019d4c..a869403b2294 100644 --- a/net/netfilter/nf_conntrack_h323_asn1.c +++ b/net/netfilter/nf_conntrack_h323_asn1.c | |||
@@ -555,15 +555,6 @@ int decode_seq(bitstr_t * bs, field_t * f, char *base, int level) | |||
555 | 555 | ||
556 | /* Decode the extension components */ | 556 | /* Decode the extension components */ |
557 | for (opt = 0; opt < bmp2_len; opt++, i++, son++) { | 557 | for (opt = 0; opt < bmp2_len; opt++, i++, son++) { |
558 | if (i < f->ub && son->attr & STOP) { | ||
559 | PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", | ||
560 | son->name); | ||
561 | return H323_ERROR_STOP; | ||
562 | } | ||
563 | |||
564 | if (!((0x80000000 >> opt) & bmp2)) /* Not present */ | ||
565 | continue; | ||
566 | |||
567 | /* Check Range */ | 558 | /* Check Range */ |
568 | if (i >= f->ub) { /* Newer Version? */ | 559 | if (i >= f->ub) { /* Newer Version? */ |
569 | CHECK_BOUND(bs, 2); | 560 | CHECK_BOUND(bs, 2); |
@@ -573,6 +564,15 @@ int decode_seq(bitstr_t * bs, field_t * f, char *base, int level) | |||
573 | continue; | 564 | continue; |
574 | } | 565 | } |
575 | 566 | ||
567 | if (son->attr & STOP) { | ||
568 | PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", | ||
569 | son->name); | ||
570 | return H323_ERROR_STOP; | ||
571 | } | ||
572 | |||
573 | if (!((0x80000000 >> opt) & bmp2)) /* Not present */ | ||
574 | continue; | ||
575 | |||
576 | CHECK_BOUND(bs, 2); | 576 | CHECK_BOUND(bs, 2); |
577 | len = get_len(bs); | 577 | len = get_len(bs); |
578 | CHECK_BOUND(bs, len); | 578 | CHECK_BOUND(bs, len); |
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index a1b95acad297..a8a9dfbe7a67 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c | |||
@@ -31,12 +31,6 @@ | |||
31 | #include <net/netfilter/nf_conntrack_helper.h> | 31 | #include <net/netfilter/nf_conntrack_helper.h> |
32 | #include <linux/netfilter/nf_conntrack_h323.h> | 32 | #include <linux/netfilter/nf_conntrack_h323.h> |
33 | 33 | ||
34 | #if 0 | ||
35 | #define DEBUGP printk | ||
36 | #else | ||
37 | #define DEBUGP(format, args...) | ||
38 | #endif | ||
39 | |||
40 | /* Parameters */ | 34 | /* Parameters */ |
41 | static unsigned int default_rrq_ttl __read_mostly = 300; | 35 | static unsigned int default_rrq_ttl __read_mostly = 300; |
42 | module_param(default_rrq_ttl, uint, 0600); | 36 | module_param(default_rrq_ttl, uint, 0600); |
@@ -150,9 +144,9 @@ static int get_tpkt_data(struct sk_buff **pskb, unsigned int protoff, | |||
150 | if (tcpdatalen < 4 || tpkt[0] != 0x03 || tpkt[1] != 0) { | 144 | if (tcpdatalen < 4 || tpkt[0] != 0x03 || tpkt[1] != 0) { |
151 | /* Netmeeting sends TPKT header and data separately */ | 145 | /* Netmeeting sends TPKT header and data separately */ |
152 | if (info->tpkt_len[dir] > 0) { | 146 | if (info->tpkt_len[dir] > 0) { |
153 | DEBUGP("nf_ct_h323: previous packet " | 147 | pr_debug("nf_ct_h323: previous packet " |
154 | "indicated separate TPKT data of %hu " | 148 | "indicated separate TPKT data of %hu " |
155 | "bytes\n", info->tpkt_len[dir]); | 149 | "bytes\n", info->tpkt_len[dir]); |
156 | if (info->tpkt_len[dir] <= tcpdatalen) { | 150 | if (info->tpkt_len[dir] <= tcpdatalen) { |
157 | /* Yes, there was a TPKT header | 151 | /* Yes, there was a TPKT header |
158 | * received */ | 152 | * received */ |
@@ -163,9 +157,7 @@ static int get_tpkt_data(struct sk_buff **pskb, unsigned int protoff, | |||
163 | } | 157 | } |
164 | 158 | ||
165 | /* Fragmented TPKT */ | 159 | /* Fragmented TPKT */ |
166 | if (net_ratelimit()) | 160 | pr_debug("nf_ct_h323: fragmented TPKT\n"); |
167 | printk("nf_ct_h323: " | ||
168 | "fragmented TPKT\n"); | ||
169 | goto clear_out; | 161 | goto clear_out; |
170 | } | 162 | } |
171 | 163 | ||
@@ -192,9 +184,9 @@ static int get_tpkt_data(struct sk_buff **pskb, unsigned int protoff, | |||
192 | if (tpktlen > tcpdatalen) { | 184 | if (tpktlen > tcpdatalen) { |
193 | if (tcpdatalen == 4) { /* Separate TPKT header */ | 185 | if (tcpdatalen == 4) { /* Separate TPKT header */ |
194 | /* Netmeeting sends TPKT header and data separately */ | 186 | /* Netmeeting sends TPKT header and data separately */ |
195 | DEBUGP("nf_ct_h323: separate TPKT header indicates " | 187 | pr_debug("nf_ct_h323: separate TPKT header indicates " |
196 | "there will be TPKT data of %hu bytes\n", | 188 | "there will be TPKT data of %hu bytes\n", |
197 | tpktlen - 4); | 189 | tpktlen - 4); |
198 | info->tpkt_len[dir] = tpktlen - 4; | 190 | info->tpkt_len[dir] = tpktlen - 4; |
199 | return 0; | 191 | return 0; |
200 | } | 192 | } |
@@ -282,22 +274,22 @@ static int expect_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, | |||
282 | rtcp_port = htons(ntohs(port) + 1); | 274 | rtcp_port = htons(ntohs(port) + 1); |
283 | 275 | ||
284 | /* Create expect for RTP */ | 276 | /* Create expect for RTP */ |
285 | if ((rtp_exp = nf_conntrack_expect_alloc(ct)) == NULL) | 277 | if ((rtp_exp = nf_ct_expect_alloc(ct)) == NULL) |
286 | return -1; | 278 | return -1; |
287 | nf_conntrack_expect_init(rtp_exp, ct->tuplehash[!dir].tuple.src.l3num, | 279 | nf_ct_expect_init(rtp_exp, ct->tuplehash[!dir].tuple.src.l3num, |
288 | &ct->tuplehash[!dir].tuple.src.u3, | 280 | &ct->tuplehash[!dir].tuple.src.u3, |
289 | &ct->tuplehash[!dir].tuple.dst.u3, | 281 | &ct->tuplehash[!dir].tuple.dst.u3, |
290 | IPPROTO_UDP, NULL, &rtp_port); | 282 | IPPROTO_UDP, NULL, &rtp_port); |
291 | 283 | ||
292 | /* Create expect for RTCP */ | 284 | /* Create expect for RTCP */ |
293 | if ((rtcp_exp = nf_conntrack_expect_alloc(ct)) == NULL) { | 285 | if ((rtcp_exp = nf_ct_expect_alloc(ct)) == NULL) { |
294 | nf_conntrack_expect_put(rtp_exp); | 286 | nf_ct_expect_put(rtp_exp); |
295 | return -1; | 287 | return -1; |
296 | } | 288 | } |
297 | nf_conntrack_expect_init(rtcp_exp, ct->tuplehash[!dir].tuple.src.l3num, | 289 | nf_ct_expect_init(rtcp_exp, ct->tuplehash[!dir].tuple.src.l3num, |
298 | &ct->tuplehash[!dir].tuple.src.u3, | 290 | &ct->tuplehash[!dir].tuple.src.u3, |
299 | &ct->tuplehash[!dir].tuple.dst.u3, | 291 | &ct->tuplehash[!dir].tuple.dst.u3, |
300 | IPPROTO_UDP, NULL, &rtcp_port); | 292 | IPPROTO_UDP, NULL, &rtcp_port); |
301 | 293 | ||
302 | if (memcmp(&ct->tuplehash[dir].tuple.src.u3, | 294 | if (memcmp(&ct->tuplehash[dir].tuple.src.u3, |
303 | &ct->tuplehash[!dir].tuple.dst.u3, | 295 | &ct->tuplehash[!dir].tuple.dst.u3, |
@@ -308,22 +300,22 @@ static int expect_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, | |||
308 | ret = nat_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, | 300 | ret = nat_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, |
309 | taddr, port, rtp_port, rtp_exp, rtcp_exp); | 301 | taddr, port, rtp_port, rtp_exp, rtcp_exp); |
310 | } else { /* Conntrack only */ | 302 | } else { /* Conntrack only */ |
311 | if (nf_conntrack_expect_related(rtp_exp) == 0) { | 303 | if (nf_ct_expect_related(rtp_exp) == 0) { |
312 | if (nf_conntrack_expect_related(rtcp_exp) == 0) { | 304 | if (nf_ct_expect_related(rtcp_exp) == 0) { |
313 | DEBUGP("nf_ct_h323: expect RTP "); | 305 | pr_debug("nf_ct_h323: expect RTP "); |
314 | NF_CT_DUMP_TUPLE(&rtp_exp->tuple); | 306 | NF_CT_DUMP_TUPLE(&rtp_exp->tuple); |
315 | DEBUGP("nf_ct_h323: expect RTCP "); | 307 | pr_debug("nf_ct_h323: expect RTCP "); |
316 | NF_CT_DUMP_TUPLE(&rtcp_exp->tuple); | 308 | NF_CT_DUMP_TUPLE(&rtcp_exp->tuple); |
317 | } else { | 309 | } else { |
318 | nf_conntrack_unexpect_related(rtp_exp); | 310 | nf_ct_unexpect_related(rtp_exp); |
319 | ret = -1; | 311 | ret = -1; |
320 | } | 312 | } |
321 | } else | 313 | } else |
322 | ret = -1; | 314 | ret = -1; |
323 | } | 315 | } |
324 | 316 | ||
325 | nf_conntrack_expect_put(rtp_exp); | 317 | nf_ct_expect_put(rtp_exp); |
326 | nf_conntrack_expect_put(rtcp_exp); | 318 | nf_ct_expect_put(rtcp_exp); |
327 | 319 | ||
328 | return ret; | 320 | return ret; |
329 | } | 321 | } |
@@ -349,12 +341,12 @@ static int expect_t120(struct sk_buff **pskb, | |||
349 | return 0; | 341 | return 0; |
350 | 342 | ||
351 | /* Create expect for T.120 connections */ | 343 | /* Create expect for T.120 connections */ |
352 | if ((exp = nf_conntrack_expect_alloc(ct)) == NULL) | 344 | if ((exp = nf_ct_expect_alloc(ct)) == NULL) |
353 | return -1; | 345 | return -1; |
354 | nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, | 346 | nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, |
355 | &ct->tuplehash[!dir].tuple.src.u3, | 347 | &ct->tuplehash[!dir].tuple.src.u3, |
356 | &ct->tuplehash[!dir].tuple.dst.u3, | 348 | &ct->tuplehash[!dir].tuple.dst.u3, |
357 | IPPROTO_TCP, NULL, &port); | 349 | IPPROTO_TCP, NULL, &port); |
358 | exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple channels */ | 350 | exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple channels */ |
359 | 351 | ||
360 | if (memcmp(&ct->tuplehash[dir].tuple.src.u3, | 352 | if (memcmp(&ct->tuplehash[dir].tuple.src.u3, |
@@ -366,14 +358,14 @@ static int expect_t120(struct sk_buff **pskb, | |||
366 | ret = nat_t120(pskb, ct, ctinfo, data, dataoff, taddr, | 358 | ret = nat_t120(pskb, ct, ctinfo, data, dataoff, taddr, |
367 | port, exp); | 359 | port, exp); |
368 | } else { /* Conntrack only */ | 360 | } else { /* Conntrack only */ |
369 | if (nf_conntrack_expect_related(exp) == 0) { | 361 | if (nf_ct_expect_related(exp) == 0) { |
370 | DEBUGP("nf_ct_h323: expect T.120 "); | 362 | pr_debug("nf_ct_h323: expect T.120 "); |
371 | NF_CT_DUMP_TUPLE(&exp->tuple); | 363 | NF_CT_DUMP_TUPLE(&exp->tuple); |
372 | } else | 364 | } else |
373 | ret = -1; | 365 | ret = -1; |
374 | } | 366 | } |
375 | 367 | ||
376 | nf_conntrack_expect_put(exp); | 368 | nf_ct_expect_put(exp); |
377 | 369 | ||
378 | return ret; | 370 | return ret; |
379 | } | 371 | } |
@@ -415,7 +407,7 @@ static int process_olc(struct sk_buff **pskb, struct nf_conn *ct, | |||
415 | { | 407 | { |
416 | int ret; | 408 | int ret; |
417 | 409 | ||
418 | DEBUGP("nf_ct_h323: OpenLogicalChannel\n"); | 410 | pr_debug("nf_ct_h323: OpenLogicalChannel\n"); |
419 | 411 | ||
420 | if (olc->forwardLogicalChannelParameters.multiplexParameters.choice == | 412 | if (olc->forwardLogicalChannelParameters.multiplexParameters.choice == |
421 | eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters) | 413 | eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters) |
@@ -475,7 +467,7 @@ static int process_olca(struct sk_buff **pskb, struct nf_conn *ct, | |||
475 | H2250LogicalChannelAckParameters *ack; | 467 | H2250LogicalChannelAckParameters *ack; |
476 | int ret; | 468 | int ret; |
477 | 469 | ||
478 | DEBUGP("nf_ct_h323: OpenLogicalChannelAck\n"); | 470 | pr_debug("nf_ct_h323: OpenLogicalChannelAck\n"); |
479 | 471 | ||
480 | if ((olca->options & | 472 | if ((olca->options & |
481 | eOpenLogicalChannelAck_reverseLogicalChannelParameters) && | 473 | eOpenLogicalChannelAck_reverseLogicalChannelParameters) && |
@@ -546,8 +538,8 @@ static int process_h245(struct sk_buff **pskb, struct nf_conn *ct, | |||
546 | return process_olc(pskb, ct, ctinfo, data, dataoff, | 538 | return process_olc(pskb, ct, ctinfo, data, dataoff, |
547 | &mscm->request.openLogicalChannel); | 539 | &mscm->request.openLogicalChannel); |
548 | } | 540 | } |
549 | DEBUGP("nf_ct_h323: H.245 Request %d\n", | 541 | pr_debug("nf_ct_h323: H.245 Request %d\n", |
550 | mscm->request.choice); | 542 | mscm->request.choice); |
551 | break; | 543 | break; |
552 | case eMultimediaSystemControlMessage_response: | 544 | case eMultimediaSystemControlMessage_response: |
553 | if (mscm->response.choice == | 545 | if (mscm->response.choice == |
@@ -556,11 +548,11 @@ static int process_h245(struct sk_buff **pskb, struct nf_conn *ct, | |||
556 | &mscm->response. | 548 | &mscm->response. |
557 | openLogicalChannelAck); | 549 | openLogicalChannelAck); |
558 | } | 550 | } |
559 | DEBUGP("nf_ct_h323: H.245 Response %d\n", | 551 | pr_debug("nf_ct_h323: H.245 Response %d\n", |
560 | mscm->response.choice); | 552 | mscm->response.choice); |
561 | break; | 553 | break; |
562 | default: | 554 | default: |
563 | DEBUGP("nf_ct_h323: H.245 signal %d\n", mscm->choice); | 555 | pr_debug("nf_ct_h323: H.245 signal %d\n", mscm->choice); |
564 | break; | 556 | break; |
565 | } | 557 | } |
566 | 558 | ||
@@ -582,24 +574,23 @@ static int h245_help(struct sk_buff **pskb, unsigned int protoff, | |||
582 | ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { | 574 | ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { |
583 | return NF_ACCEPT; | 575 | return NF_ACCEPT; |
584 | } | 576 | } |
585 | DEBUGP("nf_ct_h245: skblen = %u\n", (*pskb)->len); | 577 | pr_debug("nf_ct_h245: skblen = %u\n", (*pskb)->len); |
586 | 578 | ||
587 | spin_lock_bh(&nf_h323_lock); | 579 | spin_lock_bh(&nf_h323_lock); |
588 | 580 | ||
589 | /* Process each TPKT */ | 581 | /* Process each TPKT */ |
590 | while (get_tpkt_data(pskb, protoff, ct, ctinfo, | 582 | while (get_tpkt_data(pskb, protoff, ct, ctinfo, |
591 | &data, &datalen, &dataoff)) { | 583 | &data, &datalen, &dataoff)) { |
592 | DEBUGP("nf_ct_h245: TPKT len=%d ", datalen); | 584 | pr_debug("nf_ct_h245: TPKT len=%d ", datalen); |
593 | NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple); | 585 | NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple); |
594 | 586 | ||
595 | /* Decode H.245 signal */ | 587 | /* Decode H.245 signal */ |
596 | ret = DecodeMultimediaSystemControlMessage(data, datalen, | 588 | ret = DecodeMultimediaSystemControlMessage(data, datalen, |
597 | &mscm); | 589 | &mscm); |
598 | if (ret < 0) { | 590 | if (ret < 0) { |
599 | if (net_ratelimit()) | 591 | pr_debug("nf_ct_h245: decoding error: %s\n", |
600 | printk("nf_ct_h245: decoding error: %s\n", | 592 | ret == H323_ERROR_BOUND ? |
601 | ret == H323_ERROR_BOUND ? | 593 | "out of bound" : "out of range"); |
602 | "out of bound" : "out of range"); | ||
603 | /* We don't drop when decoding error */ | 594 | /* We don't drop when decoding error */ |
604 | break; | 595 | break; |
605 | } | 596 | } |
@@ -626,8 +617,6 @@ static struct nf_conntrack_helper nf_conntrack_helper_h245 __read_mostly = { | |||
626 | .max_expected = H323_RTP_CHANNEL_MAX * 4 + 2 /* T.120 */, | 617 | .max_expected = H323_RTP_CHANNEL_MAX * 4 + 2 /* T.120 */, |
627 | .timeout = 240, | 618 | .timeout = 240, |
628 | .tuple.dst.protonum = IPPROTO_UDP, | 619 | .tuple.dst.protonum = IPPROTO_UDP, |
629 | .mask.src.u.udp.port = __constant_htons(0xFFFF), | ||
630 | .mask.dst.protonum = 0xFF, | ||
631 | .help = h245_help | 620 | .help = h245_help |
632 | }; | 621 | }; |
633 | 622 | ||
@@ -684,12 +673,12 @@ static int expect_h245(struct sk_buff **pskb, struct nf_conn *ct, | |||
684 | return 0; | 673 | return 0; |
685 | 674 | ||
686 | /* Create expect for h245 connection */ | 675 | /* Create expect for h245 connection */ |
687 | if ((exp = nf_conntrack_expect_alloc(ct)) == NULL) | 676 | if ((exp = nf_ct_expect_alloc(ct)) == NULL) |
688 | return -1; | 677 | return -1; |
689 | nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, | 678 | nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, |
690 | &ct->tuplehash[!dir].tuple.src.u3, | 679 | &ct->tuplehash[!dir].tuple.src.u3, |
691 | &ct->tuplehash[!dir].tuple.dst.u3, | 680 | &ct->tuplehash[!dir].tuple.dst.u3, |
692 | IPPROTO_TCP, NULL, &port); | 681 | IPPROTO_TCP, NULL, &port); |
693 | exp->helper = &nf_conntrack_helper_h245; | 682 | exp->helper = &nf_conntrack_helper_h245; |
694 | 683 | ||
695 | if (memcmp(&ct->tuplehash[dir].tuple.src.u3, | 684 | if (memcmp(&ct->tuplehash[dir].tuple.src.u3, |
@@ -701,14 +690,14 @@ static int expect_h245(struct sk_buff **pskb, struct nf_conn *ct, | |||
701 | ret = nat_h245(pskb, ct, ctinfo, data, dataoff, taddr, | 690 | ret = nat_h245(pskb, ct, ctinfo, data, dataoff, taddr, |
702 | port, exp); | 691 | port, exp); |
703 | } else { /* Conntrack only */ | 692 | } else { /* Conntrack only */ |
704 | if (nf_conntrack_expect_related(exp) == 0) { | 693 | if (nf_ct_expect_related(exp) == 0) { |
705 | DEBUGP("nf_ct_q931: expect H.245 "); | 694 | pr_debug("nf_ct_q931: expect H.245 "); |
706 | NF_CT_DUMP_TUPLE(&exp->tuple); | 695 | NF_CT_DUMP_TUPLE(&exp->tuple); |
707 | } else | 696 | } else |
708 | ret = -1; | 697 | ret = -1; |
709 | } | 698 | } |
710 | 699 | ||
711 | nf_conntrack_expect_put(exp); | 700 | nf_ct_expect_put(exp); |
712 | 701 | ||
713 | return ret; | 702 | return ret; |
714 | } | 703 | } |
@@ -791,16 +780,16 @@ static int expect_callforwarding(struct sk_buff **pskb, | |||
791 | if (callforward_filter && | 780 | if (callforward_filter && |
792 | callforward_do_filter(&addr, &ct->tuplehash[!dir].tuple.src.u3, | 781 | callforward_do_filter(&addr, &ct->tuplehash[!dir].tuple.src.u3, |
793 | ct->tuplehash[!dir].tuple.src.l3num)) { | 782 | ct->tuplehash[!dir].tuple.src.l3num)) { |
794 | DEBUGP("nf_ct_q931: Call Forwarding not tracked\n"); | 783 | pr_debug("nf_ct_q931: Call Forwarding not tracked\n"); |
795 | return 0; | 784 | return 0; |
796 | } | 785 | } |
797 | 786 | ||
798 | /* Create expect for the second call leg */ | 787 | /* Create expect for the second call leg */ |
799 | if ((exp = nf_conntrack_expect_alloc(ct)) == NULL) | 788 | if ((exp = nf_ct_expect_alloc(ct)) == NULL) |
800 | return -1; | 789 | return -1; |
801 | nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, | 790 | nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, |
802 | &ct->tuplehash[!dir].tuple.src.u3, &addr, | 791 | &ct->tuplehash[!dir].tuple.src.u3, &addr, |
803 | IPPROTO_TCP, NULL, &port); | 792 | IPPROTO_TCP, NULL, &port); |
804 | exp->helper = nf_conntrack_helper_q931; | 793 | exp->helper = nf_conntrack_helper_q931; |
805 | 794 | ||
806 | if (memcmp(&ct->tuplehash[dir].tuple.src.u3, | 795 | if (memcmp(&ct->tuplehash[dir].tuple.src.u3, |
@@ -812,14 +801,14 @@ static int expect_callforwarding(struct sk_buff **pskb, | |||
812 | ret = nat_callforwarding(pskb, ct, ctinfo, data, dataoff, | 801 | ret = nat_callforwarding(pskb, ct, ctinfo, data, dataoff, |
813 | taddr, port, exp); | 802 | taddr, port, exp); |
814 | } else { /* Conntrack only */ | 803 | } else { /* Conntrack only */ |
815 | if (nf_conntrack_expect_related(exp) == 0) { | 804 | if (nf_ct_expect_related(exp) == 0) { |
816 | DEBUGP("nf_ct_q931: expect Call Forwarding "); | 805 | pr_debug("nf_ct_q931: expect Call Forwarding "); |
817 | NF_CT_DUMP_TUPLE(&exp->tuple); | 806 | NF_CT_DUMP_TUPLE(&exp->tuple); |
818 | } else | 807 | } else |
819 | ret = -1; | 808 | ret = -1; |
820 | } | 809 | } |
821 | 810 | ||
822 | nf_conntrack_expect_put(exp); | 811 | nf_ct_expect_put(exp); |
823 | 812 | ||
824 | return ret; | 813 | return ret; |
825 | } | 814 | } |
@@ -837,7 +826,7 @@ static int process_setup(struct sk_buff **pskb, struct nf_conn *ct, | |||
837 | union nf_conntrack_address addr; | 826 | union nf_conntrack_address addr; |
838 | typeof(set_h225_addr_hook) set_h225_addr; | 827 | typeof(set_h225_addr_hook) set_h225_addr; |
839 | 828 | ||
840 | DEBUGP("nf_ct_q931: Setup\n"); | 829 | pr_debug("nf_ct_q931: Setup\n"); |
841 | 830 | ||
842 | if (setup->options & eSetup_UUIE_h245Address) { | 831 | if (setup->options & eSetup_UUIE_h245Address) { |
843 | ret = expect_h245(pskb, ct, ctinfo, data, dataoff, | 832 | ret = expect_h245(pskb, ct, ctinfo, data, dataoff, |
@@ -852,11 +841,11 @@ static int process_setup(struct sk_buff **pskb, struct nf_conn *ct, | |||
852 | get_h225_addr(ct, *data, &setup->destCallSignalAddress, | 841 | get_h225_addr(ct, *data, &setup->destCallSignalAddress, |
853 | &addr, &port) && | 842 | &addr, &port) && |
854 | memcmp(&addr, &ct->tuplehash[!dir].tuple.src.u3, sizeof(addr))) { | 843 | memcmp(&addr, &ct->tuplehash[!dir].tuple.src.u3, sizeof(addr))) { |
855 | DEBUGP("nf_ct_q931: set destCallSignalAddress " | 844 | pr_debug("nf_ct_q931: set destCallSignalAddress " |
856 | NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n", | 845 | NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n", |
857 | NIP6(*(struct in6_addr *)&addr), ntohs(port), | 846 | NIP6(*(struct in6_addr *)&addr), ntohs(port), |
858 | NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.src.u3), | 847 | NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.src.u3), |
859 | ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port)); | 848 | ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port)); |
860 | ret = set_h225_addr(pskb, data, dataoff, | 849 | ret = set_h225_addr(pskb, data, dataoff, |
861 | &setup->destCallSignalAddress, | 850 | &setup->destCallSignalAddress, |
862 | &ct->tuplehash[!dir].tuple.src.u3, | 851 | &ct->tuplehash[!dir].tuple.src.u3, |
@@ -870,11 +859,11 @@ static int process_setup(struct sk_buff **pskb, struct nf_conn *ct, | |||
870 | get_h225_addr(ct, *data, &setup->sourceCallSignalAddress, | 859 | get_h225_addr(ct, *data, &setup->sourceCallSignalAddress, |
871 | &addr, &port) && | 860 | &addr, &port) && |
872 | memcmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3, sizeof(addr))) { | 861 | memcmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3, sizeof(addr))) { |
873 | DEBUGP("nf_ct_q931: set sourceCallSignalAddress " | 862 | pr_debug("nf_ct_q931: set sourceCallSignalAddress " |
874 | NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n", | 863 | NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n", |
875 | NIP6(*(struct in6_addr *)&addr), ntohs(port), | 864 | NIP6(*(struct in6_addr *)&addr), ntohs(port), |
876 | NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.dst.u3), | 865 | NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.dst.u3), |
877 | ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port)); | 866 | ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port)); |
878 | ret = set_h225_addr(pskb, data, dataoff, | 867 | ret = set_h225_addr(pskb, data, dataoff, |
879 | &setup->sourceCallSignalAddress, | 868 | &setup->sourceCallSignalAddress, |
880 | &ct->tuplehash[!dir].tuple.dst.u3, | 869 | &ct->tuplehash[!dir].tuple.dst.u3, |
@@ -905,7 +894,7 @@ static int process_callproceeding(struct sk_buff **pskb, | |||
905 | int ret; | 894 | int ret; |
906 | int i; | 895 | int i; |
907 | 896 | ||
908 | DEBUGP("nf_ct_q931: CallProceeding\n"); | 897 | pr_debug("nf_ct_q931: CallProceeding\n"); |
909 | 898 | ||
910 | if (callproc->options & eCallProceeding_UUIE_h245Address) { | 899 | if (callproc->options & eCallProceeding_UUIE_h245Address) { |
911 | ret = expect_h245(pskb, ct, ctinfo, data, dataoff, | 900 | ret = expect_h245(pskb, ct, ctinfo, data, dataoff, |
@@ -935,7 +924,7 @@ static int process_connect(struct sk_buff **pskb, struct nf_conn *ct, | |||
935 | int ret; | 924 | int ret; |
936 | int i; | 925 | int i; |
937 | 926 | ||
938 | DEBUGP("nf_ct_q931: Connect\n"); | 927 | pr_debug("nf_ct_q931: Connect\n"); |
939 | 928 | ||
940 | if (connect->options & eConnect_UUIE_h245Address) { | 929 | if (connect->options & eConnect_UUIE_h245Address) { |
941 | ret = expect_h245(pskb, ct, ctinfo, data, dataoff, | 930 | ret = expect_h245(pskb, ct, ctinfo, data, dataoff, |
@@ -965,7 +954,7 @@ static int process_alerting(struct sk_buff **pskb, struct nf_conn *ct, | |||
965 | int ret; | 954 | int ret; |
966 | int i; | 955 | int i; |
967 | 956 | ||
968 | DEBUGP("nf_ct_q931: Alerting\n"); | 957 | pr_debug("nf_ct_q931: Alerting\n"); |
969 | 958 | ||
970 | if (alert->options & eAlerting_UUIE_h245Address) { | 959 | if (alert->options & eAlerting_UUIE_h245Address) { |
971 | ret = expect_h245(pskb, ct, ctinfo, data, dataoff, | 960 | ret = expect_h245(pskb, ct, ctinfo, data, dataoff, |
@@ -995,7 +984,7 @@ static int process_facility(struct sk_buff **pskb, struct nf_conn *ct, | |||
995 | int ret; | 984 | int ret; |
996 | int i; | 985 | int i; |
997 | 986 | ||
998 | DEBUGP("nf_ct_q931: Facility\n"); | 987 | pr_debug("nf_ct_q931: Facility\n"); |
999 | 988 | ||
1000 | if (facility->reason.choice == eFacilityReason_callForwarded) { | 989 | if (facility->reason.choice == eFacilityReason_callForwarded) { |
1001 | if (facility->options & eFacility_UUIE_alternativeAddress) | 990 | if (facility->options & eFacility_UUIE_alternativeAddress) |
@@ -1034,7 +1023,7 @@ static int process_progress(struct sk_buff **pskb, struct nf_conn *ct, | |||
1034 | int ret; | 1023 | int ret; |
1035 | int i; | 1024 | int i; |
1036 | 1025 | ||
1037 | DEBUGP("nf_ct_q931: Progress\n"); | 1026 | pr_debug("nf_ct_q931: Progress\n"); |
1038 | 1027 | ||
1039 | if (progress->options & eProgress_UUIE_h245Address) { | 1028 | if (progress->options & eProgress_UUIE_h245Address) { |
1040 | ret = expect_h245(pskb, ct, ctinfo, data, dataoff, | 1029 | ret = expect_h245(pskb, ct, ctinfo, data, dataoff, |
@@ -1091,8 +1080,8 @@ static int process_q931(struct sk_buff **pskb, struct nf_conn *ct, | |||
1091 | &pdu->h323_message_body.progress); | 1080 | &pdu->h323_message_body.progress); |
1092 | break; | 1081 | break; |
1093 | default: | 1082 | default: |
1094 | DEBUGP("nf_ct_q931: Q.931 signal %d\n", | 1083 | pr_debug("nf_ct_q931: Q.931 signal %d\n", |
1095 | pdu->h323_message_body.choice); | 1084 | pdu->h323_message_body.choice); |
1096 | break; | 1085 | break; |
1097 | } | 1086 | } |
1098 | 1087 | ||
@@ -1126,23 +1115,22 @@ static int q931_help(struct sk_buff **pskb, unsigned int protoff, | |||
1126 | ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { | 1115 | ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { |
1127 | return NF_ACCEPT; | 1116 | return NF_ACCEPT; |
1128 | } | 1117 | } |
1129 | DEBUGP("nf_ct_q931: skblen = %u\n", (*pskb)->len); | 1118 | pr_debug("nf_ct_q931: skblen = %u\n", (*pskb)->len); |
1130 | 1119 | ||
1131 | spin_lock_bh(&nf_h323_lock); | 1120 | spin_lock_bh(&nf_h323_lock); |
1132 | 1121 | ||
1133 | /* Process each TPKT */ | 1122 | /* Process each TPKT */ |
1134 | while (get_tpkt_data(pskb, protoff, ct, ctinfo, | 1123 | while (get_tpkt_data(pskb, protoff, ct, ctinfo, |
1135 | &data, &datalen, &dataoff)) { | 1124 | &data, &datalen, &dataoff)) { |
1136 | DEBUGP("nf_ct_q931: TPKT len=%d ", datalen); | 1125 | pr_debug("nf_ct_q931: TPKT len=%d ", datalen); |
1137 | NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple); | 1126 | NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple); |
1138 | 1127 | ||
1139 | /* Decode Q.931 signal */ | 1128 | /* Decode Q.931 signal */ |
1140 | ret = DecodeQ931(data, datalen, &q931); | 1129 | ret = DecodeQ931(data, datalen, &q931); |
1141 | if (ret < 0) { | 1130 | if (ret < 0) { |
1142 | if (net_ratelimit()) | 1131 | pr_debug("nf_ct_q931: decoding error: %s\n", |
1143 | printk("nf_ct_q931: decoding error: %s\n", | 1132 | ret == H323_ERROR_BOUND ? |
1144 | ret == H323_ERROR_BOUND ? | 1133 | "out of bound" : "out of range"); |
1145 | "out of bound" : "out of range"); | ||
1146 | /* We don't drop when decoding error */ | 1134 | /* We don't drop when decoding error */ |
1147 | break; | 1135 | break; |
1148 | } | 1136 | } |
@@ -1173,9 +1161,6 @@ static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = { | |||
1173 | .tuple.src.l3num = AF_INET, | 1161 | .tuple.src.l3num = AF_INET, |
1174 | .tuple.src.u.tcp.port = __constant_htons(Q931_PORT), | 1162 | .tuple.src.u.tcp.port = __constant_htons(Q931_PORT), |
1175 | .tuple.dst.protonum = IPPROTO_TCP, | 1163 | .tuple.dst.protonum = IPPROTO_TCP, |
1176 | .mask.src.l3num = 0xFFFF, | ||
1177 | .mask.src.u.tcp.port = __constant_htons(0xFFFF), | ||
1178 | .mask.dst.protonum = 0xFF, | ||
1179 | .help = q931_help | 1164 | .help = q931_help |
1180 | }, | 1165 | }, |
1181 | { | 1166 | { |
@@ -1187,9 +1172,6 @@ static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = { | |||
1187 | .tuple.src.l3num = AF_INET6, | 1172 | .tuple.src.l3num = AF_INET6, |
1188 | .tuple.src.u.tcp.port = __constant_htons(Q931_PORT), | 1173 | .tuple.src.u.tcp.port = __constant_htons(Q931_PORT), |
1189 | .tuple.dst.protonum = IPPROTO_TCP, | 1174 | .tuple.dst.protonum = IPPROTO_TCP, |
1190 | .mask.src.l3num = 0xFFFF, | ||
1191 | .mask.src.u.tcp.port = __constant_htons(0xFFFF), | ||
1192 | .mask.dst.protonum = 0xFF, | ||
1193 | .help = q931_help | 1175 | .help = q931_help |
1194 | }, | 1176 | }, |
1195 | }; | 1177 | }; |
@@ -1225,7 +1207,7 @@ static struct nf_conntrack_expect *find_expect(struct nf_conn *ct, | |||
1225 | tuple.dst.u.tcp.port = port; | 1207 | tuple.dst.u.tcp.port = port; |
1226 | tuple.dst.protonum = IPPROTO_TCP; | 1208 | tuple.dst.protonum = IPPROTO_TCP; |
1227 | 1209 | ||
1228 | exp = __nf_conntrack_expect_find(&tuple); | 1210 | exp = __nf_ct_expect_find(&tuple); |
1229 | if (exp && exp->master == ct) | 1211 | if (exp && exp->master == ct) |
1230 | return exp; | 1212 | return exp; |
1231 | return NULL; | 1213 | return NULL; |
@@ -1271,14 +1253,13 @@ static int expect_q931(struct sk_buff **pskb, struct nf_conn *ct, | |||
1271 | return 0; | 1253 | return 0; |
1272 | 1254 | ||
1273 | /* Create expect for Q.931 */ | 1255 | /* Create expect for Q.931 */ |
1274 | if ((exp = nf_conntrack_expect_alloc(ct)) == NULL) | 1256 | if ((exp = nf_ct_expect_alloc(ct)) == NULL) |
1275 | return -1; | 1257 | return -1; |
1276 | nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, | 1258 | nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, |
1277 | gkrouted_only ? /* only accept calls from GK? */ | 1259 | gkrouted_only ? /* only accept calls from GK? */ |
1278 | &ct->tuplehash[!dir].tuple.src.u3 : | 1260 | &ct->tuplehash[!dir].tuple.src.u3 : NULL, |
1279 | NULL, | 1261 | &ct->tuplehash[!dir].tuple.dst.u3, |
1280 | &ct->tuplehash[!dir].tuple.dst.u3, | 1262 | IPPROTO_TCP, NULL, &port); |
1281 | IPPROTO_TCP, NULL, &port); | ||
1282 | exp->helper = nf_conntrack_helper_q931; | 1263 | exp->helper = nf_conntrack_helper_q931; |
1283 | exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple calls */ | 1264 | exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple calls */ |
1284 | 1265 | ||
@@ -1286,8 +1267,8 @@ static int expect_q931(struct sk_buff **pskb, struct nf_conn *ct, | |||
1286 | if (nat_q931 && ct->status & IPS_NAT_MASK) { /* Need NAT */ | 1267 | if (nat_q931 && ct->status & IPS_NAT_MASK) { /* Need NAT */ |
1287 | ret = nat_q931(pskb, ct, ctinfo, data, taddr, i, port, exp); | 1268 | ret = nat_q931(pskb, ct, ctinfo, data, taddr, i, port, exp); |
1288 | } else { /* Conntrack only */ | 1269 | } else { /* Conntrack only */ |
1289 | if (nf_conntrack_expect_related(exp) == 0) { | 1270 | if (nf_ct_expect_related(exp) == 0) { |
1290 | DEBUGP("nf_ct_ras: expect Q.931 "); | 1271 | pr_debug("nf_ct_ras: expect Q.931 "); |
1291 | NF_CT_DUMP_TUPLE(&exp->tuple); | 1272 | NF_CT_DUMP_TUPLE(&exp->tuple); |
1292 | 1273 | ||
1293 | /* Save port for looking up expect in processing RCF */ | 1274 | /* Save port for looking up expect in processing RCF */ |
@@ -1296,7 +1277,7 @@ static int expect_q931(struct sk_buff **pskb, struct nf_conn *ct, | |||
1296 | ret = -1; | 1277 | ret = -1; |
1297 | } | 1278 | } |
1298 | 1279 | ||
1299 | nf_conntrack_expect_put(exp); | 1280 | nf_ct_expect_put(exp); |
1300 | 1281 | ||
1301 | return ret; | 1282 | return ret; |
1302 | } | 1283 | } |
@@ -1308,7 +1289,7 @@ static int process_grq(struct sk_buff **pskb, struct nf_conn *ct, | |||
1308 | { | 1289 | { |
1309 | typeof(set_ras_addr_hook) set_ras_addr; | 1290 | typeof(set_ras_addr_hook) set_ras_addr; |
1310 | 1291 | ||
1311 | DEBUGP("nf_ct_ras: GRQ\n"); | 1292 | pr_debug("nf_ct_ras: GRQ\n"); |
1312 | 1293 | ||
1313 | set_ras_addr = rcu_dereference(set_ras_addr_hook); | 1294 | set_ras_addr = rcu_dereference(set_ras_addr_hook); |
1314 | if (set_ras_addr && ct->status & IPS_NAT_MASK) /* NATed */ | 1295 | if (set_ras_addr && ct->status & IPS_NAT_MASK) /* NATed */ |
@@ -1328,7 +1309,7 @@ static int process_gcf(struct sk_buff **pskb, struct nf_conn *ct, | |||
1328 | union nf_conntrack_address addr; | 1309 | union nf_conntrack_address addr; |
1329 | struct nf_conntrack_expect *exp; | 1310 | struct nf_conntrack_expect *exp; |
1330 | 1311 | ||
1331 | DEBUGP("nf_ct_ras: GCF\n"); | 1312 | pr_debug("nf_ct_ras: GCF\n"); |
1332 | 1313 | ||
1333 | if (!get_h225_addr(ct, *data, &gcf->rasAddress, &addr, &port)) | 1314 | if (!get_h225_addr(ct, *data, &gcf->rasAddress, &addr, &port)) |
1334 | return 0; | 1315 | return 0; |
@@ -1343,20 +1324,20 @@ static int process_gcf(struct sk_buff **pskb, struct nf_conn *ct, | |||
1343 | return 0; | 1324 | return 0; |
1344 | 1325 | ||
1345 | /* Need new expect */ | 1326 | /* Need new expect */ |
1346 | if ((exp = nf_conntrack_expect_alloc(ct)) == NULL) | 1327 | if ((exp = nf_ct_expect_alloc(ct)) == NULL) |
1347 | return -1; | 1328 | return -1; |
1348 | nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, | 1329 | nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, |
1349 | &ct->tuplehash[!dir].tuple.src.u3, &addr, | 1330 | &ct->tuplehash[!dir].tuple.src.u3, &addr, |
1350 | IPPROTO_UDP, NULL, &port); | 1331 | IPPROTO_UDP, NULL, &port); |
1351 | exp->helper = nf_conntrack_helper_ras; | 1332 | exp->helper = nf_conntrack_helper_ras; |
1352 | 1333 | ||
1353 | if (nf_conntrack_expect_related(exp) == 0) { | 1334 | if (nf_ct_expect_related(exp) == 0) { |
1354 | DEBUGP("nf_ct_ras: expect RAS "); | 1335 | pr_debug("nf_ct_ras: expect RAS "); |
1355 | NF_CT_DUMP_TUPLE(&exp->tuple); | 1336 | NF_CT_DUMP_TUPLE(&exp->tuple); |
1356 | } else | 1337 | } else |
1357 | ret = -1; | 1338 | ret = -1; |
1358 | 1339 | ||
1359 | nf_conntrack_expect_put(exp); | 1340 | nf_ct_expect_put(exp); |
1360 | 1341 | ||
1361 | return ret; | 1342 | return ret; |
1362 | } | 1343 | } |
@@ -1370,7 +1351,7 @@ static int process_rrq(struct sk_buff **pskb, struct nf_conn *ct, | |||
1370 | int ret; | 1351 | int ret; |
1371 | typeof(set_ras_addr_hook) set_ras_addr; | 1352 | typeof(set_ras_addr_hook) set_ras_addr; |
1372 | 1353 | ||
1373 | DEBUGP("nf_ct_ras: RRQ\n"); | 1354 | pr_debug("nf_ct_ras: RRQ\n"); |
1374 | 1355 | ||
1375 | ret = expect_q931(pskb, ct, ctinfo, data, | 1356 | ret = expect_q931(pskb, ct, ctinfo, data, |
1376 | rrq->callSignalAddress.item, | 1357 | rrq->callSignalAddress.item, |
@@ -1388,7 +1369,7 @@ static int process_rrq(struct sk_buff **pskb, struct nf_conn *ct, | |||
1388 | } | 1369 | } |
1389 | 1370 | ||
1390 | if (rrq->options & eRegistrationRequest_timeToLive) { | 1371 | if (rrq->options & eRegistrationRequest_timeToLive) { |
1391 | DEBUGP("nf_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive); | 1372 | pr_debug("nf_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive); |
1392 | info->timeout = rrq->timeToLive; | 1373 | info->timeout = rrq->timeToLive; |
1393 | } else | 1374 | } else |
1394 | info->timeout = default_rrq_ttl; | 1375 | info->timeout = default_rrq_ttl; |
@@ -1407,7 +1388,7 @@ static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct, | |||
1407 | struct nf_conntrack_expect *exp; | 1388 | struct nf_conntrack_expect *exp; |
1408 | typeof(set_sig_addr_hook) set_sig_addr; | 1389 | typeof(set_sig_addr_hook) set_sig_addr; |
1409 | 1390 | ||
1410 | DEBUGP("nf_ct_ras: RCF\n"); | 1391 | pr_debug("nf_ct_ras: RCF\n"); |
1411 | 1392 | ||
1412 | set_sig_addr = rcu_dereference(set_sig_addr_hook); | 1393 | set_sig_addr = rcu_dereference(set_sig_addr_hook); |
1413 | if (set_sig_addr && ct->status & IPS_NAT_MASK) { | 1394 | if (set_sig_addr && ct->status & IPS_NAT_MASK) { |
@@ -1419,14 +1400,13 @@ static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct, | |||
1419 | } | 1400 | } |
1420 | 1401 | ||
1421 | if (rcf->options & eRegistrationConfirm_timeToLive) { | 1402 | if (rcf->options & eRegistrationConfirm_timeToLive) { |
1422 | DEBUGP("nf_ct_ras: RCF TTL = %u seconds\n", rcf->timeToLive); | 1403 | pr_debug("nf_ct_ras: RCF TTL = %u seconds\n", rcf->timeToLive); |
1423 | info->timeout = rcf->timeToLive; | 1404 | info->timeout = rcf->timeToLive; |
1424 | } | 1405 | } |
1425 | 1406 | ||
1426 | if (info->timeout > 0) { | 1407 | if (info->timeout > 0) { |
1427 | DEBUGP | 1408 | pr_debug("nf_ct_ras: set RAS connection timeout to " |
1428 | ("nf_ct_ras: set RAS connection timeout to %u seconds\n", | 1409 | "%u seconds\n", info->timeout); |
1429 | info->timeout); | ||
1430 | nf_ct_refresh(ct, *pskb, info->timeout * HZ); | 1410 | nf_ct_refresh(ct, *pskb, info->timeout * HZ); |
1431 | 1411 | ||
1432 | /* Set expect timeout */ | 1412 | /* Set expect timeout */ |
@@ -1434,9 +1414,9 @@ static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct, | |||
1434 | exp = find_expect(ct, &ct->tuplehash[dir].tuple.dst.u3, | 1414 | exp = find_expect(ct, &ct->tuplehash[dir].tuple.dst.u3, |
1435 | info->sig_port[!dir]); | 1415 | info->sig_port[!dir]); |
1436 | if (exp) { | 1416 | if (exp) { |
1437 | DEBUGP("nf_ct_ras: set Q.931 expect " | 1417 | pr_debug("nf_ct_ras: set Q.931 expect " |
1438 | "timeout to %u seconds for", | 1418 | "timeout to %u seconds for", |
1439 | info->timeout); | 1419 | info->timeout); |
1440 | NF_CT_DUMP_TUPLE(&exp->tuple); | 1420 | NF_CT_DUMP_TUPLE(&exp->tuple); |
1441 | set_expect_timeout(exp, info->timeout); | 1421 | set_expect_timeout(exp, info->timeout); |
1442 | } | 1422 | } |
@@ -1456,7 +1436,7 @@ static int process_urq(struct sk_buff **pskb, struct nf_conn *ct, | |||
1456 | int ret; | 1436 | int ret; |
1457 | typeof(set_sig_addr_hook) set_sig_addr; | 1437 | typeof(set_sig_addr_hook) set_sig_addr; |
1458 | 1438 | ||
1459 | DEBUGP("nf_ct_ras: URQ\n"); | 1439 | pr_debug("nf_ct_ras: URQ\n"); |
1460 | 1440 | ||
1461 | set_sig_addr = rcu_dereference(set_sig_addr_hook); | 1441 | set_sig_addr = rcu_dereference(set_sig_addr_hook); |
1462 | if (set_sig_addr && ct->status & IPS_NAT_MASK) { | 1442 | if (set_sig_addr && ct->status & IPS_NAT_MASK) { |
@@ -1489,7 +1469,7 @@ static int process_arq(struct sk_buff **pskb, struct nf_conn *ct, | |||
1489 | union nf_conntrack_address addr; | 1469 | union nf_conntrack_address addr; |
1490 | typeof(set_h225_addr_hook) set_h225_addr; | 1470 | typeof(set_h225_addr_hook) set_h225_addr; |
1491 | 1471 | ||
1492 | DEBUGP("nf_ct_ras: ARQ\n"); | 1472 | pr_debug("nf_ct_ras: ARQ\n"); |
1493 | 1473 | ||
1494 | set_h225_addr = rcu_dereference(set_h225_addr_hook); | 1474 | set_h225_addr = rcu_dereference(set_h225_addr_hook); |
1495 | if ((arq->options & eAdmissionRequest_destCallSignalAddress) && | 1475 | if ((arq->options & eAdmissionRequest_destCallSignalAddress) && |
@@ -1532,7 +1512,7 @@ static int process_acf(struct sk_buff **pskb, struct nf_conn *ct, | |||
1532 | struct nf_conntrack_expect *exp; | 1512 | struct nf_conntrack_expect *exp; |
1533 | typeof(set_sig_addr_hook) set_sig_addr; | 1513 | typeof(set_sig_addr_hook) set_sig_addr; |
1534 | 1514 | ||
1535 | DEBUGP("nf_ct_ras: ACF\n"); | 1515 | pr_debug("nf_ct_ras: ACF\n"); |
1536 | 1516 | ||
1537 | if (!get_h225_addr(ct, *data, &acf->destCallSignalAddress, | 1517 | if (!get_h225_addr(ct, *data, &acf->destCallSignalAddress, |
1538 | &addr, &port)) | 1518 | &addr, &port)) |
@@ -1548,21 +1528,21 @@ static int process_acf(struct sk_buff **pskb, struct nf_conn *ct, | |||
1548 | } | 1528 | } |
1549 | 1529 | ||
1550 | /* Need new expect */ | 1530 | /* Need new expect */ |
1551 | if ((exp = nf_conntrack_expect_alloc(ct)) == NULL) | 1531 | if ((exp = nf_ct_expect_alloc(ct)) == NULL) |
1552 | return -1; | 1532 | return -1; |
1553 | nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, | 1533 | nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, |
1554 | &ct->tuplehash[!dir].tuple.src.u3, &addr, | 1534 | &ct->tuplehash[!dir].tuple.src.u3, &addr, |
1555 | IPPROTO_TCP, NULL, &port); | 1535 | IPPROTO_TCP, NULL, &port); |
1556 | exp->flags = NF_CT_EXPECT_PERMANENT; | 1536 | exp->flags = NF_CT_EXPECT_PERMANENT; |
1557 | exp->helper = nf_conntrack_helper_q931; | 1537 | exp->helper = nf_conntrack_helper_q931; |
1558 | 1538 | ||
1559 | if (nf_conntrack_expect_related(exp) == 0) { | 1539 | if (nf_ct_expect_related(exp) == 0) { |
1560 | DEBUGP("nf_ct_ras: expect Q.931 "); | 1540 | pr_debug("nf_ct_ras: expect Q.931 "); |
1561 | NF_CT_DUMP_TUPLE(&exp->tuple); | 1541 | NF_CT_DUMP_TUPLE(&exp->tuple); |
1562 | } else | 1542 | } else |
1563 | ret = -1; | 1543 | ret = -1; |
1564 | 1544 | ||
1565 | nf_conntrack_expect_put(exp); | 1545 | nf_ct_expect_put(exp); |
1566 | 1546 | ||
1567 | return ret; | 1547 | return ret; |
1568 | } | 1548 | } |
@@ -1574,7 +1554,7 @@ static int process_lrq(struct sk_buff **pskb, struct nf_conn *ct, | |||
1574 | { | 1554 | { |
1575 | typeof(set_ras_addr_hook) set_ras_addr; | 1555 | typeof(set_ras_addr_hook) set_ras_addr; |
1576 | 1556 | ||
1577 | DEBUGP("nf_ct_ras: LRQ\n"); | 1557 | pr_debug("nf_ct_ras: LRQ\n"); |
1578 | 1558 | ||
1579 | set_ras_addr = rcu_dereference(set_ras_addr_hook); | 1559 | set_ras_addr = rcu_dereference(set_ras_addr_hook); |
1580 | if (set_ras_addr && ct->status & IPS_NAT_MASK) | 1560 | if (set_ras_addr && ct->status & IPS_NAT_MASK) |
@@ -1594,28 +1574,28 @@ static int process_lcf(struct sk_buff **pskb, struct nf_conn *ct, | |||
1594 | union nf_conntrack_address addr; | 1574 | union nf_conntrack_address addr; |
1595 | struct nf_conntrack_expect *exp; | 1575 | struct nf_conntrack_expect *exp; |
1596 | 1576 | ||
1597 | DEBUGP("nf_ct_ras: LCF\n"); | 1577 | pr_debug("nf_ct_ras: LCF\n"); |
1598 | 1578 | ||
1599 | if (!get_h225_addr(ct, *data, &lcf->callSignalAddress, | 1579 | if (!get_h225_addr(ct, *data, &lcf->callSignalAddress, |
1600 | &addr, &port)) | 1580 | &addr, &port)) |
1601 | return 0; | 1581 | return 0; |
1602 | 1582 | ||
1603 | /* Need new expect for call signal */ | 1583 | /* Need new expect for call signal */ |
1604 | if ((exp = nf_conntrack_expect_alloc(ct)) == NULL) | 1584 | if ((exp = nf_ct_expect_alloc(ct)) == NULL) |
1605 | return -1; | 1585 | return -1; |
1606 | nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, | 1586 | nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, |
1607 | &ct->tuplehash[!dir].tuple.src.u3, &addr, | 1587 | &ct->tuplehash[!dir].tuple.src.u3, &addr, |
1608 | IPPROTO_TCP, NULL, &port); | 1588 | IPPROTO_TCP, NULL, &port); |
1609 | exp->flags = NF_CT_EXPECT_PERMANENT; | 1589 | exp->flags = NF_CT_EXPECT_PERMANENT; |
1610 | exp->helper = nf_conntrack_helper_q931; | 1590 | exp->helper = nf_conntrack_helper_q931; |
1611 | 1591 | ||
1612 | if (nf_conntrack_expect_related(exp) == 0) { | 1592 | if (nf_ct_expect_related(exp) == 0) { |
1613 | DEBUGP("nf_ct_ras: expect Q.931 "); | 1593 | pr_debug("nf_ct_ras: expect Q.931 "); |
1614 | NF_CT_DUMP_TUPLE(&exp->tuple); | 1594 | NF_CT_DUMP_TUPLE(&exp->tuple); |
1615 | } else | 1595 | } else |
1616 | ret = -1; | 1596 | ret = -1; |
1617 | 1597 | ||
1618 | nf_conntrack_expect_put(exp); | 1598 | nf_ct_expect_put(exp); |
1619 | 1599 | ||
1620 | /* Ignore rasAddress */ | 1600 | /* Ignore rasAddress */ |
1621 | 1601 | ||
@@ -1631,7 +1611,7 @@ static int process_irr(struct sk_buff **pskb, struct nf_conn *ct, | |||
1631 | typeof(set_ras_addr_hook) set_ras_addr; | 1611 | typeof(set_ras_addr_hook) set_ras_addr; |
1632 | typeof(set_sig_addr_hook) set_sig_addr; | 1612 | typeof(set_sig_addr_hook) set_sig_addr; |
1633 | 1613 | ||
1634 | DEBUGP("nf_ct_ras: IRR\n"); | 1614 | pr_debug("nf_ct_ras: IRR\n"); |
1635 | 1615 | ||
1636 | set_ras_addr = rcu_dereference(set_ras_addr_hook); | 1616 | set_ras_addr = rcu_dereference(set_ras_addr_hook); |
1637 | if (set_ras_addr && ct->status & IPS_NAT_MASK) { | 1617 | if (set_ras_addr && ct->status & IPS_NAT_MASK) { |
@@ -1690,7 +1670,7 @@ static int process_ras(struct sk_buff **pskb, struct nf_conn *ct, | |||
1690 | return process_irr(pskb, ct, ctinfo, data, | 1670 | return process_irr(pskb, ct, ctinfo, data, |
1691 | &ras->infoRequestResponse); | 1671 | &ras->infoRequestResponse); |
1692 | default: | 1672 | default: |
1693 | DEBUGP("nf_ct_ras: RAS message %d\n", ras->choice); | 1673 | pr_debug("nf_ct_ras: RAS message %d\n", ras->choice); |
1694 | break; | 1674 | break; |
1695 | } | 1675 | } |
1696 | 1676 | ||
@@ -1706,7 +1686,7 @@ static int ras_help(struct sk_buff **pskb, unsigned int protoff, | |||
1706 | int datalen = 0; | 1686 | int datalen = 0; |
1707 | int ret; | 1687 | int ret; |
1708 | 1688 | ||
1709 | DEBUGP("nf_ct_ras: skblen = %u\n", (*pskb)->len); | 1689 | pr_debug("nf_ct_ras: skblen = %u\n", (*pskb)->len); |
1710 | 1690 | ||
1711 | spin_lock_bh(&nf_h323_lock); | 1691 | spin_lock_bh(&nf_h323_lock); |
1712 | 1692 | ||
@@ -1714,16 +1694,15 @@ static int ras_help(struct sk_buff **pskb, unsigned int protoff, | |||
1714 | data = get_udp_data(pskb, protoff, &datalen); | 1694 | data = get_udp_data(pskb, protoff, &datalen); |
1715 | if (data == NULL) | 1695 | if (data == NULL) |
1716 | goto accept; | 1696 | goto accept; |
1717 | DEBUGP("nf_ct_ras: RAS message len=%d ", datalen); | 1697 | pr_debug("nf_ct_ras: RAS message len=%d ", datalen); |
1718 | NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple); | 1698 | NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple); |
1719 | 1699 | ||
1720 | /* Decode RAS message */ | 1700 | /* Decode RAS message */ |
1721 | ret = DecodeRasMessage(data, datalen, &ras); | 1701 | ret = DecodeRasMessage(data, datalen, &ras); |
1722 | if (ret < 0) { | 1702 | if (ret < 0) { |
1723 | if (net_ratelimit()) | 1703 | pr_debug("nf_ct_ras: decoding error: %s\n", |
1724 | printk("nf_ct_ras: decoding error: %s\n", | 1704 | ret == H323_ERROR_BOUND ? |
1725 | ret == H323_ERROR_BOUND ? | 1705 | "out of bound" : "out of range"); |
1726 | "out of bound" : "out of range"); | ||
1727 | goto accept; | 1706 | goto accept; |
1728 | } | 1707 | } |
1729 | 1708 | ||
@@ -1752,9 +1731,6 @@ static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = { | |||
1752 | .tuple.src.l3num = AF_INET, | 1731 | .tuple.src.l3num = AF_INET, |
1753 | .tuple.src.u.udp.port = __constant_htons(RAS_PORT), | 1732 | .tuple.src.u.udp.port = __constant_htons(RAS_PORT), |
1754 | .tuple.dst.protonum = IPPROTO_UDP, | 1733 | .tuple.dst.protonum = IPPROTO_UDP, |
1755 | .mask.src.l3num = 0xFFFF, | ||
1756 | .mask.src.u.udp.port = __constant_htons(0xFFFF), | ||
1757 | .mask.dst.protonum = 0xFF, | ||
1758 | .help = ras_help, | 1734 | .help = ras_help, |
1759 | }, | 1735 | }, |
1760 | { | 1736 | { |
@@ -1765,9 +1741,6 @@ static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = { | |||
1765 | .tuple.src.l3num = AF_INET6, | 1741 | .tuple.src.l3num = AF_INET6, |
1766 | .tuple.src.u.udp.port = __constant_htons(RAS_PORT), | 1742 | .tuple.src.u.udp.port = __constant_htons(RAS_PORT), |
1767 | .tuple.dst.protonum = IPPROTO_UDP, | 1743 | .tuple.dst.protonum = IPPROTO_UDP, |
1768 | .mask.src.l3num = 0xFFFF, | ||
1769 | .mask.src.u.udp.port = __constant_htons(0xFFFF), | ||
1770 | .mask.dst.protonum = 0xFF, | ||
1771 | .help = ras_help, | 1744 | .help = ras_help, |
1772 | }, | 1745 | }, |
1773 | }; | 1746 | }; |
@@ -1780,7 +1753,7 @@ static void __exit nf_conntrack_h323_fini(void) | |||
1780 | nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[1]); | 1753 | nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[1]); |
1781 | nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[0]); | 1754 | nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[0]); |
1782 | kfree(h323_buffer); | 1755 | kfree(h323_buffer); |
1783 | DEBUGP("nf_ct_h323: fini\n"); | 1756 | pr_debug("nf_ct_h323: fini\n"); |
1784 | } | 1757 | } |
1785 | 1758 | ||
1786 | /****************************************************************************/ | 1759 | /****************************************************************************/ |
@@ -1803,7 +1776,7 @@ static int __init nf_conntrack_h323_init(void) | |||
1803 | ret = nf_conntrack_helper_register(&nf_conntrack_helper_ras[1]); | 1776 | ret = nf_conntrack_helper_register(&nf_conntrack_helper_ras[1]); |
1804 | if (ret < 0) | 1777 | if (ret < 0) |
1805 | goto err4; | 1778 | goto err4; |
1806 | DEBUGP("nf_ct_h323: init success\n"); | 1779 | pr_debug("nf_ct_h323: init success\n"); |
1807 | return 0; | 1780 | return 0; |
1808 | 1781 | ||
1809 | err4: | 1782 | err4: |
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index f868b7fbd9b4..b1179dd3d8c3 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c | |||
@@ -26,23 +26,43 @@ | |||
26 | #include <net/netfilter/nf_conntrack_l4proto.h> | 26 | #include <net/netfilter/nf_conntrack_l4proto.h> |
27 | #include <net/netfilter/nf_conntrack_helper.h> | 27 | #include <net/netfilter/nf_conntrack_helper.h> |
28 | #include <net/netfilter/nf_conntrack_core.h> | 28 | #include <net/netfilter/nf_conntrack_core.h> |
29 | #include <net/netfilter/nf_conntrack_extend.h> | ||
29 | 30 | ||
30 | static __read_mostly LIST_HEAD(helpers); | 31 | static struct hlist_head *nf_ct_helper_hash __read_mostly; |
32 | static unsigned int nf_ct_helper_hsize __read_mostly; | ||
33 | static unsigned int nf_ct_helper_count __read_mostly; | ||
34 | static int nf_ct_helper_vmalloc; | ||
35 | |||
36 | |||
37 | /* Stupid hash, but collision free for the default registrations of the | ||
38 | * helpers currently in the kernel. */ | ||
39 | static unsigned int helper_hash(const struct nf_conntrack_tuple *tuple) | ||
40 | { | ||
41 | return (((tuple->src.l3num << 8) | tuple->dst.protonum) ^ | ||
42 | tuple->src.u.all) % nf_ct_helper_hsize; | ||
43 | } | ||
31 | 44 | ||
32 | struct nf_conntrack_helper * | 45 | struct nf_conntrack_helper * |
33 | __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple) | 46 | __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple) |
34 | { | 47 | { |
35 | struct nf_conntrack_helper *h; | 48 | struct nf_conntrack_helper *helper; |
49 | struct nf_conntrack_tuple_mask mask = { .src.u.all = htons(0xFFFF) }; | ||
50 | struct hlist_node *n; | ||
51 | unsigned int h; | ||
52 | |||
53 | if (!nf_ct_helper_count) | ||
54 | return NULL; | ||
36 | 55 | ||
37 | list_for_each_entry(h, &helpers, list) { | 56 | h = helper_hash(tuple); |
38 | if (nf_ct_tuple_mask_cmp(tuple, &h->tuple, &h->mask)) | 57 | hlist_for_each_entry(helper, n, &nf_ct_helper_hash[h], hnode) { |
39 | return h; | 58 | if (nf_ct_tuple_src_mask_cmp(tuple, &helper->tuple, &mask)) |
59 | return helper; | ||
40 | } | 60 | } |
41 | return NULL; | 61 | return NULL; |
42 | } | 62 | } |
43 | 63 | ||
44 | struct nf_conntrack_helper * | 64 | struct nf_conntrack_helper * |
45 | nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple) | 65 | nf_ct_helper_find_get(const struct nf_conntrack_tuple *tuple) |
46 | { | 66 | { |
47 | struct nf_conntrack_helper *helper; | 67 | struct nf_conntrack_helper *helper; |
48 | 68 | ||
@@ -75,16 +95,32 @@ struct nf_conntrack_helper * | |||
75 | __nf_conntrack_helper_find_byname(const char *name) | 95 | __nf_conntrack_helper_find_byname(const char *name) |
76 | { | 96 | { |
77 | struct nf_conntrack_helper *h; | 97 | struct nf_conntrack_helper *h; |
98 | struct hlist_node *n; | ||
99 | unsigned int i; | ||
78 | 100 | ||
79 | list_for_each_entry(h, &helpers, list) { | 101 | for (i = 0; i < nf_ct_helper_hsize; i++) { |
80 | if (!strcmp(h->name, name)) | 102 | hlist_for_each_entry(h, n, &nf_ct_helper_hash[i], hnode) { |
81 | return h; | 103 | if (!strcmp(h->name, name)) |
104 | return h; | ||
105 | } | ||
82 | } | 106 | } |
83 | |||
84 | return NULL; | 107 | return NULL; |
85 | } | 108 | } |
86 | EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find_byname); | 109 | EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find_byname); |
87 | 110 | ||
111 | struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp) | ||
112 | { | ||
113 | struct nf_conn_help *help; | ||
114 | |||
115 | help = nf_ct_ext_add(ct, NF_CT_EXT_HELPER, gfp); | ||
116 | if (help) | ||
117 | INIT_HLIST_HEAD(&help->expectations); | ||
118 | else | ||
119 | pr_debug("failed to add helper extension area"); | ||
120 | return help; | ||
121 | } | ||
122 | EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add); | ||
123 | |||
88 | static inline int unhelp(struct nf_conntrack_tuple_hash *i, | 124 | static inline int unhelp(struct nf_conntrack_tuple_hash *i, |
89 | const struct nf_conntrack_helper *me) | 125 | const struct nf_conntrack_helper *me) |
90 | { | 126 | { |
@@ -100,20 +136,13 @@ static inline int unhelp(struct nf_conntrack_tuple_hash *i, | |||
100 | 136 | ||
101 | int nf_conntrack_helper_register(struct nf_conntrack_helper *me) | 137 | int nf_conntrack_helper_register(struct nf_conntrack_helper *me) |
102 | { | 138 | { |
103 | int size, ret; | 139 | unsigned int h = helper_hash(&me->tuple); |
104 | 140 | ||
105 | BUG_ON(me->timeout == 0); | 141 | BUG_ON(me->timeout == 0); |
106 | 142 | ||
107 | size = ALIGN(sizeof(struct nf_conn), __alignof__(struct nf_conn_help)) + | ||
108 | sizeof(struct nf_conn_help); | ||
109 | ret = nf_conntrack_register_cache(NF_CT_F_HELP, "nf_conntrack:help", | ||
110 | size); | ||
111 | if (ret < 0) { | ||
112 | printk(KERN_ERR "nf_conntrack_helper_register: Unable to create slab cache for conntracks\n"); | ||
113 | return ret; | ||
114 | } | ||
115 | write_lock_bh(&nf_conntrack_lock); | 143 | write_lock_bh(&nf_conntrack_lock); |
116 | list_add(&me->list, &helpers); | 144 | hlist_add_head(&me->hnode, &nf_ct_helper_hash[h]); |
145 | nf_ct_helper_count++; | ||
117 | write_unlock_bh(&nf_conntrack_lock); | 146 | write_unlock_bh(&nf_conntrack_lock); |
118 | 147 | ||
119 | return 0; | 148 | return 0; |
@@ -122,29 +151,34 @@ EXPORT_SYMBOL_GPL(nf_conntrack_helper_register); | |||
122 | 151 | ||
123 | void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) | 152 | void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) |
124 | { | 153 | { |
125 | unsigned int i; | ||
126 | struct nf_conntrack_tuple_hash *h; | 154 | struct nf_conntrack_tuple_hash *h; |
127 | struct nf_conntrack_expect *exp, *tmp; | 155 | struct nf_conntrack_expect *exp; |
156 | struct hlist_node *n, *next; | ||
157 | unsigned int i; | ||
128 | 158 | ||
129 | /* Need write lock here, to delete helper. */ | 159 | /* Need write lock here, to delete helper. */ |
130 | write_lock_bh(&nf_conntrack_lock); | 160 | write_lock_bh(&nf_conntrack_lock); |
131 | list_del(&me->list); | 161 | hlist_del(&me->hnode); |
162 | nf_ct_helper_count--; | ||
132 | 163 | ||
133 | /* Get rid of expectations */ | 164 | /* Get rid of expectations */ |
134 | list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) { | 165 | for (i = 0; i < nf_ct_expect_hsize; i++) { |
135 | struct nf_conn_help *help = nfct_help(exp->master); | 166 | hlist_for_each_entry_safe(exp, n, next, |
136 | if ((help->helper == me || exp->helper == me) && | 167 | &nf_ct_expect_hash[i], hnode) { |
137 | del_timer(&exp->timeout)) { | 168 | struct nf_conn_help *help = nfct_help(exp->master); |
138 | nf_ct_unlink_expect(exp); | 169 | if ((help->helper == me || exp->helper == me) && |
139 | nf_conntrack_expect_put(exp); | 170 | del_timer(&exp->timeout)) { |
171 | nf_ct_unlink_expect(exp); | ||
172 | nf_ct_expect_put(exp); | ||
173 | } | ||
140 | } | 174 | } |
141 | } | 175 | } |
142 | 176 | ||
143 | /* Get rid of expecteds, set helpers to NULL. */ | 177 | /* Get rid of expecteds, set helpers to NULL. */ |
144 | list_for_each_entry(h, &unconfirmed, list) | 178 | hlist_for_each_entry(h, n, &unconfirmed, hnode) |
145 | unhelp(h, me); | 179 | unhelp(h, me); |
146 | for (i = 0; i < nf_conntrack_htable_size; i++) { | 180 | for (i = 0; i < nf_conntrack_htable_size; i++) { |
147 | list_for_each_entry(h, &nf_conntrack_hash[i], list) | 181 | hlist_for_each_entry(h, n, &nf_conntrack_hash[i], hnode) |
148 | unhelp(h, me); | 182 | unhelp(h, me); |
149 | } | 183 | } |
150 | write_unlock_bh(&nf_conntrack_lock); | 184 | write_unlock_bh(&nf_conntrack_lock); |
@@ -153,3 +187,38 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) | |||
153 | synchronize_net(); | 187 | synchronize_net(); |
154 | } | 188 | } |
155 | EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister); | 189 | EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister); |
190 | |||
191 | static struct nf_ct_ext_type helper_extend __read_mostly = { | ||
192 | .len = sizeof(struct nf_conn_help), | ||
193 | .align = __alignof__(struct nf_conn_help), | ||
194 | .id = NF_CT_EXT_HELPER, | ||
195 | }; | ||
196 | |||
197 | int nf_conntrack_helper_init() | ||
198 | { | ||
199 | int err; | ||
200 | |||
201 | nf_ct_helper_hsize = 1; /* gets rounded up to use one page */ | ||
202 | nf_ct_helper_hash = nf_ct_alloc_hashtable(&nf_ct_helper_hsize, | ||
203 | &nf_ct_helper_vmalloc); | ||
204 | if (!nf_ct_helper_hash) | ||
205 | return -ENOMEM; | ||
206 | |||
207 | err = nf_ct_extend_register(&helper_extend); | ||
208 | if (err < 0) | ||
209 | goto err1; | ||
210 | |||
211 | return 0; | ||
212 | |||
213 | err1: | ||
214 | nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_vmalloc, | ||
215 | nf_ct_helper_hsize); | ||
216 | return err; | ||
217 | } | ||
218 | |||
219 | void nf_conntrack_helper_fini() | ||
220 | { | ||
221 | nf_ct_extend_unregister(&helper_extend); | ||
222 | nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_vmalloc, | ||
223 | nf_ct_helper_hsize); | ||
224 | } | ||
diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c index 43ccd0e2e8ae..1562ca97a349 100644 --- a/net/netfilter/nf_conntrack_irc.c +++ b/net/netfilter/nf_conntrack_irc.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/moduleparam.h> | 12 | #include <linux/moduleparam.h> |
13 | #include <linux/skbuff.h> | 13 | #include <linux/skbuff.h> |
14 | #include <linux/in.h> | 14 | #include <linux/in.h> |
15 | #include <linux/ip.h> | ||
15 | #include <linux/tcp.h> | 16 | #include <linux/tcp.h> |
16 | #include <linux/netfilter.h> | 17 | #include <linux/netfilter.h> |
17 | 18 | ||
@@ -55,13 +56,6 @@ static const char *dccprotos[] = { | |||
55 | 56 | ||
56 | #define MINMATCHLEN 5 | 57 | #define MINMATCHLEN 5 |
57 | 58 | ||
58 | #if 0 | ||
59 | #define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s:" format, \ | ||
60 | __FILE__, __FUNCTION__ , ## args) | ||
61 | #else | ||
62 | #define DEBUGP(format, args...) | ||
63 | #endif | ||
64 | |||
65 | /* tries to get the ip_addr and port out of a dcc command | 59 | /* tries to get the ip_addr and port out of a dcc command |
66 | * return value: -1 on failure, 0 on success | 60 | * return value: -1 on failure, 0 on success |
67 | * data pointer to first byte of DCC command data | 61 | * data pointer to first byte of DCC command data |
@@ -99,6 +93,7 @@ static int help(struct sk_buff **pskb, unsigned int protoff, | |||
99 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) | 93 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) |
100 | { | 94 | { |
101 | unsigned int dataoff; | 95 | unsigned int dataoff; |
96 | struct iphdr *iph; | ||
102 | struct tcphdr _tcph, *th; | 97 | struct tcphdr _tcph, *th; |
103 | char *data, *data_limit, *ib_ptr; | 98 | char *data, *data_limit, *ib_ptr; |
104 | int dir = CTINFO2DIR(ctinfo); | 99 | int dir = CTINFO2DIR(ctinfo); |
@@ -148,9 +143,10 @@ static int help(struct sk_buff **pskb, unsigned int protoff, | |||
148 | data += 5; | 143 | data += 5; |
149 | /* we have at least (19+MINMATCHLEN)-5 bytes valid data left */ | 144 | /* we have at least (19+MINMATCHLEN)-5 bytes valid data left */ |
150 | 145 | ||
151 | DEBUGP("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u...\n", | 146 | iph = ip_hdr(*pskb); |
152 | NIPQUAD(iph->saddr), ntohs(th->source), | 147 | pr_debug("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u\n", |
153 | NIPQUAD(iph->daddr), ntohs(th->dest)); | 148 | NIPQUAD(iph->saddr), ntohs(th->source), |
149 | NIPQUAD(iph->daddr), ntohs(th->dest)); | ||
154 | 150 | ||
155 | for (i = 0; i < ARRAY_SIZE(dccprotos); i++) { | 151 | for (i = 0; i < ARRAY_SIZE(dccprotos); i++) { |
156 | if (memcmp(data, dccprotos[i], strlen(dccprotos[i]))) { | 152 | if (memcmp(data, dccprotos[i], strlen(dccprotos[i]))) { |
@@ -158,18 +154,18 @@ static int help(struct sk_buff **pskb, unsigned int protoff, | |||
158 | continue; | 154 | continue; |
159 | } | 155 | } |
160 | data += strlen(dccprotos[i]); | 156 | data += strlen(dccprotos[i]); |
161 | DEBUGP("DCC %s detected\n", dccprotos[i]); | 157 | pr_debug("DCC %s detected\n", dccprotos[i]); |
162 | 158 | ||
163 | /* we have at least | 159 | /* we have at least |
164 | * (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid | 160 | * (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid |
165 | * data left (== 14/13 bytes) */ | 161 | * data left (== 14/13 bytes) */ |
166 | if (parse_dcc((char *)data, data_limit, &dcc_ip, | 162 | if (parse_dcc((char *)data, data_limit, &dcc_ip, |
167 | &dcc_port, &addr_beg_p, &addr_end_p)) { | 163 | &dcc_port, &addr_beg_p, &addr_end_p)) { |
168 | DEBUGP("unable to parse dcc command\n"); | 164 | pr_debug("unable to parse dcc command\n"); |
169 | continue; | 165 | continue; |
170 | } | 166 | } |
171 | DEBUGP("DCC bound ip/port: %u.%u.%u.%u:%u\n", | 167 | pr_debug("DCC bound ip/port: %u.%u.%u.%u:%u\n", |
172 | HIPQUAD(dcc_ip), dcc_port); | 168 | HIPQUAD(dcc_ip), dcc_port); |
173 | 169 | ||
174 | /* dcc_ip can be the internal OR external (NAT'ed) IP */ | 170 | /* dcc_ip can be the internal OR external (NAT'ed) IP */ |
175 | tuple = &ct->tuplehash[dir].tuple; | 171 | tuple = &ct->tuplehash[dir].tuple; |
@@ -184,16 +180,16 @@ static int help(struct sk_buff **pskb, unsigned int protoff, | |||
184 | continue; | 180 | continue; |
185 | } | 181 | } |
186 | 182 | ||
187 | exp = nf_conntrack_expect_alloc(ct); | 183 | exp = nf_ct_expect_alloc(ct); |
188 | if (exp == NULL) { | 184 | if (exp == NULL) { |
189 | ret = NF_DROP; | 185 | ret = NF_DROP; |
190 | goto out; | 186 | goto out; |
191 | } | 187 | } |
192 | tuple = &ct->tuplehash[!dir].tuple; | 188 | tuple = &ct->tuplehash[!dir].tuple; |
193 | port = htons(dcc_port); | 189 | port = htons(dcc_port); |
194 | nf_conntrack_expect_init(exp, tuple->src.l3num, | 190 | nf_ct_expect_init(exp, tuple->src.l3num, |
195 | NULL, &tuple->dst.u3, | 191 | NULL, &tuple->dst.u3, |
196 | IPPROTO_TCP, NULL, &port); | 192 | IPPROTO_TCP, NULL, &port); |
197 | 193 | ||
198 | nf_nat_irc = rcu_dereference(nf_nat_irc_hook); | 194 | nf_nat_irc = rcu_dereference(nf_nat_irc_hook); |
199 | if (nf_nat_irc && ct->status & IPS_NAT_MASK) | 195 | if (nf_nat_irc && ct->status & IPS_NAT_MASK) |
@@ -201,9 +197,9 @@ static int help(struct sk_buff **pskb, unsigned int protoff, | |||
201 | addr_beg_p - ib_ptr, | 197 | addr_beg_p - ib_ptr, |
202 | addr_end_p - addr_beg_p, | 198 | addr_end_p - addr_beg_p, |
203 | exp); | 199 | exp); |
204 | else if (nf_conntrack_expect_related(exp) != 0) | 200 | else if (nf_ct_expect_related(exp) != 0) |
205 | ret = NF_DROP; | 201 | ret = NF_DROP; |
206 | nf_conntrack_expect_put(exp); | 202 | nf_ct_expect_put(exp); |
207 | goto out; | 203 | goto out; |
208 | } | 204 | } |
209 | } | 205 | } |
@@ -239,9 +235,6 @@ static int __init nf_conntrack_irc_init(void) | |||
239 | irc[i].tuple.src.l3num = AF_INET; | 235 | irc[i].tuple.src.l3num = AF_INET; |
240 | irc[i].tuple.src.u.tcp.port = htons(ports[i]); | 236 | irc[i].tuple.src.u.tcp.port = htons(ports[i]); |
241 | irc[i].tuple.dst.protonum = IPPROTO_TCP; | 237 | irc[i].tuple.dst.protonum = IPPROTO_TCP; |
242 | irc[i].mask.src.l3num = 0xFFFF; | ||
243 | irc[i].mask.src.u.tcp.port = htons(0xFFFF); | ||
244 | irc[i].mask.dst.protonum = 0xFF; | ||
245 | irc[i].max_expected = max_dcc_channels; | 238 | irc[i].max_expected = max_dcc_channels; |
246 | irc[i].timeout = dcc_timeout; | 239 | irc[i].timeout = dcc_timeout; |
247 | irc[i].me = THIS_MODULE; | 240 | irc[i].me = THIS_MODULE; |
diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c index cbd96f3c1b89..991c52c9a28b 100644 --- a/net/netfilter/nf_conntrack_l3proto_generic.c +++ b/net/netfilter/nf_conntrack_l3proto_generic.c | |||
@@ -31,12 +31,6 @@ | |||
31 | #include <net/netfilter/nf_conntrack_core.h> | 31 | #include <net/netfilter/nf_conntrack_core.h> |
32 | #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> | 32 | #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> |
33 | 33 | ||
34 | #if 0 | ||
35 | #define DEBUGP printk | ||
36 | #else | ||
37 | #define DEBUGP(format, args...) | ||
38 | #endif | ||
39 | |||
40 | static int generic_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, | 34 | static int generic_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, |
41 | struct nf_conntrack_tuple *tuple) | 35 | struct nf_conntrack_tuple *tuple) |
42 | { | 36 | { |
@@ -67,29 +61,21 @@ static int generic_print_conntrack(struct seq_file *s, | |||
67 | return 0; | 61 | return 0; |
68 | } | 62 | } |
69 | 63 | ||
70 | static int | 64 | static int generic_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, |
71 | generic_prepare(struct sk_buff **pskb, unsigned int hooknum, | 65 | unsigned int *dataoff, u_int8_t *protonum) |
72 | unsigned int *dataoff, u_int8_t *protonum) | ||
73 | { | 66 | { |
74 | /* Never track !!! */ | 67 | /* Never track !!! */ |
75 | return -NF_ACCEPT; | 68 | return -NF_ACCEPT; |
76 | } | 69 | } |
77 | 70 | ||
78 | 71 | ||
79 | static u_int32_t generic_get_features(const struct nf_conntrack_tuple *tuple) | 72 | struct nf_conntrack_l3proto nf_conntrack_l3proto_generic __read_mostly = { |
80 | |||
81 | { | ||
82 | return NF_CT_F_BASIC; | ||
83 | } | ||
84 | |||
85 | struct nf_conntrack_l3proto nf_conntrack_l3proto_generic = { | ||
86 | .l3proto = PF_UNSPEC, | 73 | .l3proto = PF_UNSPEC, |
87 | .name = "unknown", | 74 | .name = "unknown", |
88 | .pkt_to_tuple = generic_pkt_to_tuple, | 75 | .pkt_to_tuple = generic_pkt_to_tuple, |
89 | .invert_tuple = generic_invert_tuple, | 76 | .invert_tuple = generic_invert_tuple, |
90 | .print_tuple = generic_print_tuple, | 77 | .print_tuple = generic_print_tuple, |
91 | .print_conntrack = generic_print_conntrack, | 78 | .print_conntrack = generic_print_conntrack, |
92 | .prepare = generic_prepare, | 79 | .get_l4proto = generic_get_l4proto, |
93 | .get_features = generic_get_features, | ||
94 | }; | 80 | }; |
95 | EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_generic); | 81 | EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_generic); |
diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c index 1093478cc007..1d59fabeb5f7 100644 --- a/net/netfilter/nf_conntrack_netbios_ns.c +++ b/net/netfilter/nf_conntrack_netbios_ns.c | |||
@@ -74,7 +74,7 @@ static int help(struct sk_buff **pskb, unsigned int protoff, | |||
74 | if (mask == 0) | 74 | if (mask == 0) |
75 | goto out; | 75 | goto out; |
76 | 76 | ||
77 | exp = nf_conntrack_expect_alloc(ct); | 77 | exp = nf_ct_expect_alloc(ct); |
78 | if (exp == NULL) | 78 | if (exp == NULL) |
79 | goto out; | 79 | goto out; |
80 | 80 | ||
@@ -83,16 +83,13 @@ static int help(struct sk_buff **pskb, unsigned int protoff, | |||
83 | 83 | ||
84 | exp->mask.src.u3.ip = mask; | 84 | exp->mask.src.u3.ip = mask; |
85 | exp->mask.src.u.udp.port = htons(0xFFFF); | 85 | exp->mask.src.u.udp.port = htons(0xFFFF); |
86 | exp->mask.dst.u3.ip = htonl(0xFFFFFFFF); | ||
87 | exp->mask.dst.u.udp.port = htons(0xFFFF); | ||
88 | exp->mask.dst.protonum = 0xFF; | ||
89 | 86 | ||
90 | exp->expectfn = NULL; | 87 | exp->expectfn = NULL; |
91 | exp->flags = NF_CT_EXPECT_PERMANENT; | 88 | exp->flags = NF_CT_EXPECT_PERMANENT; |
92 | exp->helper = NULL; | 89 | exp->helper = NULL; |
93 | 90 | ||
94 | nf_conntrack_expect_related(exp); | 91 | nf_ct_expect_related(exp); |
95 | nf_conntrack_expect_put(exp); | 92 | nf_ct_expect_put(exp); |
96 | 93 | ||
97 | nf_ct_refresh(ct, *pskb, timeout * HZ); | 94 | nf_ct_refresh(ct, *pskb, timeout * HZ); |
98 | out: | 95 | out: |
@@ -104,9 +101,6 @@ static struct nf_conntrack_helper helper __read_mostly = { | |||
104 | .tuple.src.l3num = AF_INET, | 101 | .tuple.src.l3num = AF_INET, |
105 | .tuple.src.u.udp.port = __constant_htons(NMBD_PORT), | 102 | .tuple.src.u.udp.port = __constant_htons(NMBD_PORT), |
106 | .tuple.dst.protonum = IPPROTO_UDP, | 103 | .tuple.dst.protonum = IPPROTO_UDP, |
107 | .mask.src.l3num = 0xFFFF, | ||
108 | .mask.src.u.udp.port = __constant_htons(0xFFFF), | ||
109 | .mask.dst.protonum = 0xFF, | ||
110 | .max_expected = 1, | 104 | .max_expected = 1, |
111 | .me = THIS_MODULE, | 105 | .me = THIS_MODULE, |
112 | .help = help, | 106 | .help = help, |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index d0fe3d769828..6f89b105a205 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -428,7 +428,7 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) | |||
428 | { | 428 | { |
429 | struct nf_conn *ct, *last; | 429 | struct nf_conn *ct, *last; |
430 | struct nf_conntrack_tuple_hash *h; | 430 | struct nf_conntrack_tuple_hash *h; |
431 | struct list_head *i; | 431 | struct hlist_node *n; |
432 | struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh); | 432 | struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh); |
433 | u_int8_t l3proto = nfmsg->nfgen_family; | 433 | u_int8_t l3proto = nfmsg->nfgen_family; |
434 | 434 | ||
@@ -436,8 +436,8 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) | |||
436 | last = (struct nf_conn *)cb->args[1]; | 436 | last = (struct nf_conn *)cb->args[1]; |
437 | for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) { | 437 | for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) { |
438 | restart: | 438 | restart: |
439 | list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) { | 439 | hlist_for_each_entry(h, n, &nf_conntrack_hash[cb->args[0]], |
440 | h = (struct nf_conntrack_tuple_hash *) i; | 440 | hnode) { |
441 | if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL) | 441 | if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL) |
442 | continue; | 442 | continue; |
443 | ct = nf_ct_tuplehash_to_ctrack(h); | 443 | ct = nf_ct_tuplehash_to_ctrack(h); |
@@ -689,7 +689,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
689 | if (err < 0) | 689 | if (err < 0) |
690 | return err; | 690 | return err; |
691 | 691 | ||
692 | h = nf_conntrack_find_get(&tuple, NULL); | 692 | h = nf_conntrack_find_get(&tuple); |
693 | if (!h) | 693 | if (!h) |
694 | return -ENOENT; | 694 | return -ENOENT; |
695 | 695 | ||
@@ -744,7 +744,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
744 | if (err < 0) | 744 | if (err < 0) |
745 | return err; | 745 | return err; |
746 | 746 | ||
747 | h = nf_conntrack_find_get(&tuple, NULL); | 747 | h = nf_conntrack_find_get(&tuple); |
748 | if (!h) | 748 | if (!h) |
749 | return -ENOENT; | 749 | return -ENOENT; |
750 | 750 | ||
@@ -856,23 +856,23 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[]) | |||
856 | return 0; | 856 | return 0; |
857 | } | 857 | } |
858 | 858 | ||
859 | if (!help) { | ||
860 | /* FIXME: we need to reallocate and rehash */ | ||
861 | return -EBUSY; | ||
862 | } | ||
863 | |||
864 | helper = __nf_conntrack_helper_find_byname(helpname); | 859 | helper = __nf_conntrack_helper_find_byname(helpname); |
865 | if (helper == NULL) | 860 | if (helper == NULL) |
866 | return -EINVAL; | 861 | return -EINVAL; |
867 | 862 | ||
868 | if (help->helper == helper) | 863 | if (help) { |
869 | return 0; | 864 | if (help->helper == helper) |
870 | 865 | return 0; | |
871 | if (help->helper) | 866 | if (help->helper) |
872 | return -EBUSY; | 867 | return -EBUSY; |
868 | /* need to zero data of old helper */ | ||
869 | memset(&help->help, 0, sizeof(help->help)); | ||
870 | } else { | ||
871 | help = nf_ct_helper_ext_add(ct, GFP_KERNEL); | ||
872 | if (help == NULL) | ||
873 | return -ENOMEM; | ||
874 | } | ||
873 | 875 | ||
874 | /* need to zero data of old helper */ | ||
875 | memset(&help->help, 0, sizeof(help->help)); | ||
876 | rcu_assign_pointer(help->helper, helper); | 876 | rcu_assign_pointer(help->helper, helper); |
877 | 877 | ||
878 | return 0; | 878 | return 0; |
@@ -957,7 +957,7 @@ ctnetlink_create_conntrack(struct nfattr *cda[], | |||
957 | struct nf_conn *ct; | 957 | struct nf_conn *ct; |
958 | int err = -EINVAL; | 958 | int err = -EINVAL; |
959 | struct nf_conn_help *help; | 959 | struct nf_conn_help *help; |
960 | struct nf_conntrack_helper *helper = NULL; | 960 | struct nf_conntrack_helper *helper; |
961 | 961 | ||
962 | ct = nf_conntrack_alloc(otuple, rtuple); | 962 | ct = nf_conntrack_alloc(otuple, rtuple); |
963 | if (ct == NULL || IS_ERR(ct)) | 963 | if (ct == NULL || IS_ERR(ct)) |
@@ -987,9 +987,14 @@ ctnetlink_create_conntrack(struct nfattr *cda[], | |||
987 | ct->mark = ntohl(*(__be32 *)NFA_DATA(cda[CTA_MARK-1])); | 987 | ct->mark = ntohl(*(__be32 *)NFA_DATA(cda[CTA_MARK-1])); |
988 | #endif | 988 | #endif |
989 | 989 | ||
990 | help = nfct_help(ct); | 990 | helper = nf_ct_helper_find_get(rtuple); |
991 | if (help) { | 991 | if (helper) { |
992 | helper = nf_ct_helper_find_get(rtuple); | 992 | help = nf_ct_helper_ext_add(ct, GFP_KERNEL); |
993 | if (help == NULL) { | ||
994 | nf_ct_helper_put(helper); | ||
995 | err = -ENOMEM; | ||
996 | goto err; | ||
997 | } | ||
993 | /* not in hash table yet so not strictly necessary */ | 998 | /* not in hash table yet so not strictly necessary */ |
994 | rcu_assign_pointer(help->helper, helper); | 999 | rcu_assign_pointer(help->helper, helper); |
995 | } | 1000 | } |
@@ -1089,22 +1094,29 @@ nfattr_failure: | |||
1089 | static inline int | 1094 | static inline int |
1090 | ctnetlink_exp_dump_mask(struct sk_buff *skb, | 1095 | ctnetlink_exp_dump_mask(struct sk_buff *skb, |
1091 | const struct nf_conntrack_tuple *tuple, | 1096 | const struct nf_conntrack_tuple *tuple, |
1092 | const struct nf_conntrack_tuple *mask) | 1097 | const struct nf_conntrack_tuple_mask *mask) |
1093 | { | 1098 | { |
1094 | int ret; | 1099 | int ret; |
1095 | struct nf_conntrack_l3proto *l3proto; | 1100 | struct nf_conntrack_l3proto *l3proto; |
1096 | struct nf_conntrack_l4proto *l4proto; | 1101 | struct nf_conntrack_l4proto *l4proto; |
1097 | struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK); | 1102 | struct nf_conntrack_tuple m; |
1103 | struct nfattr *nest_parms; | ||
1104 | |||
1105 | memset(&m, 0xFF, sizeof(m)); | ||
1106 | m.src.u.all = mask->src.u.all; | ||
1107 | memcpy(&m.src.u3, &mask->src.u3, sizeof(m.src.u3)); | ||
1108 | |||
1109 | nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK); | ||
1098 | 1110 | ||
1099 | l3proto = nf_ct_l3proto_find_get(tuple->src.l3num); | 1111 | l3proto = nf_ct_l3proto_find_get(tuple->src.l3num); |
1100 | ret = ctnetlink_dump_tuples_ip(skb, mask, l3proto); | 1112 | ret = ctnetlink_dump_tuples_ip(skb, &m, l3proto); |
1101 | nf_ct_l3proto_put(l3proto); | 1113 | nf_ct_l3proto_put(l3proto); |
1102 | 1114 | ||
1103 | if (unlikely(ret < 0)) | 1115 | if (unlikely(ret < 0)) |
1104 | goto nfattr_failure; | 1116 | goto nfattr_failure; |
1105 | 1117 | ||
1106 | l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum); | 1118 | l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum); |
1107 | ret = ctnetlink_dump_tuples_proto(skb, mask, l4proto); | 1119 | ret = ctnetlink_dump_tuples_proto(skb, &m, l4proto); |
1108 | nf_ct_l4proto_put(l4proto); | 1120 | nf_ct_l4proto_put(l4proto); |
1109 | if (unlikely(ret < 0)) | 1121 | if (unlikely(ret < 0)) |
1110 | goto nfattr_failure; | 1122 | goto nfattr_failure; |
@@ -1223,32 +1235,52 @@ nfattr_failure: | |||
1223 | return NOTIFY_DONE; | 1235 | return NOTIFY_DONE; |
1224 | } | 1236 | } |
1225 | #endif | 1237 | #endif |
1238 | static int ctnetlink_exp_done(struct netlink_callback *cb) | ||
1239 | { | ||
1240 | if (cb->args[1]) | ||
1241 | nf_ct_expect_put((struct nf_conntrack_expect *)cb->args[1]); | ||
1242 | return 0; | ||
1243 | } | ||
1226 | 1244 | ||
1227 | static int | 1245 | static int |
1228 | ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb) | 1246 | ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb) |
1229 | { | 1247 | { |
1230 | struct nf_conntrack_expect *exp = NULL; | 1248 | struct nf_conntrack_expect *exp, *last; |
1231 | struct list_head *i; | ||
1232 | u_int32_t *id = (u_int32_t *) &cb->args[0]; | ||
1233 | struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh); | 1249 | struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh); |
1250 | struct hlist_node *n; | ||
1234 | u_int8_t l3proto = nfmsg->nfgen_family; | 1251 | u_int8_t l3proto = nfmsg->nfgen_family; |
1235 | 1252 | ||
1236 | read_lock_bh(&nf_conntrack_lock); | 1253 | read_lock_bh(&nf_conntrack_lock); |
1237 | list_for_each_prev(i, &nf_conntrack_expect_list) { | 1254 | last = (struct nf_conntrack_expect *)cb->args[1]; |
1238 | exp = (struct nf_conntrack_expect *) i; | 1255 | for (; cb->args[0] < nf_ct_expect_hsize; cb->args[0]++) { |
1239 | if (l3proto && exp->tuple.src.l3num != l3proto) | 1256 | restart: |
1240 | continue; | 1257 | hlist_for_each_entry(exp, n, &nf_ct_expect_hash[cb->args[0]], |
1241 | if (exp->id <= *id) | 1258 | hnode) { |
1242 | continue; | 1259 | if (l3proto && exp->tuple.src.l3num != l3proto) |
1243 | if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).pid, | 1260 | continue; |
1244 | cb->nlh->nlmsg_seq, | 1261 | if (cb->args[1]) { |
1245 | IPCTNL_MSG_EXP_NEW, | 1262 | if (exp != last) |
1246 | 1, exp) < 0) | 1263 | continue; |
1247 | goto out; | 1264 | cb->args[1] = 0; |
1248 | *id = exp->id; | 1265 | } |
1266 | if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).pid, | ||
1267 | cb->nlh->nlmsg_seq, | ||
1268 | IPCTNL_MSG_EXP_NEW, | ||
1269 | 1, exp) < 0) { | ||
1270 | atomic_inc(&exp->use); | ||
1271 | cb->args[1] = (unsigned long)exp; | ||
1272 | goto out; | ||
1273 | } | ||
1274 | } | ||
1275 | if (cb->args[1]) { | ||
1276 | cb->args[1] = 0; | ||
1277 | goto restart; | ||
1278 | } | ||
1249 | } | 1279 | } |
1250 | out: | 1280 | out: |
1251 | read_unlock_bh(&nf_conntrack_lock); | 1281 | read_unlock_bh(&nf_conntrack_lock); |
1282 | if (last) | ||
1283 | nf_ct_expect_put(last); | ||
1252 | 1284 | ||
1253 | return skb->len; | 1285 | return skb->len; |
1254 | } | 1286 | } |
@@ -1275,7 +1307,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1275 | if (nlh->nlmsg_flags & NLM_F_DUMP) { | 1307 | if (nlh->nlmsg_flags & NLM_F_DUMP) { |
1276 | return netlink_dump_start(ctnl, skb, nlh, | 1308 | return netlink_dump_start(ctnl, skb, nlh, |
1277 | ctnetlink_exp_dump_table, | 1309 | ctnetlink_exp_dump_table, |
1278 | ctnetlink_done); | 1310 | ctnetlink_exp_done); |
1279 | } | 1311 | } |
1280 | 1312 | ||
1281 | if (cda[CTA_EXPECT_MASTER-1]) | 1313 | if (cda[CTA_EXPECT_MASTER-1]) |
@@ -1286,14 +1318,14 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1286 | if (err < 0) | 1318 | if (err < 0) |
1287 | return err; | 1319 | return err; |
1288 | 1320 | ||
1289 | exp = nf_conntrack_expect_find_get(&tuple); | 1321 | exp = nf_ct_expect_find_get(&tuple); |
1290 | if (!exp) | 1322 | if (!exp) |
1291 | return -ENOENT; | 1323 | return -ENOENT; |
1292 | 1324 | ||
1293 | if (cda[CTA_EXPECT_ID-1]) { | 1325 | if (cda[CTA_EXPECT_ID-1]) { |
1294 | __be32 id = *(__be32 *)NFA_DATA(cda[CTA_EXPECT_ID-1]); | 1326 | __be32 id = *(__be32 *)NFA_DATA(cda[CTA_EXPECT_ID-1]); |
1295 | if (exp->id != ntohl(id)) { | 1327 | if (exp->id != ntohl(id)) { |
1296 | nf_conntrack_expect_put(exp); | 1328 | nf_ct_expect_put(exp); |
1297 | return -ENOENT; | 1329 | return -ENOENT; |
1298 | } | 1330 | } |
1299 | } | 1331 | } |
@@ -1309,14 +1341,14 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1309 | if (err <= 0) | 1341 | if (err <= 0) |
1310 | goto free; | 1342 | goto free; |
1311 | 1343 | ||
1312 | nf_conntrack_expect_put(exp); | 1344 | nf_ct_expect_put(exp); |
1313 | 1345 | ||
1314 | return netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT); | 1346 | return netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT); |
1315 | 1347 | ||
1316 | free: | 1348 | free: |
1317 | kfree_skb(skb2); | 1349 | kfree_skb(skb2); |
1318 | out: | 1350 | out: |
1319 | nf_conntrack_expect_put(exp); | 1351 | nf_ct_expect_put(exp); |
1320 | return err; | 1352 | return err; |
1321 | } | 1353 | } |
1322 | 1354 | ||
@@ -1324,11 +1356,13 @@ static int | |||
1324 | ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | 1356 | ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, |
1325 | struct nlmsghdr *nlh, struct nfattr *cda[]) | 1357 | struct nlmsghdr *nlh, struct nfattr *cda[]) |
1326 | { | 1358 | { |
1327 | struct nf_conntrack_expect *exp, *tmp; | 1359 | struct nf_conntrack_expect *exp; |
1328 | struct nf_conntrack_tuple tuple; | 1360 | struct nf_conntrack_tuple tuple; |
1329 | struct nf_conntrack_helper *h; | 1361 | struct nf_conntrack_helper *h; |
1330 | struct nfgenmsg *nfmsg = NLMSG_DATA(nlh); | 1362 | struct nfgenmsg *nfmsg = NLMSG_DATA(nlh); |
1363 | struct hlist_node *n, *next; | ||
1331 | u_int8_t u3 = nfmsg->nfgen_family; | 1364 | u_int8_t u3 = nfmsg->nfgen_family; |
1365 | unsigned int i; | ||
1332 | int err; | 1366 | int err; |
1333 | 1367 | ||
1334 | if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp)) | 1368 | if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp)) |
@@ -1341,25 +1375,26 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1341 | return err; | 1375 | return err; |
1342 | 1376 | ||
1343 | /* bump usage count to 2 */ | 1377 | /* bump usage count to 2 */ |
1344 | exp = nf_conntrack_expect_find_get(&tuple); | 1378 | exp = nf_ct_expect_find_get(&tuple); |
1345 | if (!exp) | 1379 | if (!exp) |
1346 | return -ENOENT; | 1380 | return -ENOENT; |
1347 | 1381 | ||
1348 | if (cda[CTA_EXPECT_ID-1]) { | 1382 | if (cda[CTA_EXPECT_ID-1]) { |
1349 | __be32 id = *(__be32 *)NFA_DATA(cda[CTA_EXPECT_ID-1]); | 1383 | __be32 id = *(__be32 *)NFA_DATA(cda[CTA_EXPECT_ID-1]); |
1350 | if (exp->id != ntohl(id)) { | 1384 | if (exp->id != ntohl(id)) { |
1351 | nf_conntrack_expect_put(exp); | 1385 | nf_ct_expect_put(exp); |
1352 | return -ENOENT; | 1386 | return -ENOENT; |
1353 | } | 1387 | } |
1354 | } | 1388 | } |
1355 | 1389 | ||
1356 | /* after list removal, usage count == 1 */ | 1390 | /* after list removal, usage count == 1 */ |
1357 | nf_conntrack_unexpect_related(exp); | 1391 | nf_ct_unexpect_related(exp); |
1358 | /* have to put what we 'get' above. | 1392 | /* have to put what we 'get' above. |
1359 | * after this line usage count == 0 */ | 1393 | * after this line usage count == 0 */ |
1360 | nf_conntrack_expect_put(exp); | 1394 | nf_ct_expect_put(exp); |
1361 | } else if (cda[CTA_EXPECT_HELP_NAME-1]) { | 1395 | } else if (cda[CTA_EXPECT_HELP_NAME-1]) { |
1362 | char *name = NFA_DATA(cda[CTA_EXPECT_HELP_NAME-1]); | 1396 | char *name = NFA_DATA(cda[CTA_EXPECT_HELP_NAME-1]); |
1397 | struct nf_conn_help *m_help; | ||
1363 | 1398 | ||
1364 | /* delete all expectations for this helper */ | 1399 | /* delete all expectations for this helper */ |
1365 | write_lock_bh(&nf_conntrack_lock); | 1400 | write_lock_bh(&nf_conntrack_lock); |
@@ -1368,24 +1403,30 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1368 | write_unlock_bh(&nf_conntrack_lock); | 1403 | write_unlock_bh(&nf_conntrack_lock); |
1369 | return -EINVAL; | 1404 | return -EINVAL; |
1370 | } | 1405 | } |
1371 | list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, | 1406 | for (i = 0; i < nf_ct_expect_hsize; i++) { |
1372 | list) { | 1407 | hlist_for_each_entry_safe(exp, n, next, |
1373 | struct nf_conn_help *m_help = nfct_help(exp->master); | 1408 | &nf_ct_expect_hash[i], |
1374 | if (m_help->helper == h | 1409 | hnode) { |
1375 | && del_timer(&exp->timeout)) { | 1410 | m_help = nfct_help(exp->master); |
1376 | nf_ct_unlink_expect(exp); | 1411 | if (m_help->helper == h |
1377 | nf_conntrack_expect_put(exp); | 1412 | && del_timer(&exp->timeout)) { |
1413 | nf_ct_unlink_expect(exp); | ||
1414 | nf_ct_expect_put(exp); | ||
1415 | } | ||
1378 | } | 1416 | } |
1379 | } | 1417 | } |
1380 | write_unlock_bh(&nf_conntrack_lock); | 1418 | write_unlock_bh(&nf_conntrack_lock); |
1381 | } else { | 1419 | } else { |
1382 | /* This basically means we have to flush everything*/ | 1420 | /* This basically means we have to flush everything*/ |
1383 | write_lock_bh(&nf_conntrack_lock); | 1421 | write_lock_bh(&nf_conntrack_lock); |
1384 | list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, | 1422 | for (i = 0; i < nf_ct_expect_hsize; i++) { |
1385 | list) { | 1423 | hlist_for_each_entry_safe(exp, n, next, |
1386 | if (del_timer(&exp->timeout)) { | 1424 | &nf_ct_expect_hash[i], |
1387 | nf_ct_unlink_expect(exp); | 1425 | hnode) { |
1388 | nf_conntrack_expect_put(exp); | 1426 | if (del_timer(&exp->timeout)) { |
1427 | nf_ct_unlink_expect(exp); | ||
1428 | nf_ct_expect_put(exp); | ||
1429 | } | ||
1389 | } | 1430 | } |
1390 | } | 1431 | } |
1391 | write_unlock_bh(&nf_conntrack_lock); | 1432 | write_unlock_bh(&nf_conntrack_lock); |
@@ -1421,7 +1462,7 @@ ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3) | |||
1421 | return err; | 1462 | return err; |
1422 | 1463 | ||
1423 | /* Look for master conntrack of this expectation */ | 1464 | /* Look for master conntrack of this expectation */ |
1424 | h = nf_conntrack_find_get(&master_tuple, NULL); | 1465 | h = nf_conntrack_find_get(&master_tuple); |
1425 | if (!h) | 1466 | if (!h) |
1426 | return -ENOENT; | 1467 | return -ENOENT; |
1427 | ct = nf_ct_tuplehash_to_ctrack(h); | 1468 | ct = nf_ct_tuplehash_to_ctrack(h); |
@@ -1433,7 +1474,7 @@ ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3) | |||
1433 | goto out; | 1474 | goto out; |
1434 | } | 1475 | } |
1435 | 1476 | ||
1436 | exp = nf_conntrack_expect_alloc(ct); | 1477 | exp = nf_ct_expect_alloc(ct); |
1437 | if (!exp) { | 1478 | if (!exp) { |
1438 | err = -ENOMEM; | 1479 | err = -ENOMEM; |
1439 | goto out; | 1480 | goto out; |
@@ -1444,10 +1485,11 @@ ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3) | |||
1444 | exp->master = ct; | 1485 | exp->master = ct; |
1445 | exp->helper = NULL; | 1486 | exp->helper = NULL; |
1446 | memcpy(&exp->tuple, &tuple, sizeof(struct nf_conntrack_tuple)); | 1487 | memcpy(&exp->tuple, &tuple, sizeof(struct nf_conntrack_tuple)); |
1447 | memcpy(&exp->mask, &mask, sizeof(struct nf_conntrack_tuple)); | 1488 | memcpy(&exp->mask.src.u3, &mask.src.u3, sizeof(exp->mask.src.u3)); |
1489 | exp->mask.src.u.all = mask.src.u.all; | ||
1448 | 1490 | ||
1449 | err = nf_conntrack_expect_related(exp); | 1491 | err = nf_ct_expect_related(exp); |
1450 | nf_conntrack_expect_put(exp); | 1492 | nf_ct_expect_put(exp); |
1451 | 1493 | ||
1452 | out: | 1494 | out: |
1453 | nf_ct_put(nf_ct_tuplehash_to_ctrack(h)); | 1495 | nf_ct_put(nf_ct_tuplehash_to_ctrack(h)); |
@@ -1477,7 +1519,7 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1477 | return err; | 1519 | return err; |
1478 | 1520 | ||
1479 | write_lock_bh(&nf_conntrack_lock); | 1521 | write_lock_bh(&nf_conntrack_lock); |
1480 | exp = __nf_conntrack_expect_find(&tuple); | 1522 | exp = __nf_ct_expect_find(&tuple); |
1481 | 1523 | ||
1482 | if (!exp) { | 1524 | if (!exp) { |
1483 | write_unlock_bh(&nf_conntrack_lock); | 1525 | write_unlock_bh(&nf_conntrack_lock); |
@@ -1567,7 +1609,7 @@ static int __init ctnetlink_init(void) | |||
1567 | goto err_unreg_exp_subsys; | 1609 | goto err_unreg_exp_subsys; |
1568 | } | 1610 | } |
1569 | 1611 | ||
1570 | ret = nf_conntrack_expect_register_notifier(&ctnl_notifier_exp); | 1612 | ret = nf_ct_expect_register_notifier(&ctnl_notifier_exp); |
1571 | if (ret < 0) { | 1613 | if (ret < 0) { |
1572 | printk("ctnetlink_init: cannot expect register notifier.\n"); | 1614 | printk("ctnetlink_init: cannot expect register notifier.\n"); |
1573 | goto err_unreg_notifier; | 1615 | goto err_unreg_notifier; |
@@ -1593,7 +1635,7 @@ static void __exit ctnetlink_exit(void) | |||
1593 | printk("ctnetlink: unregistering from nfnetlink.\n"); | 1635 | printk("ctnetlink: unregistering from nfnetlink.\n"); |
1594 | 1636 | ||
1595 | #ifdef CONFIG_NF_CONNTRACK_EVENTS | 1637 | #ifdef CONFIG_NF_CONNTRACK_EVENTS |
1596 | nf_conntrack_expect_unregister_notifier(&ctnl_notifier_exp); | 1638 | nf_ct_expect_unregister_notifier(&ctnl_notifier_exp); |
1597 | nf_conntrack_unregister_notifier(&ctnl_notifier); | 1639 | nf_conntrack_unregister_notifier(&ctnl_notifier); |
1598 | #endif | 1640 | #endif |
1599 | 1641 | ||
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c index 115bcb5d5a7c..b0804199ab59 100644 --- a/net/netfilter/nf_conntrack_pptp.c +++ b/net/netfilter/nf_conntrack_pptp.c | |||
@@ -65,7 +65,7 @@ void | |||
65 | struct nf_conntrack_expect *exp) __read_mostly; | 65 | struct nf_conntrack_expect *exp) __read_mostly; |
66 | EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_expectfn); | 66 | EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_expectfn); |
67 | 67 | ||
68 | #if 0 | 68 | #ifdef DEBUG |
69 | /* PptpControlMessageType names */ | 69 | /* PptpControlMessageType names */ |
70 | const char *pptp_msg_name[] = { | 70 | const char *pptp_msg_name[] = { |
71 | "UNKNOWN_MESSAGE", | 71 | "UNKNOWN_MESSAGE", |
@@ -86,9 +86,6 @@ const char *pptp_msg_name[] = { | |||
86 | "SET_LINK_INFO" | 86 | "SET_LINK_INFO" |
87 | }; | 87 | }; |
88 | EXPORT_SYMBOL(pptp_msg_name); | 88 | EXPORT_SYMBOL(pptp_msg_name); |
89 | #define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args) | ||
90 | #else | ||
91 | #define DEBUGP(format, args...) | ||
92 | #endif | 89 | #endif |
93 | 90 | ||
94 | #define SECS *HZ | 91 | #define SECS *HZ |
@@ -102,7 +99,7 @@ static void pptp_expectfn(struct nf_conn *ct, | |||
102 | struct nf_conntrack_expect *exp) | 99 | struct nf_conntrack_expect *exp) |
103 | { | 100 | { |
104 | typeof(nf_nat_pptp_hook_expectfn) nf_nat_pptp_expectfn; | 101 | typeof(nf_nat_pptp_hook_expectfn) nf_nat_pptp_expectfn; |
105 | DEBUGP("increasing timeouts\n"); | 102 | pr_debug("increasing timeouts\n"); |
106 | 103 | ||
107 | /* increase timeout of GRE data channel conntrack entry */ | 104 | /* increase timeout of GRE data channel conntrack entry */ |
108 | ct->proto.gre.timeout = PPTP_GRE_TIMEOUT; | 105 | ct->proto.gre.timeout = PPTP_GRE_TIMEOUT; |
@@ -121,17 +118,17 @@ static void pptp_expectfn(struct nf_conn *ct, | |||
121 | 118 | ||
122 | /* obviously this tuple inversion only works until you do NAT */ | 119 | /* obviously this tuple inversion only works until you do NAT */ |
123 | nf_ct_invert_tuplepr(&inv_t, &exp->tuple); | 120 | nf_ct_invert_tuplepr(&inv_t, &exp->tuple); |
124 | DEBUGP("trying to unexpect other dir: "); | 121 | pr_debug("trying to unexpect other dir: "); |
125 | NF_CT_DUMP_TUPLE(&inv_t); | 122 | NF_CT_DUMP_TUPLE(&inv_t); |
126 | 123 | ||
127 | exp_other = nf_conntrack_expect_find_get(&inv_t); | 124 | exp_other = nf_ct_expect_find_get(&inv_t); |
128 | if (exp_other) { | 125 | if (exp_other) { |
129 | /* delete other expectation. */ | 126 | /* delete other expectation. */ |
130 | DEBUGP("found\n"); | 127 | pr_debug("found\n"); |
131 | nf_conntrack_unexpect_related(exp_other); | 128 | nf_ct_unexpect_related(exp_other); |
132 | nf_conntrack_expect_put(exp_other); | 129 | nf_ct_expect_put(exp_other); |
133 | } else { | 130 | } else { |
134 | DEBUGP("not found\n"); | 131 | pr_debug("not found\n"); |
135 | } | 132 | } |
136 | } | 133 | } |
137 | rcu_read_unlock(); | 134 | rcu_read_unlock(); |
@@ -143,13 +140,13 @@ static int destroy_sibling_or_exp(const struct nf_conntrack_tuple *t) | |||
143 | struct nf_conntrack_expect *exp; | 140 | struct nf_conntrack_expect *exp; |
144 | struct nf_conn *sibling; | 141 | struct nf_conn *sibling; |
145 | 142 | ||
146 | DEBUGP("trying to timeout ct or exp for tuple "); | 143 | pr_debug("trying to timeout ct or exp for tuple "); |
147 | NF_CT_DUMP_TUPLE(t); | 144 | NF_CT_DUMP_TUPLE(t); |
148 | 145 | ||
149 | h = nf_conntrack_find_get(t, NULL); | 146 | h = nf_conntrack_find_get(t); |
150 | if (h) { | 147 | if (h) { |
151 | sibling = nf_ct_tuplehash_to_ctrack(h); | 148 | sibling = nf_ct_tuplehash_to_ctrack(h); |
152 | DEBUGP("setting timeout of conntrack %p to 0\n", sibling); | 149 | pr_debug("setting timeout of conntrack %p to 0\n", sibling); |
153 | sibling->proto.gre.timeout = 0; | 150 | sibling->proto.gre.timeout = 0; |
154 | sibling->proto.gre.stream_timeout = 0; | 151 | sibling->proto.gre.stream_timeout = 0; |
155 | if (del_timer(&sibling->timeout)) | 152 | if (del_timer(&sibling->timeout)) |
@@ -157,11 +154,11 @@ static int destroy_sibling_or_exp(const struct nf_conntrack_tuple *t) | |||
157 | nf_ct_put(sibling); | 154 | nf_ct_put(sibling); |
158 | return 1; | 155 | return 1; |
159 | } else { | 156 | } else { |
160 | exp = nf_conntrack_expect_find_get(t); | 157 | exp = nf_ct_expect_find_get(t); |
161 | if (exp) { | 158 | if (exp) { |
162 | DEBUGP("unexpect_related of expect %p\n", exp); | 159 | pr_debug("unexpect_related of expect %p\n", exp); |
163 | nf_conntrack_unexpect_related(exp); | 160 | nf_ct_unexpect_related(exp); |
164 | nf_conntrack_expect_put(exp); | 161 | nf_ct_expect_put(exp); |
165 | return 1; | 162 | return 1; |
166 | } | 163 | } |
167 | } | 164 | } |
@@ -182,7 +179,7 @@ static void pptp_destroy_siblings(struct nf_conn *ct) | |||
182 | t.src.u.gre.key = help->help.ct_pptp_info.pns_call_id; | 179 | t.src.u.gre.key = help->help.ct_pptp_info.pns_call_id; |
183 | t.dst.u.gre.key = help->help.ct_pptp_info.pac_call_id; | 180 | t.dst.u.gre.key = help->help.ct_pptp_info.pac_call_id; |
184 | if (!destroy_sibling_or_exp(&t)) | 181 | if (!destroy_sibling_or_exp(&t)) |
185 | DEBUGP("failed to timeout original pns->pac ct/exp\n"); | 182 | pr_debug("failed to timeout original pns->pac ct/exp\n"); |
186 | 183 | ||
187 | /* try reply (pac->pns) tuple */ | 184 | /* try reply (pac->pns) tuple */ |
188 | memcpy(&t, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, sizeof(t)); | 185 | memcpy(&t, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, sizeof(t)); |
@@ -190,7 +187,7 @@ static void pptp_destroy_siblings(struct nf_conn *ct) | |||
190 | t.src.u.gre.key = help->help.ct_pptp_info.pac_call_id; | 187 | t.src.u.gre.key = help->help.ct_pptp_info.pac_call_id; |
191 | t.dst.u.gre.key = help->help.ct_pptp_info.pns_call_id; | 188 | t.dst.u.gre.key = help->help.ct_pptp_info.pns_call_id; |
192 | if (!destroy_sibling_or_exp(&t)) | 189 | if (!destroy_sibling_or_exp(&t)) |
193 | DEBUGP("failed to timeout reply pac->pns ct/exp\n"); | 190 | pr_debug("failed to timeout reply pac->pns ct/exp\n"); |
194 | } | 191 | } |
195 | 192 | ||
196 | /* expect GRE connections (PNS->PAC and PAC->PNS direction) */ | 193 | /* expect GRE connections (PNS->PAC and PAC->PNS direction) */ |
@@ -201,36 +198,36 @@ static int exp_gre(struct nf_conn *ct, __be16 callid, __be16 peer_callid) | |||
201 | int ret = 1; | 198 | int ret = 1; |
202 | typeof(nf_nat_pptp_hook_exp_gre) nf_nat_pptp_exp_gre; | 199 | typeof(nf_nat_pptp_hook_exp_gre) nf_nat_pptp_exp_gre; |
203 | 200 | ||
204 | exp_orig = nf_conntrack_expect_alloc(ct); | 201 | exp_orig = nf_ct_expect_alloc(ct); |
205 | if (exp_orig == NULL) | 202 | if (exp_orig == NULL) |
206 | goto out; | 203 | goto out; |
207 | 204 | ||
208 | exp_reply = nf_conntrack_expect_alloc(ct); | 205 | exp_reply = nf_ct_expect_alloc(ct); |
209 | if (exp_reply == NULL) | 206 | if (exp_reply == NULL) |
210 | goto out_put_orig; | 207 | goto out_put_orig; |
211 | 208 | ||
212 | /* original direction, PNS->PAC */ | 209 | /* original direction, PNS->PAC */ |
213 | dir = IP_CT_DIR_ORIGINAL; | 210 | dir = IP_CT_DIR_ORIGINAL; |
214 | nf_conntrack_expect_init(exp_orig, ct->tuplehash[dir].tuple.src.l3num, | 211 | nf_ct_expect_init(exp_orig, ct->tuplehash[dir].tuple.src.l3num, |
215 | &ct->tuplehash[dir].tuple.src.u3, | 212 | &ct->tuplehash[dir].tuple.src.u3, |
216 | &ct->tuplehash[dir].tuple.dst.u3, | 213 | &ct->tuplehash[dir].tuple.dst.u3, |
217 | IPPROTO_GRE, &peer_callid, &callid); | 214 | IPPROTO_GRE, &peer_callid, &callid); |
218 | exp_orig->expectfn = pptp_expectfn; | 215 | exp_orig->expectfn = pptp_expectfn; |
219 | 216 | ||
220 | /* reply direction, PAC->PNS */ | 217 | /* reply direction, PAC->PNS */ |
221 | dir = IP_CT_DIR_REPLY; | 218 | dir = IP_CT_DIR_REPLY; |
222 | nf_conntrack_expect_init(exp_reply, ct->tuplehash[dir].tuple.src.l3num, | 219 | nf_ct_expect_init(exp_reply, ct->tuplehash[dir].tuple.src.l3num, |
223 | &ct->tuplehash[dir].tuple.src.u3, | 220 | &ct->tuplehash[dir].tuple.src.u3, |
224 | &ct->tuplehash[dir].tuple.dst.u3, | 221 | &ct->tuplehash[dir].tuple.dst.u3, |
225 | IPPROTO_GRE, &callid, &peer_callid); | 222 | IPPROTO_GRE, &callid, &peer_callid); |
226 | exp_reply->expectfn = pptp_expectfn; | 223 | exp_reply->expectfn = pptp_expectfn; |
227 | 224 | ||
228 | nf_nat_pptp_exp_gre = rcu_dereference(nf_nat_pptp_hook_exp_gre); | 225 | nf_nat_pptp_exp_gre = rcu_dereference(nf_nat_pptp_hook_exp_gre); |
229 | if (nf_nat_pptp_exp_gre && ct->status & IPS_NAT_MASK) | 226 | if (nf_nat_pptp_exp_gre && ct->status & IPS_NAT_MASK) |
230 | nf_nat_pptp_exp_gre(exp_orig, exp_reply); | 227 | nf_nat_pptp_exp_gre(exp_orig, exp_reply); |
231 | if (nf_conntrack_expect_related(exp_orig) != 0) | 228 | if (nf_ct_expect_related(exp_orig) != 0) |
232 | goto out_put_both; | 229 | goto out_put_both; |
233 | if (nf_conntrack_expect_related(exp_reply) != 0) | 230 | if (nf_ct_expect_related(exp_reply) != 0) |
234 | goto out_unexpect_orig; | 231 | goto out_unexpect_orig; |
235 | 232 | ||
236 | /* Add GRE keymap entries */ | 233 | /* Add GRE keymap entries */ |
@@ -243,16 +240,16 @@ static int exp_gre(struct nf_conn *ct, __be16 callid, __be16 peer_callid) | |||
243 | ret = 0; | 240 | ret = 0; |
244 | 241 | ||
245 | out_put_both: | 242 | out_put_both: |
246 | nf_conntrack_expect_put(exp_reply); | 243 | nf_ct_expect_put(exp_reply); |
247 | out_put_orig: | 244 | out_put_orig: |
248 | nf_conntrack_expect_put(exp_orig); | 245 | nf_ct_expect_put(exp_orig); |
249 | out: | 246 | out: |
250 | return ret; | 247 | return ret; |
251 | 248 | ||
252 | out_unexpect_both: | 249 | out_unexpect_both: |
253 | nf_conntrack_unexpect_related(exp_reply); | 250 | nf_ct_unexpect_related(exp_reply); |
254 | out_unexpect_orig: | 251 | out_unexpect_orig: |
255 | nf_conntrack_unexpect_related(exp_orig); | 252 | nf_ct_unexpect_related(exp_orig); |
256 | goto out_put_both; | 253 | goto out_put_both; |
257 | } | 254 | } |
258 | 255 | ||
@@ -270,7 +267,7 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
270 | typeof(nf_nat_pptp_hook_inbound) nf_nat_pptp_inbound; | 267 | typeof(nf_nat_pptp_hook_inbound) nf_nat_pptp_inbound; |
271 | 268 | ||
272 | msg = ntohs(ctlh->messageType); | 269 | msg = ntohs(ctlh->messageType); |
273 | DEBUGP("inbound control message %s\n", pptp_msg_name[msg]); | 270 | pr_debug("inbound control message %s\n", pptp_msg_name[msg]); |
274 | 271 | ||
275 | switch (msg) { | 272 | switch (msg) { |
276 | case PPTP_START_SESSION_REPLY: | 273 | case PPTP_START_SESSION_REPLY: |
@@ -305,8 +302,8 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
305 | pcid = pptpReq->ocack.peersCallID; | 302 | pcid = pptpReq->ocack.peersCallID; |
306 | if (info->pns_call_id != pcid) | 303 | if (info->pns_call_id != pcid) |
307 | goto invalid; | 304 | goto invalid; |
308 | DEBUGP("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg], | 305 | pr_debug("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg], |
309 | ntohs(cid), ntohs(pcid)); | 306 | ntohs(cid), ntohs(pcid)); |
310 | 307 | ||
311 | if (pptpReq->ocack.resultCode == PPTP_OUTCALL_CONNECT) { | 308 | if (pptpReq->ocack.resultCode == PPTP_OUTCALL_CONNECT) { |
312 | info->cstate = PPTP_CALL_OUT_CONF; | 309 | info->cstate = PPTP_CALL_OUT_CONF; |
@@ -322,7 +319,7 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
322 | goto invalid; | 319 | goto invalid; |
323 | 320 | ||
324 | cid = pptpReq->icreq.callID; | 321 | cid = pptpReq->icreq.callID; |
325 | DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid)); | 322 | pr_debug("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid)); |
326 | info->cstate = PPTP_CALL_IN_REQ; | 323 | info->cstate = PPTP_CALL_IN_REQ; |
327 | info->pac_call_id = cid; | 324 | info->pac_call_id = cid; |
328 | break; | 325 | break; |
@@ -341,7 +338,7 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
341 | if (info->pns_call_id != pcid) | 338 | if (info->pns_call_id != pcid) |
342 | goto invalid; | 339 | goto invalid; |
343 | 340 | ||
344 | DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(pcid)); | 341 | pr_debug("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(pcid)); |
345 | info->cstate = PPTP_CALL_IN_CONF; | 342 | info->cstate = PPTP_CALL_IN_CONF; |
346 | 343 | ||
347 | /* we expect a GRE connection from PAC to PNS */ | 344 | /* we expect a GRE connection from PAC to PNS */ |
@@ -351,7 +348,7 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
351 | case PPTP_CALL_DISCONNECT_NOTIFY: | 348 | case PPTP_CALL_DISCONNECT_NOTIFY: |
352 | /* server confirms disconnect */ | 349 | /* server confirms disconnect */ |
353 | cid = pptpReq->disc.callID; | 350 | cid = pptpReq->disc.callID; |
354 | DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid)); | 351 | pr_debug("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid)); |
355 | info->cstate = PPTP_CALL_NONE; | 352 | info->cstate = PPTP_CALL_NONE; |
356 | 353 | ||
357 | /* untrack this call id, unexpect GRE packets */ | 354 | /* untrack this call id, unexpect GRE packets */ |
@@ -374,11 +371,11 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
374 | return NF_ACCEPT; | 371 | return NF_ACCEPT; |
375 | 372 | ||
376 | invalid: | 373 | invalid: |
377 | DEBUGP("invalid %s: type=%d cid=%u pcid=%u " | 374 | pr_debug("invalid %s: type=%d cid=%u pcid=%u " |
378 | "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n", | 375 | "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n", |
379 | msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0], | 376 | msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0], |
380 | msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate, | 377 | msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate, |
381 | ntohs(info->pns_call_id), ntohs(info->pac_call_id)); | 378 | ntohs(info->pns_call_id), ntohs(info->pac_call_id)); |
382 | return NF_ACCEPT; | 379 | return NF_ACCEPT; |
383 | } | 380 | } |
384 | 381 | ||
@@ -396,7 +393,7 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
396 | typeof(nf_nat_pptp_hook_outbound) nf_nat_pptp_outbound; | 393 | typeof(nf_nat_pptp_hook_outbound) nf_nat_pptp_outbound; |
397 | 394 | ||
398 | msg = ntohs(ctlh->messageType); | 395 | msg = ntohs(ctlh->messageType); |
399 | DEBUGP("outbound control message %s\n", pptp_msg_name[msg]); | 396 | pr_debug("outbound control message %s\n", pptp_msg_name[msg]); |
400 | 397 | ||
401 | switch (msg) { | 398 | switch (msg) { |
402 | case PPTP_START_SESSION_REQUEST: | 399 | case PPTP_START_SESSION_REQUEST: |
@@ -418,7 +415,7 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
418 | info->cstate = PPTP_CALL_OUT_REQ; | 415 | info->cstate = PPTP_CALL_OUT_REQ; |
419 | /* track PNS call id */ | 416 | /* track PNS call id */ |
420 | cid = pptpReq->ocreq.callID; | 417 | cid = pptpReq->ocreq.callID; |
421 | DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid)); | 418 | pr_debug("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid)); |
422 | info->pns_call_id = cid; | 419 | info->pns_call_id = cid; |
423 | break; | 420 | break; |
424 | 421 | ||
@@ -432,8 +429,8 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
432 | pcid = pptpReq->icack.peersCallID; | 429 | pcid = pptpReq->icack.peersCallID; |
433 | if (info->pac_call_id != pcid) | 430 | if (info->pac_call_id != pcid) |
434 | goto invalid; | 431 | goto invalid; |
435 | DEBUGP("%s, CID=%X PCID=%X\n", pptp_msg_name[msg], | 432 | pr_debug("%s, CID=%X PCID=%X\n", pptp_msg_name[msg], |
436 | ntohs(cid), ntohs(pcid)); | 433 | ntohs(cid), ntohs(pcid)); |
437 | 434 | ||
438 | if (pptpReq->icack.resultCode == PPTP_INCALL_ACCEPT) { | 435 | if (pptpReq->icack.resultCode == PPTP_INCALL_ACCEPT) { |
439 | /* part two of the three-way handshake */ | 436 | /* part two of the three-way handshake */ |
@@ -469,11 +466,11 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
469 | return NF_ACCEPT; | 466 | return NF_ACCEPT; |
470 | 467 | ||
471 | invalid: | 468 | invalid: |
472 | DEBUGP("invalid %s: type=%d cid=%u pcid=%u " | 469 | pr_debug("invalid %s: type=%d cid=%u pcid=%u " |
473 | "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n", | 470 | "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n", |
474 | msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0], | 471 | msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0], |
475 | msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate, | 472 | msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate, |
476 | ntohs(info->pns_call_id), ntohs(info->pac_call_id)); | 473 | ntohs(info->pns_call_id), ntohs(info->pac_call_id)); |
477 | return NF_ACCEPT; | 474 | return NF_ACCEPT; |
478 | } | 475 | } |
479 | 476 | ||
@@ -524,7 +521,7 @@ conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff, | |||
524 | 521 | ||
525 | pptph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_pptph), &_pptph); | 522 | pptph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_pptph), &_pptph); |
526 | if (!pptph) { | 523 | if (!pptph) { |
527 | DEBUGP("no full PPTP header, can't track\n"); | 524 | pr_debug("no full PPTP header, can't track\n"); |
528 | return NF_ACCEPT; | 525 | return NF_ACCEPT; |
529 | } | 526 | } |
530 | nexthdr_off += sizeof(_pptph); | 527 | nexthdr_off += sizeof(_pptph); |
@@ -533,7 +530,7 @@ conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff, | |||
533 | /* if it's not a control message we can't do anything with it */ | 530 | /* if it's not a control message we can't do anything with it */ |
534 | if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL || | 531 | if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL || |
535 | ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) { | 532 | ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) { |
536 | DEBUGP("not a control packet\n"); | 533 | pr_debug("not a control packet\n"); |
537 | return NF_ACCEPT; | 534 | return NF_ACCEPT; |
538 | } | 535 | } |
539 | 536 | ||
@@ -569,8 +566,8 @@ conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff, | |||
569 | /* server -> client (PAC -> PNS) */ | 566 | /* server -> client (PAC -> PNS) */ |
570 | ret = pptp_inbound_pkt(pskb, ctlh, pptpReq, reqlen, ct, | 567 | ret = pptp_inbound_pkt(pskb, ctlh, pptpReq, reqlen, ct, |
571 | ctinfo); | 568 | ctinfo); |
572 | DEBUGP("sstate: %d->%d, cstate: %d->%d\n", | 569 | pr_debug("sstate: %d->%d, cstate: %d->%d\n", |
573 | oldsstate, info->sstate, oldcstate, info->cstate); | 570 | oldsstate, info->sstate, oldcstate, info->cstate); |
574 | spin_unlock_bh(&nf_pptp_lock); | 571 | spin_unlock_bh(&nf_pptp_lock); |
575 | 572 | ||
576 | return ret; | 573 | return ret; |
@@ -585,9 +582,6 @@ static struct nf_conntrack_helper pptp __read_mostly = { | |||
585 | .tuple.src.l3num = AF_INET, | 582 | .tuple.src.l3num = AF_INET, |
586 | .tuple.src.u.tcp.port = __constant_htons(PPTP_CONTROL_PORT), | 583 | .tuple.src.u.tcp.port = __constant_htons(PPTP_CONTROL_PORT), |
587 | .tuple.dst.protonum = IPPROTO_TCP, | 584 | .tuple.dst.protonum = IPPROTO_TCP, |
588 | .mask.src.l3num = 0xffff, | ||
589 | .mask.src.u.tcp.port = __constant_htons(0xffff), | ||
590 | .mask.dst.protonum = 0xff, | ||
591 | .help = conntrack_pptp_help, | 585 | .help = conntrack_pptp_help, |
592 | .destroy = pptp_destroy_siblings, | 586 | .destroy = pptp_destroy_siblings, |
593 | }; | 587 | }; |
diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c index 6faf1bed7224..d8b501878d9f 100644 --- a/net/netfilter/nf_conntrack_proto_generic.c +++ b/net/netfilter/nf_conntrack_proto_generic.c | |||
@@ -98,7 +98,7 @@ static struct ctl_table generic_compat_sysctl_table[] = { | |||
98 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ | 98 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ |
99 | #endif /* CONFIG_SYSCTL */ | 99 | #endif /* CONFIG_SYSCTL */ |
100 | 100 | ||
101 | struct nf_conntrack_l4proto nf_conntrack_l4proto_generic = | 101 | struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly = |
102 | { | 102 | { |
103 | .l3proto = PF_UNSPEC, | 103 | .l3proto = PF_UNSPEC, |
104 | .l4proto = 0, | 104 | .l4proto = 0, |
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c index 339c397d1b5f..bdbead8a7a83 100644 --- a/net/netfilter/nf_conntrack_proto_gre.c +++ b/net/netfilter/nf_conntrack_proto_gre.c | |||
@@ -40,12 +40,6 @@ | |||
40 | #define GRE_TIMEOUT (30 * HZ) | 40 | #define GRE_TIMEOUT (30 * HZ) |
41 | #define GRE_STREAM_TIMEOUT (180 * HZ) | 41 | #define GRE_STREAM_TIMEOUT (180 * HZ) |
42 | 42 | ||
43 | #if 0 | ||
44 | #define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args) | ||
45 | #else | ||
46 | #define DEBUGP(x, args...) | ||
47 | #endif | ||
48 | |||
49 | static DEFINE_RWLOCK(nf_ct_gre_lock); | 43 | static DEFINE_RWLOCK(nf_ct_gre_lock); |
50 | static LIST_HEAD(gre_keymap_list); | 44 | static LIST_HEAD(gre_keymap_list); |
51 | 45 | ||
@@ -87,7 +81,7 @@ static __be16 gre_keymap_lookup(struct nf_conntrack_tuple *t) | |||
87 | } | 81 | } |
88 | read_unlock_bh(&nf_ct_gre_lock); | 82 | read_unlock_bh(&nf_ct_gre_lock); |
89 | 83 | ||
90 | DEBUGP("lookup src key 0x%x for ", key); | 84 | pr_debug("lookup src key 0x%x for ", key); |
91 | NF_CT_DUMP_TUPLE(t); | 85 | NF_CT_DUMP_TUPLE(t); |
92 | 86 | ||
93 | return key; | 87 | return key; |
@@ -107,8 +101,8 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir, | |||
107 | if (gre_key_cmpfn(km, t) && km == *kmp) | 101 | if (gre_key_cmpfn(km, t) && km == *kmp) |
108 | return 0; | 102 | return 0; |
109 | } | 103 | } |
110 | DEBUGP("trying to override keymap_%s for ct %p\n", | 104 | pr_debug("trying to override keymap_%s for ct %p\n", |
111 | dir == IP_CT_DIR_REPLY ? "reply" : "orig", ct); | 105 | dir == IP_CT_DIR_REPLY ? "reply" : "orig", ct); |
112 | return -EEXIST; | 106 | return -EEXIST; |
113 | } | 107 | } |
114 | 108 | ||
@@ -118,7 +112,7 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir, | |||
118 | memcpy(&km->tuple, t, sizeof(*t)); | 112 | memcpy(&km->tuple, t, sizeof(*t)); |
119 | *kmp = km; | 113 | *kmp = km; |
120 | 114 | ||
121 | DEBUGP("adding new entry %p: ", km); | 115 | pr_debug("adding new entry %p: ", km); |
122 | NF_CT_DUMP_TUPLE(&km->tuple); | 116 | NF_CT_DUMP_TUPLE(&km->tuple); |
123 | 117 | ||
124 | write_lock_bh(&nf_ct_gre_lock); | 118 | write_lock_bh(&nf_ct_gre_lock); |
@@ -135,13 +129,13 @@ void nf_ct_gre_keymap_destroy(struct nf_conn *ct) | |||
135 | struct nf_conn_help *help = nfct_help(ct); | 129 | struct nf_conn_help *help = nfct_help(ct); |
136 | enum ip_conntrack_dir dir; | 130 | enum ip_conntrack_dir dir; |
137 | 131 | ||
138 | DEBUGP("entering for ct %p\n", ct); | 132 | pr_debug("entering for ct %p\n", ct); |
139 | 133 | ||
140 | write_lock_bh(&nf_ct_gre_lock); | 134 | write_lock_bh(&nf_ct_gre_lock); |
141 | for (dir = IP_CT_DIR_ORIGINAL; dir < IP_CT_DIR_MAX; dir++) { | 135 | for (dir = IP_CT_DIR_ORIGINAL; dir < IP_CT_DIR_MAX; dir++) { |
142 | if (help->help.ct_pptp_info.keymap[dir]) { | 136 | if (help->help.ct_pptp_info.keymap[dir]) { |
143 | DEBUGP("removing %p from list\n", | 137 | pr_debug("removing %p from list\n", |
144 | help->help.ct_pptp_info.keymap[dir]); | 138 | help->help.ct_pptp_info.keymap[dir]); |
145 | list_del(&help->help.ct_pptp_info.keymap[dir]->list); | 139 | list_del(&help->help.ct_pptp_info.keymap[dir]->list); |
146 | kfree(help->help.ct_pptp_info.keymap[dir]); | 140 | kfree(help->help.ct_pptp_info.keymap[dir]); |
147 | help->help.ct_pptp_info.keymap[dir] = NULL; | 141 | help->help.ct_pptp_info.keymap[dir] = NULL; |
@@ -186,7 +180,7 @@ static int gre_pkt_to_tuple(const struct sk_buff *skb, | |||
186 | return 1; | 180 | return 1; |
187 | 181 | ||
188 | if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) { | 182 | if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) { |
189 | DEBUGP("GRE_VERSION_PPTP but unknown proto\n"); | 183 | pr_debug("GRE_VERSION_PPTP but unknown proto\n"); |
190 | return 0; | 184 | return 0; |
191 | } | 185 | } |
192 | 186 | ||
@@ -242,7 +236,7 @@ static int gre_packet(struct nf_conn *ct, | |||
242 | static int gre_new(struct nf_conn *ct, const struct sk_buff *skb, | 236 | static int gre_new(struct nf_conn *ct, const struct sk_buff *skb, |
243 | unsigned int dataoff) | 237 | unsigned int dataoff) |
244 | { | 238 | { |
245 | DEBUGP(": "); | 239 | pr_debug(": "); |
246 | NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); | 240 | NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); |
247 | 241 | ||
248 | /* initialize to sane value. Ideally a conntrack helper | 242 | /* initialize to sane value. Ideally a conntrack helper |
@@ -258,16 +252,16 @@ static int gre_new(struct nf_conn *ct, const struct sk_buff *skb, | |||
258 | static void gre_destroy(struct nf_conn *ct) | 252 | static void gre_destroy(struct nf_conn *ct) |
259 | { | 253 | { |
260 | struct nf_conn *master = ct->master; | 254 | struct nf_conn *master = ct->master; |
261 | DEBUGP(" entering\n"); | 255 | pr_debug(" entering\n"); |
262 | 256 | ||
263 | if (!master) | 257 | if (!master) |
264 | DEBUGP("no master !?!\n"); | 258 | pr_debug("no master !?!\n"); |
265 | else | 259 | else |
266 | nf_ct_gre_keymap_destroy(master); | 260 | nf_ct_gre_keymap_destroy(master); |
267 | } | 261 | } |
268 | 262 | ||
269 | /* protocol helper struct */ | 263 | /* protocol helper struct */ |
270 | static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 = { | 264 | static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = { |
271 | .l3proto = AF_INET, | 265 | .l3proto = AF_INET, |
272 | .l4proto = IPPROTO_GRE, | 266 | .l4proto = IPPROTO_GRE, |
273 | .name = "gre", | 267 | .name = "gre", |
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index 0d3254b974c5..04192acc7c40 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c | |||
@@ -25,12 +25,6 @@ | |||
25 | #include <net/netfilter/nf_conntrack_l4proto.h> | 25 | #include <net/netfilter/nf_conntrack_l4proto.h> |
26 | #include <net/netfilter/nf_conntrack_ecache.h> | 26 | #include <net/netfilter/nf_conntrack_ecache.h> |
27 | 27 | ||
28 | #if 0 | ||
29 | #define DEBUGP(format, ...) printk(format, ## __VA_ARGS__) | ||
30 | #else | ||
31 | #define DEBUGP(format, args...) | ||
32 | #endif | ||
33 | |||
34 | /* Protects conntrack->proto.sctp */ | 28 | /* Protects conntrack->proto.sctp */ |
35 | static DEFINE_RWLOCK(sctp_lock); | 29 | static DEFINE_RWLOCK(sctp_lock); |
36 | 30 | ||
@@ -151,9 +145,6 @@ static int sctp_pkt_to_tuple(const struct sk_buff *skb, | |||
151 | { | 145 | { |
152 | sctp_sctphdr_t _hdr, *hp; | 146 | sctp_sctphdr_t _hdr, *hp; |
153 | 147 | ||
154 | DEBUGP(__FUNCTION__); | ||
155 | DEBUGP("\n"); | ||
156 | |||
157 | /* Actually only need first 8 bytes. */ | 148 | /* Actually only need first 8 bytes. */ |
158 | hp = skb_header_pointer(skb, dataoff, 8, &_hdr); | 149 | hp = skb_header_pointer(skb, dataoff, 8, &_hdr); |
159 | if (hp == NULL) | 150 | if (hp == NULL) |
@@ -167,9 +158,6 @@ static int sctp_pkt_to_tuple(const struct sk_buff *skb, | |||
167 | static int sctp_invert_tuple(struct nf_conntrack_tuple *tuple, | 158 | static int sctp_invert_tuple(struct nf_conntrack_tuple *tuple, |
168 | const struct nf_conntrack_tuple *orig) | 159 | const struct nf_conntrack_tuple *orig) |
169 | { | 160 | { |
170 | DEBUGP(__FUNCTION__); | ||
171 | DEBUGP("\n"); | ||
172 | |||
173 | tuple->src.u.sctp.port = orig->dst.u.sctp.port; | 161 | tuple->src.u.sctp.port = orig->dst.u.sctp.port; |
174 | tuple->dst.u.sctp.port = orig->src.u.sctp.port; | 162 | tuple->dst.u.sctp.port = orig->src.u.sctp.port; |
175 | return 1; | 163 | return 1; |
@@ -179,9 +167,6 @@ static int sctp_invert_tuple(struct nf_conntrack_tuple *tuple, | |||
179 | static int sctp_print_tuple(struct seq_file *s, | 167 | static int sctp_print_tuple(struct seq_file *s, |
180 | const struct nf_conntrack_tuple *tuple) | 168 | const struct nf_conntrack_tuple *tuple) |
181 | { | 169 | { |
182 | DEBUGP(__FUNCTION__); | ||
183 | DEBUGP("\n"); | ||
184 | |||
185 | return seq_printf(s, "sport=%hu dport=%hu ", | 170 | return seq_printf(s, "sport=%hu dport=%hu ", |
186 | ntohs(tuple->src.u.sctp.port), | 171 | ntohs(tuple->src.u.sctp.port), |
187 | ntohs(tuple->dst.u.sctp.port)); | 172 | ntohs(tuple->dst.u.sctp.port)); |
@@ -193,9 +178,6 @@ static int sctp_print_conntrack(struct seq_file *s, | |||
193 | { | 178 | { |
194 | enum sctp_conntrack state; | 179 | enum sctp_conntrack state; |
195 | 180 | ||
196 | DEBUGP(__FUNCTION__); | ||
197 | DEBUGP("\n"); | ||
198 | |||
199 | read_lock_bh(&sctp_lock); | 181 | read_lock_bh(&sctp_lock); |
200 | state = conntrack->proto.sctp.state; | 182 | state = conntrack->proto.sctp.state; |
201 | read_unlock_bh(&sctp_lock); | 183 | read_unlock_bh(&sctp_lock); |
@@ -219,13 +201,10 @@ static int do_basic_checks(struct nf_conn *conntrack, | |||
219 | sctp_chunkhdr_t _sch, *sch; | 201 | sctp_chunkhdr_t _sch, *sch; |
220 | int flag; | 202 | int flag; |
221 | 203 | ||
222 | DEBUGP(__FUNCTION__); | ||
223 | DEBUGP("\n"); | ||
224 | |||
225 | flag = 0; | 204 | flag = 0; |
226 | 205 | ||
227 | for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) { | 206 | for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) { |
228 | DEBUGP("Chunk Num: %d Type: %d\n", count, sch->type); | 207 | pr_debug("Chunk Num: %d Type: %d\n", count, sch->type); |
229 | 208 | ||
230 | if (sch->type == SCTP_CID_INIT | 209 | if (sch->type == SCTP_CID_INIT |
231 | || sch->type == SCTP_CID_INIT_ACK | 210 | || sch->type == SCTP_CID_INIT_ACK |
@@ -242,7 +221,7 @@ static int do_basic_checks(struct nf_conn *conntrack, | |||
242 | || sch->type == SCTP_CID_COOKIE_ECHO | 221 | || sch->type == SCTP_CID_COOKIE_ECHO |
243 | || flag) | 222 | || flag) |
244 | && count !=0) || !sch->length) { | 223 | && count !=0) || !sch->length) { |
245 | DEBUGP("Basic checks failed\n"); | 224 | pr_debug("Basic checks failed\n"); |
246 | return 1; | 225 | return 1; |
247 | } | 226 | } |
248 | 227 | ||
@@ -251,7 +230,7 @@ static int do_basic_checks(struct nf_conn *conntrack, | |||
251 | } | 230 | } |
252 | } | 231 | } |
253 | 232 | ||
254 | DEBUGP("Basic checks passed\n"); | 233 | pr_debug("Basic checks passed\n"); |
255 | return count == 0; | 234 | return count == 0; |
256 | } | 235 | } |
257 | 236 | ||
@@ -261,50 +240,47 @@ static int new_state(enum ip_conntrack_dir dir, | |||
261 | { | 240 | { |
262 | int i; | 241 | int i; |
263 | 242 | ||
264 | DEBUGP(__FUNCTION__); | 243 | pr_debug("Chunk type: %d\n", chunk_type); |
265 | DEBUGP("\n"); | ||
266 | |||
267 | DEBUGP("Chunk type: %d\n", chunk_type); | ||
268 | 244 | ||
269 | switch (chunk_type) { | 245 | switch (chunk_type) { |
270 | case SCTP_CID_INIT: | 246 | case SCTP_CID_INIT: |
271 | DEBUGP("SCTP_CID_INIT\n"); | 247 | pr_debug("SCTP_CID_INIT\n"); |
272 | i = 0; break; | 248 | i = 0; break; |
273 | case SCTP_CID_INIT_ACK: | 249 | case SCTP_CID_INIT_ACK: |
274 | DEBUGP("SCTP_CID_INIT_ACK\n"); | 250 | pr_debug("SCTP_CID_INIT_ACK\n"); |
275 | i = 1; break; | 251 | i = 1; break; |
276 | case SCTP_CID_ABORT: | 252 | case SCTP_CID_ABORT: |
277 | DEBUGP("SCTP_CID_ABORT\n"); | 253 | pr_debug("SCTP_CID_ABORT\n"); |
278 | i = 2; break; | 254 | i = 2; break; |
279 | case SCTP_CID_SHUTDOWN: | 255 | case SCTP_CID_SHUTDOWN: |
280 | DEBUGP("SCTP_CID_SHUTDOWN\n"); | 256 | pr_debug("SCTP_CID_SHUTDOWN\n"); |
281 | i = 3; break; | 257 | i = 3; break; |
282 | case SCTP_CID_SHUTDOWN_ACK: | 258 | case SCTP_CID_SHUTDOWN_ACK: |
283 | DEBUGP("SCTP_CID_SHUTDOWN_ACK\n"); | 259 | pr_debug("SCTP_CID_SHUTDOWN_ACK\n"); |
284 | i = 4; break; | 260 | i = 4; break; |
285 | case SCTP_CID_ERROR: | 261 | case SCTP_CID_ERROR: |
286 | DEBUGP("SCTP_CID_ERROR\n"); | 262 | pr_debug("SCTP_CID_ERROR\n"); |
287 | i = 5; break; | 263 | i = 5; break; |
288 | case SCTP_CID_COOKIE_ECHO: | 264 | case SCTP_CID_COOKIE_ECHO: |
289 | DEBUGP("SCTP_CID_COOKIE_ECHO\n"); | 265 | pr_debug("SCTP_CID_COOKIE_ECHO\n"); |
290 | i = 6; break; | 266 | i = 6; break; |
291 | case SCTP_CID_COOKIE_ACK: | 267 | case SCTP_CID_COOKIE_ACK: |
292 | DEBUGP("SCTP_CID_COOKIE_ACK\n"); | 268 | pr_debug("SCTP_CID_COOKIE_ACK\n"); |
293 | i = 7; break; | 269 | i = 7; break; |
294 | case SCTP_CID_SHUTDOWN_COMPLETE: | 270 | case SCTP_CID_SHUTDOWN_COMPLETE: |
295 | DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n"); | 271 | pr_debug("SCTP_CID_SHUTDOWN_COMPLETE\n"); |
296 | i = 8; break; | 272 | i = 8; break; |
297 | default: | 273 | default: |
298 | /* Other chunks like DATA, SACK, HEARTBEAT and | 274 | /* Other chunks like DATA, SACK, HEARTBEAT and |
299 | its ACK do not cause a change in state */ | 275 | its ACK do not cause a change in state */ |
300 | DEBUGP("Unknown chunk type, Will stay in %s\n", | 276 | pr_debug("Unknown chunk type, Will stay in %s\n", |
301 | sctp_conntrack_names[cur_state]); | 277 | sctp_conntrack_names[cur_state]); |
302 | return cur_state; | 278 | return cur_state; |
303 | } | 279 | } |
304 | 280 | ||
305 | DEBUGP("dir: %d cur_state: %s chunk_type: %d new_state: %s\n", | 281 | pr_debug("dir: %d cur_state: %s chunk_type: %d new_state: %s\n", |
306 | dir, sctp_conntrack_names[cur_state], chunk_type, | 282 | dir, sctp_conntrack_names[cur_state], chunk_type, |
307 | sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]); | 283 | sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]); |
308 | 284 | ||
309 | return sctp_conntracks[dir][i][cur_state]; | 285 | return sctp_conntracks[dir][i][cur_state]; |
310 | } | 286 | } |
@@ -323,9 +299,6 @@ static int sctp_packet(struct nf_conn *conntrack, | |||
323 | u_int32_t offset, count; | 299 | u_int32_t offset, count; |
324 | char map[256 / sizeof (char)] = {0}; | 300 | char map[256 / sizeof (char)] = {0}; |
325 | 301 | ||
326 | DEBUGP(__FUNCTION__); | ||
327 | DEBUGP("\n"); | ||
328 | |||
329 | sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph); | 302 | sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph); |
330 | if (sh == NULL) | 303 | if (sh == NULL) |
331 | return -1; | 304 | return -1; |
@@ -340,7 +313,7 @@ static int sctp_packet(struct nf_conn *conntrack, | |||
340 | && !test_bit(SCTP_CID_ABORT, (void *)map) | 313 | && !test_bit(SCTP_CID_ABORT, (void *)map) |
341 | && !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map) | 314 | && !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map) |
342 | && (sh->vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) { | 315 | && (sh->vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) { |
343 | DEBUGP("Verification tag check failed\n"); | 316 | pr_debug("Verification tag check failed\n"); |
344 | return -1; | 317 | return -1; |
345 | } | 318 | } |
346 | 319 | ||
@@ -385,8 +358,9 @@ static int sctp_packet(struct nf_conn *conntrack, | |||
385 | 358 | ||
386 | /* Invalid */ | 359 | /* Invalid */ |
387 | if (newconntrack == SCTP_CONNTRACK_MAX) { | 360 | if (newconntrack == SCTP_CONNTRACK_MAX) { |
388 | DEBUGP("nf_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n", | 361 | pr_debug("nf_conntrack_sctp: Invalid dir=%i ctype=%u " |
389 | CTINFO2DIR(ctinfo), sch->type, oldsctpstate); | 362 | "conntrack=%u\n", |
363 | CTINFO2DIR(ctinfo), sch->type, oldsctpstate); | ||
390 | write_unlock_bh(&sctp_lock); | 364 | write_unlock_bh(&sctp_lock); |
391 | return -1; | 365 | return -1; |
392 | } | 366 | } |
@@ -402,8 +376,8 @@ static int sctp_packet(struct nf_conn *conntrack, | |||
402 | write_unlock_bh(&sctp_lock); | 376 | write_unlock_bh(&sctp_lock); |
403 | return -1; | 377 | return -1; |
404 | } | 378 | } |
405 | DEBUGP("Setting vtag %x for dir %d\n", | 379 | pr_debug("Setting vtag %x for dir %d\n", |
406 | ih->init_tag, !CTINFO2DIR(ctinfo)); | 380 | ih->init_tag, !CTINFO2DIR(ctinfo)); |
407 | conntrack->proto.sctp.vtag[!CTINFO2DIR(ctinfo)] = ih->init_tag; | 381 | conntrack->proto.sctp.vtag[!CTINFO2DIR(ctinfo)] = ih->init_tag; |
408 | } | 382 | } |
409 | 383 | ||
@@ -418,7 +392,7 @@ static int sctp_packet(struct nf_conn *conntrack, | |||
418 | if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED | 392 | if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED |
419 | && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY | 393 | && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY |
420 | && newconntrack == SCTP_CONNTRACK_ESTABLISHED) { | 394 | && newconntrack == SCTP_CONNTRACK_ESTABLISHED) { |
421 | DEBUGP("Setting assured bit\n"); | 395 | pr_debug("Setting assured bit\n"); |
422 | set_bit(IPS_ASSURED_BIT, &conntrack->status); | 396 | set_bit(IPS_ASSURED_BIT, &conntrack->status); |
423 | nf_conntrack_event_cache(IPCT_STATUS, skb); | 397 | nf_conntrack_event_cache(IPCT_STATUS, skb); |
424 | } | 398 | } |
@@ -436,9 +410,6 @@ static int sctp_new(struct nf_conn *conntrack, const struct sk_buff *skb, | |||
436 | u_int32_t offset, count; | 410 | u_int32_t offset, count; |
437 | char map[256 / sizeof (char)] = {0}; | 411 | char map[256 / sizeof (char)] = {0}; |
438 | 412 | ||
439 | DEBUGP(__FUNCTION__); | ||
440 | DEBUGP("\n"); | ||
441 | |||
442 | sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph); | 413 | sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph); |
443 | if (sh == NULL) | 414 | if (sh == NULL) |
444 | return 0; | 415 | return 0; |
@@ -460,8 +431,9 @@ static int sctp_new(struct nf_conn *conntrack, const struct sk_buff *skb, | |||
460 | SCTP_CONNTRACK_NONE, sch->type); | 431 | SCTP_CONNTRACK_NONE, sch->type); |
461 | 432 | ||
462 | /* Invalid: delete conntrack */ | 433 | /* Invalid: delete conntrack */ |
463 | if (newconntrack == SCTP_CONNTRACK_MAX) { | 434 | if (newconntrack == SCTP_CONNTRACK_NONE || |
464 | DEBUGP("nf_conntrack_sctp: invalid new deleting.\n"); | 435 | newconntrack == SCTP_CONNTRACK_MAX) { |
436 | pr_debug("nf_conntrack_sctp: invalid new deleting.\n"); | ||
465 | return 0; | 437 | return 0; |
466 | } | 438 | } |
467 | 439 | ||
@@ -475,8 +447,8 @@ static int sctp_new(struct nf_conn *conntrack, const struct sk_buff *skb, | |||
475 | if (ih == NULL) | 447 | if (ih == NULL) |
476 | return 0; | 448 | return 0; |
477 | 449 | ||
478 | DEBUGP("Setting vtag %x for new conn\n", | 450 | pr_debug("Setting vtag %x for new conn\n", |
479 | ih->init_tag); | 451 | ih->init_tag); |
480 | 452 | ||
481 | conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = | 453 | conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = |
482 | ih->init_tag; | 454 | ih->init_tag; |
@@ -488,8 +460,8 @@ static int sctp_new(struct nf_conn *conntrack, const struct sk_buff *skb, | |||
488 | /* If it is a shutdown ack OOTB packet, we expect a return | 460 | /* If it is a shutdown ack OOTB packet, we expect a return |
489 | shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */ | 461 | shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */ |
490 | else { | 462 | else { |
491 | DEBUGP("Setting vtag %x for new conn OOTB\n", | 463 | pr_debug("Setting vtag %x for new conn OOTB\n", |
492 | sh->vtag); | 464 | sh->vtag); |
493 | conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sh->vtag; | 465 | conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sh->vtag; |
494 | } | 466 | } |
495 | 467 | ||
@@ -629,7 +601,7 @@ static struct ctl_table sctp_compat_sysctl_table[] = { | |||
629 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ | 601 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ |
630 | #endif | 602 | #endif |
631 | 603 | ||
632 | struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = { | 604 | static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = { |
633 | .l3proto = PF_INET, | 605 | .l3proto = PF_INET, |
634 | .l4proto = IPPROTO_SCTP, | 606 | .l4proto = IPPROTO_SCTP, |
635 | .name = "sctp", | 607 | .name = "sctp", |
@@ -650,7 +622,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = { | |||
650 | #endif | 622 | #endif |
651 | }; | 623 | }; |
652 | 624 | ||
653 | struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 = { | 625 | static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = { |
654 | .l3proto = PF_INET6, | 626 | .l3proto = PF_INET6, |
655 | .l4proto = IPPROTO_SCTP, | 627 | .l4proto = IPPROTO_SCTP, |
656 | .name = "sctp", | 628 | .name = "sctp", |
@@ -688,8 +660,6 @@ int __init nf_conntrack_proto_sctp_init(void) | |||
688 | cleanup_sctp4: | 660 | cleanup_sctp4: |
689 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4); | 661 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4); |
690 | out: | 662 | out: |
691 | DEBUGP("SCTP conntrack module loading %s\n", | ||
692 | ret ? "failed": "succeeded"); | ||
693 | return ret; | 663 | return ret; |
694 | } | 664 | } |
695 | 665 | ||
@@ -697,7 +667,6 @@ void __exit nf_conntrack_proto_sctp_fini(void) | |||
697 | { | 667 | { |
698 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6); | 668 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6); |
699 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4); | 669 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4); |
700 | DEBUGP("SCTP conntrack module unloaded\n"); | ||
701 | } | 670 | } |
702 | 671 | ||
703 | module_init(nf_conntrack_proto_sctp_init); | 672 | module_init(nf_conntrack_proto_sctp_init); |
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index ccdd5d231e0d..87ad3ccf8aff 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
@@ -26,13 +26,6 @@ | |||
26 | #include <net/netfilter/nf_conntrack_l4proto.h> | 26 | #include <net/netfilter/nf_conntrack_l4proto.h> |
27 | #include <net/netfilter/nf_conntrack_ecache.h> | 27 | #include <net/netfilter/nf_conntrack_ecache.h> |
28 | 28 | ||
29 | #if 0 | ||
30 | #define DEBUGP printk | ||
31 | #define DEBUGP_VARS | ||
32 | #else | ||
33 | #define DEBUGP(format, args...) | ||
34 | #endif | ||
35 | |||
36 | /* Protects conntrack->proto.tcp */ | 29 | /* Protects conntrack->proto.tcp */ |
37 | static DEFINE_RWLOCK(tcp_lock); | 30 | static DEFINE_RWLOCK(tcp_lock); |
38 | 31 | ||
@@ -496,7 +489,8 @@ static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff, | |||
496 | } | 489 | } |
497 | } | 490 | } |
498 | 491 | ||
499 | static int tcp_in_window(struct ip_ct_tcp *state, | 492 | static int tcp_in_window(struct nf_conn *ct, |
493 | struct ip_ct_tcp *state, | ||
500 | enum ip_conntrack_dir dir, | 494 | enum ip_conntrack_dir dir, |
501 | unsigned int index, | 495 | unsigned int index, |
502 | const struct sk_buff *skb, | 496 | const struct sk_buff *skb, |
@@ -506,6 +500,7 @@ static int tcp_in_window(struct ip_ct_tcp *state, | |||
506 | { | 500 | { |
507 | struct ip_ct_tcp_state *sender = &state->seen[dir]; | 501 | struct ip_ct_tcp_state *sender = &state->seen[dir]; |
508 | struct ip_ct_tcp_state *receiver = &state->seen[!dir]; | 502 | struct ip_ct_tcp_state *receiver = &state->seen[!dir]; |
503 | struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple; | ||
509 | __u32 seq, ack, sack, end, win, swin; | 504 | __u32 seq, ack, sack, end, win, swin; |
510 | int res; | 505 | int res; |
511 | 506 | ||
@@ -520,18 +515,17 @@ static int tcp_in_window(struct ip_ct_tcp *state, | |||
520 | if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM) | 515 | if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM) |
521 | tcp_sack(skb, dataoff, tcph, &sack); | 516 | tcp_sack(skb, dataoff, tcph, &sack); |
522 | 517 | ||
523 | DEBUGP("tcp_in_window: START\n"); | 518 | pr_debug("tcp_in_window: START\n"); |
524 | DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu " | 519 | pr_debug("tcp_in_window: "); |
525 | "seq=%u ack=%u sack=%u win=%u end=%u\n", | 520 | NF_CT_DUMP_TUPLE(tuple); |
526 | NIPQUAD(iph->saddr), ntohs(tcph->source), | 521 | pr_debug("seq=%u ack=%u sack=%u win=%u end=%u\n", |
527 | NIPQUAD(iph->daddr), ntohs(tcph->dest), | 522 | seq, ack, sack, win, end); |
528 | seq, ack, sack, win, end); | 523 | pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i " |
529 | DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i " | 524 | "receiver end=%u maxend=%u maxwin=%u scale=%i\n", |
530 | "receiver end=%u maxend=%u maxwin=%u scale=%i\n", | 525 | sender->td_end, sender->td_maxend, sender->td_maxwin, |
531 | sender->td_end, sender->td_maxend, sender->td_maxwin, | 526 | sender->td_scale, |
532 | sender->td_scale, | 527 | receiver->td_end, receiver->td_maxend, receiver->td_maxwin, |
533 | receiver->td_end, receiver->td_maxend, receiver->td_maxwin, | 528 | receiver->td_scale); |
534 | receiver->td_scale); | ||
535 | 529 | ||
536 | if (sender->td_end == 0) { | 530 | if (sender->td_end == 0) { |
537 | /* | 531 | /* |
@@ -609,23 +603,22 @@ static int tcp_in_window(struct ip_ct_tcp *state, | |||
609 | */ | 603 | */ |
610 | seq = end = sender->td_end; | 604 | seq = end = sender->td_end; |
611 | 605 | ||
612 | DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu " | 606 | pr_debug("tcp_in_window: "); |
613 | "seq=%u ack=%u sack =%u win=%u end=%u\n", | 607 | NF_CT_DUMP_TUPLE(tuple); |
614 | NIPQUAD(iph->saddr), ntohs(tcph->source), | 608 | pr_debug("seq=%u ack=%u sack =%u win=%u end=%u\n", |
615 | NIPQUAD(iph->daddr), ntohs(tcph->dest), | 609 | seq, ack, sack, win, end); |
616 | seq, ack, sack, win, end); | 610 | pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i " |
617 | DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i " | 611 | "receiver end=%u maxend=%u maxwin=%u scale=%i\n", |
618 | "receiver end=%u maxend=%u maxwin=%u scale=%i\n", | 612 | sender->td_end, sender->td_maxend, sender->td_maxwin, |
619 | sender->td_end, sender->td_maxend, sender->td_maxwin, | 613 | sender->td_scale, |
620 | sender->td_scale, | 614 | receiver->td_end, receiver->td_maxend, receiver->td_maxwin, |
621 | receiver->td_end, receiver->td_maxend, receiver->td_maxwin, | 615 | receiver->td_scale); |
622 | receiver->td_scale); | 616 | |
623 | 617 | pr_debug("tcp_in_window: I=%i II=%i III=%i IV=%i\n", | |
624 | DEBUGP("tcp_in_window: I=%i II=%i III=%i IV=%i\n", | 618 | before(seq, sender->td_maxend + 1), |
625 | before(seq, sender->td_maxend + 1), | 619 | after(end, sender->td_end - receiver->td_maxwin - 1), |
626 | after(end, sender->td_end - receiver->td_maxwin - 1), | 620 | before(sack, receiver->td_end + 1), |
627 | before(sack, receiver->td_end + 1), | 621 | after(ack, receiver->td_end - MAXACKWINDOW(sender))); |
628 | after(ack, receiver->td_end - MAXACKWINDOW(sender))); | ||
629 | 622 | ||
630 | if (before(seq, sender->td_maxend + 1) && | 623 | if (before(seq, sender->td_maxend + 1) && |
631 | after(end, sender->td_end - receiver->td_maxwin - 1) && | 624 | after(end, sender->td_end - receiver->td_maxwin - 1) && |
@@ -694,10 +687,10 @@ static int tcp_in_window(struct ip_ct_tcp *state, | |||
694 | : "SEQ is over the upper bound (over the window of the receiver)"); | 687 | : "SEQ is over the upper bound (over the window of the receiver)"); |
695 | } | 688 | } |
696 | 689 | ||
697 | DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u " | 690 | pr_debug("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u " |
698 | "receiver end=%u maxend=%u maxwin=%u\n", | 691 | "receiver end=%u maxend=%u maxwin=%u\n", |
699 | res, sender->td_end, sender->td_maxend, sender->td_maxwin, | 692 | res, sender->td_end, sender->td_maxend, sender->td_maxwin, |
700 | receiver->td_end, receiver->td_maxend, receiver->td_maxwin); | 693 | receiver->td_end, receiver->td_maxend, receiver->td_maxwin); |
701 | 694 | ||
702 | return res; | 695 | return res; |
703 | } | 696 | } |
@@ -711,11 +704,9 @@ void nf_conntrack_tcp_update(struct sk_buff *skb, | |||
711 | int dir) | 704 | int dir) |
712 | { | 705 | { |
713 | struct tcphdr *tcph = (void *)skb->data + dataoff; | 706 | struct tcphdr *tcph = (void *)skb->data + dataoff; |
714 | __u32 end; | ||
715 | #ifdef DEBUGP_VARS | ||
716 | struct ip_ct_tcp_state *sender = &conntrack->proto.tcp.seen[dir]; | 707 | struct ip_ct_tcp_state *sender = &conntrack->proto.tcp.seen[dir]; |
717 | struct ip_ct_tcp_state *receiver = &conntrack->proto.tcp.seen[!dir]; | 708 | struct ip_ct_tcp_state *receiver = &conntrack->proto.tcp.seen[!dir]; |
718 | #endif | 709 | __u32 end; |
719 | 710 | ||
720 | end = segment_seq_plus_len(ntohl(tcph->seq), skb->len, dataoff, tcph); | 711 | end = segment_seq_plus_len(ntohl(tcph->seq), skb->len, dataoff, tcph); |
721 | 712 | ||
@@ -727,12 +718,12 @@ void nf_conntrack_tcp_update(struct sk_buff *skb, | |||
727 | conntrack->proto.tcp.seen[dir].td_end = end; | 718 | conntrack->proto.tcp.seen[dir].td_end = end; |
728 | conntrack->proto.tcp.last_end = end; | 719 | conntrack->proto.tcp.last_end = end; |
729 | write_unlock_bh(&tcp_lock); | 720 | write_unlock_bh(&tcp_lock); |
730 | DEBUGP("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i " | 721 | pr_debug("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i " |
731 | "receiver end=%u maxend=%u maxwin=%u scale=%i\n", | 722 | "receiver end=%u maxend=%u maxwin=%u scale=%i\n", |
732 | sender->td_end, sender->td_maxend, sender->td_maxwin, | 723 | sender->td_end, sender->td_maxend, sender->td_maxwin, |
733 | sender->td_scale, | 724 | sender->td_scale, |
734 | receiver->td_end, receiver->td_maxend, receiver->td_maxwin, | 725 | receiver->td_end, receiver->td_maxend, receiver->td_maxwin, |
735 | receiver->td_scale); | 726 | receiver->td_scale); |
736 | } | 727 | } |
737 | EXPORT_SYMBOL_GPL(nf_conntrack_tcp_update); | 728 | EXPORT_SYMBOL_GPL(nf_conntrack_tcp_update); |
738 | #endif | 729 | #endif |
@@ -823,6 +814,7 @@ static int tcp_packet(struct nf_conn *conntrack, | |||
823 | int pf, | 814 | int pf, |
824 | unsigned int hooknum) | 815 | unsigned int hooknum) |
825 | { | 816 | { |
817 | struct nf_conntrack_tuple *tuple; | ||
826 | enum tcp_conntrack new_state, old_state; | 818 | enum tcp_conntrack new_state, old_state; |
827 | enum ip_conntrack_dir dir; | 819 | enum ip_conntrack_dir dir; |
828 | struct tcphdr *th, _tcph; | 820 | struct tcphdr *th, _tcph; |
@@ -837,6 +829,7 @@ static int tcp_packet(struct nf_conn *conntrack, | |||
837 | dir = CTINFO2DIR(ctinfo); | 829 | dir = CTINFO2DIR(ctinfo); |
838 | index = get_conntrack_index(th); | 830 | index = get_conntrack_index(th); |
839 | new_state = tcp_conntracks[dir][index][old_state]; | 831 | new_state = tcp_conntracks[dir][index][old_state]; |
832 | tuple = &conntrack->tuplehash[dir].tuple; | ||
840 | 833 | ||
841 | switch (new_state) { | 834 | switch (new_state) { |
842 | case TCP_CONNTRACK_IGNORE: | 835 | case TCP_CONNTRACK_IGNORE: |
@@ -880,9 +873,8 @@ static int tcp_packet(struct nf_conn *conntrack, | |||
880 | return NF_ACCEPT; | 873 | return NF_ACCEPT; |
881 | case TCP_CONNTRACK_MAX: | 874 | case TCP_CONNTRACK_MAX: |
882 | /* Invalid packet */ | 875 | /* Invalid packet */ |
883 | DEBUGP("nf_ct_tcp: Invalid dir=%i index=%u ostate=%u\n", | 876 | pr_debug("nf_ct_tcp: Invalid dir=%i index=%u ostate=%u\n", |
884 | dir, get_conntrack_index(th), | 877 | dir, get_conntrack_index(th), old_state); |
885 | old_state); | ||
886 | write_unlock_bh(&tcp_lock); | 878 | write_unlock_bh(&tcp_lock); |
887 | if (LOG_INVALID(IPPROTO_TCP)) | 879 | if (LOG_INVALID(IPPROTO_TCP)) |
888 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, | 880 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, |
@@ -933,7 +925,7 @@ static int tcp_packet(struct nf_conn *conntrack, | |||
933 | break; | 925 | break; |
934 | } | 926 | } |
935 | 927 | ||
936 | if (!tcp_in_window(&conntrack->proto.tcp, dir, index, | 928 | if (!tcp_in_window(conntrack, &conntrack->proto.tcp, dir, index, |
937 | skb, dataoff, th, pf)) { | 929 | skb, dataoff, th, pf)) { |
938 | write_unlock_bh(&tcp_lock); | 930 | write_unlock_bh(&tcp_lock); |
939 | return -NF_ACCEPT; | 931 | return -NF_ACCEPT; |
@@ -942,13 +934,12 @@ static int tcp_packet(struct nf_conn *conntrack, | |||
942 | /* From now on we have got in-window packets */ | 934 | /* From now on we have got in-window packets */ |
943 | conntrack->proto.tcp.last_index = index; | 935 | conntrack->proto.tcp.last_index = index; |
944 | 936 | ||
945 | DEBUGP("tcp_conntracks: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu " | 937 | pr_debug("tcp_conntracks: "); |
946 | "syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n", | 938 | NF_CT_DUMP_TUPLE(tuple); |
947 | NIPQUAD(iph->saddr), ntohs(th->source), | 939 | pr_debug("syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n", |
948 | NIPQUAD(iph->daddr), ntohs(th->dest), | 940 | (th->syn ? 1 : 0), (th->ack ? 1 : 0), |
949 | (th->syn ? 1 : 0), (th->ack ? 1 : 0), | 941 | (th->fin ? 1 : 0), (th->rst ? 1 : 0), |
950 | (th->fin ? 1 : 0), (th->rst ? 1 : 0), | 942 | old_state, new_state); |
951 | old_state, new_state); | ||
952 | 943 | ||
953 | conntrack->proto.tcp.state = new_state; | 944 | conntrack->proto.tcp.state = new_state; |
954 | if (old_state != new_state | 945 | if (old_state != new_state |
@@ -997,10 +988,8 @@ static int tcp_new(struct nf_conn *conntrack, | |||
997 | { | 988 | { |
998 | enum tcp_conntrack new_state; | 989 | enum tcp_conntrack new_state; |
999 | struct tcphdr *th, _tcph; | 990 | struct tcphdr *th, _tcph; |
1000 | #ifdef DEBUGP_VARS | ||
1001 | struct ip_ct_tcp_state *sender = &conntrack->proto.tcp.seen[0]; | 991 | struct ip_ct_tcp_state *sender = &conntrack->proto.tcp.seen[0]; |
1002 | struct ip_ct_tcp_state *receiver = &conntrack->proto.tcp.seen[1]; | 992 | struct ip_ct_tcp_state *receiver = &conntrack->proto.tcp.seen[1]; |
1003 | #endif | ||
1004 | 993 | ||
1005 | th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph); | 994 | th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph); |
1006 | BUG_ON(th == NULL); | 995 | BUG_ON(th == NULL); |
@@ -1012,7 +1001,7 @@ static int tcp_new(struct nf_conn *conntrack, | |||
1012 | 1001 | ||
1013 | /* Invalid: delete conntrack */ | 1002 | /* Invalid: delete conntrack */ |
1014 | if (new_state >= TCP_CONNTRACK_MAX) { | 1003 | if (new_state >= TCP_CONNTRACK_MAX) { |
1015 | DEBUGP("nf_ct_tcp: invalid new deleting.\n"); | 1004 | pr_debug("nf_ct_tcp: invalid new deleting.\n"); |
1016 | return 0; | 1005 | return 0; |
1017 | } | 1006 | } |
1018 | 1007 | ||
@@ -1065,12 +1054,12 @@ static int tcp_new(struct nf_conn *conntrack, | |||
1065 | conntrack->proto.tcp.state = TCP_CONNTRACK_NONE; | 1054 | conntrack->proto.tcp.state = TCP_CONNTRACK_NONE; |
1066 | conntrack->proto.tcp.last_index = TCP_NONE_SET; | 1055 | conntrack->proto.tcp.last_index = TCP_NONE_SET; |
1067 | 1056 | ||
1068 | DEBUGP("tcp_new: sender end=%u maxend=%u maxwin=%u scale=%i " | 1057 | pr_debug("tcp_new: sender end=%u maxend=%u maxwin=%u scale=%i " |
1069 | "receiver end=%u maxend=%u maxwin=%u scale=%i\n", | 1058 | "receiver end=%u maxend=%u maxwin=%u scale=%i\n", |
1070 | sender->td_end, sender->td_maxend, sender->td_maxwin, | 1059 | sender->td_end, sender->td_maxend, sender->td_maxwin, |
1071 | sender->td_scale, | 1060 | sender->td_scale, |
1072 | receiver->td_end, receiver->td_maxend, receiver->td_maxwin, | 1061 | receiver->td_end, receiver->td_maxend, receiver->td_maxwin, |
1073 | receiver->td_scale); | 1062 | receiver->td_scale); |
1074 | return 1; | 1063 | return 1; |
1075 | } | 1064 | } |
1076 | 1065 | ||
@@ -1383,7 +1372,7 @@ static struct ctl_table tcp_compat_sysctl_table[] = { | |||
1383 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ | 1372 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ |
1384 | #endif /* CONFIG_SYSCTL */ | 1373 | #endif /* CONFIG_SYSCTL */ |
1385 | 1374 | ||
1386 | struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 = | 1375 | struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 __read_mostly = |
1387 | { | 1376 | { |
1388 | .l3proto = PF_INET, | 1377 | .l3proto = PF_INET, |
1389 | .l4proto = IPPROTO_TCP, | 1378 | .l4proto = IPPROTO_TCP, |
@@ -1412,7 +1401,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 = | |||
1412 | }; | 1401 | }; |
1413 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp4); | 1402 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp4); |
1414 | 1403 | ||
1415 | struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 = | 1404 | struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 __read_mostly = |
1416 | { | 1405 | { |
1417 | .l3proto = PF_INET6, | 1406 | .l3proto = PF_INET6, |
1418 | .l4proto = IPPROTO_TCP, | 1407 | .l4proto = IPPROTO_TCP, |
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index 3620ecc095fd..13d94a025723 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c | |||
@@ -191,7 +191,7 @@ static struct ctl_table udp_compat_sysctl_table[] = { | |||
191 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ | 191 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ |
192 | #endif /* CONFIG_SYSCTL */ | 192 | #endif /* CONFIG_SYSCTL */ |
193 | 193 | ||
194 | struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 = | 194 | struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly = |
195 | { | 195 | { |
196 | .l3proto = PF_INET, | 196 | .l3proto = PF_INET, |
197 | .l4proto = IPPROTO_UDP, | 197 | .l4proto = IPPROTO_UDP, |
@@ -218,7 +218,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 = | |||
218 | }; | 218 | }; |
219 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp4); | 219 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp4); |
220 | 220 | ||
221 | struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 = | 221 | struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 __read_mostly = |
222 | { | 222 | { |
223 | .l3proto = PF_INET6, | 223 | .l3proto = PF_INET6, |
224 | .l4proto = IPPROTO_UDP, | 224 | .l4proto = IPPROTO_UDP, |
diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c new file mode 100644 index 000000000000..93e747b5396e --- /dev/null +++ b/net/netfilter/nf_conntrack_proto_udplite.c | |||
@@ -0,0 +1,266 @@ | |||
1 | /* (C) 1999-2001 Paul `Rusty' Russell | ||
2 | * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> | ||
3 | * (C) 2007 Patrick McHardy <kaber@trash.net> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | #include <linux/types.h> | ||
11 | #include <linux/timer.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/netfilter.h> | ||
14 | #include <linux/udp.h> | ||
15 | #include <linux/seq_file.h> | ||
16 | #include <linux/skbuff.h> | ||
17 | #include <linux/ipv6.h> | ||
18 | #include <net/ip6_checksum.h> | ||
19 | #include <net/checksum.h> | ||
20 | |||
21 | #include <linux/netfilter.h> | ||
22 | #include <linux/netfilter_ipv4.h> | ||
23 | #include <linux/netfilter_ipv6.h> | ||
24 | #include <net/netfilter/nf_conntrack_l4proto.h> | ||
25 | #include <net/netfilter/nf_conntrack_ecache.h> | ||
26 | |||
27 | static unsigned int nf_ct_udplite_timeout __read_mostly = 30*HZ; | ||
28 | static unsigned int nf_ct_udplite_timeout_stream __read_mostly = 180*HZ; | ||
29 | |||
30 | static int udplite_pkt_to_tuple(const struct sk_buff *skb, | ||
31 | unsigned int dataoff, | ||
32 | struct nf_conntrack_tuple *tuple) | ||
33 | { | ||
34 | struct udphdr _hdr, *hp; | ||
35 | |||
36 | hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr); | ||
37 | if (hp == NULL) | ||
38 | return 0; | ||
39 | |||
40 | tuple->src.u.udp.port = hp->source; | ||
41 | tuple->dst.u.udp.port = hp->dest; | ||
42 | return 1; | ||
43 | } | ||
44 | |||
45 | static int udplite_invert_tuple(struct nf_conntrack_tuple *tuple, | ||
46 | const struct nf_conntrack_tuple *orig) | ||
47 | { | ||
48 | tuple->src.u.udp.port = orig->dst.u.udp.port; | ||
49 | tuple->dst.u.udp.port = orig->src.u.udp.port; | ||
50 | return 1; | ||
51 | } | ||
52 | |||
53 | /* Print out the per-protocol part of the tuple. */ | ||
54 | static int udplite_print_tuple(struct seq_file *s, | ||
55 | const struct nf_conntrack_tuple *tuple) | ||
56 | { | ||
57 | return seq_printf(s, "sport=%hu dport=%hu ", | ||
58 | ntohs(tuple->src.u.udp.port), | ||
59 | ntohs(tuple->dst.u.udp.port)); | ||
60 | } | ||
61 | |||
62 | /* Print out the private part of the conntrack. */ | ||
63 | static int udplite_print_conntrack(struct seq_file *s, | ||
64 | const struct nf_conn *conntrack) | ||
65 | { | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | /* Returns verdict for packet, and may modify conntracktype */ | ||
70 | static int udplite_packet(struct nf_conn *conntrack, | ||
71 | const struct sk_buff *skb, | ||
72 | unsigned int dataoff, | ||
73 | enum ip_conntrack_info ctinfo, | ||
74 | int pf, | ||
75 | unsigned int hooknum) | ||
76 | { | ||
77 | /* If we've seen traffic both ways, this is some kind of UDP | ||
78 | stream. Extend timeout. */ | ||
79 | if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) { | ||
80 | nf_ct_refresh_acct(conntrack, ctinfo, skb, | ||
81 | nf_ct_udplite_timeout_stream); | ||
82 | /* Also, more likely to be important, and not a probe */ | ||
83 | if (!test_and_set_bit(IPS_ASSURED_BIT, &conntrack->status)) | ||
84 | nf_conntrack_event_cache(IPCT_STATUS, skb); | ||
85 | } else | ||
86 | nf_ct_refresh_acct(conntrack, ctinfo, skb, | ||
87 | nf_ct_udplite_timeout); | ||
88 | |||
89 | return NF_ACCEPT; | ||
90 | } | ||
91 | |||
92 | /* Called when a new connection for this protocol found. */ | ||
93 | static int udplite_new(struct nf_conn *conntrack, const struct sk_buff *skb, | ||
94 | unsigned int dataoff) | ||
95 | { | ||
96 | return 1; | ||
97 | } | ||
98 | |||
99 | static int udplite_error(struct sk_buff *skb, unsigned int dataoff, | ||
100 | enum ip_conntrack_info *ctinfo, | ||
101 | int pf, | ||
102 | unsigned int hooknum) | ||
103 | { | ||
104 | unsigned int udplen = skb->len - dataoff; | ||
105 | struct udphdr _hdr, *hdr; | ||
106 | unsigned int cscov; | ||
107 | |||
108 | /* Header is too small? */ | ||
109 | hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr); | ||
110 | if (hdr == NULL) { | ||
111 | if (LOG_INVALID(IPPROTO_UDPLITE)) | ||
112 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, | ||
113 | "nf_ct_udplite: short packet "); | ||
114 | return -NF_ACCEPT; | ||
115 | } | ||
116 | |||
117 | cscov = ntohs(hdr->len); | ||
118 | if (cscov == 0) | ||
119 | cscov = udplen; | ||
120 | else if (cscov < sizeof(*hdr) || cscov > udplen) { | ||
121 | if (LOG_INVALID(IPPROTO_UDPLITE)) | ||
122 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, | ||
123 | "nf_ct_udplite: invalid checksum coverage "); | ||
124 | return -NF_ACCEPT; | ||
125 | } | ||
126 | |||
127 | /* UDPLITE mandates checksums */ | ||
128 | if (!hdr->check) { | ||
129 | if (LOG_INVALID(IPPROTO_UDPLITE)) | ||
130 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, | ||
131 | "nf_ct_udplite: checksum missing "); | ||
132 | return -NF_ACCEPT; | ||
133 | } | ||
134 | |||
135 | /* Checksum invalid? Ignore. */ | ||
136 | if (nf_conntrack_checksum && !skb_csum_unnecessary(skb) && | ||
137 | ((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) || | ||
138 | (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING))) { | ||
139 | if (pf == PF_INET) { | ||
140 | struct iphdr *iph = ip_hdr(skb); | ||
141 | |||
142 | skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr, | ||
143 | udplen, IPPROTO_UDPLITE, 0); | ||
144 | } else { | ||
145 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); | ||
146 | __wsum hsum = skb_checksum(skb, 0, dataoff, 0); | ||
147 | |||
148 | skb->csum = ~csum_unfold( | ||
149 | csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, | ||
150 | udplen, IPPROTO_UDPLITE, | ||
151 | csum_sub(0, hsum))); | ||
152 | } | ||
153 | |||
154 | skb->ip_summed = CHECKSUM_NONE; | ||
155 | if (__skb_checksum_complete_head(skb, dataoff + cscov)) { | ||
156 | if (LOG_INVALID(IPPROTO_UDPLITE)) | ||
157 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, | ||
158 | "nf_ct_udplite: bad UDPLite " | ||
159 | "checksum "); | ||
160 | return -NF_ACCEPT; | ||
161 | } | ||
162 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
163 | } | ||
164 | |||
165 | return NF_ACCEPT; | ||
166 | } | ||
167 | |||
168 | #ifdef CONFIG_SYSCTL | ||
169 | static unsigned int udplite_sysctl_table_users; | ||
170 | static struct ctl_table_header *udplite_sysctl_header; | ||
171 | static struct ctl_table udplite_sysctl_table[] = { | ||
172 | { | ||
173 | .ctl_name = CTL_UNNUMBERED, | ||
174 | .procname = "nf_conntrack_udplite_timeout", | ||
175 | .data = &nf_ct_udplite_timeout, | ||
176 | .maxlen = sizeof(unsigned int), | ||
177 | .mode = 0644, | ||
178 | .proc_handler = &proc_dointvec_jiffies, | ||
179 | }, | ||
180 | { | ||
181 | .ctl_name = CTL_UNNUMBERED, | ||
182 | .procname = "nf_conntrack_udplite_timeout_stream", | ||
183 | .data = &nf_ct_udplite_timeout_stream, | ||
184 | .maxlen = sizeof(unsigned int), | ||
185 | .mode = 0644, | ||
186 | .proc_handler = &proc_dointvec_jiffies, | ||
187 | }, | ||
188 | { | ||
189 | .ctl_name = 0 | ||
190 | } | ||
191 | }; | ||
192 | #endif /* CONFIG_SYSCTL */ | ||
193 | |||
194 | static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly = | ||
195 | { | ||
196 | .l3proto = PF_INET, | ||
197 | .l4proto = IPPROTO_UDPLITE, | ||
198 | .name = "udplite", | ||
199 | .pkt_to_tuple = udplite_pkt_to_tuple, | ||
200 | .invert_tuple = udplite_invert_tuple, | ||
201 | .print_tuple = udplite_print_tuple, | ||
202 | .print_conntrack = udplite_print_conntrack, | ||
203 | .packet = udplite_packet, | ||
204 | .new = udplite_new, | ||
205 | .error = udplite_error, | ||
206 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | ||
207 | .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, | ||
208 | .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple, | ||
209 | #endif | ||
210 | #ifdef CONFIG_SYSCTL | ||
211 | .ctl_table_users = &udplite_sysctl_table_users, | ||
212 | .ctl_table_header = &udplite_sysctl_header, | ||
213 | .ctl_table = udplite_sysctl_table, | ||
214 | #endif | ||
215 | }; | ||
216 | |||
217 | static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly = | ||
218 | { | ||
219 | .l3proto = PF_INET6, | ||
220 | .l4proto = IPPROTO_UDPLITE, | ||
221 | .name = "udplite", | ||
222 | .pkt_to_tuple = udplite_pkt_to_tuple, | ||
223 | .invert_tuple = udplite_invert_tuple, | ||
224 | .print_tuple = udplite_print_tuple, | ||
225 | .print_conntrack = udplite_print_conntrack, | ||
226 | .packet = udplite_packet, | ||
227 | .new = udplite_new, | ||
228 | .error = udplite_error, | ||
229 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | ||
230 | .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, | ||
231 | .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple, | ||
232 | #endif | ||
233 | #ifdef CONFIG_SYSCTL | ||
234 | .ctl_table_users = &udplite_sysctl_table_users, | ||
235 | .ctl_table_header = &udplite_sysctl_header, | ||
236 | .ctl_table = udplite_sysctl_table, | ||
237 | #endif | ||
238 | }; | ||
239 | |||
240 | static int __init nf_conntrack_proto_udplite_init(void) | ||
241 | { | ||
242 | int err; | ||
243 | |||
244 | err = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite4); | ||
245 | if (err < 0) | ||
246 | goto err1; | ||
247 | err = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite6); | ||
248 | if (err < 0) | ||
249 | goto err2; | ||
250 | return 0; | ||
251 | err2: | ||
252 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4); | ||
253 | err1: | ||
254 | return err; | ||
255 | } | ||
256 | |||
257 | static void __exit nf_conntrack_proto_udplite_exit(void) | ||
258 | { | ||
259 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite6); | ||
260 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4); | ||
261 | } | ||
262 | |||
263 | module_init(nf_conntrack_proto_udplite_init); | ||
264 | module_exit(nf_conntrack_proto_udplite_exit); | ||
265 | |||
266 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c index eb2d1dc46d45..355d371bac93 100644 --- a/net/netfilter/nf_conntrack_sane.c +++ b/net/netfilter/nf_conntrack_sane.c | |||
@@ -40,12 +40,6 @@ static u_int16_t ports[MAX_PORTS]; | |||
40 | static unsigned int ports_c; | 40 | static unsigned int ports_c; |
41 | module_param_array(ports, ushort, &ports_c, 0400); | 41 | module_param_array(ports, ushort, &ports_c, 0400); |
42 | 42 | ||
43 | #if 0 | ||
44 | #define DEBUGP printk | ||
45 | #else | ||
46 | #define DEBUGP(format, args...) | ||
47 | #endif | ||
48 | |||
49 | struct sane_request { | 43 | struct sane_request { |
50 | __be32 RPC_code; | 44 | __be32 RPC_code; |
51 | #define SANE_NET_START 7 /* RPC code */ | 45 | #define SANE_NET_START 7 /* RPC code */ |
@@ -125,15 +119,15 @@ static int help(struct sk_buff **pskb, | |||
125 | ct_sane_info->state = SANE_STATE_NORMAL; | 119 | ct_sane_info->state = SANE_STATE_NORMAL; |
126 | 120 | ||
127 | if (datalen < sizeof(struct sane_reply_net_start)) { | 121 | if (datalen < sizeof(struct sane_reply_net_start)) { |
128 | DEBUGP("nf_ct_sane: NET_START reply too short\n"); | 122 | pr_debug("nf_ct_sane: NET_START reply too short\n"); |
129 | goto out; | 123 | goto out; |
130 | } | 124 | } |
131 | 125 | ||
132 | reply = (struct sane_reply_net_start *)sb_ptr; | 126 | reply = (struct sane_reply_net_start *)sb_ptr; |
133 | if (reply->status != htonl(SANE_STATUS_SUCCESS)) { | 127 | if (reply->status != htonl(SANE_STATUS_SUCCESS)) { |
134 | /* saned refused the command */ | 128 | /* saned refused the command */ |
135 | DEBUGP("nf_ct_sane: unsuccessful SANE_STATUS = %u\n", | 129 | pr_debug("nf_ct_sane: unsuccessful SANE_STATUS = %u\n", |
136 | ntohl(reply->status)); | 130 | ntohl(reply->status)); |
137 | goto out; | 131 | goto out; |
138 | } | 132 | } |
139 | 133 | ||
@@ -141,35 +135,32 @@ static int help(struct sk_buff **pskb, | |||
141 | if (reply->zero != 0) | 135 | if (reply->zero != 0) |
142 | goto out; | 136 | goto out; |
143 | 137 | ||
144 | exp = nf_conntrack_expect_alloc(ct); | 138 | exp = nf_ct_expect_alloc(ct); |
145 | if (exp == NULL) { | 139 | if (exp == NULL) { |
146 | ret = NF_DROP; | 140 | ret = NF_DROP; |
147 | goto out; | 141 | goto out; |
148 | } | 142 | } |
149 | 143 | ||
150 | tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; | 144 | tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; |
151 | nf_conntrack_expect_init(exp, family, | 145 | nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3, |
152 | &tuple->src.u3, &tuple->dst.u3, | 146 | IPPROTO_TCP, NULL, &reply->port); |
153 | IPPROTO_TCP, | ||
154 | NULL, &reply->port); | ||
155 | 147 | ||
156 | DEBUGP("nf_ct_sane: expect: "); | 148 | pr_debug("nf_ct_sane: expect: "); |
157 | NF_CT_DUMP_TUPLE(&exp->tuple); | 149 | NF_CT_DUMP_TUPLE(&exp->tuple); |
158 | NF_CT_DUMP_TUPLE(&exp->mask); | ||
159 | 150 | ||
160 | /* Can't expect this? Best to drop packet now. */ | 151 | /* Can't expect this? Best to drop packet now. */ |
161 | if (nf_conntrack_expect_related(exp) != 0) | 152 | if (nf_ct_expect_related(exp) != 0) |
162 | ret = NF_DROP; | 153 | ret = NF_DROP; |
163 | 154 | ||
164 | nf_conntrack_expect_put(exp); | 155 | nf_ct_expect_put(exp); |
165 | 156 | ||
166 | out: | 157 | out: |
167 | spin_unlock_bh(&nf_sane_lock); | 158 | spin_unlock_bh(&nf_sane_lock); |
168 | return ret; | 159 | return ret; |
169 | } | 160 | } |
170 | 161 | ||
171 | static struct nf_conntrack_helper sane[MAX_PORTS][2]; | 162 | static struct nf_conntrack_helper sane[MAX_PORTS][2] __read_mostly; |
172 | static char sane_names[MAX_PORTS][2][sizeof("sane-65535")]; | 163 | static char sane_names[MAX_PORTS][2][sizeof("sane-65535")] __read_mostly; |
173 | 164 | ||
174 | /* don't make this __exit, since it's called from __init ! */ | 165 | /* don't make this __exit, since it's called from __init ! */ |
175 | static void nf_conntrack_sane_fini(void) | 166 | static void nf_conntrack_sane_fini(void) |
@@ -178,9 +169,9 @@ static void nf_conntrack_sane_fini(void) | |||
178 | 169 | ||
179 | for (i = 0; i < ports_c; i++) { | 170 | for (i = 0; i < ports_c; i++) { |
180 | for (j = 0; j < 2; j++) { | 171 | for (j = 0; j < 2; j++) { |
181 | DEBUGP("nf_ct_sane: unregistering helper for pf: %d " | 172 | pr_debug("nf_ct_sane: unregistering helper for pf: %d " |
182 | "port: %d\n", | 173 | "port: %d\n", |
183 | sane[i][j].tuple.src.l3num, ports[i]); | 174 | sane[i][j].tuple.src.l3num, ports[i]); |
184 | nf_conntrack_helper_unregister(&sane[i][j]); | 175 | nf_conntrack_helper_unregister(&sane[i][j]); |
185 | } | 176 | } |
186 | } | 177 | } |
@@ -208,8 +199,6 @@ static int __init nf_conntrack_sane_init(void) | |||
208 | for (j = 0; j < 2; j++) { | 199 | for (j = 0; j < 2; j++) { |
209 | sane[i][j].tuple.src.u.tcp.port = htons(ports[i]); | 200 | sane[i][j].tuple.src.u.tcp.port = htons(ports[i]); |
210 | sane[i][j].tuple.dst.protonum = IPPROTO_TCP; | 201 | sane[i][j].tuple.dst.protonum = IPPROTO_TCP; |
211 | sane[i][j].mask.src.u.tcp.port = 0xFFFF; | ||
212 | sane[i][j].mask.dst.protonum = 0xFF; | ||
213 | sane[i][j].max_expected = 1; | 202 | sane[i][j].max_expected = 1; |
214 | sane[i][j].timeout = 5 * 60; /* 5 Minutes */ | 203 | sane[i][j].timeout = 5 * 60; /* 5 Minutes */ |
215 | sane[i][j].me = THIS_MODULE; | 204 | sane[i][j].me = THIS_MODULE; |
@@ -221,9 +210,9 @@ static int __init nf_conntrack_sane_init(void) | |||
221 | sprintf(tmpname, "sane-%d", ports[i]); | 210 | sprintf(tmpname, "sane-%d", ports[i]); |
222 | sane[i][j].name = tmpname; | 211 | sane[i][j].name = tmpname; |
223 | 212 | ||
224 | DEBUGP("nf_ct_sane: registering helper for pf: %d " | 213 | pr_debug("nf_ct_sane: registering helper for pf: %d " |
225 | "port: %d\n", | 214 | "port: %d\n", |
226 | sane[i][j].tuple.src.l3num, ports[i]); | 215 | sane[i][j].tuple.src.l3num, ports[i]); |
227 | ret = nf_conntrack_helper_register(&sane[i][j]); | 216 | ret = nf_conntrack_helper_register(&sane[i][j]); |
228 | if (ret) { | 217 | if (ret) { |
229 | printk(KERN_ERR "nf_ct_sane: failed to " | 218 | printk(KERN_ERR "nf_ct_sane: failed to " |
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 1b5c6c1055f7..1276a442f10c 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c | |||
@@ -21,12 +21,6 @@ | |||
21 | #include <net/netfilter/nf_conntrack_helper.h> | 21 | #include <net/netfilter/nf_conntrack_helper.h> |
22 | #include <linux/netfilter/nf_conntrack_sip.h> | 22 | #include <linux/netfilter/nf_conntrack_sip.h> |
23 | 23 | ||
24 | #if 0 | ||
25 | #define DEBUGP printk | ||
26 | #else | ||
27 | #define DEBUGP(format, args...) | ||
28 | #endif | ||
29 | |||
30 | MODULE_LICENSE("GPL"); | 24 | MODULE_LICENSE("GPL"); |
31 | MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>"); | 25 | MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>"); |
32 | MODULE_DESCRIPTION("SIP connection tracking helper"); | 26 | MODULE_DESCRIPTION("SIP connection tracking helper"); |
@@ -285,7 +279,7 @@ static int epaddr_len(struct nf_conn *ct, const char *dptr, | |||
285 | const char *aux = dptr; | 279 | const char *aux = dptr; |
286 | 280 | ||
287 | if (!parse_addr(ct, dptr, &dptr, &addr, limit)) { | 281 | if (!parse_addr(ct, dptr, &dptr, &addr, limit)) { |
288 | DEBUGP("ip: %s parse failed.!\n", dptr); | 282 | pr_debug("ip: %s parse failed.!\n", dptr); |
289 | return 0; | 283 | return 0; |
290 | } | 284 | } |
291 | 285 | ||
@@ -344,8 +338,8 @@ int ct_sip_get_info(struct nf_conn *ct, | |||
344 | ct_sip_lnlen(dptr, limit), | 338 | ct_sip_lnlen(dptr, limit), |
345 | hnfo->case_sensitive); | 339 | hnfo->case_sensitive); |
346 | if (!aux) { | 340 | if (!aux) { |
347 | DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str, | 341 | pr_debug("'%s' not found in '%s'.\n", hnfo->ln_str, |
348 | hnfo->lname); | 342 | hnfo->lname); |
349 | return -1; | 343 | return -1; |
350 | } | 344 | } |
351 | aux += hnfo->ln_strlen; | 345 | aux += hnfo->ln_strlen; |
@@ -356,11 +350,11 @@ int ct_sip_get_info(struct nf_conn *ct, | |||
356 | 350 | ||
357 | *matchoff = (aux - k) + shift; | 351 | *matchoff = (aux - k) + shift; |
358 | 352 | ||
359 | DEBUGP("%s match succeeded! - len: %u\n", hnfo->lname, | 353 | pr_debug("%s match succeeded! - len: %u\n", hnfo->lname, |
360 | *matchlen); | 354 | *matchlen); |
361 | return 1; | 355 | return 1; |
362 | } | 356 | } |
363 | DEBUGP("%s header not found.\n", hnfo->lname); | 357 | pr_debug("%s header not found.\n", hnfo->lname); |
364 | return 0; | 358 | return 0; |
365 | } | 359 | } |
366 | EXPORT_SYMBOL_GPL(ct_sip_get_info); | 360 | EXPORT_SYMBOL_GPL(ct_sip_get_info); |
@@ -378,23 +372,23 @@ static int set_expected_rtp(struct sk_buff **pskb, | |||
378 | int ret; | 372 | int ret; |
379 | typeof(nf_nat_sdp_hook) nf_nat_sdp; | 373 | typeof(nf_nat_sdp_hook) nf_nat_sdp; |
380 | 374 | ||
381 | exp = nf_conntrack_expect_alloc(ct); | 375 | exp = nf_ct_expect_alloc(ct); |
382 | if (exp == NULL) | 376 | if (exp == NULL) |
383 | return NF_DROP; | 377 | return NF_DROP; |
384 | nf_conntrack_expect_init(exp, family, | 378 | nf_ct_expect_init(exp, family, |
385 | &ct->tuplehash[!dir].tuple.src.u3, addr, | 379 | &ct->tuplehash[!dir].tuple.src.u3, addr, |
386 | IPPROTO_UDP, NULL, &port); | 380 | IPPROTO_UDP, NULL, &port); |
387 | 381 | ||
388 | nf_nat_sdp = rcu_dereference(nf_nat_sdp_hook); | 382 | nf_nat_sdp = rcu_dereference(nf_nat_sdp_hook); |
389 | if (nf_nat_sdp && ct->status & IPS_NAT_MASK) | 383 | if (nf_nat_sdp && ct->status & IPS_NAT_MASK) |
390 | ret = nf_nat_sdp(pskb, ctinfo, exp, dptr); | 384 | ret = nf_nat_sdp(pskb, ctinfo, exp, dptr); |
391 | else { | 385 | else { |
392 | if (nf_conntrack_expect_related(exp) != 0) | 386 | if (nf_ct_expect_related(exp) != 0) |
393 | ret = NF_DROP; | 387 | ret = NF_DROP; |
394 | else | 388 | else |
395 | ret = NF_ACCEPT; | 389 | ret = NF_ACCEPT; |
396 | } | 390 | } |
397 | nf_conntrack_expect_put(exp); | 391 | nf_ct_expect_put(exp); |
398 | 392 | ||
399 | return ret; | 393 | return ret; |
400 | } | 394 | } |
@@ -424,7 +418,7 @@ static int sip_help(struct sk_buff **pskb, | |||
424 | if (!skb_is_nonlinear(*pskb)) | 418 | if (!skb_is_nonlinear(*pskb)) |
425 | dptr = (*pskb)->data + dataoff; | 419 | dptr = (*pskb)->data + dataoff; |
426 | else { | 420 | else { |
427 | DEBUGP("Copy of skbuff not supported yet.\n"); | 421 | pr_debug("Copy of skbuff not supported yet.\n"); |
428 | goto out; | 422 | goto out; |
429 | } | 423 | } |
430 | 424 | ||
@@ -506,9 +500,6 @@ static int __init nf_conntrack_sip_init(void) | |||
506 | for (j = 0; j < 2; j++) { | 500 | for (j = 0; j < 2; j++) { |
507 | sip[i][j].tuple.dst.protonum = IPPROTO_UDP; | 501 | sip[i][j].tuple.dst.protonum = IPPROTO_UDP; |
508 | sip[i][j].tuple.src.u.udp.port = htons(ports[i]); | 502 | sip[i][j].tuple.src.u.udp.port = htons(ports[i]); |
509 | sip[i][j].mask.src.l3num = 0xFFFF; | ||
510 | sip[i][j].mask.src.u.udp.port = htons(0xFFFF); | ||
511 | sip[i][j].mask.dst.protonum = 0xFF; | ||
512 | sip[i][j].max_expected = 2; | 503 | sip[i][j].max_expected = 2; |
513 | sip[i][j].timeout = 3 * 60; /* 3 minutes */ | 504 | sip[i][j].timeout = 3 * 60; /* 3 minutes */ |
514 | sip[i][j].me = THIS_MODULE; | 505 | sip[i][j].me = THIS_MODULE; |
@@ -521,7 +512,7 @@ static int __init nf_conntrack_sip_init(void) | |||
521 | sprintf(tmpname, "sip-%u", i); | 512 | sprintf(tmpname, "sip-%u", i); |
522 | sip[i][j].name = tmpname; | 513 | sip[i][j].name = tmpname; |
523 | 514 | ||
524 | DEBUGP("port #%u: %u\n", i, ports[i]); | 515 | pr_debug("port #%u: %u\n", i, ports[i]); |
525 | 516 | ||
526 | ret = nf_conntrack_helper_register(&sip[i][j]); | 517 | ret = nf_conntrack_helper_register(&sip[i][j]); |
527 | if (ret) { | 518 | if (ret) { |
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 45baeb0e30f9..ffb6ff8c3528 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c | |||
@@ -25,12 +25,6 @@ | |||
25 | #include <net/netfilter/nf_conntrack_expect.h> | 25 | #include <net/netfilter/nf_conntrack_expect.h> |
26 | #include <net/netfilter/nf_conntrack_helper.h> | 26 | #include <net/netfilter/nf_conntrack_helper.h> |
27 | 27 | ||
28 | #if 0 | ||
29 | #define DEBUGP printk | ||
30 | #else | ||
31 | #define DEBUGP(format, args...) | ||
32 | #endif | ||
33 | |||
34 | MODULE_LICENSE("GPL"); | 28 | MODULE_LICENSE("GPL"); |
35 | 29 | ||
36 | #ifdef CONFIG_PROC_FS | 30 | #ifdef CONFIG_PROC_FS |
@@ -60,35 +54,36 @@ struct ct_iter_state { | |||
60 | unsigned int bucket; | 54 | unsigned int bucket; |
61 | }; | 55 | }; |
62 | 56 | ||
63 | static struct list_head *ct_get_first(struct seq_file *seq) | 57 | static struct hlist_node *ct_get_first(struct seq_file *seq) |
64 | { | 58 | { |
65 | struct ct_iter_state *st = seq->private; | 59 | struct ct_iter_state *st = seq->private; |
66 | 60 | ||
67 | for (st->bucket = 0; | 61 | for (st->bucket = 0; |
68 | st->bucket < nf_conntrack_htable_size; | 62 | st->bucket < nf_conntrack_htable_size; |
69 | st->bucket++) { | 63 | st->bucket++) { |
70 | if (!list_empty(&nf_conntrack_hash[st->bucket])) | 64 | if (!hlist_empty(&nf_conntrack_hash[st->bucket])) |
71 | return nf_conntrack_hash[st->bucket].next; | 65 | return nf_conntrack_hash[st->bucket].first; |
72 | } | 66 | } |
73 | return NULL; | 67 | return NULL; |
74 | } | 68 | } |
75 | 69 | ||
76 | static struct list_head *ct_get_next(struct seq_file *seq, struct list_head *head) | 70 | static struct hlist_node *ct_get_next(struct seq_file *seq, |
71 | struct hlist_node *head) | ||
77 | { | 72 | { |
78 | struct ct_iter_state *st = seq->private; | 73 | struct ct_iter_state *st = seq->private; |
79 | 74 | ||
80 | head = head->next; | 75 | head = head->next; |
81 | while (head == &nf_conntrack_hash[st->bucket]) { | 76 | while (head == NULL) { |
82 | if (++st->bucket >= nf_conntrack_htable_size) | 77 | if (++st->bucket >= nf_conntrack_htable_size) |
83 | return NULL; | 78 | return NULL; |
84 | head = nf_conntrack_hash[st->bucket].next; | 79 | head = nf_conntrack_hash[st->bucket].first; |
85 | } | 80 | } |
86 | return head; | 81 | return head; |
87 | } | 82 | } |
88 | 83 | ||
89 | static struct list_head *ct_get_idx(struct seq_file *seq, loff_t pos) | 84 | static struct hlist_node *ct_get_idx(struct seq_file *seq, loff_t pos) |
90 | { | 85 | { |
91 | struct list_head *head = ct_get_first(seq); | 86 | struct hlist_node *head = ct_get_first(seq); |
92 | 87 | ||
93 | if (head) | 88 | if (head) |
94 | while (pos && (head = ct_get_next(seq, head))) | 89 | while (pos && (head = ct_get_next(seq, head))) |
@@ -190,7 +185,7 @@ static int ct_seq_show(struct seq_file *s, void *v) | |||
190 | return 0; | 185 | return 0; |
191 | } | 186 | } |
192 | 187 | ||
193 | static struct seq_operations ct_seq_ops = { | 188 | static const struct seq_operations ct_seq_ops = { |
194 | .start = ct_seq_start, | 189 | .start = ct_seq_start, |
195 | .next = ct_seq_next, | 190 | .next = ct_seq_next, |
196 | .stop = ct_seq_stop, | 191 | .stop = ct_seq_stop, |
@@ -294,7 +289,7 @@ static int ct_cpu_seq_show(struct seq_file *seq, void *v) | |||
294 | return 0; | 289 | return 0; |
295 | } | 290 | } |
296 | 291 | ||
297 | static struct seq_operations ct_cpu_seq_ops = { | 292 | static const struct seq_operations ct_cpu_seq_ops = { |
298 | .start = ct_cpu_seq_start, | 293 | .start = ct_cpu_seq_start, |
299 | .next = ct_cpu_seq_next, | 294 | .next = ct_cpu_seq_next, |
300 | .stop = ct_cpu_seq_stop, | 295 | .stop = ct_cpu_seq_stop, |
@@ -371,7 +366,14 @@ static ctl_table nf_ct_sysctl_table[] = { | |||
371 | .extra1 = &log_invalid_proto_min, | 366 | .extra1 = &log_invalid_proto_min, |
372 | .extra2 = &log_invalid_proto_max, | 367 | .extra2 = &log_invalid_proto_max, |
373 | }, | 368 | }, |
374 | 369 | { | |
370 | .ctl_name = CTL_UNNUMBERED, | ||
371 | .procname = "nf_conntrack_expect_max", | ||
372 | .data = &nf_ct_expect_max, | ||
373 | .maxlen = sizeof(int), | ||
374 | .mode = 0644, | ||
375 | .proc_handler = &proc_dointvec, | ||
376 | }, | ||
375 | { .ctl_name = 0 } | 377 | { .ctl_name = 0 } |
376 | }; | 378 | }; |
377 | 379 | ||
@@ -410,7 +412,7 @@ EXPORT_SYMBOL_GPL(nf_ct_log_invalid); | |||
410 | static int __init nf_conntrack_standalone_init(void) | 412 | static int __init nf_conntrack_standalone_init(void) |
411 | { | 413 | { |
412 | #ifdef CONFIG_PROC_FS | 414 | #ifdef CONFIG_PROC_FS |
413 | struct proc_dir_entry *proc, *proc_exp, *proc_stat; | 415 | struct proc_dir_entry *proc, *proc_stat; |
414 | #endif | 416 | #endif |
415 | int ret = 0; | 417 | int ret = 0; |
416 | 418 | ||
@@ -422,13 +424,9 @@ static int __init nf_conntrack_standalone_init(void) | |||
422 | proc = proc_net_fops_create("nf_conntrack", 0440, &ct_file_ops); | 424 | proc = proc_net_fops_create("nf_conntrack", 0440, &ct_file_ops); |
423 | if (!proc) goto cleanup_init; | 425 | if (!proc) goto cleanup_init; |
424 | 426 | ||
425 | proc_exp = proc_net_fops_create("nf_conntrack_expect", 0440, | ||
426 | &exp_file_ops); | ||
427 | if (!proc_exp) goto cleanup_proc; | ||
428 | |||
429 | proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, proc_net_stat); | 427 | proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, proc_net_stat); |
430 | if (!proc_stat) | 428 | if (!proc_stat) |
431 | goto cleanup_proc_exp; | 429 | goto cleanup_proc; |
432 | 430 | ||
433 | proc_stat->proc_fops = &ct_cpu_seq_fops; | 431 | proc_stat->proc_fops = &ct_cpu_seq_fops; |
434 | proc_stat->owner = THIS_MODULE; | 432 | proc_stat->owner = THIS_MODULE; |
@@ -448,8 +446,6 @@ static int __init nf_conntrack_standalone_init(void) | |||
448 | #endif | 446 | #endif |
449 | #ifdef CONFIG_PROC_FS | 447 | #ifdef CONFIG_PROC_FS |
450 | remove_proc_entry("nf_conntrack", proc_net_stat); | 448 | remove_proc_entry("nf_conntrack", proc_net_stat); |
451 | cleanup_proc_exp: | ||
452 | proc_net_remove("nf_conntrack_expect"); | ||
453 | cleanup_proc: | 449 | cleanup_proc: |
454 | proc_net_remove("nf_conntrack"); | 450 | proc_net_remove("nf_conntrack"); |
455 | cleanup_init: | 451 | cleanup_init: |
@@ -465,7 +461,6 @@ static void __exit nf_conntrack_standalone_fini(void) | |||
465 | #endif | 461 | #endif |
466 | #ifdef CONFIG_PROC_FS | 462 | #ifdef CONFIG_PROC_FS |
467 | remove_proc_entry("nf_conntrack", proc_net_stat); | 463 | remove_proc_entry("nf_conntrack", proc_net_stat); |
468 | proc_net_remove("nf_conntrack_expect"); | ||
469 | proc_net_remove("nf_conntrack"); | 464 | proc_net_remove("nf_conntrack"); |
470 | #endif /* CNFIG_PROC_FS */ | 465 | #endif /* CNFIG_PROC_FS */ |
471 | nf_conntrack_cleanup(); | 466 | nf_conntrack_cleanup(); |
diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c index 37c4542e3112..cc19506cf2f8 100644 --- a/net/netfilter/nf_conntrack_tftp.c +++ b/net/netfilter/nf_conntrack_tftp.c | |||
@@ -29,13 +29,6 @@ static int ports_c; | |||
29 | module_param_array(ports, ushort, &ports_c, 0400); | 29 | module_param_array(ports, ushort, &ports_c, 0400); |
30 | MODULE_PARM_DESC(ports, "Port numbers of TFTP servers"); | 30 | MODULE_PARM_DESC(ports, "Port numbers of TFTP servers"); |
31 | 31 | ||
32 | #if 0 | ||
33 | #define DEBUGP(format, args...) printk("%s:%s:" format, \ | ||
34 | __FILE__, __FUNCTION__ , ## args) | ||
35 | #else | ||
36 | #define DEBUGP(format, args...) | ||
37 | #endif | ||
38 | |||
39 | unsigned int (*nf_nat_tftp_hook)(struct sk_buff **pskb, | 32 | unsigned int (*nf_nat_tftp_hook)(struct sk_buff **pskb, |
40 | enum ip_conntrack_info ctinfo, | 33 | enum ip_conntrack_info ctinfo, |
41 | struct nf_conntrack_expect *exp) __read_mostly; | 34 | struct nf_conntrack_expect *exp) __read_mostly; |
@@ -62,39 +55,35 @@ static int tftp_help(struct sk_buff **pskb, | |||
62 | case TFTP_OPCODE_READ: | 55 | case TFTP_OPCODE_READ: |
63 | case TFTP_OPCODE_WRITE: | 56 | case TFTP_OPCODE_WRITE: |
64 | /* RRQ and WRQ works the same way */ | 57 | /* RRQ and WRQ works the same way */ |
65 | DEBUGP(""); | ||
66 | NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); | 58 | NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); |
67 | NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); | 59 | NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); |
68 | 60 | ||
69 | exp = nf_conntrack_expect_alloc(ct); | 61 | exp = nf_ct_expect_alloc(ct); |
70 | if (exp == NULL) | 62 | if (exp == NULL) |
71 | return NF_DROP; | 63 | return NF_DROP; |
72 | tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; | 64 | tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; |
73 | nf_conntrack_expect_init(exp, family, | 65 | nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3, |
74 | &tuple->src.u3, &tuple->dst.u3, | 66 | IPPROTO_UDP, NULL, &tuple->dst.u.udp.port); |
75 | IPPROTO_UDP, | ||
76 | NULL, &tuple->dst.u.udp.port); | ||
77 | 67 | ||
78 | DEBUGP("expect: "); | 68 | pr_debug("expect: "); |
79 | NF_CT_DUMP_TUPLE(&exp->tuple); | 69 | NF_CT_DUMP_TUPLE(&exp->tuple); |
80 | NF_CT_DUMP_TUPLE(&exp->mask); | ||
81 | 70 | ||
82 | nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook); | 71 | nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook); |
83 | if (nf_nat_tftp && ct->status & IPS_NAT_MASK) | 72 | if (nf_nat_tftp && ct->status & IPS_NAT_MASK) |
84 | ret = nf_nat_tftp(pskb, ctinfo, exp); | 73 | ret = nf_nat_tftp(pskb, ctinfo, exp); |
85 | else if (nf_conntrack_expect_related(exp) != 0) | 74 | else if (nf_ct_expect_related(exp) != 0) |
86 | ret = NF_DROP; | 75 | ret = NF_DROP; |
87 | nf_conntrack_expect_put(exp); | 76 | nf_ct_expect_put(exp); |
88 | break; | 77 | break; |
89 | case TFTP_OPCODE_DATA: | 78 | case TFTP_OPCODE_DATA: |
90 | case TFTP_OPCODE_ACK: | 79 | case TFTP_OPCODE_ACK: |
91 | DEBUGP("Data/ACK opcode\n"); | 80 | pr_debug("Data/ACK opcode\n"); |
92 | break; | 81 | break; |
93 | case TFTP_OPCODE_ERROR: | 82 | case TFTP_OPCODE_ERROR: |
94 | DEBUGP("Error opcode\n"); | 83 | pr_debug("Error opcode\n"); |
95 | break; | 84 | break; |
96 | default: | 85 | default: |
97 | DEBUGP("Unknown opcode\n"); | 86 | pr_debug("Unknown opcode\n"); |
98 | } | 87 | } |
99 | return ret; | 88 | return ret; |
100 | } | 89 | } |
@@ -128,9 +117,6 @@ static int __init nf_conntrack_tftp_init(void) | |||
128 | for (j = 0; j < 2; j++) { | 117 | for (j = 0; j < 2; j++) { |
129 | tftp[i][j].tuple.dst.protonum = IPPROTO_UDP; | 118 | tftp[i][j].tuple.dst.protonum = IPPROTO_UDP; |
130 | tftp[i][j].tuple.src.u.udp.port = htons(ports[i]); | 119 | tftp[i][j].tuple.src.u.udp.port = htons(ports[i]); |
131 | tftp[i][j].mask.src.l3num = 0xFFFF; | ||
132 | tftp[i][j].mask.dst.protonum = 0xFF; | ||
133 | tftp[i][j].mask.src.u.udp.port = htons(0xFFFF); | ||
134 | tftp[i][j].max_expected = 1; | 120 | tftp[i][j].max_expected = 1; |
135 | tftp[i][j].timeout = 5 * 60; /* 5 minutes */ | 121 | tftp[i][j].timeout = 5 * 60; /* 5 minutes */ |
136 | tftp[i][j].me = THIS_MODULE; | 122 | tftp[i][j].me = THIS_MODULE; |
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index 91b220cf5a1f..94985792b79a 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c | |||
@@ -140,7 +140,7 @@ static int seq_show(struct seq_file *s, void *v) | |||
140 | return seq_printf(s, "%2lld %s\n", *pos, logger->name); | 140 | return seq_printf(s, "%2lld %s\n", *pos, logger->name); |
141 | } | 141 | } |
142 | 142 | ||
143 | static struct seq_operations nflog_seq_ops = { | 143 | static const struct seq_operations nflog_seq_ops = { |
144 | .start = seq_start, | 144 | .start = seq_start, |
145 | .next = seq_next, | 145 | .next = seq_next, |
146 | .stop = seq_stop, | 146 | .stop = seq_stop, |
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index b1f2ace96f6d..a481a349f7bf 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c | |||
@@ -17,7 +17,7 @@ | |||
17 | */ | 17 | */ |
18 | static struct nf_queue_handler *queue_handler[NPROTO]; | 18 | static struct nf_queue_handler *queue_handler[NPROTO]; |
19 | 19 | ||
20 | static DEFINE_RWLOCK(queue_handler_lock); | 20 | static DEFINE_MUTEX(queue_handler_mutex); |
21 | 21 | ||
22 | /* return EBUSY when somebody else is registered, return EEXIST if the | 22 | /* return EBUSY when somebody else is registered, return EEXIST if the |
23 | * same handler is registered, return 0 in case of success. */ | 23 | * same handler is registered, return 0 in case of success. */ |
@@ -28,30 +28,37 @@ int nf_register_queue_handler(int pf, struct nf_queue_handler *qh) | |||
28 | if (pf >= NPROTO) | 28 | if (pf >= NPROTO) |
29 | return -EINVAL; | 29 | return -EINVAL; |
30 | 30 | ||
31 | write_lock_bh(&queue_handler_lock); | 31 | mutex_lock(&queue_handler_mutex); |
32 | if (queue_handler[pf] == qh) | 32 | if (queue_handler[pf] == qh) |
33 | ret = -EEXIST; | 33 | ret = -EEXIST; |
34 | else if (queue_handler[pf]) | 34 | else if (queue_handler[pf]) |
35 | ret = -EBUSY; | 35 | ret = -EBUSY; |
36 | else { | 36 | else { |
37 | queue_handler[pf] = qh; | 37 | rcu_assign_pointer(queue_handler[pf], qh); |
38 | ret = 0; | 38 | ret = 0; |
39 | } | 39 | } |
40 | write_unlock_bh(&queue_handler_lock); | 40 | mutex_unlock(&queue_handler_mutex); |
41 | 41 | ||
42 | return ret; | 42 | return ret; |
43 | } | 43 | } |
44 | EXPORT_SYMBOL(nf_register_queue_handler); | 44 | EXPORT_SYMBOL(nf_register_queue_handler); |
45 | 45 | ||
46 | /* The caller must flush their queue before this */ | 46 | /* The caller must flush their queue before this */ |
47 | int nf_unregister_queue_handler(int pf) | 47 | int nf_unregister_queue_handler(int pf, struct nf_queue_handler *qh) |
48 | { | 48 | { |
49 | if (pf >= NPROTO) | 49 | if (pf >= NPROTO) |
50 | return -EINVAL; | 50 | return -EINVAL; |
51 | 51 | ||
52 | write_lock_bh(&queue_handler_lock); | 52 | mutex_lock(&queue_handler_mutex); |
53 | queue_handler[pf] = NULL; | 53 | if (queue_handler[pf] != qh) { |
54 | write_unlock_bh(&queue_handler_lock); | 54 | mutex_unlock(&queue_handler_mutex); |
55 | return -EINVAL; | ||
56 | } | ||
57 | |||
58 | rcu_assign_pointer(queue_handler[pf], NULL); | ||
59 | mutex_unlock(&queue_handler_mutex); | ||
60 | |||
61 | synchronize_rcu(); | ||
55 | 62 | ||
56 | return 0; | 63 | return 0; |
57 | } | 64 | } |
@@ -61,12 +68,14 @@ void nf_unregister_queue_handlers(struct nf_queue_handler *qh) | |||
61 | { | 68 | { |
62 | int pf; | 69 | int pf; |
63 | 70 | ||
64 | write_lock_bh(&queue_handler_lock); | 71 | mutex_lock(&queue_handler_mutex); |
65 | for (pf = 0; pf < NPROTO; pf++) { | 72 | for (pf = 0; pf < NPROTO; pf++) { |
66 | if (queue_handler[pf] == qh) | 73 | if (queue_handler[pf] == qh) |
67 | queue_handler[pf] = NULL; | 74 | rcu_assign_pointer(queue_handler[pf], NULL); |
68 | } | 75 | } |
69 | write_unlock_bh(&queue_handler_lock); | 76 | mutex_unlock(&queue_handler_mutex); |
77 | |||
78 | synchronize_rcu(); | ||
70 | } | 79 | } |
71 | EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers); | 80 | EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers); |
72 | 81 | ||
@@ -89,18 +98,21 @@ static int __nf_queue(struct sk_buff *skb, | |||
89 | struct net_device *physoutdev = NULL; | 98 | struct net_device *physoutdev = NULL; |
90 | #endif | 99 | #endif |
91 | struct nf_afinfo *afinfo; | 100 | struct nf_afinfo *afinfo; |
101 | struct nf_queue_handler *qh; | ||
92 | 102 | ||
93 | /* QUEUE == DROP if noone is waiting, to be safe. */ | 103 | /* QUEUE == DROP if noone is waiting, to be safe. */ |
94 | read_lock(&queue_handler_lock); | 104 | rcu_read_lock(); |
95 | if (!queue_handler[pf]) { | 105 | |
96 | read_unlock(&queue_handler_lock); | 106 | qh = rcu_dereference(queue_handler[pf]); |
107 | if (!qh) { | ||
108 | rcu_read_unlock(); | ||
97 | kfree_skb(skb); | 109 | kfree_skb(skb); |
98 | return 1; | 110 | return 1; |
99 | } | 111 | } |
100 | 112 | ||
101 | afinfo = nf_get_afinfo(pf); | 113 | afinfo = nf_get_afinfo(pf); |
102 | if (!afinfo) { | 114 | if (!afinfo) { |
103 | read_unlock(&queue_handler_lock); | 115 | rcu_read_unlock(); |
104 | kfree_skb(skb); | 116 | kfree_skb(skb); |
105 | return 1; | 117 | return 1; |
106 | } | 118 | } |
@@ -110,7 +122,7 @@ static int __nf_queue(struct sk_buff *skb, | |||
110 | if (net_ratelimit()) | 122 | if (net_ratelimit()) |
111 | printk(KERN_ERR "OOM queueing packet %p\n", | 123 | printk(KERN_ERR "OOM queueing packet %p\n", |
112 | skb); | 124 | skb); |
113 | read_unlock(&queue_handler_lock); | 125 | rcu_read_unlock(); |
114 | kfree_skb(skb); | 126 | kfree_skb(skb); |
115 | return 1; | 127 | return 1; |
116 | } | 128 | } |
@@ -120,7 +132,7 @@ static int __nf_queue(struct sk_buff *skb, | |||
120 | 132 | ||
121 | /* If it's going away, ignore hook. */ | 133 | /* If it's going away, ignore hook. */ |
122 | if (!try_module_get(info->elem->owner)) { | 134 | if (!try_module_get(info->elem->owner)) { |
123 | read_unlock(&queue_handler_lock); | 135 | rcu_read_unlock(); |
124 | kfree(info); | 136 | kfree(info); |
125 | return 0; | 137 | return 0; |
126 | } | 138 | } |
@@ -138,10 +150,9 @@ static int __nf_queue(struct sk_buff *skb, | |||
138 | } | 150 | } |
139 | #endif | 151 | #endif |
140 | afinfo->saveroute(skb, info); | 152 | afinfo->saveroute(skb, info); |
141 | status = queue_handler[pf]->outfn(skb, info, queuenum, | 153 | status = qh->outfn(skb, info, queuenum, qh->data); |
142 | queue_handler[pf]->data); | ||
143 | 154 | ||
144 | read_unlock(&queue_handler_lock); | 155 | rcu_read_unlock(); |
145 | 156 | ||
146 | if (status < 0) { | 157 | if (status < 0) { |
147 | /* James M doesn't say fuck enough. */ | 158 | /* James M doesn't say fuck enough. */ |
@@ -308,18 +319,18 @@ static int seq_show(struct seq_file *s, void *v) | |||
308 | loff_t *pos = v; | 319 | loff_t *pos = v; |
309 | struct nf_queue_handler *qh; | 320 | struct nf_queue_handler *qh; |
310 | 321 | ||
311 | read_lock_bh(&queue_handler_lock); | 322 | rcu_read_lock(); |
312 | qh = queue_handler[*pos]; | 323 | qh = rcu_dereference(queue_handler[*pos]); |
313 | if (!qh) | 324 | if (!qh) |
314 | ret = seq_printf(s, "%2lld NONE\n", *pos); | 325 | ret = seq_printf(s, "%2lld NONE\n", *pos); |
315 | else | 326 | else |
316 | ret = seq_printf(s, "%2lld %s\n", *pos, qh->name); | 327 | ret = seq_printf(s, "%2lld %s\n", *pos, qh->name); |
317 | read_unlock_bh(&queue_handler_lock); | 328 | rcu_read_unlock(); |
318 | 329 | ||
319 | return ret; | 330 | return ret; |
320 | } | 331 | } |
321 | 332 | ||
322 | static struct seq_operations nfqueue_seq_ops = { | 333 | static const struct seq_operations nfqueue_seq_ops = { |
323 | .start = seq_start, | 334 | .start = seq_start, |
324 | .next = seq_next, | 335 | .next = seq_next, |
325 | .stop = seq_stop, | 336 | .stop = seq_stop, |
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index e32e30e7a17c..e185a5b55913 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
@@ -962,7 +962,7 @@ static int seq_show(struct seq_file *s, void *v) | |||
962 | inst->flushtimeout, atomic_read(&inst->use)); | 962 | inst->flushtimeout, atomic_read(&inst->use)); |
963 | } | 963 | } |
964 | 964 | ||
965 | static struct seq_operations nful_seq_ops = { | 965 | static const struct seq_operations nful_seq_ops = { |
966 | .start = seq_start, | 966 | .start = seq_start, |
967 | .next = seq_next, | 967 | .next = seq_next, |
968 | .stop = seq_stop, | 968 | .stop = seq_stop, |
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 7a97bec67729..bb65a38c816c 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c | |||
@@ -913,9 +913,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, | |||
913 | case NFQNL_CFG_CMD_PF_UNBIND: | 913 | case NFQNL_CFG_CMD_PF_UNBIND: |
914 | QDEBUG("unregistering queue handler for pf=%u\n", | 914 | QDEBUG("unregistering queue handler for pf=%u\n", |
915 | ntohs(cmd->pf)); | 915 | ntohs(cmd->pf)); |
916 | /* This is a bug and a feature. We can unregister | 916 | ret = nf_unregister_queue_handler(ntohs(cmd->pf), &nfqh); |
917 | * other handlers(!) */ | ||
918 | ret = nf_unregister_queue_handler(ntohs(cmd->pf)); | ||
919 | break; | 917 | break; |
920 | default: | 918 | default: |
921 | ret = -EINVAL; | 919 | ret = -EINVAL; |
@@ -1050,7 +1048,7 @@ static int seq_show(struct seq_file *s, void *v) | |||
1050 | atomic_read(&inst->use)); | 1048 | atomic_read(&inst->use)); |
1051 | } | 1049 | } |
1052 | 1050 | ||
1053 | static struct seq_operations nfqnl_seq_ops = { | 1051 | static const struct seq_operations nfqnl_seq_ops = { |
1054 | .start = seq_start, | 1052 | .start = seq_start, |
1055 | .next = seq_next, | 1053 | .next = seq_next, |
1056 | .stop = seq_stop, | 1054 | .stop = seq_stop, |
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 0eb2504b89b5..cc2baa6d5a7a 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c | |||
@@ -320,8 +320,8 @@ int xt_check_match(const struct xt_match *match, unsigned short family, | |||
320 | return -EINVAL; | 320 | return -EINVAL; |
321 | } | 321 | } |
322 | if (match->hooks && (hook_mask & ~match->hooks) != 0) { | 322 | if (match->hooks && (hook_mask & ~match->hooks) != 0) { |
323 | printk("%s_tables: %s match: bad hook_mask %u\n", | 323 | printk("%s_tables: %s match: bad hook_mask %u/%u\n", |
324 | xt_prefix[family], match->name, hook_mask); | 324 | xt_prefix[family], match->name, hook_mask, match->hooks); |
325 | return -EINVAL; | 325 | return -EINVAL; |
326 | } | 326 | } |
327 | if (match->proto && (match->proto != proto || inv_proto)) { | 327 | if (match->proto && (match->proto != proto || inv_proto)) { |
@@ -410,8 +410,9 @@ int xt_check_target(const struct xt_target *target, unsigned short family, | |||
410 | return -EINVAL; | 410 | return -EINVAL; |
411 | } | 411 | } |
412 | if (target->hooks && (hook_mask & ~target->hooks) != 0) { | 412 | if (target->hooks && (hook_mask & ~target->hooks) != 0) { |
413 | printk("%s_tables: %s target: bad hook_mask %u\n", | 413 | printk("%s_tables: %s target: bad hook_mask %u/%u\n", |
414 | xt_prefix[family], target->name, hook_mask); | 414 | xt_prefix[family], target->name, hook_mask, |
415 | target->hooks); | ||
415 | return -EINVAL; | 416 | return -EINVAL; |
416 | } | 417 | } |
417 | if (target->proto && (target->proto != proto || inv_proto)) { | 418 | if (target->proto && (target->proto != proto || inv_proto)) { |
@@ -744,7 +745,7 @@ static int xt_name_seq_show(struct seq_file *seq, void *v) | |||
744 | return 0; | 745 | return 0; |
745 | } | 746 | } |
746 | 747 | ||
747 | static struct seq_operations xt_tgt_seq_ops = { | 748 | static const struct seq_operations xt_tgt_seq_ops = { |
748 | .start = xt_tgt_seq_start, | 749 | .start = xt_tgt_seq_start, |
749 | .next = xt_tgt_seq_next, | 750 | .next = xt_tgt_seq_next, |
750 | .stop = xt_tgt_seq_stop, | 751 | .stop = xt_tgt_seq_stop, |
diff --git a/net/netfilter/xt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c index 30884833e665..519428566829 100644 --- a/net/netfilter/xt_CLASSIFY.c +++ b/net/netfilter/xt_CLASSIFY.c | |||
@@ -39,7 +39,7 @@ target(struct sk_buff **pskb, | |||
39 | return XT_CONTINUE; | 39 | return XT_CONTINUE; |
40 | } | 40 | } |
41 | 41 | ||
42 | static struct xt_target xt_classify_target[] = { | 42 | static struct xt_target xt_classify_target[] __read_mostly = { |
43 | { | 43 | { |
44 | .family = AF_INET, | 44 | .family = AF_INET, |
45 | .name = "CLASSIFY", | 45 | .name = "CLASSIFY", |
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c index b03ce009d0bf..5a00c5444334 100644 --- a/net/netfilter/xt_CONNMARK.c +++ b/net/netfilter/xt_CONNMARK.c | |||
@@ -76,33 +76,33 @@ target(struct sk_buff **pskb, | |||
76 | return XT_CONTINUE; | 76 | return XT_CONTINUE; |
77 | } | 77 | } |
78 | 78 | ||
79 | static int | 79 | static bool |
80 | checkentry(const char *tablename, | 80 | checkentry(const char *tablename, |
81 | const void *entry, | 81 | const void *entry, |
82 | const struct xt_target *target, | 82 | const struct xt_target *target, |
83 | void *targinfo, | 83 | void *targinfo, |
84 | unsigned int hook_mask) | 84 | unsigned int hook_mask) |
85 | { | 85 | { |
86 | struct xt_connmark_target_info *matchinfo = targinfo; | 86 | const struct xt_connmark_target_info *matchinfo = targinfo; |
87 | 87 | ||
88 | if (nf_ct_l3proto_try_module_get(target->family) < 0) { | 88 | if (nf_ct_l3proto_try_module_get(target->family) < 0) { |
89 | printk(KERN_WARNING "can't load conntrack support for " | 89 | printk(KERN_WARNING "can't load conntrack support for " |
90 | "proto=%d\n", target->family); | 90 | "proto=%d\n", target->family); |
91 | return 0; | 91 | return false; |
92 | } | 92 | } |
93 | if (matchinfo->mode == XT_CONNMARK_RESTORE) { | 93 | if (matchinfo->mode == XT_CONNMARK_RESTORE) { |
94 | if (strcmp(tablename, "mangle") != 0) { | 94 | if (strcmp(tablename, "mangle") != 0) { |
95 | printk(KERN_WARNING "CONNMARK: restore can only be " | 95 | printk(KERN_WARNING "CONNMARK: restore can only be " |
96 | "called from \"mangle\" table, not \"%s\"\n", | 96 | "called from \"mangle\" table, not \"%s\"\n", |
97 | tablename); | 97 | tablename); |
98 | return 0; | 98 | return false; |
99 | } | 99 | } |
100 | } | 100 | } |
101 | if (matchinfo->mark > 0xffffffff || matchinfo->mask > 0xffffffff) { | 101 | if (matchinfo->mark > 0xffffffff || matchinfo->mask > 0xffffffff) { |
102 | printk(KERN_WARNING "CONNMARK: Only supports 32bit mark\n"); | 102 | printk(KERN_WARNING "CONNMARK: Only supports 32bit mark\n"); |
103 | return 0; | 103 | return false; |
104 | } | 104 | } |
105 | return 1; | 105 | return true; |
106 | } | 106 | } |
107 | 107 | ||
108 | static void | 108 | static void |
@@ -121,7 +121,7 @@ struct compat_xt_connmark_target_info { | |||
121 | 121 | ||
122 | static void compat_from_user(void *dst, void *src) | 122 | static void compat_from_user(void *dst, void *src) |
123 | { | 123 | { |
124 | struct compat_xt_connmark_target_info *cm = src; | 124 | const struct compat_xt_connmark_target_info *cm = src; |
125 | struct xt_connmark_target_info m = { | 125 | struct xt_connmark_target_info m = { |
126 | .mark = cm->mark, | 126 | .mark = cm->mark, |
127 | .mask = cm->mask, | 127 | .mask = cm->mask, |
@@ -132,7 +132,7 @@ static void compat_from_user(void *dst, void *src) | |||
132 | 132 | ||
133 | static int compat_to_user(void __user *dst, void *src) | 133 | static int compat_to_user(void __user *dst, void *src) |
134 | { | 134 | { |
135 | struct xt_connmark_target_info *m = src; | 135 | const struct xt_connmark_target_info *m = src; |
136 | struct compat_xt_connmark_target_info cm = { | 136 | struct compat_xt_connmark_target_info cm = { |
137 | .mark = m->mark, | 137 | .mark = m->mark, |
138 | .mask = m->mask, | 138 | .mask = m->mask, |
@@ -142,7 +142,7 @@ static int compat_to_user(void __user *dst, void *src) | |||
142 | } | 142 | } |
143 | #endif /* CONFIG_COMPAT */ | 143 | #endif /* CONFIG_COMPAT */ |
144 | 144 | ||
145 | static struct xt_target xt_connmark_target[] = { | 145 | static struct xt_target xt_connmark_target[] __read_mostly = { |
146 | { | 146 | { |
147 | .name = "CONNMARK", | 147 | .name = "CONNMARK", |
148 | .family = AF_INET, | 148 | .family = AF_INET, |
diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c index 81c0c58bab47..63d73138c1b9 100644 --- a/net/netfilter/xt_CONNSECMARK.c +++ b/net/netfilter/xt_CONNSECMARK.c | |||
@@ -33,7 +33,7 @@ MODULE_ALIAS("ip6t_CONNSECMARK"); | |||
33 | * If the packet has a security mark and the connection does not, copy | 33 | * If the packet has a security mark and the connection does not, copy |
34 | * the security mark from the packet to the connection. | 34 | * the security mark from the packet to the connection. |
35 | */ | 35 | */ |
36 | static void secmark_save(struct sk_buff *skb) | 36 | static void secmark_save(const struct sk_buff *skb) |
37 | { | 37 | { |
38 | if (skb->secmark) { | 38 | if (skb->secmark) { |
39 | struct nf_conn *ct; | 39 | struct nf_conn *ct; |
@@ -85,16 +85,16 @@ static unsigned int target(struct sk_buff **pskb, const struct net_device *in, | |||
85 | return XT_CONTINUE; | 85 | return XT_CONTINUE; |
86 | } | 86 | } |
87 | 87 | ||
88 | static int checkentry(const char *tablename, const void *entry, | 88 | static bool checkentry(const char *tablename, const void *entry, |
89 | const struct xt_target *target, void *targinfo, | 89 | const struct xt_target *target, void *targinfo, |
90 | unsigned int hook_mask) | 90 | unsigned int hook_mask) |
91 | { | 91 | { |
92 | struct xt_connsecmark_target_info *info = targinfo; | 92 | const struct xt_connsecmark_target_info *info = targinfo; |
93 | 93 | ||
94 | if (nf_ct_l3proto_try_module_get(target->family) < 0) { | 94 | if (nf_ct_l3proto_try_module_get(target->family) < 0) { |
95 | printk(KERN_WARNING "can't load conntrack support for " | 95 | printk(KERN_WARNING "can't load conntrack support for " |
96 | "proto=%d\n", target->family); | 96 | "proto=%d\n", target->family); |
97 | return 0; | 97 | return false; |
98 | } | 98 | } |
99 | switch (info->mode) { | 99 | switch (info->mode) { |
100 | case CONNSECMARK_SAVE: | 100 | case CONNSECMARK_SAVE: |
@@ -103,10 +103,10 @@ static int checkentry(const char *tablename, const void *entry, | |||
103 | 103 | ||
104 | default: | 104 | default: |
105 | printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode); | 105 | printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode); |
106 | return 0; | 106 | return false; |
107 | } | 107 | } |
108 | 108 | ||
109 | return 1; | 109 | return true; |
110 | } | 110 | } |
111 | 111 | ||
112 | static void | 112 | static void |
@@ -115,7 +115,7 @@ destroy(const struct xt_target *target, void *targinfo) | |||
115 | nf_ct_l3proto_module_put(target->family); | 115 | nf_ct_l3proto_module_put(target->family); |
116 | } | 116 | } |
117 | 117 | ||
118 | static struct xt_target xt_connsecmark_target[] = { | 118 | static struct xt_target xt_connsecmark_target[] __read_mostly = { |
119 | { | 119 | { |
120 | .name = "CONNSECMARK", | 120 | .name = "CONNSECMARK", |
121 | .family = AF_INET, | 121 | .family = AF_INET, |
diff --git a/net/netfilter/xt_DSCP.c b/net/netfilter/xt_DSCP.c index 9f2f2201f6ae..798ab731009d 100644 --- a/net/netfilter/xt_DSCP.c +++ b/net/netfilter/xt_DSCP.c | |||
@@ -66,22 +66,22 @@ static unsigned int target6(struct sk_buff **pskb, | |||
66 | return XT_CONTINUE; | 66 | return XT_CONTINUE; |
67 | } | 67 | } |
68 | 68 | ||
69 | static int checkentry(const char *tablename, | 69 | static bool checkentry(const char *tablename, |
70 | const void *e_void, | 70 | const void *e_void, |
71 | const struct xt_target *target, | 71 | const struct xt_target *target, |
72 | void *targinfo, | 72 | void *targinfo, |
73 | unsigned int hook_mask) | 73 | unsigned int hook_mask) |
74 | { | 74 | { |
75 | const u_int8_t dscp = ((struct xt_DSCP_info *)targinfo)->dscp; | 75 | const u_int8_t dscp = ((struct xt_DSCP_info *)targinfo)->dscp; |
76 | 76 | ||
77 | if ((dscp > XT_DSCP_MAX)) { | 77 | if (dscp > XT_DSCP_MAX) { |
78 | printk(KERN_WARNING "DSCP: dscp %x out of range\n", dscp); | 78 | printk(KERN_WARNING "DSCP: dscp %x out of range\n", dscp); |
79 | return 0; | 79 | return false; |
80 | } | 80 | } |
81 | return 1; | 81 | return true; |
82 | } | 82 | } |
83 | 83 | ||
84 | static struct xt_target xt_dscp_target[] = { | 84 | static struct xt_target xt_dscp_target[] __read_mostly = { |
85 | { | 85 | { |
86 | .name = "DSCP", | 86 | .name = "DSCP", |
87 | .family = AF_INET, | 87 | .family = AF_INET, |
diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c index 43817808d865..f30fe0baf7de 100644 --- a/net/netfilter/xt_MARK.c +++ b/net/netfilter/xt_MARK.c | |||
@@ -65,43 +65,43 @@ target_v1(struct sk_buff **pskb, | |||
65 | } | 65 | } |
66 | 66 | ||
67 | 67 | ||
68 | static int | 68 | static bool |
69 | checkentry_v0(const char *tablename, | 69 | checkentry_v0(const char *tablename, |
70 | const void *entry, | 70 | const void *entry, |
71 | const struct xt_target *target, | 71 | const struct xt_target *target, |
72 | void *targinfo, | 72 | void *targinfo, |
73 | unsigned int hook_mask) | 73 | unsigned int hook_mask) |
74 | { | 74 | { |
75 | struct xt_mark_target_info *markinfo = targinfo; | 75 | const struct xt_mark_target_info *markinfo = targinfo; |
76 | 76 | ||
77 | if (markinfo->mark > 0xffffffff) { | 77 | if (markinfo->mark > 0xffffffff) { |
78 | printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n"); | 78 | printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n"); |
79 | return 0; | 79 | return false; |
80 | } | 80 | } |
81 | return 1; | 81 | return true; |
82 | } | 82 | } |
83 | 83 | ||
84 | static int | 84 | static bool |
85 | checkentry_v1(const char *tablename, | 85 | checkentry_v1(const char *tablename, |
86 | const void *entry, | 86 | const void *entry, |
87 | const struct xt_target *target, | 87 | const struct xt_target *target, |
88 | void *targinfo, | 88 | void *targinfo, |
89 | unsigned int hook_mask) | 89 | unsigned int hook_mask) |
90 | { | 90 | { |
91 | struct xt_mark_target_info_v1 *markinfo = targinfo; | 91 | const struct xt_mark_target_info_v1 *markinfo = targinfo; |
92 | 92 | ||
93 | if (markinfo->mode != XT_MARK_SET | 93 | if (markinfo->mode != XT_MARK_SET |
94 | && markinfo->mode != XT_MARK_AND | 94 | && markinfo->mode != XT_MARK_AND |
95 | && markinfo->mode != XT_MARK_OR) { | 95 | && markinfo->mode != XT_MARK_OR) { |
96 | printk(KERN_WARNING "MARK: unknown mode %u\n", | 96 | printk(KERN_WARNING "MARK: unknown mode %u\n", |
97 | markinfo->mode); | 97 | markinfo->mode); |
98 | return 0; | 98 | return false; |
99 | } | 99 | } |
100 | if (markinfo->mark > 0xffffffff) { | 100 | if (markinfo->mark > 0xffffffff) { |
101 | printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n"); | 101 | printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n"); |
102 | return 0; | 102 | return false; |
103 | } | 103 | } |
104 | return 1; | 104 | return true; |
105 | } | 105 | } |
106 | 106 | ||
107 | #ifdef CONFIG_COMPAT | 107 | #ifdef CONFIG_COMPAT |
@@ -114,7 +114,7 @@ struct compat_xt_mark_target_info_v1 { | |||
114 | 114 | ||
115 | static void compat_from_user_v1(void *dst, void *src) | 115 | static void compat_from_user_v1(void *dst, void *src) |
116 | { | 116 | { |
117 | struct compat_xt_mark_target_info_v1 *cm = src; | 117 | const struct compat_xt_mark_target_info_v1 *cm = src; |
118 | struct xt_mark_target_info_v1 m = { | 118 | struct xt_mark_target_info_v1 m = { |
119 | .mark = cm->mark, | 119 | .mark = cm->mark, |
120 | .mode = cm->mode, | 120 | .mode = cm->mode, |
@@ -124,7 +124,7 @@ static void compat_from_user_v1(void *dst, void *src) | |||
124 | 124 | ||
125 | static int compat_to_user_v1(void __user *dst, void *src) | 125 | static int compat_to_user_v1(void __user *dst, void *src) |
126 | { | 126 | { |
127 | struct xt_mark_target_info_v1 *m = src; | 127 | const struct xt_mark_target_info_v1 *m = src; |
128 | struct compat_xt_mark_target_info_v1 cm = { | 128 | struct compat_xt_mark_target_info_v1 cm = { |
129 | .mark = m->mark, | 129 | .mark = m->mark, |
130 | .mode = m->mode, | 130 | .mode = m->mode, |
@@ -133,7 +133,7 @@ static int compat_to_user_v1(void __user *dst, void *src) | |||
133 | } | 133 | } |
134 | #endif /* CONFIG_COMPAT */ | 134 | #endif /* CONFIG_COMPAT */ |
135 | 135 | ||
136 | static struct xt_target xt_mark_target[] = { | 136 | static struct xt_target xt_mark_target[] __read_mostly = { |
137 | { | 137 | { |
138 | .name = "MARK", | 138 | .name = "MARK", |
139 | .family = AF_INET, | 139 | .family = AF_INET, |
diff --git a/net/netfilter/xt_NFLOG.c b/net/netfilter/xt_NFLOG.c index 901ed7abaa1b..d3594c7ccb26 100644 --- a/net/netfilter/xt_NFLOG.c +++ b/net/netfilter/xt_NFLOG.c | |||
@@ -38,21 +38,21 @@ nflog_target(struct sk_buff **pskb, | |||
38 | return XT_CONTINUE; | 38 | return XT_CONTINUE; |
39 | } | 39 | } |
40 | 40 | ||
41 | static int | 41 | static bool |
42 | nflog_checkentry(const char *tablename, const void *entry, | 42 | nflog_checkentry(const char *tablename, const void *entry, |
43 | const struct xt_target *target, void *targetinfo, | 43 | const struct xt_target *target, void *targetinfo, |
44 | unsigned int hookmask) | 44 | unsigned int hookmask) |
45 | { | 45 | { |
46 | struct xt_nflog_info *info = targetinfo; | 46 | const struct xt_nflog_info *info = targetinfo; |
47 | 47 | ||
48 | if (info->flags & ~XT_NFLOG_MASK) | 48 | if (info->flags & ~XT_NFLOG_MASK) |
49 | return 0; | 49 | return false; |
50 | if (info->prefix[sizeof(info->prefix) - 1] != '\0') | 50 | if (info->prefix[sizeof(info->prefix) - 1] != '\0') |
51 | return 0; | 51 | return false; |
52 | return 1; | 52 | return true; |
53 | } | 53 | } |
54 | 54 | ||
55 | static struct xt_target xt_nflog_target[] = { | 55 | static struct xt_target xt_nflog_target[] __read_mostly = { |
56 | { | 56 | { |
57 | .name = "NFLOG", | 57 | .name = "NFLOG", |
58 | .family = AF_INET, | 58 | .family = AF_INET, |
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c index 201155b316e0..13f59f3e8c38 100644 --- a/net/netfilter/xt_NFQUEUE.c +++ b/net/netfilter/xt_NFQUEUE.c | |||
@@ -36,7 +36,7 @@ target(struct sk_buff **pskb, | |||
36 | return NF_QUEUE_NR(tinfo->queuenum); | 36 | return NF_QUEUE_NR(tinfo->queuenum); |
37 | } | 37 | } |
38 | 38 | ||
39 | static struct xt_target xt_nfqueue_target[] = { | 39 | static struct xt_target xt_nfqueue_target[] __read_mostly = { |
40 | { | 40 | { |
41 | .name = "NFQUEUE", | 41 | .name = "NFQUEUE", |
42 | .family = AF_INET, | 42 | .family = AF_INET, |
diff --git a/net/netfilter/xt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c index 5085fb3d1e2d..b7d6312fccc7 100644 --- a/net/netfilter/xt_NOTRACK.c +++ b/net/netfilter/xt_NOTRACK.c | |||
@@ -33,7 +33,7 @@ target(struct sk_buff **pskb, | |||
33 | return XT_CONTINUE; | 33 | return XT_CONTINUE; |
34 | } | 34 | } |
35 | 35 | ||
36 | static struct xt_target xt_notrack_target[] = { | 36 | static struct xt_target xt_notrack_target[] __read_mostly = { |
37 | { | 37 | { |
38 | .name = "NOTRACK", | 38 | .name = "NOTRACK", |
39 | .family = AF_INET, | 39 | .family = AF_INET, |
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c index 705f0e830a79..c83779a941a1 100644 --- a/net/netfilter/xt_SECMARK.c +++ b/net/netfilter/xt_SECMARK.c | |||
@@ -51,7 +51,7 @@ static unsigned int target(struct sk_buff **pskb, const struct net_device *in, | |||
51 | return XT_CONTINUE; | 51 | return XT_CONTINUE; |
52 | } | 52 | } |
53 | 53 | ||
54 | static int checkentry_selinux(struct xt_secmark_target_info *info) | 54 | static bool checkentry_selinux(struct xt_secmark_target_info *info) |
55 | { | 55 | { |
56 | int err; | 56 | int err; |
57 | struct xt_secmark_target_selinux_info *sel = &info->u.sel; | 57 | struct xt_secmark_target_selinux_info *sel = &info->u.sel; |
@@ -63,53 +63,53 @@ static int checkentry_selinux(struct xt_secmark_target_info *info) | |||
63 | if (err == -EINVAL) | 63 | if (err == -EINVAL) |
64 | printk(KERN_INFO PFX "invalid SELinux context \'%s\'\n", | 64 | printk(KERN_INFO PFX "invalid SELinux context \'%s\'\n", |
65 | sel->selctx); | 65 | sel->selctx); |
66 | return 0; | 66 | return false; |
67 | } | 67 | } |
68 | 68 | ||
69 | if (!sel->selsid) { | 69 | if (!sel->selsid) { |
70 | printk(KERN_INFO PFX "unable to map SELinux context \'%s\'\n", | 70 | printk(KERN_INFO PFX "unable to map SELinux context \'%s\'\n", |
71 | sel->selctx); | 71 | sel->selctx); |
72 | return 0; | 72 | return false; |
73 | } | 73 | } |
74 | 74 | ||
75 | err = selinux_relabel_packet_permission(sel->selsid); | 75 | err = selinux_relabel_packet_permission(sel->selsid); |
76 | if (err) { | 76 | if (err) { |
77 | printk(KERN_INFO PFX "unable to obtain relabeling permission\n"); | 77 | printk(KERN_INFO PFX "unable to obtain relabeling permission\n"); |
78 | return 0; | 78 | return false; |
79 | } | 79 | } |
80 | 80 | ||
81 | return 1; | 81 | return true; |
82 | } | 82 | } |
83 | 83 | ||
84 | static int checkentry(const char *tablename, const void *entry, | 84 | static bool checkentry(const char *tablename, const void *entry, |
85 | const struct xt_target *target, void *targinfo, | 85 | const struct xt_target *target, void *targinfo, |
86 | unsigned int hook_mask) | 86 | unsigned int hook_mask) |
87 | { | 87 | { |
88 | struct xt_secmark_target_info *info = targinfo; | 88 | struct xt_secmark_target_info *info = targinfo; |
89 | 89 | ||
90 | if (mode && mode != info->mode) { | 90 | if (mode && mode != info->mode) { |
91 | printk(KERN_INFO PFX "mode already set to %hu cannot mix with " | 91 | printk(KERN_INFO PFX "mode already set to %hu cannot mix with " |
92 | "rules for mode %hu\n", mode, info->mode); | 92 | "rules for mode %hu\n", mode, info->mode); |
93 | return 0; | 93 | return false; |
94 | } | 94 | } |
95 | 95 | ||
96 | switch (info->mode) { | 96 | switch (info->mode) { |
97 | case SECMARK_MODE_SEL: | 97 | case SECMARK_MODE_SEL: |
98 | if (!checkentry_selinux(info)) | 98 | if (!checkentry_selinux(info)) |
99 | return 0; | 99 | return false; |
100 | break; | 100 | break; |
101 | 101 | ||
102 | default: | 102 | default: |
103 | printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode); | 103 | printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode); |
104 | return 0; | 104 | return false; |
105 | } | 105 | } |
106 | 106 | ||
107 | if (!mode) | 107 | if (!mode) |
108 | mode = info->mode; | 108 | mode = info->mode; |
109 | return 1; | 109 | return true; |
110 | } | 110 | } |
111 | 111 | ||
112 | static struct xt_target xt_secmark_target[] = { | 112 | static struct xt_target xt_secmark_target[] __read_mostly = { |
113 | { | 113 | { |
114 | .name = "SECMARK", | 114 | .name = "SECMARK", |
115 | .family = AF_INET, | 115 | .family = AF_INET, |
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index 15fe8f649510..d40f7e4b1289 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c | |||
@@ -93,7 +93,7 @@ tcpmss_mangle_packet(struct sk_buff **pskb, | |||
93 | return 0; | 93 | return 0; |
94 | 94 | ||
95 | opt[i+2] = (newmss & 0xff00) >> 8; | 95 | opt[i+2] = (newmss & 0xff00) >> 8; |
96 | opt[i+3] = (newmss & 0x00ff); | 96 | opt[i+3] = newmss & 0x00ff; |
97 | 97 | ||
98 | nf_proto_csum_replace2(&tcph->check, *pskb, | 98 | nf_proto_csum_replace2(&tcph->check, *pskb, |
99 | htons(oldmss), htons(newmss), 0); | 99 | htons(oldmss), htons(newmss), 0); |
@@ -126,7 +126,7 @@ tcpmss_mangle_packet(struct sk_buff **pskb, | |||
126 | opt[0] = TCPOPT_MSS; | 126 | opt[0] = TCPOPT_MSS; |
127 | opt[1] = TCPOLEN_MSS; | 127 | opt[1] = TCPOLEN_MSS; |
128 | opt[2] = (newmss & 0xff00) >> 8; | 128 | opt[2] = (newmss & 0xff00) >> 8; |
129 | opt[3] = (newmss & 0x00ff); | 129 | opt[3] = newmss & 0x00ff; |
130 | 130 | ||
131 | nf_proto_csum_replace4(&tcph->check, *pskb, 0, *((__be32 *)opt), 0); | 131 | nf_proto_csum_replace4(&tcph->check, *pskb, 0, *((__be32 *)opt), 0); |
132 | 132 | ||
@@ -197,19 +197,19 @@ xt_tcpmss_target6(struct sk_buff **pskb, | |||
197 | #define TH_SYN 0x02 | 197 | #define TH_SYN 0x02 |
198 | 198 | ||
199 | /* Must specify -p tcp --syn */ | 199 | /* Must specify -p tcp --syn */ |
200 | static inline int find_syn_match(const struct xt_entry_match *m) | 200 | static inline bool find_syn_match(const struct xt_entry_match *m) |
201 | { | 201 | { |
202 | const struct xt_tcp *tcpinfo = (const struct xt_tcp *)m->data; | 202 | const struct xt_tcp *tcpinfo = (const struct xt_tcp *)m->data; |
203 | 203 | ||
204 | if (strcmp(m->u.kernel.match->name, "tcp") == 0 && | 204 | if (strcmp(m->u.kernel.match->name, "tcp") == 0 && |
205 | tcpinfo->flg_cmp & TH_SYN && | 205 | tcpinfo->flg_cmp & TH_SYN && |
206 | !(tcpinfo->invflags & XT_TCP_INV_FLAGS)) | 206 | !(tcpinfo->invflags & XT_TCP_INV_FLAGS)) |
207 | return 1; | 207 | return true; |
208 | 208 | ||
209 | return 0; | 209 | return false; |
210 | } | 210 | } |
211 | 211 | ||
212 | static int | 212 | static bool |
213 | xt_tcpmss_checkentry4(const char *tablename, | 213 | xt_tcpmss_checkentry4(const char *tablename, |
214 | const void *entry, | 214 | const void *entry, |
215 | const struct xt_target *target, | 215 | const struct xt_target *target, |
@@ -225,16 +225,16 @@ xt_tcpmss_checkentry4(const char *tablename, | |||
225 | (1 << NF_IP_POST_ROUTING))) != 0) { | 225 | (1 << NF_IP_POST_ROUTING))) != 0) { |
226 | printk("xt_TCPMSS: path-MTU clamping only supported in " | 226 | printk("xt_TCPMSS: path-MTU clamping only supported in " |
227 | "FORWARD, OUTPUT and POSTROUTING hooks\n"); | 227 | "FORWARD, OUTPUT and POSTROUTING hooks\n"); |
228 | return 0; | 228 | return false; |
229 | } | 229 | } |
230 | if (IPT_MATCH_ITERATE(e, find_syn_match)) | 230 | if (IPT_MATCH_ITERATE(e, find_syn_match)) |
231 | return 1; | 231 | return true; |
232 | printk("xt_TCPMSS: Only works on TCP SYN packets\n"); | 232 | printk("xt_TCPMSS: Only works on TCP SYN packets\n"); |
233 | return 0; | 233 | return false; |
234 | } | 234 | } |
235 | 235 | ||
236 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) | 236 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) |
237 | static int | 237 | static bool |
238 | xt_tcpmss_checkentry6(const char *tablename, | 238 | xt_tcpmss_checkentry6(const char *tablename, |
239 | const void *entry, | 239 | const void *entry, |
240 | const struct xt_target *target, | 240 | const struct xt_target *target, |
@@ -250,16 +250,16 @@ xt_tcpmss_checkentry6(const char *tablename, | |||
250 | (1 << NF_IP6_POST_ROUTING))) != 0) { | 250 | (1 << NF_IP6_POST_ROUTING))) != 0) { |
251 | printk("xt_TCPMSS: path-MTU clamping only supported in " | 251 | printk("xt_TCPMSS: path-MTU clamping only supported in " |
252 | "FORWARD, OUTPUT and POSTROUTING hooks\n"); | 252 | "FORWARD, OUTPUT and POSTROUTING hooks\n"); |
253 | return 0; | 253 | return false; |
254 | } | 254 | } |
255 | if (IP6T_MATCH_ITERATE(e, find_syn_match)) | 255 | if (IP6T_MATCH_ITERATE(e, find_syn_match)) |
256 | return 1; | 256 | return true; |
257 | printk("xt_TCPMSS: Only works on TCP SYN packets\n"); | 257 | printk("xt_TCPMSS: Only works on TCP SYN packets\n"); |
258 | return 0; | 258 | return false; |
259 | } | 259 | } |
260 | #endif | 260 | #endif |
261 | 261 | ||
262 | static struct xt_target xt_tcpmss_reg[] = { | 262 | static struct xt_target xt_tcpmss_reg[] __read_mostly = { |
263 | { | 263 | { |
264 | .family = AF_INET, | 264 | .family = AF_INET, |
265 | .name = "TCPMSS", | 265 | .name = "TCPMSS", |
diff --git a/net/netfilter/xt_TRACE.c b/net/netfilter/xt_TRACE.c new file mode 100644 index 000000000000..4df2dedcc0b5 --- /dev/null +++ b/net/netfilter/xt_TRACE.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /* This is a module which is used to mark packets for tracing. | ||
2 | */ | ||
3 | #include <linux/module.h> | ||
4 | #include <linux/skbuff.h> | ||
5 | |||
6 | #include <linux/netfilter/x_tables.h> | ||
7 | |||
8 | MODULE_LICENSE("GPL"); | ||
9 | MODULE_ALIAS("ipt_TRACE"); | ||
10 | MODULE_ALIAS("ip6t_TRACE"); | ||
11 | |||
12 | static unsigned int | ||
13 | target(struct sk_buff **pskb, | ||
14 | const struct net_device *in, | ||
15 | const struct net_device *out, | ||
16 | unsigned int hooknum, | ||
17 | const struct xt_target *target, | ||
18 | const void *targinfo) | ||
19 | { | ||
20 | (*pskb)->nf_trace = 1; | ||
21 | return XT_CONTINUE; | ||
22 | } | ||
23 | |||
24 | static struct xt_target xt_trace_target[] __read_mostly = { | ||
25 | { | ||
26 | .name = "TRACE", | ||
27 | .family = AF_INET, | ||
28 | .target = target, | ||
29 | .table = "raw", | ||
30 | .me = THIS_MODULE, | ||
31 | }, | ||
32 | { | ||
33 | .name = "TRACE", | ||
34 | .family = AF_INET6, | ||
35 | .target = target, | ||
36 | .table = "raw", | ||
37 | .me = THIS_MODULE, | ||
38 | }, | ||
39 | }; | ||
40 | |||
41 | static int __init xt_trace_init(void) | ||
42 | { | ||
43 | return xt_register_targets(xt_trace_target, | ||
44 | ARRAY_SIZE(xt_trace_target)); | ||
45 | } | ||
46 | |||
47 | static void __exit xt_trace_fini(void) | ||
48 | { | ||
49 | xt_unregister_targets(xt_trace_target, ARRAY_SIZE(xt_trace_target)); | ||
50 | } | ||
51 | |||
52 | module_init(xt_trace_init); | ||
53 | module_exit(xt_trace_fini); | ||
diff --git a/net/netfilter/xt_comment.c b/net/netfilter/xt_comment.c index 7db492d65220..64bcdb0fe1e6 100644 --- a/net/netfilter/xt_comment.c +++ b/net/netfilter/xt_comment.c | |||
@@ -15,7 +15,7 @@ MODULE_LICENSE("GPL"); | |||
15 | MODULE_ALIAS("ipt_comment"); | 15 | MODULE_ALIAS("ipt_comment"); |
16 | MODULE_ALIAS("ip6t_comment"); | 16 | MODULE_ALIAS("ip6t_comment"); |
17 | 17 | ||
18 | static int | 18 | static bool |
19 | match(const struct sk_buff *skb, | 19 | match(const struct sk_buff *skb, |
20 | const struct net_device *in, | 20 | const struct net_device *in, |
21 | const struct net_device *out, | 21 | const struct net_device *out, |
@@ -23,13 +23,13 @@ match(const struct sk_buff *skb, | |||
23 | const void *matchinfo, | 23 | const void *matchinfo, |
24 | int offset, | 24 | int offset, |
25 | unsigned int protooff, | 25 | unsigned int protooff, |
26 | int *hotdrop) | 26 | bool *hotdrop) |
27 | { | 27 | { |
28 | /* We always match */ | 28 | /* We always match */ |
29 | return 1; | 29 | return true; |
30 | } | 30 | } |
31 | 31 | ||
32 | static struct xt_match xt_comment_match[] = { | 32 | static struct xt_match xt_comment_match[] __read_mostly = { |
33 | { | 33 | { |
34 | .name = "comment", | 34 | .name = "comment", |
35 | .family = AF_INET, | 35 | .family = AF_INET, |
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c index 804afe55e141..dd4d79b8fc9d 100644 --- a/net/netfilter/xt_connbytes.c +++ b/net/netfilter/xt_connbytes.c | |||
@@ -15,7 +15,7 @@ MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | |||
15 | MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection"); | 15 | MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection"); |
16 | MODULE_ALIAS("ipt_connbytes"); | 16 | MODULE_ALIAS("ipt_connbytes"); |
17 | 17 | ||
18 | static int | 18 | static bool |
19 | match(const struct sk_buff *skb, | 19 | match(const struct sk_buff *skb, |
20 | const struct net_device *in, | 20 | const struct net_device *in, |
21 | const struct net_device *out, | 21 | const struct net_device *out, |
@@ -23,10 +23,10 @@ match(const struct sk_buff *skb, | |||
23 | const void *matchinfo, | 23 | const void *matchinfo, |
24 | int offset, | 24 | int offset, |
25 | unsigned int protoff, | 25 | unsigned int protoff, |
26 | int *hotdrop) | 26 | bool *hotdrop) |
27 | { | 27 | { |
28 | const struct xt_connbytes_info *sinfo = matchinfo; | 28 | const struct xt_connbytes_info *sinfo = matchinfo; |
29 | struct nf_conn *ct; | 29 | const struct nf_conn *ct; |
30 | enum ip_conntrack_info ctinfo; | 30 | enum ip_conntrack_info ctinfo; |
31 | u_int64_t what = 0; /* initialize to make gcc happy */ | 31 | u_int64_t what = 0; /* initialize to make gcc happy */ |
32 | u_int64_t bytes = 0; | 32 | u_int64_t bytes = 0; |
@@ -35,7 +35,7 @@ match(const struct sk_buff *skb, | |||
35 | 35 | ||
36 | ct = nf_ct_get(skb, &ctinfo); | 36 | ct = nf_ct_get(skb, &ctinfo); |
37 | if (!ct) | 37 | if (!ct) |
38 | return 0; | 38 | return false; |
39 | counters = ct->counters; | 39 | counters = ct->counters; |
40 | 40 | ||
41 | switch (sinfo->what) { | 41 | switch (sinfo->what) { |
@@ -90,36 +90,36 @@ match(const struct sk_buff *skb, | |||
90 | } | 90 | } |
91 | 91 | ||
92 | if (sinfo->count.to) | 92 | if (sinfo->count.to) |
93 | return (what <= sinfo->count.to && what >= sinfo->count.from); | 93 | return what <= sinfo->count.to && what >= sinfo->count.from; |
94 | else | 94 | else |
95 | return (what >= sinfo->count.from); | 95 | return what >= sinfo->count.from; |
96 | } | 96 | } |
97 | 97 | ||
98 | static int check(const char *tablename, | 98 | static bool check(const char *tablename, |
99 | const void *ip, | 99 | const void *ip, |
100 | const struct xt_match *match, | 100 | const struct xt_match *match, |
101 | void *matchinfo, | 101 | void *matchinfo, |
102 | unsigned int hook_mask) | 102 | unsigned int hook_mask) |
103 | { | 103 | { |
104 | const struct xt_connbytes_info *sinfo = matchinfo; | 104 | const struct xt_connbytes_info *sinfo = matchinfo; |
105 | 105 | ||
106 | if (sinfo->what != XT_CONNBYTES_PKTS && | 106 | if (sinfo->what != XT_CONNBYTES_PKTS && |
107 | sinfo->what != XT_CONNBYTES_BYTES && | 107 | sinfo->what != XT_CONNBYTES_BYTES && |
108 | sinfo->what != XT_CONNBYTES_AVGPKT) | 108 | sinfo->what != XT_CONNBYTES_AVGPKT) |
109 | return 0; | 109 | return false; |
110 | 110 | ||
111 | if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL && | 111 | if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL && |
112 | sinfo->direction != XT_CONNBYTES_DIR_REPLY && | 112 | sinfo->direction != XT_CONNBYTES_DIR_REPLY && |
113 | sinfo->direction != XT_CONNBYTES_DIR_BOTH) | 113 | sinfo->direction != XT_CONNBYTES_DIR_BOTH) |
114 | return 0; | 114 | return false; |
115 | 115 | ||
116 | if (nf_ct_l3proto_try_module_get(match->family) < 0) { | 116 | if (nf_ct_l3proto_try_module_get(match->family) < 0) { |
117 | printk(KERN_WARNING "can't load conntrack support for " | 117 | printk(KERN_WARNING "can't load conntrack support for " |
118 | "proto=%d\n", match->family); | 118 | "proto=%d\n", match->family); |
119 | return 0; | 119 | return false; |
120 | } | 120 | } |
121 | 121 | ||
122 | return 1; | 122 | return true; |
123 | } | 123 | } |
124 | 124 | ||
125 | static void | 125 | static void |
@@ -128,7 +128,7 @@ destroy(const struct xt_match *match, void *matchinfo) | |||
128 | nf_ct_l3proto_module_put(match->family); | 128 | nf_ct_l3proto_module_put(match->family); |
129 | } | 129 | } |
130 | 130 | ||
131 | static struct xt_match xt_connbytes_match[] = { | 131 | static struct xt_match xt_connbytes_match[] __read_mostly = { |
132 | { | 132 | { |
133 | .name = "connbytes", | 133 | .name = "connbytes", |
134 | .family = AF_INET, | 134 | .family = AF_INET, |
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c new file mode 100644 index 000000000000..3335dd5be962 --- /dev/null +++ b/net/netfilter/xt_connlimit.c | |||
@@ -0,0 +1,313 @@ | |||
1 | /* | ||
2 | * netfilter module to limit the number of parallel tcp | ||
3 | * connections per IP address. | ||
4 | * (c) 2000 Gerd Knorr <kraxel@bytesex.org> | ||
5 | * Nov 2002: Martin Bene <martin.bene@icomedias.com>: | ||
6 | * only ignore TIME_WAIT or gone connections | ||
7 | * Copyright © Jan Engelhardt <jengelh@gmx.de>, 2007 | ||
8 | * | ||
9 | * based on ... | ||
10 | * | ||
11 | * Kernel module to match connection tracking information. | ||
12 | * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au). | ||
13 | */ | ||
14 | #include <linux/in.h> | ||
15 | #include <linux/in6.h> | ||
16 | #include <linux/ip.h> | ||
17 | #include <linux/ipv6.h> | ||
18 | #include <linux/jhash.h> | ||
19 | #include <linux/list.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/random.h> | ||
22 | #include <linux/skbuff.h> | ||
23 | #include <linux/spinlock.h> | ||
24 | #include <linux/netfilter/nf_conntrack_tcp.h> | ||
25 | #include <linux/netfilter/x_tables.h> | ||
26 | #include <linux/netfilter/xt_connlimit.h> | ||
27 | #include <net/netfilter/nf_conntrack.h> | ||
28 | #include <net/netfilter/nf_conntrack_core.h> | ||
29 | #include <net/netfilter/nf_conntrack_tuple.h> | ||
30 | |||
31 | /* we will save the tuples of all connections we care about */ | ||
32 | struct xt_connlimit_conn { | ||
33 | struct list_head list; | ||
34 | struct nf_conntrack_tuple tuple; | ||
35 | }; | ||
36 | |||
37 | struct xt_connlimit_data { | ||
38 | struct list_head iphash[256]; | ||
39 | spinlock_t lock; | ||
40 | }; | ||
41 | |||
42 | static u_int32_t connlimit_rnd; | ||
43 | static bool connlimit_rnd_inited; | ||
44 | |||
45 | static inline unsigned int connlimit_iphash(u_int32_t addr) | ||
46 | { | ||
47 | if (unlikely(!connlimit_rnd_inited)) { | ||
48 | get_random_bytes(&connlimit_rnd, sizeof(connlimit_rnd)); | ||
49 | connlimit_rnd_inited = true; | ||
50 | } | ||
51 | return jhash_1word(addr, connlimit_rnd) & 0xFF; | ||
52 | } | ||
53 | |||
54 | static inline unsigned int | ||
55 | connlimit_iphash6(const union nf_conntrack_address *addr, | ||
56 | const union nf_conntrack_address *mask) | ||
57 | { | ||
58 | union nf_conntrack_address res; | ||
59 | unsigned int i; | ||
60 | |||
61 | if (unlikely(!connlimit_rnd_inited)) { | ||
62 | get_random_bytes(&connlimit_rnd, sizeof(connlimit_rnd)); | ||
63 | connlimit_rnd_inited = true; | ||
64 | } | ||
65 | |||
66 | for (i = 0; i < ARRAY_SIZE(addr->ip6); ++i) | ||
67 | res.ip6[i] = addr->ip6[i] & mask->ip6[i]; | ||
68 | |||
69 | return jhash2(res.ip6, ARRAY_SIZE(res.ip6), connlimit_rnd) & 0xFF; | ||
70 | } | ||
71 | |||
72 | static inline bool already_closed(const struct nf_conn *conn) | ||
73 | { | ||
74 | u_int16_t proto = conn->tuplehash[0].tuple.dst.protonum; | ||
75 | |||
76 | if (proto == IPPROTO_TCP) | ||
77 | return conn->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT; | ||
78 | else | ||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static inline unsigned int | ||
83 | same_source_net(const union nf_conntrack_address *addr, | ||
84 | const union nf_conntrack_address *mask, | ||
85 | const union nf_conntrack_address *u3, unsigned int family) | ||
86 | { | ||
87 | if (family == AF_INET) { | ||
88 | return (addr->ip & mask->ip) == (u3->ip & mask->ip); | ||
89 | } else { | ||
90 | union nf_conntrack_address lh, rh; | ||
91 | unsigned int i; | ||
92 | |||
93 | for (i = 0; i < ARRAY_SIZE(addr->ip6); ++i) { | ||
94 | lh.ip6[i] = addr->ip6[i] & mask->ip6[i]; | ||
95 | rh.ip6[i] = u3->ip6[i] & mask->ip6[i]; | ||
96 | } | ||
97 | |||
98 | return memcmp(&lh.ip6, &rh.ip6, sizeof(lh.ip6)) == 0; | ||
99 | } | ||
100 | } | ||
101 | |||
102 | static int count_them(struct xt_connlimit_data *data, | ||
103 | const struct nf_conntrack_tuple *tuple, | ||
104 | const union nf_conntrack_address *addr, | ||
105 | const union nf_conntrack_address *mask, | ||
106 | const struct xt_match *match) | ||
107 | { | ||
108 | struct nf_conntrack_tuple_hash *found; | ||
109 | struct xt_connlimit_conn *conn; | ||
110 | struct xt_connlimit_conn *tmp; | ||
111 | struct nf_conn *found_ct; | ||
112 | struct list_head *hash; | ||
113 | bool addit = true; | ||
114 | int matches = 0; | ||
115 | |||
116 | |||
117 | if (match->family == AF_INET6) | ||
118 | hash = &data->iphash[connlimit_iphash6(addr, mask)]; | ||
119 | else | ||
120 | hash = &data->iphash[connlimit_iphash(addr->ip & mask->ip)]; | ||
121 | |||
122 | read_lock_bh(&nf_conntrack_lock); | ||
123 | |||
124 | /* check the saved connections */ | ||
125 | list_for_each_entry_safe(conn, tmp, hash, list) { | ||
126 | found = __nf_conntrack_find(&conn->tuple, NULL); | ||
127 | found_ct = NULL; | ||
128 | |||
129 | if (found != NULL) | ||
130 | found_ct = nf_ct_tuplehash_to_ctrack(found); | ||
131 | |||
132 | if (found_ct != NULL && | ||
133 | nf_ct_tuple_equal(&conn->tuple, tuple) && | ||
134 | !already_closed(found_ct)) | ||
135 | /* | ||
136 | * Just to be sure we have it only once in the list. | ||
137 | * We should not see tuples twice unless someone hooks | ||
138 | * this into a table without "-p tcp --syn". | ||
139 | */ | ||
140 | addit = false; | ||
141 | |||
142 | if (found == NULL) { | ||
143 | /* this one is gone */ | ||
144 | list_del(&conn->list); | ||
145 | kfree(conn); | ||
146 | continue; | ||
147 | } | ||
148 | |||
149 | if (already_closed(found_ct)) { | ||
150 | /* | ||
151 | * we do not care about connections which are | ||
152 | * closed already -> ditch it | ||
153 | */ | ||
154 | list_del(&conn->list); | ||
155 | kfree(conn); | ||
156 | continue; | ||
157 | } | ||
158 | |||
159 | if (same_source_net(addr, mask, &conn->tuple.src.u3, | ||
160 | match->family)) | ||
161 | /* same source network -> be counted! */ | ||
162 | ++matches; | ||
163 | } | ||
164 | |||
165 | read_unlock_bh(&nf_conntrack_lock); | ||
166 | |||
167 | if (addit) { | ||
168 | /* save the new connection in our list */ | ||
169 | conn = kzalloc(sizeof(*conn), GFP_ATOMIC); | ||
170 | if (conn == NULL) | ||
171 | return -ENOMEM; | ||
172 | conn->tuple = *tuple; | ||
173 | list_add(&conn->list, hash); | ||
174 | ++matches; | ||
175 | } | ||
176 | |||
177 | return matches; | ||
178 | } | ||
179 | |||
180 | static bool connlimit_match(const struct sk_buff *skb, | ||
181 | const struct net_device *in, | ||
182 | const struct net_device *out, | ||
183 | const struct xt_match *match, | ||
184 | const void *matchinfo, int offset, | ||
185 | unsigned int protoff, bool *hotdrop) | ||
186 | { | ||
187 | const struct xt_connlimit_info *info = matchinfo; | ||
188 | union nf_conntrack_address addr, mask; | ||
189 | struct nf_conntrack_tuple tuple; | ||
190 | const struct nf_conntrack_tuple *tuple_ptr = &tuple; | ||
191 | enum ip_conntrack_info ctinfo; | ||
192 | const struct nf_conn *ct; | ||
193 | int connections; | ||
194 | |||
195 | ct = nf_ct_get(skb, &ctinfo); | ||
196 | if (ct != NULL) | ||
197 | tuple_ptr = &ct->tuplehash[0].tuple; | ||
198 | else if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), | ||
199 | match->family, &tuple)) | ||
200 | goto hotdrop; | ||
201 | |||
202 | if (match->family == AF_INET6) { | ||
203 | const struct ipv6hdr *iph = ipv6_hdr(skb); | ||
204 | memcpy(&addr.ip6, &iph->saddr, sizeof(iph->saddr)); | ||
205 | memcpy(&mask.ip6, info->v6_mask, sizeof(info->v6_mask)); | ||
206 | } else { | ||
207 | const struct iphdr *iph = ip_hdr(skb); | ||
208 | addr.ip = iph->saddr; | ||
209 | mask.ip = info->v4_mask; | ||
210 | } | ||
211 | |||
212 | spin_lock_bh(&info->data->lock); | ||
213 | connections = count_them(info->data, tuple_ptr, &addr, &mask, match); | ||
214 | spin_unlock_bh(&info->data->lock); | ||
215 | |||
216 | if (connections < 0) { | ||
217 | /* kmalloc failed, drop it entirely */ | ||
218 | *hotdrop = true; | ||
219 | return false; | ||
220 | } | ||
221 | |||
222 | return (connections > info->limit) ^ info->inverse; | ||
223 | |||
224 | hotdrop: | ||
225 | *hotdrop = true; | ||
226 | return false; | ||
227 | } | ||
228 | |||
229 | static bool connlimit_check(const char *tablename, const void *ip, | ||
230 | const struct xt_match *match, void *matchinfo, | ||
231 | unsigned int hook_mask) | ||
232 | { | ||
233 | struct xt_connlimit_info *info = matchinfo; | ||
234 | unsigned int i; | ||
235 | |||
236 | if (nf_ct_l3proto_try_module_get(match->family) < 0) { | ||
237 | printk(KERN_WARNING "cannot load conntrack support for " | ||
238 | "address family %u\n", match->family); | ||
239 | return false; | ||
240 | } | ||
241 | |||
242 | /* init private data */ | ||
243 | info->data = kmalloc(sizeof(struct xt_connlimit_data), GFP_KERNEL); | ||
244 | if (info->data == NULL) { | ||
245 | nf_ct_l3proto_module_put(match->family); | ||
246 | return false; | ||
247 | } | ||
248 | |||
249 | spin_lock_init(&info->data->lock); | ||
250 | for (i = 0; i < ARRAY_SIZE(info->data->iphash); ++i) | ||
251 | INIT_LIST_HEAD(&info->data->iphash[i]); | ||
252 | |||
253 | return true; | ||
254 | } | ||
255 | |||
256 | static void connlimit_destroy(const struct xt_match *match, void *matchinfo) | ||
257 | { | ||
258 | struct xt_connlimit_info *info = matchinfo; | ||
259 | struct xt_connlimit_conn *conn; | ||
260 | struct xt_connlimit_conn *tmp; | ||
261 | struct list_head *hash = info->data->iphash; | ||
262 | unsigned int i; | ||
263 | |||
264 | nf_ct_l3proto_module_put(match->family); | ||
265 | |||
266 | for (i = 0; i < ARRAY_SIZE(info->data->iphash); ++i) { | ||
267 | list_for_each_entry_safe(conn, tmp, &hash[i], list) { | ||
268 | list_del(&conn->list); | ||
269 | kfree(conn); | ||
270 | } | ||
271 | } | ||
272 | |||
273 | kfree(info->data); | ||
274 | } | ||
275 | |||
276 | static struct xt_match connlimit_reg[] __read_mostly = { | ||
277 | { | ||
278 | .name = "connlimit", | ||
279 | .family = AF_INET, | ||
280 | .checkentry = connlimit_check, | ||
281 | .match = connlimit_match, | ||
282 | .matchsize = sizeof(struct xt_connlimit_info), | ||
283 | .destroy = connlimit_destroy, | ||
284 | .me = THIS_MODULE, | ||
285 | }, | ||
286 | { | ||
287 | .name = "connlimit", | ||
288 | .family = AF_INET6, | ||
289 | .checkentry = connlimit_check, | ||
290 | .match = connlimit_match, | ||
291 | .matchsize = sizeof(struct xt_connlimit_info), | ||
292 | .destroy = connlimit_destroy, | ||
293 | .me = THIS_MODULE, | ||
294 | }, | ||
295 | }; | ||
296 | |||
297 | static int __init xt_connlimit_init(void) | ||
298 | { | ||
299 | return xt_register_matches(connlimit_reg, ARRAY_SIZE(connlimit_reg)); | ||
300 | } | ||
301 | |||
302 | static void __exit xt_connlimit_exit(void) | ||
303 | { | ||
304 | xt_unregister_matches(connlimit_reg, ARRAY_SIZE(connlimit_reg)); | ||
305 | } | ||
306 | |||
307 | module_init(xt_connlimit_init); | ||
308 | module_exit(xt_connlimit_exit); | ||
309 | MODULE_AUTHOR("Jan Engelhardt <jengelh@gmx.de>"); | ||
310 | MODULE_DESCRIPTION("netfilter xt_connlimit match module"); | ||
311 | MODULE_LICENSE("GPL"); | ||
312 | MODULE_ALIAS("ipt_connlimit"); | ||
313 | MODULE_ALIAS("ip6t_connlimit"); | ||
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c index e1803256c792..e73fa9b46cf7 100644 --- a/net/netfilter/xt_connmark.c +++ b/net/netfilter/xt_connmark.c | |||
@@ -30,7 +30,7 @@ MODULE_DESCRIPTION("IP tables connmark match module"); | |||
30 | MODULE_LICENSE("GPL"); | 30 | MODULE_LICENSE("GPL"); |
31 | MODULE_ALIAS("ipt_connmark"); | 31 | MODULE_ALIAS("ipt_connmark"); |
32 | 32 | ||
33 | static int | 33 | static bool |
34 | match(const struct sk_buff *skb, | 34 | match(const struct sk_buff *skb, |
35 | const struct net_device *in, | 35 | const struct net_device *in, |
36 | const struct net_device *out, | 36 | const struct net_device *out, |
@@ -38,38 +38,38 @@ match(const struct sk_buff *skb, | |||
38 | const void *matchinfo, | 38 | const void *matchinfo, |
39 | int offset, | 39 | int offset, |
40 | unsigned int protoff, | 40 | unsigned int protoff, |
41 | int *hotdrop) | 41 | bool *hotdrop) |
42 | { | 42 | { |
43 | const struct xt_connmark_info *info = matchinfo; | 43 | const struct xt_connmark_info *info = matchinfo; |
44 | struct nf_conn *ct; | 44 | const struct nf_conn *ct; |
45 | enum ip_conntrack_info ctinfo; | 45 | enum ip_conntrack_info ctinfo; |
46 | 46 | ||
47 | ct = nf_ct_get(skb, &ctinfo); | 47 | ct = nf_ct_get(skb, &ctinfo); |
48 | if (!ct) | 48 | if (!ct) |
49 | return 0; | 49 | return false; |
50 | 50 | ||
51 | return (((ct->mark) & info->mask) == info->mark) ^ info->invert; | 51 | return ((ct->mark & info->mask) == info->mark) ^ info->invert; |
52 | } | 52 | } |
53 | 53 | ||
54 | static int | 54 | static bool |
55 | checkentry(const char *tablename, | 55 | checkentry(const char *tablename, |
56 | const void *ip, | 56 | const void *ip, |
57 | const struct xt_match *match, | 57 | const struct xt_match *match, |
58 | void *matchinfo, | 58 | void *matchinfo, |
59 | unsigned int hook_mask) | 59 | unsigned int hook_mask) |
60 | { | 60 | { |
61 | struct xt_connmark_info *cm = matchinfo; | 61 | const struct xt_connmark_info *cm = matchinfo; |
62 | 62 | ||
63 | if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) { | 63 | if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) { |
64 | printk(KERN_WARNING "connmark: only support 32bit mark\n"); | 64 | printk(KERN_WARNING "connmark: only support 32bit mark\n"); |
65 | return 0; | 65 | return false; |
66 | } | 66 | } |
67 | if (nf_ct_l3proto_try_module_get(match->family) < 0) { | 67 | if (nf_ct_l3proto_try_module_get(match->family) < 0) { |
68 | printk(KERN_WARNING "can't load conntrack support for " | 68 | printk(KERN_WARNING "can't load conntrack support for " |
69 | "proto=%d\n", match->family); | 69 | "proto=%d\n", match->family); |
70 | return 0; | 70 | return false; |
71 | } | 71 | } |
72 | return 1; | 72 | return true; |
73 | } | 73 | } |
74 | 74 | ||
75 | static void | 75 | static void |
@@ -88,7 +88,7 @@ struct compat_xt_connmark_info { | |||
88 | 88 | ||
89 | static void compat_from_user(void *dst, void *src) | 89 | static void compat_from_user(void *dst, void *src) |
90 | { | 90 | { |
91 | struct compat_xt_connmark_info *cm = src; | 91 | const struct compat_xt_connmark_info *cm = src; |
92 | struct xt_connmark_info m = { | 92 | struct xt_connmark_info m = { |
93 | .mark = cm->mark, | 93 | .mark = cm->mark, |
94 | .mask = cm->mask, | 94 | .mask = cm->mask, |
@@ -99,7 +99,7 @@ static void compat_from_user(void *dst, void *src) | |||
99 | 99 | ||
100 | static int compat_to_user(void __user *dst, void *src) | 100 | static int compat_to_user(void __user *dst, void *src) |
101 | { | 101 | { |
102 | struct xt_connmark_info *m = src; | 102 | const struct xt_connmark_info *m = src; |
103 | struct compat_xt_connmark_info cm = { | 103 | struct compat_xt_connmark_info cm = { |
104 | .mark = m->mark, | 104 | .mark = m->mark, |
105 | .mask = m->mask, | 105 | .mask = m->mask, |
@@ -109,7 +109,7 @@ static int compat_to_user(void __user *dst, void *src) | |||
109 | } | 109 | } |
110 | #endif /* CONFIG_COMPAT */ | 110 | #endif /* CONFIG_COMPAT */ |
111 | 111 | ||
112 | static struct xt_match xt_connmark_match[] = { | 112 | static struct xt_match xt_connmark_match[] __read_mostly = { |
113 | { | 113 | { |
114 | .name = "connmark", | 114 | .name = "connmark", |
115 | .family = AF_INET, | 115 | .family = AF_INET, |
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c index 189ded5f378b..ca4b69f020a8 100644 --- a/net/netfilter/xt_conntrack.c +++ b/net/netfilter/xt_conntrack.c | |||
@@ -19,7 +19,7 @@ MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); | |||
19 | MODULE_DESCRIPTION("iptables connection tracking match module"); | 19 | MODULE_DESCRIPTION("iptables connection tracking match module"); |
20 | MODULE_ALIAS("ipt_conntrack"); | 20 | MODULE_ALIAS("ipt_conntrack"); |
21 | 21 | ||
22 | static int | 22 | static bool |
23 | match(const struct sk_buff *skb, | 23 | match(const struct sk_buff *skb, |
24 | const struct net_device *in, | 24 | const struct net_device *in, |
25 | const struct net_device *out, | 25 | const struct net_device *out, |
@@ -27,14 +27,14 @@ match(const struct sk_buff *skb, | |||
27 | const void *matchinfo, | 27 | const void *matchinfo, |
28 | int offset, | 28 | int offset, |
29 | unsigned int protoff, | 29 | unsigned int protoff, |
30 | int *hotdrop) | 30 | bool *hotdrop) |
31 | { | 31 | { |
32 | const struct xt_conntrack_info *sinfo = matchinfo; | 32 | const struct xt_conntrack_info *sinfo = matchinfo; |
33 | struct nf_conn *ct; | 33 | const struct nf_conn *ct; |
34 | enum ip_conntrack_info ctinfo; | 34 | enum ip_conntrack_info ctinfo; |
35 | unsigned int statebit; | 35 | unsigned int statebit; |
36 | 36 | ||
37 | ct = nf_ct_get((struct sk_buff *)skb, &ctinfo); | 37 | ct = nf_ct_get(skb, &ctinfo); |
38 | 38 | ||
39 | #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) | 39 | #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) |
40 | 40 | ||
@@ -54,53 +54,53 @@ match(const struct sk_buff *skb, | |||
54 | } | 54 | } |
55 | if (FWINV((statebit & sinfo->statemask) == 0, | 55 | if (FWINV((statebit & sinfo->statemask) == 0, |
56 | XT_CONNTRACK_STATE)) | 56 | XT_CONNTRACK_STATE)) |
57 | return 0; | 57 | return false; |
58 | } | 58 | } |
59 | 59 | ||
60 | if (ct == NULL) { | 60 | if (ct == NULL) { |
61 | if (sinfo->flags & ~XT_CONNTRACK_STATE) | 61 | if (sinfo->flags & ~XT_CONNTRACK_STATE) |
62 | return 0; | 62 | return false; |
63 | return 1; | 63 | return true; |
64 | } | 64 | } |
65 | 65 | ||
66 | if (sinfo->flags & XT_CONNTRACK_PROTO && | 66 | if (sinfo->flags & XT_CONNTRACK_PROTO && |
67 | FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != | 67 | FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != |
68 | sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, | 68 | sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, |
69 | XT_CONNTRACK_PROTO)) | 69 | XT_CONNTRACK_PROTO)) |
70 | return 0; | 70 | return false; |
71 | 71 | ||
72 | if (sinfo->flags & XT_CONNTRACK_ORIGSRC && | 72 | if (sinfo->flags & XT_CONNTRACK_ORIGSRC && |
73 | FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip & | 73 | FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip & |
74 | sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != | 74 | sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != |
75 | sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, | 75 | sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, |
76 | XT_CONNTRACK_ORIGSRC)) | 76 | XT_CONNTRACK_ORIGSRC)) |
77 | return 0; | 77 | return false; |
78 | 78 | ||
79 | if (sinfo->flags & XT_CONNTRACK_ORIGDST && | 79 | if (sinfo->flags & XT_CONNTRACK_ORIGDST && |
80 | FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip & | 80 | FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip & |
81 | sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != | 81 | sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != |
82 | sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, | 82 | sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, |
83 | XT_CONNTRACK_ORIGDST)) | 83 | XT_CONNTRACK_ORIGDST)) |
84 | return 0; | 84 | return false; |
85 | 85 | ||
86 | if (sinfo->flags & XT_CONNTRACK_REPLSRC && | 86 | if (sinfo->flags & XT_CONNTRACK_REPLSRC && |
87 | FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip & | 87 | FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip & |
88 | sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != | 88 | sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != |
89 | sinfo->tuple[IP_CT_DIR_REPLY].src.ip, | 89 | sinfo->tuple[IP_CT_DIR_REPLY].src.ip, |
90 | XT_CONNTRACK_REPLSRC)) | 90 | XT_CONNTRACK_REPLSRC)) |
91 | return 0; | 91 | return false; |
92 | 92 | ||
93 | if (sinfo->flags & XT_CONNTRACK_REPLDST && | 93 | if (sinfo->flags & XT_CONNTRACK_REPLDST && |
94 | FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip & | 94 | FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip & |
95 | sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != | 95 | sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != |
96 | sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, | 96 | sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, |
97 | XT_CONNTRACK_REPLDST)) | 97 | XT_CONNTRACK_REPLDST)) |
98 | return 0; | 98 | return false; |
99 | 99 | ||
100 | if (sinfo->flags & XT_CONNTRACK_STATUS && | 100 | if (sinfo->flags & XT_CONNTRACK_STATUS && |
101 | FWINV((ct->status & sinfo->statusmask) == 0, | 101 | FWINV((ct->status & sinfo->statusmask) == 0, |
102 | XT_CONNTRACK_STATUS)) | 102 | XT_CONNTRACK_STATUS)) |
103 | return 0; | 103 | return false; |
104 | 104 | ||
105 | if(sinfo->flags & XT_CONNTRACK_EXPIRES) { | 105 | if(sinfo->flags & XT_CONNTRACK_EXPIRES) { |
106 | unsigned long expires = timer_pending(&ct->timeout) ? | 106 | unsigned long expires = timer_pending(&ct->timeout) ? |
@@ -109,12 +109,12 @@ match(const struct sk_buff *skb, | |||
109 | if (FWINV(!(expires >= sinfo->expires_min && | 109 | if (FWINV(!(expires >= sinfo->expires_min && |
110 | expires <= sinfo->expires_max), | 110 | expires <= sinfo->expires_max), |
111 | XT_CONNTRACK_EXPIRES)) | 111 | XT_CONNTRACK_EXPIRES)) |
112 | return 0; | 112 | return false; |
113 | } | 113 | } |
114 | return 1; | 114 | return true; |
115 | } | 115 | } |
116 | 116 | ||
117 | static int | 117 | static bool |
118 | checkentry(const char *tablename, | 118 | checkentry(const char *tablename, |
119 | const void *ip, | 119 | const void *ip, |
120 | const struct xt_match *match, | 120 | const struct xt_match *match, |
@@ -124,9 +124,9 @@ checkentry(const char *tablename, | |||
124 | if (nf_ct_l3proto_try_module_get(match->family) < 0) { | 124 | if (nf_ct_l3proto_try_module_get(match->family) < 0) { |
125 | printk(KERN_WARNING "can't load conntrack support for " | 125 | printk(KERN_WARNING "can't load conntrack support for " |
126 | "proto=%d\n", match->family); | 126 | "proto=%d\n", match->family); |
127 | return 0; | 127 | return false; |
128 | } | 128 | } |
129 | return 1; | 129 | return true; |
130 | } | 130 | } |
131 | 131 | ||
132 | static void destroy(const struct xt_match *match, void *matchinfo) | 132 | static void destroy(const struct xt_match *match, void *matchinfo) |
@@ -150,7 +150,7 @@ struct compat_xt_conntrack_info | |||
150 | 150 | ||
151 | static void compat_from_user(void *dst, void *src) | 151 | static void compat_from_user(void *dst, void *src) |
152 | { | 152 | { |
153 | struct compat_xt_conntrack_info *cm = src; | 153 | const struct compat_xt_conntrack_info *cm = src; |
154 | struct xt_conntrack_info m = { | 154 | struct xt_conntrack_info m = { |
155 | .statemask = cm->statemask, | 155 | .statemask = cm->statemask, |
156 | .statusmask = cm->statusmask, | 156 | .statusmask = cm->statusmask, |
@@ -167,7 +167,7 @@ static void compat_from_user(void *dst, void *src) | |||
167 | 167 | ||
168 | static int compat_to_user(void __user *dst, void *src) | 168 | static int compat_to_user(void __user *dst, void *src) |
169 | { | 169 | { |
170 | struct xt_conntrack_info *m = src; | 170 | const struct xt_conntrack_info *m = src; |
171 | struct compat_xt_conntrack_info cm = { | 171 | struct compat_xt_conntrack_info cm = { |
172 | .statemask = m->statemask, | 172 | .statemask = m->statemask, |
173 | .statusmask = m->statusmask, | 173 | .statusmask = m->statusmask, |
@@ -183,7 +183,7 @@ static int compat_to_user(void __user *dst, void *src) | |||
183 | } | 183 | } |
184 | #endif | 184 | #endif |
185 | 185 | ||
186 | static struct xt_match conntrack_match = { | 186 | static struct xt_match conntrack_match __read_mostly = { |
187 | .name = "conntrack", | 187 | .name = "conntrack", |
188 | .match = match, | 188 | .match = match, |
189 | .checkentry = checkentry, | 189 | .checkentry = checkentry, |
diff --git a/net/netfilter/xt_dccp.c b/net/netfilter/xt_dccp.c index 2c9c0dee8aaf..83224ec89cc0 100644 --- a/net/netfilter/xt_dccp.c +++ b/net/netfilter/xt_dccp.c | |||
@@ -31,40 +31,40 @@ MODULE_ALIAS("ipt_dccp"); | |||
31 | static unsigned char *dccp_optbuf; | 31 | static unsigned char *dccp_optbuf; |
32 | static DEFINE_SPINLOCK(dccp_buflock); | 32 | static DEFINE_SPINLOCK(dccp_buflock); |
33 | 33 | ||
34 | static inline int | 34 | static inline bool |
35 | dccp_find_option(u_int8_t option, | 35 | dccp_find_option(u_int8_t option, |
36 | const struct sk_buff *skb, | 36 | const struct sk_buff *skb, |
37 | unsigned int protoff, | 37 | unsigned int protoff, |
38 | const struct dccp_hdr *dh, | 38 | const struct dccp_hdr *dh, |
39 | int *hotdrop) | 39 | bool *hotdrop) |
40 | { | 40 | { |
41 | /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */ | 41 | /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */ |
42 | unsigned char *op; | 42 | const unsigned char *op; |
43 | unsigned int optoff = __dccp_hdr_len(dh); | 43 | unsigned int optoff = __dccp_hdr_len(dh); |
44 | unsigned int optlen = dh->dccph_doff*4 - __dccp_hdr_len(dh); | 44 | unsigned int optlen = dh->dccph_doff*4 - __dccp_hdr_len(dh); |
45 | unsigned int i; | 45 | unsigned int i; |
46 | 46 | ||
47 | if (dh->dccph_doff * 4 < __dccp_hdr_len(dh)) { | 47 | if (dh->dccph_doff * 4 < __dccp_hdr_len(dh)) { |
48 | *hotdrop = 1; | 48 | *hotdrop = true; |
49 | return 0; | 49 | return false; |
50 | } | 50 | } |
51 | 51 | ||
52 | if (!optlen) | 52 | if (!optlen) |
53 | return 0; | 53 | return false; |
54 | 54 | ||
55 | spin_lock_bh(&dccp_buflock); | 55 | spin_lock_bh(&dccp_buflock); |
56 | op = skb_header_pointer(skb, protoff + optoff, optlen, dccp_optbuf); | 56 | op = skb_header_pointer(skb, protoff + optoff, optlen, dccp_optbuf); |
57 | if (op == NULL) { | 57 | if (op == NULL) { |
58 | /* If we don't have the whole header, drop packet. */ | 58 | /* If we don't have the whole header, drop packet. */ |
59 | spin_unlock_bh(&dccp_buflock); | 59 | spin_unlock_bh(&dccp_buflock); |
60 | *hotdrop = 1; | 60 | *hotdrop = true; |
61 | return 0; | 61 | return false; |
62 | } | 62 | } |
63 | 63 | ||
64 | for (i = 0; i < optlen; ) { | 64 | for (i = 0; i < optlen; ) { |
65 | if (op[i] == option) { | 65 | if (op[i] == option) { |
66 | spin_unlock_bh(&dccp_buflock); | 66 | spin_unlock_bh(&dccp_buflock); |
67 | return 1; | 67 | return true; |
68 | } | 68 | } |
69 | 69 | ||
70 | if (op[i] < 2) | 70 | if (op[i] < 2) |
@@ -74,24 +74,24 @@ dccp_find_option(u_int8_t option, | |||
74 | } | 74 | } |
75 | 75 | ||
76 | spin_unlock_bh(&dccp_buflock); | 76 | spin_unlock_bh(&dccp_buflock); |
77 | return 0; | 77 | return false; |
78 | } | 78 | } |
79 | 79 | ||
80 | 80 | ||
81 | static inline int | 81 | static inline bool |
82 | match_types(const struct dccp_hdr *dh, u_int16_t typemask) | 82 | match_types(const struct dccp_hdr *dh, u_int16_t typemask) |
83 | { | 83 | { |
84 | return (typemask & (1 << dh->dccph_type)); | 84 | return typemask & (1 << dh->dccph_type); |
85 | } | 85 | } |
86 | 86 | ||
87 | static inline int | 87 | static inline bool |
88 | match_option(u_int8_t option, const struct sk_buff *skb, unsigned int protoff, | 88 | match_option(u_int8_t option, const struct sk_buff *skb, unsigned int protoff, |
89 | const struct dccp_hdr *dh, int *hotdrop) | 89 | const struct dccp_hdr *dh, bool *hotdrop) |
90 | { | 90 | { |
91 | return dccp_find_option(option, skb, protoff, dh, hotdrop); | 91 | return dccp_find_option(option, skb, protoff, dh, hotdrop); |
92 | } | 92 | } |
93 | 93 | ||
94 | static int | 94 | static bool |
95 | match(const struct sk_buff *skb, | 95 | match(const struct sk_buff *skb, |
96 | const struct net_device *in, | 96 | const struct net_device *in, |
97 | const struct net_device *out, | 97 | const struct net_device *out, |
@@ -99,25 +99,25 @@ match(const struct sk_buff *skb, | |||
99 | const void *matchinfo, | 99 | const void *matchinfo, |
100 | int offset, | 100 | int offset, |
101 | unsigned int protoff, | 101 | unsigned int protoff, |
102 | int *hotdrop) | 102 | bool *hotdrop) |
103 | { | 103 | { |
104 | const struct xt_dccp_info *info = matchinfo; | 104 | const struct xt_dccp_info *info = matchinfo; |
105 | struct dccp_hdr _dh, *dh; | 105 | struct dccp_hdr _dh, *dh; |
106 | 106 | ||
107 | if (offset) | 107 | if (offset) |
108 | return 0; | 108 | return false; |
109 | 109 | ||
110 | dh = skb_header_pointer(skb, protoff, sizeof(_dh), &_dh); | 110 | dh = skb_header_pointer(skb, protoff, sizeof(_dh), &_dh); |
111 | if (dh == NULL) { | 111 | if (dh == NULL) { |
112 | *hotdrop = 1; | 112 | *hotdrop = true; |
113 | return 0; | 113 | return false; |
114 | } | 114 | } |
115 | 115 | ||
116 | return DCCHECK(((ntohs(dh->dccph_sport) >= info->spts[0]) | 116 | return DCCHECK(ntohs(dh->dccph_sport) >= info->spts[0] |
117 | && (ntohs(dh->dccph_sport) <= info->spts[1])), | 117 | && ntohs(dh->dccph_sport) <= info->spts[1], |
118 | XT_DCCP_SRC_PORTS, info->flags, info->invflags) | 118 | XT_DCCP_SRC_PORTS, info->flags, info->invflags) |
119 | && DCCHECK(((ntohs(dh->dccph_dport) >= info->dpts[0]) | 119 | && DCCHECK(ntohs(dh->dccph_dport) >= info->dpts[0] |
120 | && (ntohs(dh->dccph_dport) <= info->dpts[1])), | 120 | && ntohs(dh->dccph_dport) <= info->dpts[1], |
121 | XT_DCCP_DEST_PORTS, info->flags, info->invflags) | 121 | XT_DCCP_DEST_PORTS, info->flags, info->invflags) |
122 | && DCCHECK(match_types(dh, info->typemask), | 122 | && DCCHECK(match_types(dh, info->typemask), |
123 | XT_DCCP_TYPE, info->flags, info->invflags) | 123 | XT_DCCP_TYPE, info->flags, info->invflags) |
@@ -126,7 +126,7 @@ match(const struct sk_buff *skb, | |||
126 | XT_DCCP_OPTION, info->flags, info->invflags); | 126 | XT_DCCP_OPTION, info->flags, info->invflags); |
127 | } | 127 | } |
128 | 128 | ||
129 | static int | 129 | static bool |
130 | checkentry(const char *tablename, | 130 | checkentry(const char *tablename, |
131 | const void *inf, | 131 | const void *inf, |
132 | const struct xt_match *match, | 132 | const struct xt_match *match, |
@@ -140,7 +140,7 @@ checkentry(const char *tablename, | |||
140 | && !(info->invflags & ~info->flags); | 140 | && !(info->invflags & ~info->flags); |
141 | } | 141 | } |
142 | 142 | ||
143 | static struct xt_match xt_dccp_match[] = { | 143 | static struct xt_match xt_dccp_match[] __read_mostly = { |
144 | { | 144 | { |
145 | .name = "dccp", | 145 | .name = "dccp", |
146 | .family = AF_INET, | 146 | .family = AF_INET, |
diff --git a/net/netfilter/xt_dscp.c b/net/netfilter/xt_dscp.c index 56b247ecc283..dde6d66e0d33 100644 --- a/net/netfilter/xt_dscp.c +++ b/net/netfilter/xt_dscp.c | |||
@@ -22,14 +22,14 @@ MODULE_LICENSE("GPL"); | |||
22 | MODULE_ALIAS("ipt_dscp"); | 22 | MODULE_ALIAS("ipt_dscp"); |
23 | MODULE_ALIAS("ip6t_dscp"); | 23 | MODULE_ALIAS("ip6t_dscp"); |
24 | 24 | ||
25 | static int match(const struct sk_buff *skb, | 25 | static bool match(const struct sk_buff *skb, |
26 | const struct net_device *in, | 26 | const struct net_device *in, |
27 | const struct net_device *out, | 27 | const struct net_device *out, |
28 | const struct xt_match *match, | 28 | const struct xt_match *match, |
29 | const void *matchinfo, | 29 | const void *matchinfo, |
30 | int offset, | 30 | int offset, |
31 | unsigned int protoff, | 31 | unsigned int protoff, |
32 | int *hotdrop) | 32 | bool *hotdrop) |
33 | { | 33 | { |
34 | const struct xt_dscp_info *info = matchinfo; | 34 | const struct xt_dscp_info *info = matchinfo; |
35 | u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT; | 35 | u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT; |
@@ -37,14 +37,14 @@ static int match(const struct sk_buff *skb, | |||
37 | return (dscp == info->dscp) ^ !!info->invert; | 37 | return (dscp == info->dscp) ^ !!info->invert; |
38 | } | 38 | } |
39 | 39 | ||
40 | static int match6(const struct sk_buff *skb, | 40 | static bool match6(const struct sk_buff *skb, |
41 | const struct net_device *in, | 41 | const struct net_device *in, |
42 | const struct net_device *out, | 42 | const struct net_device *out, |
43 | const struct xt_match *match, | 43 | const struct xt_match *match, |
44 | const void *matchinfo, | 44 | const void *matchinfo, |
45 | int offset, | 45 | int offset, |
46 | unsigned int protoff, | 46 | unsigned int protoff, |
47 | int *hotdrop) | 47 | bool *hotdrop) |
48 | { | 48 | { |
49 | const struct xt_dscp_info *info = matchinfo; | 49 | const struct xt_dscp_info *info = matchinfo; |
50 | u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT; | 50 | u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT; |
@@ -52,23 +52,23 @@ static int match6(const struct sk_buff *skb, | |||
52 | return (dscp == info->dscp) ^ !!info->invert; | 52 | return (dscp == info->dscp) ^ !!info->invert; |
53 | } | 53 | } |
54 | 54 | ||
55 | static int checkentry(const char *tablename, | 55 | static bool checkentry(const char *tablename, |
56 | const void *info, | 56 | const void *info, |
57 | const struct xt_match *match, | 57 | const struct xt_match *match, |
58 | void *matchinfo, | 58 | void *matchinfo, |
59 | unsigned int hook_mask) | 59 | unsigned int hook_mask) |
60 | { | 60 | { |
61 | const u_int8_t dscp = ((struct xt_dscp_info *)matchinfo)->dscp; | 61 | const u_int8_t dscp = ((struct xt_dscp_info *)matchinfo)->dscp; |
62 | 62 | ||
63 | if (dscp > XT_DSCP_MAX) { | 63 | if (dscp > XT_DSCP_MAX) { |
64 | printk(KERN_ERR "xt_dscp: dscp %x out of range\n", dscp); | 64 | printk(KERN_ERR "xt_dscp: dscp %x out of range\n", dscp); |
65 | return 0; | 65 | return false; |
66 | } | 66 | } |
67 | 67 | ||
68 | return 1; | 68 | return true; |
69 | } | 69 | } |
70 | 70 | ||
71 | static struct xt_match xt_dscp_match[] = { | 71 | static struct xt_match xt_dscp_match[] __read_mostly = { |
72 | { | 72 | { |
73 | .name = "dscp", | 73 | .name = "dscp", |
74 | .family = AF_INET, | 74 | .family = AF_INET, |
diff --git a/net/netfilter/xt_esp.c b/net/netfilter/xt_esp.c index 7c95f149d942..b11378e001b6 100644 --- a/net/netfilter/xt_esp.c +++ b/net/netfilter/xt_esp.c | |||
@@ -31,10 +31,10 @@ MODULE_ALIAS("ip6t_esp"); | |||
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | /* Returns 1 if the spi is matched by the range, 0 otherwise */ | 33 | /* Returns 1 if the spi is matched by the range, 0 otherwise */ |
34 | static inline int | 34 | static inline bool |
35 | spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert) | 35 | spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert) |
36 | { | 36 | { |
37 | int r = 0; | 37 | bool r; |
38 | duprintf("esp spi_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ', | 38 | duprintf("esp spi_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ', |
39 | min, spi, max); | 39 | min, spi, max); |
40 | r = (spi >= min && spi <= max) ^ invert; | 40 | r = (spi >= min && spi <= max) ^ invert; |
@@ -42,7 +42,7 @@ spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert) | |||
42 | return r; | 42 | return r; |
43 | } | 43 | } |
44 | 44 | ||
45 | static int | 45 | static bool |
46 | match(const struct sk_buff *skb, | 46 | match(const struct sk_buff *skb, |
47 | const struct net_device *in, | 47 | const struct net_device *in, |
48 | const struct net_device *out, | 48 | const struct net_device *out, |
@@ -50,14 +50,14 @@ match(const struct sk_buff *skb, | |||
50 | const void *matchinfo, | 50 | const void *matchinfo, |
51 | int offset, | 51 | int offset, |
52 | unsigned int protoff, | 52 | unsigned int protoff, |
53 | int *hotdrop) | 53 | bool *hotdrop) |
54 | { | 54 | { |
55 | struct ip_esp_hdr _esp, *eh; | 55 | struct ip_esp_hdr _esp, *eh; |
56 | const struct xt_esp *espinfo = matchinfo; | 56 | const struct xt_esp *espinfo = matchinfo; |
57 | 57 | ||
58 | /* Must not be a fragment. */ | 58 | /* Must not be a fragment. */ |
59 | if (offset) | 59 | if (offset) |
60 | return 0; | 60 | return false; |
61 | 61 | ||
62 | eh = skb_header_pointer(skb, protoff, sizeof(_esp), &_esp); | 62 | eh = skb_header_pointer(skb, protoff, sizeof(_esp), &_esp); |
63 | if (eh == NULL) { | 63 | if (eh == NULL) { |
@@ -65,8 +65,8 @@ match(const struct sk_buff *skb, | |||
65 | * can't. Hence, no choice but to drop. | 65 | * can't. Hence, no choice but to drop. |
66 | */ | 66 | */ |
67 | duprintf("Dropping evil ESP tinygram.\n"); | 67 | duprintf("Dropping evil ESP tinygram.\n"); |
68 | *hotdrop = 1; | 68 | *hotdrop = true; |
69 | return 0; | 69 | return false; |
70 | } | 70 | } |
71 | 71 | ||
72 | return spi_match(espinfo->spis[0], espinfo->spis[1], ntohl(eh->spi), | 72 | return spi_match(espinfo->spis[0], espinfo->spis[1], ntohl(eh->spi), |
@@ -74,7 +74,7 @@ match(const struct sk_buff *skb, | |||
74 | } | 74 | } |
75 | 75 | ||
76 | /* Called when user tries to insert an entry of this type. */ | 76 | /* Called when user tries to insert an entry of this type. */ |
77 | static int | 77 | static bool |
78 | checkentry(const char *tablename, | 78 | checkentry(const char *tablename, |
79 | const void *ip_void, | 79 | const void *ip_void, |
80 | const struct xt_match *match, | 80 | const struct xt_match *match, |
@@ -85,13 +85,13 @@ checkentry(const char *tablename, | |||
85 | 85 | ||
86 | if (espinfo->invflags & ~XT_ESP_INV_MASK) { | 86 | if (espinfo->invflags & ~XT_ESP_INV_MASK) { |
87 | duprintf("xt_esp: unknown flags %X\n", espinfo->invflags); | 87 | duprintf("xt_esp: unknown flags %X\n", espinfo->invflags); |
88 | return 0; | 88 | return false; |
89 | } | 89 | } |
90 | 90 | ||
91 | return 1; | 91 | return true; |
92 | } | 92 | } |
93 | 93 | ||
94 | static struct xt_match xt_esp_match[] = { | 94 | static struct xt_match xt_esp_match[] __read_mostly = { |
95 | { | 95 | { |
96 | .name = "esp", | 96 | .name = "esp", |
97 | .family = AF_INET, | 97 | .family = AF_INET, |
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index d3043fa32ebc..d6b3d01975b6 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c | |||
@@ -94,7 +94,8 @@ static DEFINE_MUTEX(hlimit_mutex); /* additional checkentry protection */ | |||
94 | static HLIST_HEAD(hashlimit_htables); | 94 | static HLIST_HEAD(hashlimit_htables); |
95 | static struct kmem_cache *hashlimit_cachep __read_mostly; | 95 | static struct kmem_cache *hashlimit_cachep __read_mostly; |
96 | 96 | ||
97 | static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b) | 97 | static inline bool dst_cmp(const struct dsthash_ent *ent, |
98 | const struct dsthash_dst *b) | ||
98 | { | 99 | { |
99 | return !memcmp(&ent->dst, b, sizeof(ent->dst)); | 100 | return !memcmp(&ent->dst, b, sizeof(ent->dst)); |
100 | } | 101 | } |
@@ -106,7 +107,8 @@ hash_dst(const struct xt_hashlimit_htable *ht, const struct dsthash_dst *dst) | |||
106 | } | 107 | } |
107 | 108 | ||
108 | static struct dsthash_ent * | 109 | static struct dsthash_ent * |
109 | dsthash_find(const struct xt_hashlimit_htable *ht, struct dsthash_dst *dst) | 110 | dsthash_find(const struct xt_hashlimit_htable *ht, |
111 | const struct dsthash_dst *dst) | ||
110 | { | 112 | { |
111 | struct dsthash_ent *ent; | 113 | struct dsthash_ent *ent; |
112 | struct hlist_node *pos; | 114 | struct hlist_node *pos; |
@@ -122,7 +124,8 @@ dsthash_find(const struct xt_hashlimit_htable *ht, struct dsthash_dst *dst) | |||
122 | 124 | ||
123 | /* allocate dsthash_ent, initialize dst, put in htable and lock it */ | 125 | /* allocate dsthash_ent, initialize dst, put in htable and lock it */ |
124 | static struct dsthash_ent * | 126 | static struct dsthash_ent * |
125 | dsthash_alloc_init(struct xt_hashlimit_htable *ht, struct dsthash_dst *dst) | 127 | dsthash_alloc_init(struct xt_hashlimit_htable *ht, |
128 | const struct dsthash_dst *dst) | ||
126 | { | 129 | { |
127 | struct dsthash_ent *ent; | 130 | struct dsthash_ent *ent; |
128 | 131 | ||
@@ -227,19 +230,21 @@ static int htable_create(struct xt_hashlimit_info *minfo, int family) | |||
227 | return 0; | 230 | return 0; |
228 | } | 231 | } |
229 | 232 | ||
230 | static int select_all(struct xt_hashlimit_htable *ht, struct dsthash_ent *he) | 233 | static bool select_all(const struct xt_hashlimit_htable *ht, |
234 | const struct dsthash_ent *he) | ||
231 | { | 235 | { |
232 | return 1; | 236 | return 1; |
233 | } | 237 | } |
234 | 238 | ||
235 | static int select_gc(struct xt_hashlimit_htable *ht, struct dsthash_ent *he) | 239 | static bool select_gc(const struct xt_hashlimit_htable *ht, |
240 | const struct dsthash_ent *he) | ||
236 | { | 241 | { |
237 | return (jiffies >= he->expires); | 242 | return jiffies >= he->expires; |
238 | } | 243 | } |
239 | 244 | ||
240 | static void htable_selective_cleanup(struct xt_hashlimit_htable *ht, | 245 | static void htable_selective_cleanup(struct xt_hashlimit_htable *ht, |
241 | int (*select)(struct xt_hashlimit_htable *ht, | 246 | bool (*select)(const struct xt_hashlimit_htable *ht, |
242 | struct dsthash_ent *he)) | 247 | const struct dsthash_ent *he)) |
243 | { | 248 | { |
244 | unsigned int i; | 249 | unsigned int i; |
245 | 250 | ||
@@ -282,7 +287,8 @@ static void htable_destroy(struct xt_hashlimit_htable *hinfo) | |||
282 | vfree(hinfo); | 287 | vfree(hinfo); |
283 | } | 288 | } |
284 | 289 | ||
285 | static struct xt_hashlimit_htable *htable_find_get(char *name, int family) | 290 | static struct xt_hashlimit_htable *htable_find_get(const char *name, |
291 | int family) | ||
286 | { | 292 | { |
287 | struct xt_hashlimit_htable *hinfo; | 293 | struct xt_hashlimit_htable *hinfo; |
288 | struct hlist_node *pos; | 294 | struct hlist_node *pos; |
@@ -367,7 +373,8 @@ static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now) | |||
367 | } | 373 | } |
368 | 374 | ||
369 | static int | 375 | static int |
370 | hashlimit_init_dst(struct xt_hashlimit_htable *hinfo, struct dsthash_dst *dst, | 376 | hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo, |
377 | struct dsthash_dst *dst, | ||
371 | const struct sk_buff *skb, unsigned int protoff) | 378 | const struct sk_buff *skb, unsigned int protoff) |
372 | { | 379 | { |
373 | __be16 _ports[2], *ports; | 380 | __be16 _ports[2], *ports; |
@@ -432,7 +439,7 @@ hashlimit_init_dst(struct xt_hashlimit_htable *hinfo, struct dsthash_dst *dst, | |||
432 | return 0; | 439 | return 0; |
433 | } | 440 | } |
434 | 441 | ||
435 | static int | 442 | static bool |
436 | hashlimit_match(const struct sk_buff *skb, | 443 | hashlimit_match(const struct sk_buff *skb, |
437 | const struct net_device *in, | 444 | const struct net_device *in, |
438 | const struct net_device *out, | 445 | const struct net_device *out, |
@@ -440,10 +447,10 @@ hashlimit_match(const struct sk_buff *skb, | |||
440 | const void *matchinfo, | 447 | const void *matchinfo, |
441 | int offset, | 448 | int offset, |
442 | unsigned int protoff, | 449 | unsigned int protoff, |
443 | int *hotdrop) | 450 | bool *hotdrop) |
444 | { | 451 | { |
445 | struct xt_hashlimit_info *r = | 452 | const struct xt_hashlimit_info *r = |
446 | ((struct xt_hashlimit_info *)matchinfo)->u.master; | 453 | ((const struct xt_hashlimit_info *)matchinfo)->u.master; |
447 | struct xt_hashlimit_htable *hinfo = r->hinfo; | 454 | struct xt_hashlimit_htable *hinfo = r->hinfo; |
448 | unsigned long now = jiffies; | 455 | unsigned long now = jiffies; |
449 | struct dsthash_ent *dh; | 456 | struct dsthash_ent *dh; |
@@ -478,20 +485,20 @@ hashlimit_match(const struct sk_buff *skb, | |||
478 | /* We're underlimit. */ | 485 | /* We're underlimit. */ |
479 | dh->rateinfo.credit -= dh->rateinfo.cost; | 486 | dh->rateinfo.credit -= dh->rateinfo.cost; |
480 | spin_unlock_bh(&hinfo->lock); | 487 | spin_unlock_bh(&hinfo->lock); |
481 | return 1; | 488 | return true; |
482 | } | 489 | } |
483 | 490 | ||
484 | spin_unlock_bh(&hinfo->lock); | 491 | spin_unlock_bh(&hinfo->lock); |
485 | 492 | ||
486 | /* default case: we're overlimit, thus don't match */ | 493 | /* default case: we're overlimit, thus don't match */ |
487 | return 0; | 494 | return false; |
488 | 495 | ||
489 | hotdrop: | 496 | hotdrop: |
490 | *hotdrop = 1; | 497 | *hotdrop = true; |
491 | return 0; | 498 | return false; |
492 | } | 499 | } |
493 | 500 | ||
494 | static int | 501 | static bool |
495 | hashlimit_checkentry(const char *tablename, | 502 | hashlimit_checkentry(const char *tablename, |
496 | const void *inf, | 503 | const void *inf, |
497 | const struct xt_match *match, | 504 | const struct xt_match *match, |
@@ -505,20 +512,20 @@ hashlimit_checkentry(const char *tablename, | |||
505 | user2credits(r->cfg.avg * r->cfg.burst) < user2credits(r->cfg.avg)) { | 512 | user2credits(r->cfg.avg * r->cfg.burst) < user2credits(r->cfg.avg)) { |
506 | printk(KERN_ERR "xt_hashlimit: overflow, try lower: %u/%u\n", | 513 | printk(KERN_ERR "xt_hashlimit: overflow, try lower: %u/%u\n", |
507 | r->cfg.avg, r->cfg.burst); | 514 | r->cfg.avg, r->cfg.burst); |
508 | return 0; | 515 | return false; |
509 | } | 516 | } |
510 | if (r->cfg.mode == 0 || | 517 | if (r->cfg.mode == 0 || |
511 | r->cfg.mode > (XT_HASHLIMIT_HASH_DPT | | 518 | r->cfg.mode > (XT_HASHLIMIT_HASH_DPT | |
512 | XT_HASHLIMIT_HASH_DIP | | 519 | XT_HASHLIMIT_HASH_DIP | |
513 | XT_HASHLIMIT_HASH_SIP | | 520 | XT_HASHLIMIT_HASH_SIP | |
514 | XT_HASHLIMIT_HASH_SPT)) | 521 | XT_HASHLIMIT_HASH_SPT)) |
515 | return 0; | 522 | return false; |
516 | if (!r->cfg.gc_interval) | 523 | if (!r->cfg.gc_interval) |
517 | return 0; | 524 | return false; |
518 | if (!r->cfg.expire) | 525 | if (!r->cfg.expire) |
519 | return 0; | 526 | return false; |
520 | if (r->name[sizeof(r->name) - 1] != '\0') | 527 | if (r->name[sizeof(r->name) - 1] != '\0') |
521 | return 0; | 528 | return false; |
522 | 529 | ||
523 | /* This is the best we've got: We cannot release and re-grab lock, | 530 | /* This is the best we've got: We cannot release and re-grab lock, |
524 | * since checkentry() is called before x_tables.c grabs xt_mutex. | 531 | * since checkentry() is called before x_tables.c grabs xt_mutex. |
@@ -530,19 +537,19 @@ hashlimit_checkentry(const char *tablename, | |||
530 | r->hinfo = htable_find_get(r->name, match->family); | 537 | r->hinfo = htable_find_get(r->name, match->family); |
531 | if (!r->hinfo && htable_create(r, match->family) != 0) { | 538 | if (!r->hinfo && htable_create(r, match->family) != 0) { |
532 | mutex_unlock(&hlimit_mutex); | 539 | mutex_unlock(&hlimit_mutex); |
533 | return 0; | 540 | return false; |
534 | } | 541 | } |
535 | mutex_unlock(&hlimit_mutex); | 542 | mutex_unlock(&hlimit_mutex); |
536 | 543 | ||
537 | /* Ugly hack: For SMP, we only want to use one set */ | 544 | /* Ugly hack: For SMP, we only want to use one set */ |
538 | r->u.master = r; | 545 | r->u.master = r; |
539 | return 1; | 546 | return true; |
540 | } | 547 | } |
541 | 548 | ||
542 | static void | 549 | static void |
543 | hashlimit_destroy(const struct xt_match *match, void *matchinfo) | 550 | hashlimit_destroy(const struct xt_match *match, void *matchinfo) |
544 | { | 551 | { |
545 | struct xt_hashlimit_info *r = matchinfo; | 552 | const struct xt_hashlimit_info *r = matchinfo; |
546 | 553 | ||
547 | htable_put(r->hinfo); | 554 | htable_put(r->hinfo); |
548 | } | 555 | } |
@@ -571,7 +578,7 @@ static int compat_to_user(void __user *dst, void *src) | |||
571 | } | 578 | } |
572 | #endif | 579 | #endif |
573 | 580 | ||
574 | static struct xt_match xt_hashlimit[] = { | 581 | static struct xt_match xt_hashlimit[] __read_mostly = { |
575 | { | 582 | { |
576 | .name = "hashlimit", | 583 | .name = "hashlimit", |
577 | .family = AF_INET, | 584 | .family = AF_INET, |
@@ -694,7 +701,7 @@ static int dl_seq_show(struct seq_file *s, void *v) | |||
694 | return 0; | 701 | return 0; |
695 | } | 702 | } |
696 | 703 | ||
697 | static struct seq_operations dl_seq_ops = { | 704 | static const struct seq_operations dl_seq_ops = { |
698 | .start = dl_seq_start, | 705 | .start = dl_seq_start, |
699 | .next = dl_seq_next, | 706 | .next = dl_seq_next, |
700 | .stop = dl_seq_stop, | 707 | .stop = dl_seq_stop, |
diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c index c139b2f43a10..0a1f4c6bcdef 100644 --- a/net/netfilter/xt_helper.c +++ b/net/netfilter/xt_helper.c | |||
@@ -22,13 +22,8 @@ MODULE_DESCRIPTION("iptables helper match module"); | |||
22 | MODULE_ALIAS("ipt_helper"); | 22 | MODULE_ALIAS("ipt_helper"); |
23 | MODULE_ALIAS("ip6t_helper"); | 23 | MODULE_ALIAS("ip6t_helper"); |
24 | 24 | ||
25 | #if 0 | ||
26 | #define DEBUGP printk | ||
27 | #else | ||
28 | #define DEBUGP(format, args...) | ||
29 | #endif | ||
30 | 25 | ||
31 | static int | 26 | static bool |
32 | match(const struct sk_buff *skb, | 27 | match(const struct sk_buff *skb, |
33 | const struct net_device *in, | 28 | const struct net_device *in, |
34 | const struct net_device *out, | 29 | const struct net_device *out, |
@@ -36,61 +31,51 @@ match(const struct sk_buff *skb, | |||
36 | const void *matchinfo, | 31 | const void *matchinfo, |
37 | int offset, | 32 | int offset, |
38 | unsigned int protoff, | 33 | unsigned int protoff, |
39 | int *hotdrop) | 34 | bool *hotdrop) |
40 | { | 35 | { |
41 | const struct xt_helper_info *info = matchinfo; | 36 | const struct xt_helper_info *info = matchinfo; |
42 | struct nf_conn *ct; | 37 | const struct nf_conn *ct; |
43 | struct nf_conn_help *master_help; | 38 | const struct nf_conn_help *master_help; |
39 | const struct nf_conntrack_helper *helper; | ||
44 | enum ip_conntrack_info ctinfo; | 40 | enum ip_conntrack_info ctinfo; |
45 | int ret = info->invert; | 41 | bool ret = info->invert; |
46 | 42 | ||
47 | ct = nf_ct_get((struct sk_buff *)skb, &ctinfo); | 43 | ct = nf_ct_get(skb, &ctinfo); |
48 | if (!ct) { | 44 | if (!ct || !ct->master) |
49 | DEBUGP("xt_helper: Eek! invalid conntrack?\n"); | ||
50 | return ret; | 45 | return ret; |
51 | } | ||
52 | |||
53 | if (!ct->master) { | ||
54 | DEBUGP("xt_helper: conntrack %p has no master\n", ct); | ||
55 | return ret; | ||
56 | } | ||
57 | 46 | ||
58 | read_lock_bh(&nf_conntrack_lock); | ||
59 | master_help = nfct_help(ct->master); | 47 | master_help = nfct_help(ct->master); |
60 | if (!master_help || !master_help->helper) { | 48 | if (!master_help) |
61 | DEBUGP("xt_helper: master ct %p has no helper\n", | 49 | return ret; |
62 | exp->expectant); | ||
63 | goto out_unlock; | ||
64 | } | ||
65 | 50 | ||
66 | DEBUGP("master's name = %s , info->name = %s\n", | 51 | /* rcu_read_lock()ed by nf_hook_slow */ |
67 | ct->master->helper->name, info->name); | 52 | helper = rcu_dereference(master_help->helper); |
53 | if (!helper) | ||
54 | return ret; | ||
68 | 55 | ||
69 | if (info->name[0] == '\0') | 56 | if (info->name[0] == '\0') |
70 | ret ^= 1; | 57 | ret = !ret; |
71 | else | 58 | else |
72 | ret ^= !strncmp(master_help->helper->name, info->name, | 59 | ret ^= !strncmp(master_help->helper->name, info->name, |
73 | strlen(master_help->helper->name)); | 60 | strlen(master_help->helper->name)); |
74 | out_unlock: | ||
75 | read_unlock_bh(&nf_conntrack_lock); | ||
76 | return ret; | 61 | return ret; |
77 | } | 62 | } |
78 | 63 | ||
79 | static int check(const char *tablename, | 64 | static bool check(const char *tablename, |
80 | const void *inf, | 65 | const void *inf, |
81 | const struct xt_match *match, | 66 | const struct xt_match *match, |
82 | void *matchinfo, | 67 | void *matchinfo, |
83 | unsigned int hook_mask) | 68 | unsigned int hook_mask) |
84 | { | 69 | { |
85 | struct xt_helper_info *info = matchinfo; | 70 | struct xt_helper_info *info = matchinfo; |
86 | 71 | ||
87 | if (nf_ct_l3proto_try_module_get(match->family) < 0) { | 72 | if (nf_ct_l3proto_try_module_get(match->family) < 0) { |
88 | printk(KERN_WARNING "can't load conntrack support for " | 73 | printk(KERN_WARNING "can't load conntrack support for " |
89 | "proto=%d\n", match->family); | 74 | "proto=%d\n", match->family); |
90 | return 0; | 75 | return false; |
91 | } | 76 | } |
92 | info->name[29] = '\0'; | 77 | info->name[29] = '\0'; |
93 | return 1; | 78 | return true; |
94 | } | 79 | } |
95 | 80 | ||
96 | static void | 81 | static void |
@@ -99,7 +84,7 @@ destroy(const struct xt_match *match, void *matchinfo) | |||
99 | nf_ct_l3proto_module_put(match->family); | 84 | nf_ct_l3proto_module_put(match->family); |
100 | } | 85 | } |
101 | 86 | ||
102 | static struct xt_match xt_helper_match[] = { | 87 | static struct xt_match xt_helper_match[] __read_mostly = { |
103 | { | 88 | { |
104 | .name = "helper", | 89 | .name = "helper", |
105 | .family = AF_INET, | 90 | .family = AF_INET, |
diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c index 77288c5ada78..3dad173d9735 100644 --- a/net/netfilter/xt_length.c +++ b/net/netfilter/xt_length.c | |||
@@ -20,7 +20,7 @@ MODULE_LICENSE("GPL"); | |||
20 | MODULE_ALIAS("ipt_length"); | 20 | MODULE_ALIAS("ipt_length"); |
21 | MODULE_ALIAS("ip6t_length"); | 21 | MODULE_ALIAS("ip6t_length"); |
22 | 22 | ||
23 | static int | 23 | static bool |
24 | match(const struct sk_buff *skb, | 24 | match(const struct sk_buff *skb, |
25 | const struct net_device *in, | 25 | const struct net_device *in, |
26 | const struct net_device *out, | 26 | const struct net_device *out, |
@@ -28,7 +28,7 @@ match(const struct sk_buff *skb, | |||
28 | const void *matchinfo, | 28 | const void *matchinfo, |
29 | int offset, | 29 | int offset, |
30 | unsigned int protoff, | 30 | unsigned int protoff, |
31 | int *hotdrop) | 31 | bool *hotdrop) |
32 | { | 32 | { |
33 | const struct xt_length_info *info = matchinfo; | 33 | const struct xt_length_info *info = matchinfo; |
34 | u_int16_t pktlen = ntohs(ip_hdr(skb)->tot_len); | 34 | u_int16_t pktlen = ntohs(ip_hdr(skb)->tot_len); |
@@ -36,7 +36,7 @@ match(const struct sk_buff *skb, | |||
36 | return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; | 36 | return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; |
37 | } | 37 | } |
38 | 38 | ||
39 | static int | 39 | static bool |
40 | match6(const struct sk_buff *skb, | 40 | match6(const struct sk_buff *skb, |
41 | const struct net_device *in, | 41 | const struct net_device *in, |
42 | const struct net_device *out, | 42 | const struct net_device *out, |
@@ -44,16 +44,16 @@ match6(const struct sk_buff *skb, | |||
44 | const void *matchinfo, | 44 | const void *matchinfo, |
45 | int offset, | 45 | int offset, |
46 | unsigned int protoff, | 46 | unsigned int protoff, |
47 | int *hotdrop) | 47 | bool *hotdrop) |
48 | { | 48 | { |
49 | const struct xt_length_info *info = matchinfo; | 49 | const struct xt_length_info *info = matchinfo; |
50 | const u_int16_t pktlen = (ntohs(ipv6_hdr(skb)->payload_len) + | 50 | const u_int16_t pktlen = ntohs(ipv6_hdr(skb)->payload_len) + |
51 | sizeof(struct ipv6hdr)); | 51 | sizeof(struct ipv6hdr); |
52 | 52 | ||
53 | return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; | 53 | return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; |
54 | } | 54 | } |
55 | 55 | ||
56 | static struct xt_match xt_length_match[] = { | 56 | static struct xt_match xt_length_match[] __read_mostly = { |
57 | { | 57 | { |
58 | .name = "length", | 58 | .name = "length", |
59 | .family = AF_INET, | 59 | .family = AF_INET, |
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c index 571a72ab89ad..4fcca797150f 100644 --- a/net/netfilter/xt_limit.c +++ b/net/netfilter/xt_limit.c | |||
@@ -57,7 +57,7 @@ static DEFINE_SPINLOCK(limit_lock); | |||
57 | 57 | ||
58 | #define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ) | 58 | #define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ) |
59 | 59 | ||
60 | static int | 60 | static bool |
61 | ipt_limit_match(const struct sk_buff *skb, | 61 | ipt_limit_match(const struct sk_buff *skb, |
62 | const struct net_device *in, | 62 | const struct net_device *in, |
63 | const struct net_device *out, | 63 | const struct net_device *out, |
@@ -65,9 +65,10 @@ ipt_limit_match(const struct sk_buff *skb, | |||
65 | const void *matchinfo, | 65 | const void *matchinfo, |
66 | int offset, | 66 | int offset, |
67 | unsigned int protoff, | 67 | unsigned int protoff, |
68 | int *hotdrop) | 68 | bool *hotdrop) |
69 | { | 69 | { |
70 | struct xt_rateinfo *r = ((struct xt_rateinfo *)matchinfo)->master; | 70 | struct xt_rateinfo *r = |
71 | ((const struct xt_rateinfo *)matchinfo)->master; | ||
71 | unsigned long now = jiffies; | 72 | unsigned long now = jiffies; |
72 | 73 | ||
73 | spin_lock_bh(&limit_lock); | 74 | spin_lock_bh(&limit_lock); |
@@ -79,11 +80,11 @@ ipt_limit_match(const struct sk_buff *skb, | |||
79 | /* We're not limited. */ | 80 | /* We're not limited. */ |
80 | r->credit -= r->cost; | 81 | r->credit -= r->cost; |
81 | spin_unlock_bh(&limit_lock); | 82 | spin_unlock_bh(&limit_lock); |
82 | return 1; | 83 | return true; |
83 | } | 84 | } |
84 | 85 | ||
85 | spin_unlock_bh(&limit_lock); | 86 | spin_unlock_bh(&limit_lock); |
86 | return 0; | 87 | return false; |
87 | } | 88 | } |
88 | 89 | ||
89 | /* Precision saver. */ | 90 | /* Precision saver. */ |
@@ -98,7 +99,7 @@ user2credits(u_int32_t user) | |||
98 | return (user * HZ * CREDITS_PER_JIFFY) / XT_LIMIT_SCALE; | 99 | return (user * HZ * CREDITS_PER_JIFFY) / XT_LIMIT_SCALE; |
99 | } | 100 | } |
100 | 101 | ||
101 | static int | 102 | static bool |
102 | ipt_limit_checkentry(const char *tablename, | 103 | ipt_limit_checkentry(const char *tablename, |
103 | const void *inf, | 104 | const void *inf, |
104 | const struct xt_match *match, | 105 | const struct xt_match *match, |
@@ -112,7 +113,7 @@ ipt_limit_checkentry(const char *tablename, | |||
112 | || user2credits(r->avg * r->burst) < user2credits(r->avg)) { | 113 | || user2credits(r->avg * r->burst) < user2credits(r->avg)) { |
113 | printk("Overflow in xt_limit, try lower: %u/%u\n", | 114 | printk("Overflow in xt_limit, try lower: %u/%u\n", |
114 | r->avg, r->burst); | 115 | r->avg, r->burst); |
115 | return 0; | 116 | return false; |
116 | } | 117 | } |
117 | 118 | ||
118 | /* For SMP, we only want to use one set of counters. */ | 119 | /* For SMP, we only want to use one set of counters. */ |
@@ -125,7 +126,7 @@ ipt_limit_checkentry(const char *tablename, | |||
125 | r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */ | 126 | r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */ |
126 | r->cost = user2credits(r->avg); | 127 | r->cost = user2credits(r->avg); |
127 | } | 128 | } |
128 | return 1; | 129 | return true; |
129 | } | 130 | } |
130 | 131 | ||
131 | #ifdef CONFIG_COMPAT | 132 | #ifdef CONFIG_COMPAT |
@@ -144,7 +145,7 @@ struct compat_xt_rateinfo { | |||
144 | * master pointer, which does not need to be preserved. */ | 145 | * master pointer, which does not need to be preserved. */ |
145 | static void compat_from_user(void *dst, void *src) | 146 | static void compat_from_user(void *dst, void *src) |
146 | { | 147 | { |
147 | struct compat_xt_rateinfo *cm = src; | 148 | const struct compat_xt_rateinfo *cm = src; |
148 | struct xt_rateinfo m = { | 149 | struct xt_rateinfo m = { |
149 | .avg = cm->avg, | 150 | .avg = cm->avg, |
150 | .burst = cm->burst, | 151 | .burst = cm->burst, |
@@ -158,7 +159,7 @@ static void compat_from_user(void *dst, void *src) | |||
158 | 159 | ||
159 | static int compat_to_user(void __user *dst, void *src) | 160 | static int compat_to_user(void __user *dst, void *src) |
160 | { | 161 | { |
161 | struct xt_rateinfo *m = src; | 162 | const struct xt_rateinfo *m = src; |
162 | struct compat_xt_rateinfo cm = { | 163 | struct compat_xt_rateinfo cm = { |
163 | .avg = m->avg, | 164 | .avg = m->avg, |
164 | .burst = m->burst, | 165 | .burst = m->burst, |
@@ -172,7 +173,7 @@ static int compat_to_user(void __user *dst, void *src) | |||
172 | } | 173 | } |
173 | #endif /* CONFIG_COMPAT */ | 174 | #endif /* CONFIG_COMPAT */ |
174 | 175 | ||
175 | static struct xt_match xt_limit_match[] = { | 176 | static struct xt_match xt_limit_match[] __read_mostly = { |
176 | { | 177 | { |
177 | .name = "limit", | 178 | .name = "limit", |
178 | .family = AF_INET, | 179 | .family = AF_INET, |
diff --git a/net/netfilter/xt_mac.c b/net/netfilter/xt_mac.c index 1d3a1d98b885..00490d777a0f 100644 --- a/net/netfilter/xt_mac.c +++ b/net/netfilter/xt_mac.c | |||
@@ -24,7 +24,7 @@ MODULE_DESCRIPTION("iptables mac matching module"); | |||
24 | MODULE_ALIAS("ipt_mac"); | 24 | MODULE_ALIAS("ipt_mac"); |
25 | MODULE_ALIAS("ip6t_mac"); | 25 | MODULE_ALIAS("ip6t_mac"); |
26 | 26 | ||
27 | static int | 27 | static bool |
28 | match(const struct sk_buff *skb, | 28 | match(const struct sk_buff *skb, |
29 | const struct net_device *in, | 29 | const struct net_device *in, |
30 | const struct net_device *out, | 30 | const struct net_device *out, |
@@ -32,19 +32,19 @@ match(const struct sk_buff *skb, | |||
32 | const void *matchinfo, | 32 | const void *matchinfo, |
33 | int offset, | 33 | int offset, |
34 | unsigned int protoff, | 34 | unsigned int protoff, |
35 | int *hotdrop) | 35 | bool *hotdrop) |
36 | { | 36 | { |
37 | const struct xt_mac_info *info = matchinfo; | 37 | const struct xt_mac_info *info = matchinfo; |
38 | 38 | ||
39 | /* Is mac pointer valid? */ | 39 | /* Is mac pointer valid? */ |
40 | return (skb_mac_header(skb) >= skb->head && | 40 | return skb_mac_header(skb) >= skb->head && |
41 | (skb_mac_header(skb) + ETH_HLEN) <= skb->data | 41 | skb_mac_header(skb) + ETH_HLEN <= skb->data |
42 | /* If so, compare... */ | 42 | /* If so, compare... */ |
43 | && ((!compare_ether_addr(eth_hdr(skb)->h_source, info->srcaddr)) | 43 | && ((!compare_ether_addr(eth_hdr(skb)->h_source, info->srcaddr)) |
44 | ^ info->invert)); | 44 | ^ info->invert); |
45 | } | 45 | } |
46 | 46 | ||
47 | static struct xt_match xt_mac_match[] = { | 47 | static struct xt_match xt_mac_match[] __read_mostly = { |
48 | { | 48 | { |
49 | .name = "mac", | 49 | .name = "mac", |
50 | .family = AF_INET, | 50 | .family = AF_INET, |
diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c index 39911dddb011..c02a7f8f3925 100644 --- a/net/netfilter/xt_mark.c +++ b/net/netfilter/xt_mark.c | |||
@@ -19,7 +19,7 @@ MODULE_DESCRIPTION("iptables mark matching module"); | |||
19 | MODULE_ALIAS("ipt_mark"); | 19 | MODULE_ALIAS("ipt_mark"); |
20 | MODULE_ALIAS("ip6t_mark"); | 20 | MODULE_ALIAS("ip6t_mark"); |
21 | 21 | ||
22 | static int | 22 | static bool |
23 | match(const struct sk_buff *skb, | 23 | match(const struct sk_buff *skb, |
24 | const struct net_device *in, | 24 | const struct net_device *in, |
25 | const struct net_device *out, | 25 | const struct net_device *out, |
@@ -27,14 +27,14 @@ match(const struct sk_buff *skb, | |||
27 | const void *matchinfo, | 27 | const void *matchinfo, |
28 | int offset, | 28 | int offset, |
29 | unsigned int protoff, | 29 | unsigned int protoff, |
30 | int *hotdrop) | 30 | bool *hotdrop) |
31 | { | 31 | { |
32 | const struct xt_mark_info *info = matchinfo; | 32 | const struct xt_mark_info *info = matchinfo; |
33 | 33 | ||
34 | return ((skb->mark & info->mask) == info->mark) ^ info->invert; | 34 | return ((skb->mark & info->mask) == info->mark) ^ info->invert; |
35 | } | 35 | } |
36 | 36 | ||
37 | static int | 37 | static bool |
38 | checkentry(const char *tablename, | 38 | checkentry(const char *tablename, |
39 | const void *entry, | 39 | const void *entry, |
40 | const struct xt_match *match, | 40 | const struct xt_match *match, |
@@ -45,9 +45,9 @@ checkentry(const char *tablename, | |||
45 | 45 | ||
46 | if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) { | 46 | if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) { |
47 | printk(KERN_WARNING "mark: only supports 32bit mark\n"); | 47 | printk(KERN_WARNING "mark: only supports 32bit mark\n"); |
48 | return 0; | 48 | return false; |
49 | } | 49 | } |
50 | return 1; | 50 | return true; |
51 | } | 51 | } |
52 | 52 | ||
53 | #ifdef CONFIG_COMPAT | 53 | #ifdef CONFIG_COMPAT |
@@ -60,7 +60,7 @@ struct compat_xt_mark_info { | |||
60 | 60 | ||
61 | static void compat_from_user(void *dst, void *src) | 61 | static void compat_from_user(void *dst, void *src) |
62 | { | 62 | { |
63 | struct compat_xt_mark_info *cm = src; | 63 | const struct compat_xt_mark_info *cm = src; |
64 | struct xt_mark_info m = { | 64 | struct xt_mark_info m = { |
65 | .mark = cm->mark, | 65 | .mark = cm->mark, |
66 | .mask = cm->mask, | 66 | .mask = cm->mask, |
@@ -71,7 +71,7 @@ static void compat_from_user(void *dst, void *src) | |||
71 | 71 | ||
72 | static int compat_to_user(void __user *dst, void *src) | 72 | static int compat_to_user(void __user *dst, void *src) |
73 | { | 73 | { |
74 | struct xt_mark_info *m = src; | 74 | const struct xt_mark_info *m = src; |
75 | struct compat_xt_mark_info cm = { | 75 | struct compat_xt_mark_info cm = { |
76 | .mark = m->mark, | 76 | .mark = m->mark, |
77 | .mask = m->mask, | 77 | .mask = m->mask, |
@@ -81,7 +81,7 @@ static int compat_to_user(void __user *dst, void *src) | |||
81 | } | 81 | } |
82 | #endif /* CONFIG_COMPAT */ | 82 | #endif /* CONFIG_COMPAT */ |
83 | 83 | ||
84 | static struct xt_match xt_mark_match[] = { | 84 | static struct xt_match xt_mark_match[] __read_mostly = { |
85 | { | 85 | { |
86 | .name = "mark", | 86 | .name = "mark", |
87 | .family = AF_INET, | 87 | .family = AF_INET, |
diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c index 4dce2a81702a..e8ae10284acd 100644 --- a/net/netfilter/xt_multiport.c +++ b/net/netfilter/xt_multiport.c | |||
@@ -33,24 +33,24 @@ MODULE_ALIAS("ip6t_multiport"); | |||
33 | #endif | 33 | #endif |
34 | 34 | ||
35 | /* Returns 1 if the port is matched by the test, 0 otherwise. */ | 35 | /* Returns 1 if the port is matched by the test, 0 otherwise. */ |
36 | static inline int | 36 | static inline bool |
37 | ports_match(const u_int16_t *portlist, enum xt_multiport_flags flags, | 37 | ports_match(const u_int16_t *portlist, enum xt_multiport_flags flags, |
38 | u_int8_t count, u_int16_t src, u_int16_t dst) | 38 | u_int8_t count, u_int16_t src, u_int16_t dst) |
39 | { | 39 | { |
40 | unsigned int i; | 40 | unsigned int i; |
41 | for (i = 0; i < count; i++) { | 41 | for (i = 0; i < count; i++) { |
42 | if (flags != XT_MULTIPORT_DESTINATION && portlist[i] == src) | 42 | if (flags != XT_MULTIPORT_DESTINATION && portlist[i] == src) |
43 | return 1; | 43 | return true; |
44 | 44 | ||
45 | if (flags != XT_MULTIPORT_SOURCE && portlist[i] == dst) | 45 | if (flags != XT_MULTIPORT_SOURCE && portlist[i] == dst) |
46 | return 1; | 46 | return true; |
47 | } | 47 | } |
48 | 48 | ||
49 | return 0; | 49 | return false; |
50 | } | 50 | } |
51 | 51 | ||
52 | /* Returns 1 if the port is matched by the test, 0 otherwise. */ | 52 | /* Returns 1 if the port is matched by the test, 0 otherwise. */ |
53 | static inline int | 53 | static inline bool |
54 | ports_match_v1(const struct xt_multiport_v1 *minfo, | 54 | ports_match_v1(const struct xt_multiport_v1 *minfo, |
55 | u_int16_t src, u_int16_t dst) | 55 | u_int16_t src, u_int16_t dst) |
56 | { | 56 | { |
@@ -67,34 +67,34 @@ ports_match_v1(const struct xt_multiport_v1 *minfo, | |||
67 | 67 | ||
68 | if (minfo->flags == XT_MULTIPORT_SOURCE | 68 | if (minfo->flags == XT_MULTIPORT_SOURCE |
69 | && src >= s && src <= e) | 69 | && src >= s && src <= e) |
70 | return 1 ^ minfo->invert; | 70 | return true ^ minfo->invert; |
71 | if (minfo->flags == XT_MULTIPORT_DESTINATION | 71 | if (minfo->flags == XT_MULTIPORT_DESTINATION |
72 | && dst >= s && dst <= e) | 72 | && dst >= s && dst <= e) |
73 | return 1 ^ minfo->invert; | 73 | return true ^ minfo->invert; |
74 | if (minfo->flags == XT_MULTIPORT_EITHER | 74 | if (minfo->flags == XT_MULTIPORT_EITHER |
75 | && ((dst >= s && dst <= e) | 75 | && ((dst >= s && dst <= e) |
76 | || (src >= s && src <= e))) | 76 | || (src >= s && src <= e))) |
77 | return 1 ^ minfo->invert; | 77 | return true ^ minfo->invert; |
78 | } else { | 78 | } else { |
79 | /* exact port matching */ | 79 | /* exact port matching */ |
80 | duprintf("src or dst matches with %d?\n", s); | 80 | duprintf("src or dst matches with %d?\n", s); |
81 | 81 | ||
82 | if (minfo->flags == XT_MULTIPORT_SOURCE | 82 | if (minfo->flags == XT_MULTIPORT_SOURCE |
83 | && src == s) | 83 | && src == s) |
84 | return 1 ^ minfo->invert; | 84 | return true ^ minfo->invert; |
85 | if (minfo->flags == XT_MULTIPORT_DESTINATION | 85 | if (minfo->flags == XT_MULTIPORT_DESTINATION |
86 | && dst == s) | 86 | && dst == s) |
87 | return 1 ^ minfo->invert; | 87 | return true ^ minfo->invert; |
88 | if (minfo->flags == XT_MULTIPORT_EITHER | 88 | if (minfo->flags == XT_MULTIPORT_EITHER |
89 | && (src == s || dst == s)) | 89 | && (src == s || dst == s)) |
90 | return 1 ^ minfo->invert; | 90 | return true ^ minfo->invert; |
91 | } | 91 | } |
92 | } | 92 | } |
93 | 93 | ||
94 | return minfo->invert; | 94 | return minfo->invert; |
95 | } | 95 | } |
96 | 96 | ||
97 | static int | 97 | static bool |
98 | match(const struct sk_buff *skb, | 98 | match(const struct sk_buff *skb, |
99 | const struct net_device *in, | 99 | const struct net_device *in, |
100 | const struct net_device *out, | 100 | const struct net_device *out, |
@@ -102,13 +102,13 @@ match(const struct sk_buff *skb, | |||
102 | const void *matchinfo, | 102 | const void *matchinfo, |
103 | int offset, | 103 | int offset, |
104 | unsigned int protoff, | 104 | unsigned int protoff, |
105 | int *hotdrop) | 105 | bool *hotdrop) |
106 | { | 106 | { |
107 | __be16 _ports[2], *pptr; | 107 | __be16 _ports[2], *pptr; |
108 | const struct xt_multiport *multiinfo = matchinfo; | 108 | const struct xt_multiport *multiinfo = matchinfo; |
109 | 109 | ||
110 | if (offset) | 110 | if (offset) |
111 | return 0; | 111 | return false; |
112 | 112 | ||
113 | pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports); | 113 | pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports); |
114 | if (pptr == NULL) { | 114 | if (pptr == NULL) { |
@@ -116,8 +116,8 @@ match(const struct sk_buff *skb, | |||
116 | * can't. Hence, no choice but to drop. | 116 | * can't. Hence, no choice but to drop. |
117 | */ | 117 | */ |
118 | duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n"); | 118 | duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n"); |
119 | *hotdrop = 1; | 119 | *hotdrop = true; |
120 | return 0; | 120 | return false; |
121 | } | 121 | } |
122 | 122 | ||
123 | return ports_match(multiinfo->ports, | 123 | return ports_match(multiinfo->ports, |
@@ -125,7 +125,7 @@ match(const struct sk_buff *skb, | |||
125 | ntohs(pptr[0]), ntohs(pptr[1])); | 125 | ntohs(pptr[0]), ntohs(pptr[1])); |
126 | } | 126 | } |
127 | 127 | ||
128 | static int | 128 | static bool |
129 | match_v1(const struct sk_buff *skb, | 129 | match_v1(const struct sk_buff *skb, |
130 | const struct net_device *in, | 130 | const struct net_device *in, |
131 | const struct net_device *out, | 131 | const struct net_device *out, |
@@ -133,13 +133,13 @@ match_v1(const struct sk_buff *skb, | |||
133 | const void *matchinfo, | 133 | const void *matchinfo, |
134 | int offset, | 134 | int offset, |
135 | unsigned int protoff, | 135 | unsigned int protoff, |
136 | int *hotdrop) | 136 | bool *hotdrop) |
137 | { | 137 | { |
138 | __be16 _ports[2], *pptr; | 138 | __be16 _ports[2], *pptr; |
139 | const struct xt_multiport_v1 *multiinfo = matchinfo; | 139 | const struct xt_multiport_v1 *multiinfo = matchinfo; |
140 | 140 | ||
141 | if (offset) | 141 | if (offset) |
142 | return 0; | 142 | return false; |
143 | 143 | ||
144 | pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports); | 144 | pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports); |
145 | if (pptr == NULL) { | 145 | if (pptr == NULL) { |
@@ -147,14 +147,14 @@ match_v1(const struct sk_buff *skb, | |||
147 | * can't. Hence, no choice but to drop. | 147 | * can't. Hence, no choice but to drop. |
148 | */ | 148 | */ |
149 | duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n"); | 149 | duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n"); |
150 | *hotdrop = 1; | 150 | *hotdrop = true; |
151 | return 0; | 151 | return false; |
152 | } | 152 | } |
153 | 153 | ||
154 | return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1])); | 154 | return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1])); |
155 | } | 155 | } |
156 | 156 | ||
157 | static inline int | 157 | static inline bool |
158 | check(u_int16_t proto, | 158 | check(u_int16_t proto, |
159 | u_int8_t ip_invflags, | 159 | u_int8_t ip_invflags, |
160 | u_int8_t match_flags, | 160 | u_int8_t match_flags, |
@@ -172,7 +172,7 @@ check(u_int16_t proto, | |||
172 | } | 172 | } |
173 | 173 | ||
174 | /* Called when user tries to insert an entry of this type. */ | 174 | /* Called when user tries to insert an entry of this type. */ |
175 | static int | 175 | static bool |
176 | checkentry(const char *tablename, | 176 | checkentry(const char *tablename, |
177 | const void *info, | 177 | const void *info, |
178 | const struct xt_match *match, | 178 | const struct xt_match *match, |
@@ -186,7 +186,7 @@ checkentry(const char *tablename, | |||
186 | multiinfo->count); | 186 | multiinfo->count); |
187 | } | 187 | } |
188 | 188 | ||
189 | static int | 189 | static bool |
190 | checkentry_v1(const char *tablename, | 190 | checkentry_v1(const char *tablename, |
191 | const void *info, | 191 | const void *info, |
192 | const struct xt_match *match, | 192 | const struct xt_match *match, |
@@ -200,7 +200,7 @@ checkentry_v1(const char *tablename, | |||
200 | multiinfo->count); | 200 | multiinfo->count); |
201 | } | 201 | } |
202 | 202 | ||
203 | static int | 203 | static bool |
204 | checkentry6(const char *tablename, | 204 | checkentry6(const char *tablename, |
205 | const void *info, | 205 | const void *info, |
206 | const struct xt_match *match, | 206 | const struct xt_match *match, |
@@ -214,7 +214,7 @@ checkentry6(const char *tablename, | |||
214 | multiinfo->count); | 214 | multiinfo->count); |
215 | } | 215 | } |
216 | 216 | ||
217 | static int | 217 | static bool |
218 | checkentry6_v1(const char *tablename, | 218 | checkentry6_v1(const char *tablename, |
219 | const void *info, | 219 | const void *info, |
220 | const struct xt_match *match, | 220 | const struct xt_match *match, |
@@ -228,7 +228,7 @@ checkentry6_v1(const char *tablename, | |||
228 | multiinfo->count); | 228 | multiinfo->count); |
229 | } | 229 | } |
230 | 230 | ||
231 | static struct xt_match xt_multiport_match[] = { | 231 | static struct xt_match xt_multiport_match[] __read_mostly = { |
232 | { | 232 | { |
233 | .name = "multiport", | 233 | .name = "multiport", |
234 | .family = AF_INET, | 234 | .family = AF_INET, |
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c index 35a0fe200c39..f47cab7a696d 100644 --- a/net/netfilter/xt_physdev.c +++ b/net/netfilter/xt_physdev.c | |||
@@ -14,8 +14,6 @@ | |||
14 | #include <linux/netfilter/xt_physdev.h> | 14 | #include <linux/netfilter/xt_physdev.h> |
15 | #include <linux/netfilter/x_tables.h> | 15 | #include <linux/netfilter/x_tables.h> |
16 | #include <linux/netfilter_bridge.h> | 16 | #include <linux/netfilter_bridge.h> |
17 | #define MATCH 1 | ||
18 | #define NOMATCH 0 | ||
19 | 17 | ||
20 | MODULE_LICENSE("GPL"); | 18 | MODULE_LICENSE("GPL"); |
21 | MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); | 19 | MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); |
@@ -23,7 +21,7 @@ MODULE_DESCRIPTION("iptables bridge physical device match module"); | |||
23 | MODULE_ALIAS("ipt_physdev"); | 21 | MODULE_ALIAS("ipt_physdev"); |
24 | MODULE_ALIAS("ip6t_physdev"); | 22 | MODULE_ALIAS("ip6t_physdev"); |
25 | 23 | ||
26 | static int | 24 | static bool |
27 | match(const struct sk_buff *skb, | 25 | match(const struct sk_buff *skb, |
28 | const struct net_device *in, | 26 | const struct net_device *in, |
29 | const struct net_device *out, | 27 | const struct net_device *out, |
@@ -31,14 +29,14 @@ match(const struct sk_buff *skb, | |||
31 | const void *matchinfo, | 29 | const void *matchinfo, |
32 | int offset, | 30 | int offset, |
33 | unsigned int protoff, | 31 | unsigned int protoff, |
34 | int *hotdrop) | 32 | bool *hotdrop) |
35 | { | 33 | { |
36 | int i; | 34 | int i; |
37 | static const char nulldevname[IFNAMSIZ]; | 35 | static const char nulldevname[IFNAMSIZ]; |
38 | const struct xt_physdev_info *info = matchinfo; | 36 | const struct xt_physdev_info *info = matchinfo; |
39 | unsigned int ret; | 37 | bool ret; |
40 | const char *indev, *outdev; | 38 | const char *indev, *outdev; |
41 | struct nf_bridge_info *nf_bridge; | 39 | const struct nf_bridge_info *nf_bridge; |
42 | 40 | ||
43 | /* Not a bridged IP packet or no info available yet: | 41 | /* Not a bridged IP packet or no info available yet: |
44 | * LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if | 42 | * LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if |
@@ -47,61 +45,61 @@ match(const struct sk_buff *skb, | |||
47 | /* Return MATCH if the invert flags of the used options are on */ | 45 | /* Return MATCH if the invert flags of the used options are on */ |
48 | if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) && | 46 | if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) && |
49 | !(info->invert & XT_PHYSDEV_OP_BRIDGED)) | 47 | !(info->invert & XT_PHYSDEV_OP_BRIDGED)) |
50 | return NOMATCH; | 48 | return false; |
51 | if ((info->bitmask & XT_PHYSDEV_OP_ISIN) && | 49 | if ((info->bitmask & XT_PHYSDEV_OP_ISIN) && |
52 | !(info->invert & XT_PHYSDEV_OP_ISIN)) | 50 | !(info->invert & XT_PHYSDEV_OP_ISIN)) |
53 | return NOMATCH; | 51 | return false; |
54 | if ((info->bitmask & XT_PHYSDEV_OP_ISOUT) && | 52 | if ((info->bitmask & XT_PHYSDEV_OP_ISOUT) && |
55 | !(info->invert & XT_PHYSDEV_OP_ISOUT)) | 53 | !(info->invert & XT_PHYSDEV_OP_ISOUT)) |
56 | return NOMATCH; | 54 | return false; |
57 | if ((info->bitmask & XT_PHYSDEV_OP_IN) && | 55 | if ((info->bitmask & XT_PHYSDEV_OP_IN) && |
58 | !(info->invert & XT_PHYSDEV_OP_IN)) | 56 | !(info->invert & XT_PHYSDEV_OP_IN)) |
59 | return NOMATCH; | 57 | return false; |
60 | if ((info->bitmask & XT_PHYSDEV_OP_OUT) && | 58 | if ((info->bitmask & XT_PHYSDEV_OP_OUT) && |
61 | !(info->invert & XT_PHYSDEV_OP_OUT)) | 59 | !(info->invert & XT_PHYSDEV_OP_OUT)) |
62 | return NOMATCH; | 60 | return false; |
63 | return MATCH; | 61 | return true; |
64 | } | 62 | } |
65 | 63 | ||
66 | /* This only makes sense in the FORWARD and POSTROUTING chains */ | 64 | /* This only makes sense in the FORWARD and POSTROUTING chains */ |
67 | if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) && | 65 | if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) && |
68 | (!!(nf_bridge->mask & BRNF_BRIDGED) ^ | 66 | (!!(nf_bridge->mask & BRNF_BRIDGED) ^ |
69 | !(info->invert & XT_PHYSDEV_OP_BRIDGED))) | 67 | !(info->invert & XT_PHYSDEV_OP_BRIDGED))) |
70 | return NOMATCH; | 68 | return false; |
71 | 69 | ||
72 | if ((info->bitmask & XT_PHYSDEV_OP_ISIN && | 70 | if ((info->bitmask & XT_PHYSDEV_OP_ISIN && |
73 | (!nf_bridge->physindev ^ !!(info->invert & XT_PHYSDEV_OP_ISIN))) || | 71 | (!nf_bridge->physindev ^ !!(info->invert & XT_PHYSDEV_OP_ISIN))) || |
74 | (info->bitmask & XT_PHYSDEV_OP_ISOUT && | 72 | (info->bitmask & XT_PHYSDEV_OP_ISOUT && |
75 | (!nf_bridge->physoutdev ^ !!(info->invert & XT_PHYSDEV_OP_ISOUT)))) | 73 | (!nf_bridge->physoutdev ^ !!(info->invert & XT_PHYSDEV_OP_ISOUT)))) |
76 | return NOMATCH; | 74 | return false; |
77 | 75 | ||
78 | if (!(info->bitmask & XT_PHYSDEV_OP_IN)) | 76 | if (!(info->bitmask & XT_PHYSDEV_OP_IN)) |
79 | goto match_outdev; | 77 | goto match_outdev; |
80 | indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname; | 78 | indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname; |
81 | for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) { | 79 | for (i = 0, ret = false; i < IFNAMSIZ/sizeof(unsigned int); i++) { |
82 | ret |= (((const unsigned int *)indev)[i] | 80 | ret |= (((const unsigned int *)indev)[i] |
83 | ^ ((const unsigned int *)info->physindev)[i]) | 81 | ^ ((const unsigned int *)info->physindev)[i]) |
84 | & ((const unsigned int *)info->in_mask)[i]; | 82 | & ((const unsigned int *)info->in_mask)[i]; |
85 | } | 83 | } |
86 | 84 | ||
87 | if ((ret == 0) ^ !(info->invert & XT_PHYSDEV_OP_IN)) | 85 | if (!ret ^ !(info->invert & XT_PHYSDEV_OP_IN)) |
88 | return NOMATCH; | 86 | return false; |
89 | 87 | ||
90 | match_outdev: | 88 | match_outdev: |
91 | if (!(info->bitmask & XT_PHYSDEV_OP_OUT)) | 89 | if (!(info->bitmask & XT_PHYSDEV_OP_OUT)) |
92 | return MATCH; | 90 | return true; |
93 | outdev = nf_bridge->physoutdev ? | 91 | outdev = nf_bridge->physoutdev ? |
94 | nf_bridge->physoutdev->name : nulldevname; | 92 | nf_bridge->physoutdev->name : nulldevname; |
95 | for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) { | 93 | for (i = 0, ret = false; i < IFNAMSIZ/sizeof(unsigned int); i++) { |
96 | ret |= (((const unsigned int *)outdev)[i] | 94 | ret |= (((const unsigned int *)outdev)[i] |
97 | ^ ((const unsigned int *)info->physoutdev)[i]) | 95 | ^ ((const unsigned int *)info->physoutdev)[i]) |
98 | & ((const unsigned int *)info->out_mask)[i]; | 96 | & ((const unsigned int *)info->out_mask)[i]; |
99 | } | 97 | } |
100 | 98 | ||
101 | return (ret != 0) ^ !(info->invert & XT_PHYSDEV_OP_OUT); | 99 | return ret ^ !(info->invert & XT_PHYSDEV_OP_OUT); |
102 | } | 100 | } |
103 | 101 | ||
104 | static int | 102 | static bool |
105 | checkentry(const char *tablename, | 103 | checkentry(const char *tablename, |
106 | const void *ip, | 104 | const void *ip, |
107 | const struct xt_match *match, | 105 | const struct xt_match *match, |
@@ -112,7 +110,7 @@ checkentry(const char *tablename, | |||
112 | 110 | ||
113 | if (!(info->bitmask & XT_PHYSDEV_OP_MASK) || | 111 | if (!(info->bitmask & XT_PHYSDEV_OP_MASK) || |
114 | info->bitmask & ~XT_PHYSDEV_OP_MASK) | 112 | info->bitmask & ~XT_PHYSDEV_OP_MASK) |
115 | return 0; | 113 | return false; |
116 | if (info->bitmask & XT_PHYSDEV_OP_OUT && | 114 | if (info->bitmask & XT_PHYSDEV_OP_OUT && |
117 | (!(info->bitmask & XT_PHYSDEV_OP_BRIDGED) || | 115 | (!(info->bitmask & XT_PHYSDEV_OP_BRIDGED) || |
118 | info->invert & XT_PHYSDEV_OP_BRIDGED) && | 116 | info->invert & XT_PHYSDEV_OP_BRIDGED) && |
@@ -122,12 +120,12 @@ checkentry(const char *tablename, | |||
122 | "OUTPUT, FORWARD and POSTROUTING chains for non-bridged " | 120 | "OUTPUT, FORWARD and POSTROUTING chains for non-bridged " |
123 | "traffic is not supported anymore.\n"); | 121 | "traffic is not supported anymore.\n"); |
124 | if (hook_mask & (1 << NF_IP_LOCAL_OUT)) | 122 | if (hook_mask & (1 << NF_IP_LOCAL_OUT)) |
125 | return 0; | 123 | return false; |
126 | } | 124 | } |
127 | return 1; | 125 | return true; |
128 | } | 126 | } |
129 | 127 | ||
130 | static struct xt_match xt_physdev_match[] = { | 128 | static struct xt_match xt_physdev_match[] __read_mostly = { |
131 | { | 129 | { |
132 | .name = "physdev", | 130 | .name = "physdev", |
133 | .family = AF_INET, | 131 | .family = AF_INET, |
diff --git a/net/netfilter/xt_pkttype.c b/net/netfilter/xt_pkttype.c index e1409fc5c288..a52925f12f35 100644 --- a/net/netfilter/xt_pkttype.c +++ b/net/netfilter/xt_pkttype.c | |||
@@ -21,29 +21,29 @@ MODULE_DESCRIPTION("IP tables match to match on linklayer packet type"); | |||
21 | MODULE_ALIAS("ipt_pkttype"); | 21 | MODULE_ALIAS("ipt_pkttype"); |
22 | MODULE_ALIAS("ip6t_pkttype"); | 22 | MODULE_ALIAS("ip6t_pkttype"); |
23 | 23 | ||
24 | static int match(const struct sk_buff *skb, | 24 | static bool match(const struct sk_buff *skb, |
25 | const struct net_device *in, | 25 | const struct net_device *in, |
26 | const struct net_device *out, | 26 | const struct net_device *out, |
27 | const struct xt_match *match, | 27 | const struct xt_match *match, |
28 | const void *matchinfo, | 28 | const void *matchinfo, |
29 | int offset, | 29 | int offset, |
30 | unsigned int protoff, | 30 | unsigned int protoff, |
31 | int *hotdrop) | 31 | bool *hotdrop) |
32 | { | 32 | { |
33 | u_int8_t type; | 33 | u_int8_t type; |
34 | const struct xt_pkttype_info *info = matchinfo; | 34 | const struct xt_pkttype_info *info = matchinfo; |
35 | 35 | ||
36 | if (skb->pkt_type == PACKET_LOOPBACK) | 36 | if (skb->pkt_type == PACKET_LOOPBACK) |
37 | type = (MULTICAST(ip_hdr(skb)->daddr) | 37 | type = MULTICAST(ip_hdr(skb)->daddr) |
38 | ? PACKET_MULTICAST | 38 | ? PACKET_MULTICAST |
39 | : PACKET_BROADCAST); | 39 | : PACKET_BROADCAST; |
40 | else | 40 | else |
41 | type = skb->pkt_type; | 41 | type = skb->pkt_type; |
42 | 42 | ||
43 | return (type == info->pkttype) ^ info->invert; | 43 | return (type == info->pkttype) ^ info->invert; |
44 | } | 44 | } |
45 | 45 | ||
46 | static struct xt_match xt_pkttype_match[] = { | 46 | static struct xt_match xt_pkttype_match[] __read_mostly = { |
47 | { | 47 | { |
48 | .name = "pkttype", | 48 | .name = "pkttype", |
49 | .family = AF_INET, | 49 | .family = AF_INET, |
diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c index 15b45a95ec13..6d6d3b7fcbb5 100644 --- a/net/netfilter/xt_policy.c +++ b/net/netfilter/xt_policy.c | |||
@@ -20,7 +20,7 @@ MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | |||
20 | MODULE_DESCRIPTION("Xtables IPsec policy matching module"); | 20 | MODULE_DESCRIPTION("Xtables IPsec policy matching module"); |
21 | MODULE_LICENSE("GPL"); | 21 | MODULE_LICENSE("GPL"); |
22 | 22 | ||
23 | static inline int | 23 | static inline bool |
24 | xt_addr_cmp(const union xt_policy_addr *a1, const union xt_policy_addr *m, | 24 | xt_addr_cmp(const union xt_policy_addr *a1, const union xt_policy_addr *m, |
25 | const union xt_policy_addr *a2, unsigned short family) | 25 | const union xt_policy_addr *a2, unsigned short family) |
26 | { | 26 | { |
@@ -30,11 +30,11 @@ xt_addr_cmp(const union xt_policy_addr *a1, const union xt_policy_addr *m, | |||
30 | case AF_INET6: | 30 | case AF_INET6: |
31 | return !ipv6_masked_addr_cmp(&a1->a6, &m->a6, &a2->a6); | 31 | return !ipv6_masked_addr_cmp(&a1->a6, &m->a6, &a2->a6); |
32 | } | 32 | } |
33 | return 0; | 33 | return false; |
34 | } | 34 | } |
35 | 35 | ||
36 | static inline int | 36 | static inline bool |
37 | match_xfrm_state(struct xfrm_state *x, const struct xt_policy_elem *e, | 37 | match_xfrm_state(const struct xfrm_state *x, const struct xt_policy_elem *e, |
38 | unsigned short family) | 38 | unsigned short family) |
39 | { | 39 | { |
40 | #define MATCH_ADDR(x,y,z) (!e->match.x || \ | 40 | #define MATCH_ADDR(x,y,z) (!e->match.x || \ |
@@ -55,7 +55,7 @@ match_policy_in(const struct sk_buff *skb, const struct xt_policy_info *info, | |||
55 | unsigned short family) | 55 | unsigned short family) |
56 | { | 56 | { |
57 | const struct xt_policy_elem *e; | 57 | const struct xt_policy_elem *e; |
58 | struct sec_path *sp = skb->sp; | 58 | const struct sec_path *sp = skb->sp; |
59 | int strict = info->flags & XT_POLICY_MATCH_STRICT; | 59 | int strict = info->flags & XT_POLICY_MATCH_STRICT; |
60 | int i, pos; | 60 | int i, pos; |
61 | 61 | ||
@@ -85,7 +85,7 @@ match_policy_out(const struct sk_buff *skb, const struct xt_policy_info *info, | |||
85 | unsigned short family) | 85 | unsigned short family) |
86 | { | 86 | { |
87 | const struct xt_policy_elem *e; | 87 | const struct xt_policy_elem *e; |
88 | struct dst_entry *dst = skb->dst; | 88 | const struct dst_entry *dst = skb->dst; |
89 | int strict = info->flags & XT_POLICY_MATCH_STRICT; | 89 | int strict = info->flags & XT_POLICY_MATCH_STRICT; |
90 | int i, pos; | 90 | int i, pos; |
91 | 91 | ||
@@ -108,14 +108,14 @@ match_policy_out(const struct sk_buff *skb, const struct xt_policy_info *info, | |||
108 | return strict ? i == info->len : 0; | 108 | return strict ? i == info->len : 0; |
109 | } | 109 | } |
110 | 110 | ||
111 | static int match(const struct sk_buff *skb, | 111 | static bool match(const struct sk_buff *skb, |
112 | const struct net_device *in, | 112 | const struct net_device *in, |
113 | const struct net_device *out, | 113 | const struct net_device *out, |
114 | const struct xt_match *match, | 114 | const struct xt_match *match, |
115 | const void *matchinfo, | 115 | const void *matchinfo, |
116 | int offset, | 116 | int offset, |
117 | unsigned int protoff, | 117 | unsigned int protoff, |
118 | int *hotdrop) | 118 | bool *hotdrop) |
119 | { | 119 | { |
120 | const struct xt_policy_info *info = matchinfo; | 120 | const struct xt_policy_info *info = matchinfo; |
121 | int ret; | 121 | int ret; |
@@ -126,45 +126,45 @@ static int match(const struct sk_buff *skb, | |||
126 | ret = match_policy_out(skb, info, match->family); | 126 | ret = match_policy_out(skb, info, match->family); |
127 | 127 | ||
128 | if (ret < 0) | 128 | if (ret < 0) |
129 | ret = info->flags & XT_POLICY_MATCH_NONE ? 1 : 0; | 129 | ret = info->flags & XT_POLICY_MATCH_NONE ? true : false; |
130 | else if (info->flags & XT_POLICY_MATCH_NONE) | 130 | else if (info->flags & XT_POLICY_MATCH_NONE) |
131 | ret = 0; | 131 | ret = false; |
132 | 132 | ||
133 | return ret; | 133 | return ret; |
134 | } | 134 | } |
135 | 135 | ||
136 | static int checkentry(const char *tablename, const void *ip_void, | 136 | static bool checkentry(const char *tablename, const void *ip_void, |
137 | const struct xt_match *match, | 137 | const struct xt_match *match, |
138 | void *matchinfo, unsigned int hook_mask) | 138 | void *matchinfo, unsigned int hook_mask) |
139 | { | 139 | { |
140 | struct xt_policy_info *info = matchinfo; | 140 | struct xt_policy_info *info = matchinfo; |
141 | 141 | ||
142 | if (!(info->flags & (XT_POLICY_MATCH_IN|XT_POLICY_MATCH_OUT))) { | 142 | if (!(info->flags & (XT_POLICY_MATCH_IN|XT_POLICY_MATCH_OUT))) { |
143 | printk(KERN_ERR "xt_policy: neither incoming nor " | 143 | printk(KERN_ERR "xt_policy: neither incoming nor " |
144 | "outgoing policy selected\n"); | 144 | "outgoing policy selected\n"); |
145 | return 0; | 145 | return false; |
146 | } | 146 | } |
147 | /* hook values are equal for IPv4 and IPv6 */ | 147 | /* hook values are equal for IPv4 and IPv6 */ |
148 | if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN) | 148 | if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN) |
149 | && info->flags & XT_POLICY_MATCH_OUT) { | 149 | && info->flags & XT_POLICY_MATCH_OUT) { |
150 | printk(KERN_ERR "xt_policy: output policy not valid in " | 150 | printk(KERN_ERR "xt_policy: output policy not valid in " |
151 | "PRE_ROUTING and INPUT\n"); | 151 | "PRE_ROUTING and INPUT\n"); |
152 | return 0; | 152 | return false; |
153 | } | 153 | } |
154 | if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT) | 154 | if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT) |
155 | && info->flags & XT_POLICY_MATCH_IN) { | 155 | && info->flags & XT_POLICY_MATCH_IN) { |
156 | printk(KERN_ERR "xt_policy: input policy not valid in " | 156 | printk(KERN_ERR "xt_policy: input policy not valid in " |
157 | "POST_ROUTING and OUTPUT\n"); | 157 | "POST_ROUTING and OUTPUT\n"); |
158 | return 0; | 158 | return false; |
159 | } | 159 | } |
160 | if (info->len > XT_POLICY_MAX_ELEM) { | 160 | if (info->len > XT_POLICY_MAX_ELEM) { |
161 | printk(KERN_ERR "xt_policy: too many policy elements\n"); | 161 | printk(KERN_ERR "xt_policy: too many policy elements\n"); |
162 | return 0; | 162 | return false; |
163 | } | 163 | } |
164 | return 1; | 164 | return true; |
165 | } | 165 | } |
166 | 166 | ||
167 | static struct xt_match xt_policy_match[] = { | 167 | static struct xt_match xt_policy_match[] __read_mostly = { |
168 | { | 168 | { |
169 | .name = "policy", | 169 | .name = "policy", |
170 | .family = AF_INET, | 170 | .family = AF_INET, |
diff --git a/net/netfilter/xt_quota.c b/net/netfilter/xt_quota.c index bfdde06ca0b7..dae97445b87b 100644 --- a/net/netfilter/xt_quota.c +++ b/net/netfilter/xt_quota.c | |||
@@ -16,19 +16,20 @@ MODULE_ALIAS("ip6t_quota"); | |||
16 | 16 | ||
17 | static DEFINE_SPINLOCK(quota_lock); | 17 | static DEFINE_SPINLOCK(quota_lock); |
18 | 18 | ||
19 | static int | 19 | static bool |
20 | match(const struct sk_buff *skb, | 20 | match(const struct sk_buff *skb, |
21 | const struct net_device *in, const struct net_device *out, | 21 | const struct net_device *in, const struct net_device *out, |
22 | const struct xt_match *match, const void *matchinfo, | 22 | const struct xt_match *match, const void *matchinfo, |
23 | int offset, unsigned int protoff, int *hotdrop) | 23 | int offset, unsigned int protoff, bool *hotdrop) |
24 | { | 24 | { |
25 | struct xt_quota_info *q = ((struct xt_quota_info *)matchinfo)->master; | 25 | struct xt_quota_info *q = |
26 | int ret = q->flags & XT_QUOTA_INVERT ? 1 : 0; | 26 | ((const struct xt_quota_info *)matchinfo)->master; |
27 | bool ret = q->flags & XT_QUOTA_INVERT; | ||
27 | 28 | ||
28 | spin_lock_bh("a_lock); | 29 | spin_lock_bh("a_lock); |
29 | if (q->quota >= skb->len) { | 30 | if (q->quota >= skb->len) { |
30 | q->quota -= skb->len; | 31 | q->quota -= skb->len; |
31 | ret ^= 1; | 32 | ret = !ret; |
32 | } else { | 33 | } else { |
33 | /* we do not allow even small packets from now on */ | 34 | /* we do not allow even small packets from now on */ |
34 | q->quota = 0; | 35 | q->quota = 0; |
@@ -38,21 +39,21 @@ match(const struct sk_buff *skb, | |||
38 | return ret; | 39 | return ret; |
39 | } | 40 | } |
40 | 41 | ||
41 | static int | 42 | static bool |
42 | checkentry(const char *tablename, const void *entry, | 43 | checkentry(const char *tablename, const void *entry, |
43 | const struct xt_match *match, void *matchinfo, | 44 | const struct xt_match *match, void *matchinfo, |
44 | unsigned int hook_mask) | 45 | unsigned int hook_mask) |
45 | { | 46 | { |
46 | struct xt_quota_info *q = (struct xt_quota_info *)matchinfo; | 47 | struct xt_quota_info *q = matchinfo; |
47 | 48 | ||
48 | if (q->flags & ~XT_QUOTA_MASK) | 49 | if (q->flags & ~XT_QUOTA_MASK) |
49 | return 0; | 50 | return false; |
50 | /* For SMP, we only want to use one set of counters. */ | 51 | /* For SMP, we only want to use one set of counters. */ |
51 | q->master = q; | 52 | q->master = q; |
52 | return 1; | 53 | return true; |
53 | } | 54 | } |
54 | 55 | ||
55 | static struct xt_match xt_quota_match[] = { | 56 | static struct xt_match xt_quota_match[] __read_mostly = { |
56 | { | 57 | { |
57 | .name = "quota", | 58 | .name = "quota", |
58 | .family = AF_INET, | 59 | .family = AF_INET, |
diff --git a/net/netfilter/xt_realm.c b/net/netfilter/xt_realm.c index c2017f8af9c4..cc3e76d77a99 100644 --- a/net/netfilter/xt_realm.c +++ b/net/netfilter/xt_realm.c | |||
@@ -21,7 +21,7 @@ MODULE_LICENSE("GPL"); | |||
21 | MODULE_DESCRIPTION("X_tables realm match"); | 21 | MODULE_DESCRIPTION("X_tables realm match"); |
22 | MODULE_ALIAS("ipt_realm"); | 22 | MODULE_ALIAS("ipt_realm"); |
23 | 23 | ||
24 | static int | 24 | static bool |
25 | match(const struct sk_buff *skb, | 25 | match(const struct sk_buff *skb, |
26 | const struct net_device *in, | 26 | const struct net_device *in, |
27 | const struct net_device *out, | 27 | const struct net_device *out, |
@@ -29,15 +29,15 @@ match(const struct sk_buff *skb, | |||
29 | const void *matchinfo, | 29 | const void *matchinfo, |
30 | int offset, | 30 | int offset, |
31 | unsigned int protoff, | 31 | unsigned int protoff, |
32 | int *hotdrop) | 32 | bool *hotdrop) |
33 | { | 33 | { |
34 | const struct xt_realm_info *info = matchinfo; | 34 | const struct xt_realm_info *info = matchinfo; |
35 | struct dst_entry *dst = skb->dst; | 35 | const struct dst_entry *dst = skb->dst; |
36 | 36 | ||
37 | return (info->id == (dst->tclassid & info->mask)) ^ info->invert; | 37 | return (info->id == (dst->tclassid & info->mask)) ^ info->invert; |
38 | } | 38 | } |
39 | 39 | ||
40 | static struct xt_match realm_match = { | 40 | static struct xt_match realm_match __read_mostly = { |
41 | .name = "realm", | 41 | .name = "realm", |
42 | .match = match, | 42 | .match = match, |
43 | .matchsize = sizeof(struct xt_realm_info), | 43 | .matchsize = sizeof(struct xt_realm_info), |
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c index f86d8d769d47..c002153b80ab 100644 --- a/net/netfilter/xt_sctp.c +++ b/net/netfilter/xt_sctp.c | |||
@@ -23,7 +23,7 @@ MODULE_ALIAS("ipt_sctp"); | |||
23 | #define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \ | 23 | #define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \ |
24 | || (!!((invflag) & (option)) ^ (cond))) | 24 | || (!!((invflag) & (option)) ^ (cond))) |
25 | 25 | ||
26 | static int | 26 | static bool |
27 | match_flags(const struct xt_sctp_flag_info *flag_info, | 27 | match_flags(const struct xt_sctp_flag_info *flag_info, |
28 | const int flag_count, | 28 | const int flag_count, |
29 | u_int8_t chunktype, | 29 | u_int8_t chunktype, |
@@ -31,23 +31,21 @@ match_flags(const struct xt_sctp_flag_info *flag_info, | |||
31 | { | 31 | { |
32 | int i; | 32 | int i; |
33 | 33 | ||
34 | for (i = 0; i < flag_count; i++) { | 34 | for (i = 0; i < flag_count; i++) |
35 | if (flag_info[i].chunktype == chunktype) { | 35 | if (flag_info[i].chunktype == chunktype) |
36 | return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag; | 36 | return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag; |
37 | } | ||
38 | } | ||
39 | 37 | ||
40 | return 1; | 38 | return true; |
41 | } | 39 | } |
42 | 40 | ||
43 | static inline int | 41 | static inline bool |
44 | match_packet(const struct sk_buff *skb, | 42 | match_packet(const struct sk_buff *skb, |
45 | unsigned int offset, | 43 | unsigned int offset, |
46 | const u_int32_t *chunkmap, | 44 | const u_int32_t *chunkmap, |
47 | int chunk_match_type, | 45 | int chunk_match_type, |
48 | const struct xt_sctp_flag_info *flag_info, | 46 | const struct xt_sctp_flag_info *flag_info, |
49 | const int flag_count, | 47 | const int flag_count, |
50 | int *hotdrop) | 48 | bool *hotdrop) |
51 | { | 49 | { |
52 | u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)]; | 50 | u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)]; |
53 | sctp_chunkhdr_t _sch, *sch; | 51 | sctp_chunkhdr_t _sch, *sch; |
@@ -56,16 +54,15 @@ match_packet(const struct sk_buff *skb, | |||
56 | int i = 0; | 54 | int i = 0; |
57 | #endif | 55 | #endif |
58 | 56 | ||
59 | if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) { | 57 | if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) |
60 | SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap); | 58 | SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap); |
61 | } | ||
62 | 59 | ||
63 | do { | 60 | do { |
64 | sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch); | 61 | sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch); |
65 | if (sch == NULL || sch->length == 0) { | 62 | if (sch == NULL || sch->length == 0) { |
66 | duprintf("Dropping invalid SCTP packet.\n"); | 63 | duprintf("Dropping invalid SCTP packet.\n"); |
67 | *hotdrop = 1; | 64 | *hotdrop = true; |
68 | return 0; | 65 | return false; |
69 | } | 66 | } |
70 | 67 | ||
71 | duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n", | 68 | duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n", |
@@ -80,28 +77,26 @@ match_packet(const struct sk_buff *skb, | |||
80 | case SCTP_CHUNK_MATCH_ANY: | 77 | case SCTP_CHUNK_MATCH_ANY: |
81 | if (match_flags(flag_info, flag_count, | 78 | if (match_flags(flag_info, flag_count, |
82 | sch->type, sch->flags)) { | 79 | sch->type, sch->flags)) { |
83 | return 1; | 80 | return true; |
84 | } | 81 | } |
85 | break; | 82 | break; |
86 | 83 | ||
87 | case SCTP_CHUNK_MATCH_ALL: | 84 | case SCTP_CHUNK_MATCH_ALL: |
88 | if (match_flags(flag_info, flag_count, | 85 | if (match_flags(flag_info, flag_count, |
89 | sch->type, sch->flags)) { | 86 | sch->type, sch->flags)) |
90 | SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch->type); | 87 | SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch->type); |
91 | } | ||
92 | break; | 88 | break; |
93 | 89 | ||
94 | case SCTP_CHUNK_MATCH_ONLY: | 90 | case SCTP_CHUNK_MATCH_ONLY: |
95 | if (!match_flags(flag_info, flag_count, | 91 | if (!match_flags(flag_info, flag_count, |
96 | sch->type, sch->flags)) { | 92 | sch->type, sch->flags)) |
97 | return 0; | 93 | return false; |
98 | } | ||
99 | break; | 94 | break; |
100 | } | 95 | } |
101 | } else { | 96 | } else { |
102 | switch (chunk_match_type) { | 97 | switch (chunk_match_type) { |
103 | case SCTP_CHUNK_MATCH_ONLY: | 98 | case SCTP_CHUNK_MATCH_ONLY: |
104 | return 0; | 99 | return false; |
105 | } | 100 | } |
106 | } | 101 | } |
107 | } while (offset < skb->len); | 102 | } while (offset < skb->len); |
@@ -110,16 +105,16 @@ match_packet(const struct sk_buff *skb, | |||
110 | case SCTP_CHUNK_MATCH_ALL: | 105 | case SCTP_CHUNK_MATCH_ALL: |
111 | return SCTP_CHUNKMAP_IS_CLEAR(chunkmap); | 106 | return SCTP_CHUNKMAP_IS_CLEAR(chunkmap); |
112 | case SCTP_CHUNK_MATCH_ANY: | 107 | case SCTP_CHUNK_MATCH_ANY: |
113 | return 0; | 108 | return false; |
114 | case SCTP_CHUNK_MATCH_ONLY: | 109 | case SCTP_CHUNK_MATCH_ONLY: |
115 | return 1; | 110 | return true; |
116 | } | 111 | } |
117 | 112 | ||
118 | /* This will never be reached, but required to stop compiler whine */ | 113 | /* This will never be reached, but required to stop compiler whine */ |
119 | return 0; | 114 | return false; |
120 | } | 115 | } |
121 | 116 | ||
122 | static int | 117 | static bool |
123 | match(const struct sk_buff *skb, | 118 | match(const struct sk_buff *skb, |
124 | const struct net_device *in, | 119 | const struct net_device *in, |
125 | const struct net_device *out, | 120 | const struct net_device *out, |
@@ -127,29 +122,29 @@ match(const struct sk_buff *skb, | |||
127 | const void *matchinfo, | 122 | const void *matchinfo, |
128 | int offset, | 123 | int offset, |
129 | unsigned int protoff, | 124 | unsigned int protoff, |
130 | int *hotdrop) | 125 | bool *hotdrop) |
131 | { | 126 | { |
132 | const struct xt_sctp_info *info = matchinfo; | 127 | const struct xt_sctp_info *info = matchinfo; |
133 | sctp_sctphdr_t _sh, *sh; | 128 | sctp_sctphdr_t _sh, *sh; |
134 | 129 | ||
135 | if (offset) { | 130 | if (offset) { |
136 | duprintf("Dropping non-first fragment.. FIXME\n"); | 131 | duprintf("Dropping non-first fragment.. FIXME\n"); |
137 | return 0; | 132 | return false; |
138 | } | 133 | } |
139 | 134 | ||
140 | sh = skb_header_pointer(skb, protoff, sizeof(_sh), &_sh); | 135 | sh = skb_header_pointer(skb, protoff, sizeof(_sh), &_sh); |
141 | if (sh == NULL) { | 136 | if (sh == NULL) { |
142 | duprintf("Dropping evil TCP offset=0 tinygram.\n"); | 137 | duprintf("Dropping evil TCP offset=0 tinygram.\n"); |
143 | *hotdrop = 1; | 138 | *hotdrop = true; |
144 | return 0; | 139 | return false; |
145 | } | 140 | } |
146 | duprintf("spt: %d\tdpt: %d\n", ntohs(sh->source), ntohs(sh->dest)); | 141 | duprintf("spt: %d\tdpt: %d\n", ntohs(sh->source), ntohs(sh->dest)); |
147 | 142 | ||
148 | return SCCHECK(((ntohs(sh->source) >= info->spts[0]) | 143 | return SCCHECK(ntohs(sh->source) >= info->spts[0] |
149 | && (ntohs(sh->source) <= info->spts[1])), | 144 | && ntohs(sh->source) <= info->spts[1], |
150 | XT_SCTP_SRC_PORTS, info->flags, info->invflags) | 145 | XT_SCTP_SRC_PORTS, info->flags, info->invflags) |
151 | && SCCHECK(((ntohs(sh->dest) >= info->dpts[0]) | 146 | && SCCHECK(ntohs(sh->dest) >= info->dpts[0] |
152 | && (ntohs(sh->dest) <= info->dpts[1])), | 147 | && ntohs(sh->dest) <= info->dpts[1], |
153 | XT_SCTP_DEST_PORTS, info->flags, info->invflags) | 148 | XT_SCTP_DEST_PORTS, info->flags, info->invflags) |
154 | && SCCHECK(match_packet(skb, protoff + sizeof (sctp_sctphdr_t), | 149 | && SCCHECK(match_packet(skb, protoff + sizeof (sctp_sctphdr_t), |
155 | info->chunkmap, info->chunk_match_type, | 150 | info->chunkmap, info->chunk_match_type, |
@@ -158,7 +153,7 @@ match(const struct sk_buff *skb, | |||
158 | XT_SCTP_CHUNK_TYPES, info->flags, info->invflags); | 153 | XT_SCTP_CHUNK_TYPES, info->flags, info->invflags); |
159 | } | 154 | } |
160 | 155 | ||
161 | static int | 156 | static bool |
162 | checkentry(const char *tablename, | 157 | checkentry(const char *tablename, |
163 | const void *inf, | 158 | const void *inf, |
164 | const struct xt_match *match, | 159 | const struct xt_match *match, |
@@ -177,7 +172,7 @@ checkentry(const char *tablename, | |||
177 | | SCTP_CHUNK_MATCH_ONLY))); | 172 | | SCTP_CHUNK_MATCH_ONLY))); |
178 | } | 173 | } |
179 | 174 | ||
180 | static struct xt_match xt_sctp_match[] = { | 175 | static struct xt_match xt_sctp_match[] __read_mostly = { |
181 | { | 176 | { |
182 | .name = "sctp", | 177 | .name = "sctp", |
183 | .family = AF_INET, | 178 | .family = AF_INET, |
diff --git a/net/netfilter/xt_state.c b/net/netfilter/xt_state.c index 149294f7df71..e0a528df19a7 100644 --- a/net/netfilter/xt_state.c +++ b/net/netfilter/xt_state.c | |||
@@ -20,7 +20,7 @@ MODULE_DESCRIPTION("ip[6]_tables connection tracking state match module"); | |||
20 | MODULE_ALIAS("ipt_state"); | 20 | MODULE_ALIAS("ipt_state"); |
21 | MODULE_ALIAS("ip6t_state"); | 21 | MODULE_ALIAS("ip6t_state"); |
22 | 22 | ||
23 | static int | 23 | static bool |
24 | match(const struct sk_buff *skb, | 24 | match(const struct sk_buff *skb, |
25 | const struct net_device *in, | 25 | const struct net_device *in, |
26 | const struct net_device *out, | 26 | const struct net_device *out, |
@@ -28,7 +28,7 @@ match(const struct sk_buff *skb, | |||
28 | const void *matchinfo, | 28 | const void *matchinfo, |
29 | int offset, | 29 | int offset, |
30 | unsigned int protoff, | 30 | unsigned int protoff, |
31 | int *hotdrop) | 31 | bool *hotdrop) |
32 | { | 32 | { |
33 | const struct xt_state_info *sinfo = matchinfo; | 33 | const struct xt_state_info *sinfo = matchinfo; |
34 | enum ip_conntrack_info ctinfo; | 34 | enum ip_conntrack_info ctinfo; |
@@ -44,18 +44,18 @@ match(const struct sk_buff *skb, | |||
44 | return (sinfo->statemask & statebit); | 44 | return (sinfo->statemask & statebit); |
45 | } | 45 | } |
46 | 46 | ||
47 | static int check(const char *tablename, | 47 | static bool check(const char *tablename, |
48 | const void *inf, | 48 | const void *inf, |
49 | const struct xt_match *match, | 49 | const struct xt_match *match, |
50 | void *matchinfo, | 50 | void *matchinfo, |
51 | unsigned int hook_mask) | 51 | unsigned int hook_mask) |
52 | { | 52 | { |
53 | if (nf_ct_l3proto_try_module_get(match->family) < 0) { | 53 | if (nf_ct_l3proto_try_module_get(match->family) < 0) { |
54 | printk(KERN_WARNING "can't load conntrack support for " | 54 | printk(KERN_WARNING "can't load conntrack support for " |
55 | "proto=%d\n", match->family); | 55 | "proto=%d\n", match->family); |
56 | return 0; | 56 | return false; |
57 | } | 57 | } |
58 | return 1; | 58 | return true; |
59 | } | 59 | } |
60 | 60 | ||
61 | static void | 61 | static void |
@@ -64,7 +64,7 @@ destroy(const struct xt_match *match, void *matchinfo) | |||
64 | nf_ct_l3proto_module_put(match->family); | 64 | nf_ct_l3proto_module_put(match->family); |
65 | } | 65 | } |
66 | 66 | ||
67 | static struct xt_match xt_state_match[] = { | 67 | static struct xt_match xt_state_match[] __read_mostly = { |
68 | { | 68 | { |
69 | .name = "state", | 69 | .name = "state", |
70 | .family = AF_INET, | 70 | .family = AF_INET, |
diff --git a/net/netfilter/xt_statistic.c b/net/netfilter/xt_statistic.c index 091a9f89f5d5..4089dae4e286 100644 --- a/net/netfilter/xt_statistic.c +++ b/net/netfilter/xt_statistic.c | |||
@@ -24,26 +24,26 @@ MODULE_ALIAS("ip6t_statistic"); | |||
24 | 24 | ||
25 | static DEFINE_SPINLOCK(nth_lock); | 25 | static DEFINE_SPINLOCK(nth_lock); |
26 | 26 | ||
27 | static int | 27 | static bool |
28 | match(const struct sk_buff *skb, | 28 | match(const struct sk_buff *skb, |
29 | const struct net_device *in, const struct net_device *out, | 29 | const struct net_device *in, const struct net_device *out, |
30 | const struct xt_match *match, const void *matchinfo, | 30 | const struct xt_match *match, const void *matchinfo, |
31 | int offset, unsigned int protoff, int *hotdrop) | 31 | int offset, unsigned int protoff, bool *hotdrop) |
32 | { | 32 | { |
33 | struct xt_statistic_info *info = (struct xt_statistic_info *)matchinfo; | 33 | struct xt_statistic_info *info = (struct xt_statistic_info *)matchinfo; |
34 | int ret = info->flags & XT_STATISTIC_INVERT ? 1 : 0; | 34 | bool ret = info->flags & XT_STATISTIC_INVERT; |
35 | 35 | ||
36 | switch (info->mode) { | 36 | switch (info->mode) { |
37 | case XT_STATISTIC_MODE_RANDOM: | 37 | case XT_STATISTIC_MODE_RANDOM: |
38 | if ((net_random() & 0x7FFFFFFF) < info->u.random.probability) | 38 | if ((net_random() & 0x7FFFFFFF) < info->u.random.probability) |
39 | ret ^= 1; | 39 | ret = !ret; |
40 | break; | 40 | break; |
41 | case XT_STATISTIC_MODE_NTH: | 41 | case XT_STATISTIC_MODE_NTH: |
42 | info = info->master; | 42 | info = info->master; |
43 | spin_lock_bh(&nth_lock); | 43 | spin_lock_bh(&nth_lock); |
44 | if (info->u.nth.count++ == info->u.nth.every) { | 44 | if (info->u.nth.count++ == info->u.nth.every) { |
45 | info->u.nth.count = 0; | 45 | info->u.nth.count = 0; |
46 | ret ^= 1; | 46 | ret = !ret; |
47 | } | 47 | } |
48 | spin_unlock_bh(&nth_lock); | 48 | spin_unlock_bh(&nth_lock); |
49 | break; | 49 | break; |
@@ -52,21 +52,21 @@ match(const struct sk_buff *skb, | |||
52 | return ret; | 52 | return ret; |
53 | } | 53 | } |
54 | 54 | ||
55 | static int | 55 | static bool |
56 | checkentry(const char *tablename, const void *entry, | 56 | checkentry(const char *tablename, const void *entry, |
57 | const struct xt_match *match, void *matchinfo, | 57 | const struct xt_match *match, void *matchinfo, |
58 | unsigned int hook_mask) | 58 | unsigned int hook_mask) |
59 | { | 59 | { |
60 | struct xt_statistic_info *info = (struct xt_statistic_info *)matchinfo; | 60 | struct xt_statistic_info *info = matchinfo; |
61 | 61 | ||
62 | if (info->mode > XT_STATISTIC_MODE_MAX || | 62 | if (info->mode > XT_STATISTIC_MODE_MAX || |
63 | info->flags & ~XT_STATISTIC_MASK) | 63 | info->flags & ~XT_STATISTIC_MASK) |
64 | return 0; | 64 | return false; |
65 | info->master = info; | 65 | info->master = info; |
66 | return 1; | 66 | return true; |
67 | } | 67 | } |
68 | 68 | ||
69 | static struct xt_match xt_statistic_match[] = { | 69 | static struct xt_match xt_statistic_match[] __read_mostly = { |
70 | { | 70 | { |
71 | .name = "statistic", | 71 | .name = "statistic", |
72 | .family = AF_INET, | 72 | .family = AF_INET, |
diff --git a/net/netfilter/xt_string.c b/net/netfilter/xt_string.c index 999a005dbd0c..864133442cda 100644 --- a/net/netfilter/xt_string.c +++ b/net/netfilter/xt_string.c | |||
@@ -21,14 +21,14 @@ MODULE_LICENSE("GPL"); | |||
21 | MODULE_ALIAS("ipt_string"); | 21 | MODULE_ALIAS("ipt_string"); |
22 | MODULE_ALIAS("ip6t_string"); | 22 | MODULE_ALIAS("ip6t_string"); |
23 | 23 | ||
24 | static int match(const struct sk_buff *skb, | 24 | static bool match(const struct sk_buff *skb, |
25 | const struct net_device *in, | 25 | const struct net_device *in, |
26 | const struct net_device *out, | 26 | const struct net_device *out, |
27 | const struct xt_match *match, | 27 | const struct xt_match *match, |
28 | const void *matchinfo, | 28 | const void *matchinfo, |
29 | int offset, | 29 | int offset, |
30 | unsigned int protoff, | 30 | unsigned int protoff, |
31 | int *hotdrop) | 31 | bool *hotdrop) |
32 | { | 32 | { |
33 | const struct xt_string_info *conf = matchinfo; | 33 | const struct xt_string_info *conf = matchinfo; |
34 | struct ts_state state; | 34 | struct ts_state state; |
@@ -42,30 +42,30 @@ static int match(const struct sk_buff *skb, | |||
42 | 42 | ||
43 | #define STRING_TEXT_PRIV(m) ((struct xt_string_info *) m) | 43 | #define STRING_TEXT_PRIV(m) ((struct xt_string_info *) m) |
44 | 44 | ||
45 | static int checkentry(const char *tablename, | 45 | static bool checkentry(const char *tablename, |
46 | const void *ip, | 46 | const void *ip, |
47 | const struct xt_match *match, | 47 | const struct xt_match *match, |
48 | void *matchinfo, | 48 | void *matchinfo, |
49 | unsigned int hook_mask) | 49 | unsigned int hook_mask) |
50 | { | 50 | { |
51 | struct xt_string_info *conf = matchinfo; | 51 | struct xt_string_info *conf = matchinfo; |
52 | struct ts_config *ts_conf; | 52 | struct ts_config *ts_conf; |
53 | 53 | ||
54 | /* Damn, can't handle this case properly with iptables... */ | 54 | /* Damn, can't handle this case properly with iptables... */ |
55 | if (conf->from_offset > conf->to_offset) | 55 | if (conf->from_offset > conf->to_offset) |
56 | return 0; | 56 | return false; |
57 | if (conf->algo[XT_STRING_MAX_ALGO_NAME_SIZE - 1] != '\0') | 57 | if (conf->algo[XT_STRING_MAX_ALGO_NAME_SIZE - 1] != '\0') |
58 | return 0; | 58 | return false; |
59 | if (conf->patlen > XT_STRING_MAX_PATTERN_SIZE) | 59 | if (conf->patlen > XT_STRING_MAX_PATTERN_SIZE) |
60 | return 0; | 60 | return false; |
61 | ts_conf = textsearch_prepare(conf->algo, conf->pattern, conf->patlen, | 61 | ts_conf = textsearch_prepare(conf->algo, conf->pattern, conf->patlen, |
62 | GFP_KERNEL, TS_AUTOLOAD); | 62 | GFP_KERNEL, TS_AUTOLOAD); |
63 | if (IS_ERR(ts_conf)) | 63 | if (IS_ERR(ts_conf)) |
64 | return 0; | 64 | return false; |
65 | 65 | ||
66 | conf->config = ts_conf; | 66 | conf->config = ts_conf; |
67 | 67 | ||
68 | return 1; | 68 | return true; |
69 | } | 69 | } |
70 | 70 | ||
71 | static void destroy(const struct xt_match *match, void *matchinfo) | 71 | static void destroy(const struct xt_match *match, void *matchinfo) |
@@ -73,7 +73,7 @@ static void destroy(const struct xt_match *match, void *matchinfo) | |||
73 | textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config); | 73 | textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config); |
74 | } | 74 | } |
75 | 75 | ||
76 | static struct xt_match xt_string_match[] = { | 76 | static struct xt_match xt_string_match[] __read_mostly = { |
77 | { | 77 | { |
78 | .name = "string", | 78 | .name = "string", |
79 | .family = AF_INET, | 79 | .family = AF_INET, |
diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c index 80571d0749f7..cd5f6d758c68 100644 --- a/net/netfilter/xt_tcpmss.c +++ b/net/netfilter/xt_tcpmss.c | |||
@@ -23,7 +23,7 @@ MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); | |||
23 | MODULE_DESCRIPTION("iptables TCP MSS match module"); | 23 | MODULE_DESCRIPTION("iptables TCP MSS match module"); |
24 | MODULE_ALIAS("ipt_tcpmss"); | 24 | MODULE_ALIAS("ipt_tcpmss"); |
25 | 25 | ||
26 | static int | 26 | static bool |
27 | match(const struct sk_buff *skb, | 27 | match(const struct sk_buff *skb, |
28 | const struct net_device *in, | 28 | const struct net_device *in, |
29 | const struct net_device *out, | 29 | const struct net_device *out, |
@@ -31,7 +31,7 @@ match(const struct sk_buff *skb, | |||
31 | const void *matchinfo, | 31 | const void *matchinfo, |
32 | int offset, | 32 | int offset, |
33 | unsigned int protoff, | 33 | unsigned int protoff, |
34 | int *hotdrop) | 34 | bool *hotdrop) |
35 | { | 35 | { |
36 | const struct xt_tcpmss_match_info *info = matchinfo; | 36 | const struct xt_tcpmss_match_info *info = matchinfo; |
37 | struct tcphdr _tcph, *th; | 37 | struct tcphdr _tcph, *th; |
@@ -77,11 +77,11 @@ out: | |||
77 | return info->invert; | 77 | return info->invert; |
78 | 78 | ||
79 | dropit: | 79 | dropit: |
80 | *hotdrop = 1; | 80 | *hotdrop = true; |
81 | return 0; | 81 | return false; |
82 | } | 82 | } |
83 | 83 | ||
84 | static struct xt_match xt_tcpmss_match[] = { | 84 | static struct xt_match xt_tcpmss_match[] __read_mostly = { |
85 | { | 85 | { |
86 | .name = "tcpmss", | 86 | .name = "tcpmss", |
87 | .family = AF_INET, | 87 | .family = AF_INET, |
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c index 46414b562a19..ab7d845224fc 100644 --- a/net/netfilter/xt_tcpudp.c +++ b/net/netfilter/xt_tcpudp.c | |||
@@ -27,22 +27,19 @@ MODULE_ALIAS("ip6t_tcp"); | |||
27 | 27 | ||
28 | 28 | ||
29 | /* Returns 1 if the port is matched by the range, 0 otherwise */ | 29 | /* Returns 1 if the port is matched by the range, 0 otherwise */ |
30 | static inline int | 30 | static inline bool |
31 | port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert) | 31 | port_match(u_int16_t min, u_int16_t max, u_int16_t port, bool invert) |
32 | { | 32 | { |
33 | int ret; | 33 | return (port >= min && port <= max) ^ invert; |
34 | |||
35 | ret = (port >= min && port <= max) ^ invert; | ||
36 | return ret; | ||
37 | } | 34 | } |
38 | 35 | ||
39 | static int | 36 | static bool |
40 | tcp_find_option(u_int8_t option, | 37 | tcp_find_option(u_int8_t option, |
41 | const struct sk_buff *skb, | 38 | const struct sk_buff *skb, |
42 | unsigned int protoff, | 39 | unsigned int protoff, |
43 | unsigned int optlen, | 40 | unsigned int optlen, |
44 | int invert, | 41 | bool invert, |
45 | int *hotdrop) | 42 | bool *hotdrop) |
46 | { | 43 | { |
47 | /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */ | 44 | /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */ |
48 | u_int8_t _opt[60 - sizeof(struct tcphdr)], *op; | 45 | u_int8_t _opt[60 - sizeof(struct tcphdr)], *op; |
@@ -57,8 +54,8 @@ tcp_find_option(u_int8_t option, | |||
57 | op = skb_header_pointer(skb, protoff + sizeof(struct tcphdr), | 54 | op = skb_header_pointer(skb, protoff + sizeof(struct tcphdr), |
58 | optlen, _opt); | 55 | optlen, _opt); |
59 | if (op == NULL) { | 56 | if (op == NULL) { |
60 | *hotdrop = 1; | 57 | *hotdrop = true; |
61 | return 0; | 58 | return false; |
62 | } | 59 | } |
63 | 60 | ||
64 | for (i = 0; i < optlen; ) { | 61 | for (i = 0; i < optlen; ) { |
@@ -70,7 +67,7 @@ tcp_find_option(u_int8_t option, | |||
70 | return invert; | 67 | return invert; |
71 | } | 68 | } |
72 | 69 | ||
73 | static int | 70 | static bool |
74 | tcp_match(const struct sk_buff *skb, | 71 | tcp_match(const struct sk_buff *skb, |
75 | const struct net_device *in, | 72 | const struct net_device *in, |
76 | const struct net_device *out, | 73 | const struct net_device *out, |
@@ -78,7 +75,7 @@ tcp_match(const struct sk_buff *skb, | |||
78 | const void *matchinfo, | 75 | const void *matchinfo, |
79 | int offset, | 76 | int offset, |
80 | unsigned int protoff, | 77 | unsigned int protoff, |
81 | int *hotdrop) | 78 | bool *hotdrop) |
82 | { | 79 | { |
83 | struct tcphdr _tcph, *th; | 80 | struct tcphdr _tcph, *th; |
84 | const struct xt_tcp *tcpinfo = matchinfo; | 81 | const struct xt_tcp *tcpinfo = matchinfo; |
@@ -92,51 +89,51 @@ tcp_match(const struct sk_buff *skb, | |||
92 | */ | 89 | */ |
93 | if (offset == 1) { | 90 | if (offset == 1) { |
94 | duprintf("Dropping evil TCP offset=1 frag.\n"); | 91 | duprintf("Dropping evil TCP offset=1 frag.\n"); |
95 | *hotdrop = 1; | 92 | *hotdrop = true; |
96 | } | 93 | } |
97 | /* Must not be a fragment. */ | 94 | /* Must not be a fragment. */ |
98 | return 0; | 95 | return false; |
99 | } | 96 | } |
100 | 97 | ||
101 | #define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg)) | 98 | #define FWINVTCP(bool, invflg) ((bool) ^ !!(tcpinfo->invflags & (invflg))) |
102 | 99 | ||
103 | th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); | 100 | th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); |
104 | if (th == NULL) { | 101 | if (th == NULL) { |
105 | /* We've been asked to examine this packet, and we | 102 | /* We've been asked to examine this packet, and we |
106 | can't. Hence, no choice but to drop. */ | 103 | can't. Hence, no choice but to drop. */ |
107 | duprintf("Dropping evil TCP offset=0 tinygram.\n"); | 104 | duprintf("Dropping evil TCP offset=0 tinygram.\n"); |
108 | *hotdrop = 1; | 105 | *hotdrop = true; |
109 | return 0; | 106 | return false; |
110 | } | 107 | } |
111 | 108 | ||
112 | if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1], | 109 | if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1], |
113 | ntohs(th->source), | 110 | ntohs(th->source), |
114 | !!(tcpinfo->invflags & XT_TCP_INV_SRCPT))) | 111 | !!(tcpinfo->invflags & XT_TCP_INV_SRCPT))) |
115 | return 0; | 112 | return false; |
116 | if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1], | 113 | if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1], |
117 | ntohs(th->dest), | 114 | ntohs(th->dest), |
118 | !!(tcpinfo->invflags & XT_TCP_INV_DSTPT))) | 115 | !!(tcpinfo->invflags & XT_TCP_INV_DSTPT))) |
119 | return 0; | 116 | return false; |
120 | if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask) | 117 | if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask) |
121 | == tcpinfo->flg_cmp, | 118 | == tcpinfo->flg_cmp, |
122 | XT_TCP_INV_FLAGS)) | 119 | XT_TCP_INV_FLAGS)) |
123 | return 0; | 120 | return false; |
124 | if (tcpinfo->option) { | 121 | if (tcpinfo->option) { |
125 | if (th->doff * 4 < sizeof(_tcph)) { | 122 | if (th->doff * 4 < sizeof(_tcph)) { |
126 | *hotdrop = 1; | 123 | *hotdrop = true; |
127 | return 0; | 124 | return false; |
128 | } | 125 | } |
129 | if (!tcp_find_option(tcpinfo->option, skb, protoff, | 126 | if (!tcp_find_option(tcpinfo->option, skb, protoff, |
130 | th->doff*4 - sizeof(_tcph), | 127 | th->doff*4 - sizeof(_tcph), |
131 | tcpinfo->invflags & XT_TCP_INV_OPTION, | 128 | tcpinfo->invflags & XT_TCP_INV_OPTION, |
132 | hotdrop)) | 129 | hotdrop)) |
133 | return 0; | 130 | return false; |
134 | } | 131 | } |
135 | return 1; | 132 | return true; |
136 | } | 133 | } |
137 | 134 | ||
138 | /* Called when user tries to insert an entry of this type. */ | 135 | /* Called when user tries to insert an entry of this type. */ |
139 | static int | 136 | static bool |
140 | tcp_checkentry(const char *tablename, | 137 | tcp_checkentry(const char *tablename, |
141 | const void *info, | 138 | const void *info, |
142 | const struct xt_match *match, | 139 | const struct xt_match *match, |
@@ -149,7 +146,7 @@ tcp_checkentry(const char *tablename, | |||
149 | return !(tcpinfo->invflags & ~XT_TCP_INV_MASK); | 146 | return !(tcpinfo->invflags & ~XT_TCP_INV_MASK); |
150 | } | 147 | } |
151 | 148 | ||
152 | static int | 149 | static bool |
153 | udp_match(const struct sk_buff *skb, | 150 | udp_match(const struct sk_buff *skb, |
154 | const struct net_device *in, | 151 | const struct net_device *in, |
155 | const struct net_device *out, | 152 | const struct net_device *out, |
@@ -157,22 +154,22 @@ udp_match(const struct sk_buff *skb, | |||
157 | const void *matchinfo, | 154 | const void *matchinfo, |
158 | int offset, | 155 | int offset, |
159 | unsigned int protoff, | 156 | unsigned int protoff, |
160 | int *hotdrop) | 157 | bool *hotdrop) |
161 | { | 158 | { |
162 | struct udphdr _udph, *uh; | 159 | struct udphdr _udph, *uh; |
163 | const struct xt_udp *udpinfo = matchinfo; | 160 | const struct xt_udp *udpinfo = matchinfo; |
164 | 161 | ||
165 | /* Must not be a fragment. */ | 162 | /* Must not be a fragment. */ |
166 | if (offset) | 163 | if (offset) |
167 | return 0; | 164 | return false; |
168 | 165 | ||
169 | uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph); | 166 | uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph); |
170 | if (uh == NULL) { | 167 | if (uh == NULL) { |
171 | /* We've been asked to examine this packet, and we | 168 | /* We've been asked to examine this packet, and we |
172 | can't. Hence, no choice but to drop. */ | 169 | can't. Hence, no choice but to drop. */ |
173 | duprintf("Dropping evil UDP tinygram.\n"); | 170 | duprintf("Dropping evil UDP tinygram.\n"); |
174 | *hotdrop = 1; | 171 | *hotdrop = true; |
175 | return 0; | 172 | return false; |
176 | } | 173 | } |
177 | 174 | ||
178 | return port_match(udpinfo->spts[0], udpinfo->spts[1], | 175 | return port_match(udpinfo->spts[0], udpinfo->spts[1], |
@@ -184,7 +181,7 @@ udp_match(const struct sk_buff *skb, | |||
184 | } | 181 | } |
185 | 182 | ||
186 | /* Called when user tries to insert an entry of this type. */ | 183 | /* Called when user tries to insert an entry of this type. */ |
187 | static int | 184 | static bool |
188 | udp_checkentry(const char *tablename, | 185 | udp_checkentry(const char *tablename, |
189 | const void *info, | 186 | const void *info, |
190 | const struct xt_match *match, | 187 | const struct xt_match *match, |
@@ -197,7 +194,7 @@ udp_checkentry(const char *tablename, | |||
197 | return !(udpinfo->invflags & ~XT_UDP_INV_MASK); | 194 | return !(udpinfo->invflags & ~XT_UDP_INV_MASK); |
198 | } | 195 | } |
199 | 196 | ||
200 | static struct xt_match xt_tcpudp_match[] = { | 197 | static struct xt_match xt_tcpudp_match[] __read_mostly = { |
201 | { | 198 | { |
202 | .name = "tcp", | 199 | .name = "tcp", |
203 | .family = AF_INET, | 200 | .family = AF_INET, |
diff --git a/net/netfilter/xt_u32.c b/net/netfilter/xt_u32.c new file mode 100644 index 000000000000..04b677ae8dae --- /dev/null +++ b/net/netfilter/xt_u32.c | |||
@@ -0,0 +1,135 @@ | |||
1 | /* | ||
2 | * xt_u32 - kernel module to match u32 packet content | ||
3 | * | ||
4 | * Original author: Don Cohen <don@isis.cs3-inc.com> | ||
5 | * © Jan Engelhardt <jengelh@gmx.de>, 2007 | ||
6 | */ | ||
7 | |||
8 | #include <linux/module.h> | ||
9 | #include <linux/moduleparam.h> | ||
10 | #include <linux/spinlock.h> | ||
11 | #include <linux/skbuff.h> | ||
12 | #include <linux/types.h> | ||
13 | #include <linux/netfilter/x_tables.h> | ||
14 | #include <linux/netfilter/xt_u32.h> | ||
15 | |||
16 | static bool u32_match_it(const struct xt_u32 *data, | ||
17 | const struct sk_buff *skb) | ||
18 | { | ||
19 | const struct xt_u32_test *ct; | ||
20 | unsigned int testind; | ||
21 | unsigned int nnums; | ||
22 | unsigned int nvals; | ||
23 | unsigned int i; | ||
24 | u_int32_t pos; | ||
25 | u_int32_t val; | ||
26 | u_int32_t at; | ||
27 | int ret; | ||
28 | |||
29 | /* | ||
30 | * Small example: "0 >> 28 == 4 && 8 & 0xFF0000 >> 16 = 6, 17" | ||
31 | * (=IPv4 and (TCP or UDP)). Outer loop runs over the "&&" operands. | ||
32 | */ | ||
33 | for (testind = 0; testind < data->ntests; ++testind) { | ||
34 | ct = &data->tests[testind]; | ||
35 | at = 0; | ||
36 | pos = ct->location[0].number; | ||
37 | |||
38 | if (skb->len < 4 || pos > skb->len - 4); | ||
39 | return false; | ||
40 | |||
41 | ret = skb_copy_bits(skb, pos, &val, sizeof(val)); | ||
42 | BUG_ON(ret < 0); | ||
43 | val = ntohl(val); | ||
44 | nnums = ct->nnums; | ||
45 | |||
46 | /* Inner loop runs over "&", "<<", ">>" and "@" operands */ | ||
47 | for (i = 1; i < nnums; ++i) { | ||
48 | u_int32_t number = ct->location[i].number; | ||
49 | switch (ct->location[i].nextop) { | ||
50 | case XT_U32_AND: | ||
51 | val &= number; | ||
52 | break; | ||
53 | case XT_U32_LEFTSH: | ||
54 | val <<= number; | ||
55 | break; | ||
56 | case XT_U32_RIGHTSH: | ||
57 | val >>= number; | ||
58 | break; | ||
59 | case XT_U32_AT: | ||
60 | if (at + val < at) | ||
61 | return false; | ||
62 | at += val; | ||
63 | pos = number; | ||
64 | if (at + 4 < at || skb->len < at + 4 || | ||
65 | pos > skb->len - at - 4) | ||
66 | return false; | ||
67 | |||
68 | ret = skb_copy_bits(skb, at + pos, &val, | ||
69 | sizeof(val)); | ||
70 | BUG_ON(ret < 0); | ||
71 | val = ntohl(val); | ||
72 | break; | ||
73 | } | ||
74 | } | ||
75 | |||
76 | /* Run over the "," and ":" operands */ | ||
77 | nvals = ct->nvalues; | ||
78 | for (i = 0; i < nvals; ++i) | ||
79 | if (ct->value[i].min <= val && val <= ct->value[i].max) | ||
80 | break; | ||
81 | |||
82 | if (i >= ct->nvalues) | ||
83 | return false; | ||
84 | } | ||
85 | |||
86 | return true; | ||
87 | } | ||
88 | |||
89 | static bool u32_match(const struct sk_buff *skb, | ||
90 | const struct net_device *in, | ||
91 | const struct net_device *out, | ||
92 | const struct xt_match *match, const void *matchinfo, | ||
93 | int offset, unsigned int protoff, bool *hotdrop) | ||
94 | { | ||
95 | const struct xt_u32 *data = matchinfo; | ||
96 | bool ret; | ||
97 | |||
98 | ret = u32_match_it(data, skb); | ||
99 | return ret ^ data->invert; | ||
100 | } | ||
101 | |||
102 | static struct xt_match u32_reg[] __read_mostly = { | ||
103 | { | ||
104 | .name = "u32", | ||
105 | .family = AF_INET, | ||
106 | .match = u32_match, | ||
107 | .matchsize = sizeof(struct xt_u32), | ||
108 | .me = THIS_MODULE, | ||
109 | }, | ||
110 | { | ||
111 | .name = "u32", | ||
112 | .family = AF_INET6, | ||
113 | .match = u32_match, | ||
114 | .matchsize = sizeof(struct xt_u32), | ||
115 | .me = THIS_MODULE, | ||
116 | }, | ||
117 | }; | ||
118 | |||
119 | static int __init xt_u32_init(void) | ||
120 | { | ||
121 | return xt_register_matches(u32_reg, ARRAY_SIZE(u32_reg)); | ||
122 | } | ||
123 | |||
124 | static void __exit xt_u32_exit(void) | ||
125 | { | ||
126 | xt_unregister_matches(u32_reg, ARRAY_SIZE(u32_reg)); | ||
127 | } | ||
128 | |||
129 | module_init(xt_u32_init); | ||
130 | module_exit(xt_u32_exit); | ||
131 | MODULE_AUTHOR("Jan Engelhardt <jengelh@gmx.de>"); | ||
132 | MODULE_DESCRIPTION("netfilter u32 match module"); | ||
133 | MODULE_LICENSE("GPL"); | ||
134 | MODULE_ALIAS("ipt_u32"); | ||
135 | MODULE_ALIAS("ip6t_u32"); | ||
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c index 42f12bd65964..89dcc485653b 100644 --- a/net/netlabel/netlabel_user.c +++ b/net/netlabel/netlabel_user.c | |||
@@ -46,10 +46,6 @@ | |||
46 | #include "netlabel_cipso_v4.h" | 46 | #include "netlabel_cipso_v4.h" |
47 | #include "netlabel_user.h" | 47 | #include "netlabel_user.h" |
48 | 48 | ||
49 | /* do not do any auditing if audit_enabled == 0, see kernel/audit.c for | ||
50 | * details */ | ||
51 | extern int audit_enabled; | ||
52 | |||
53 | /* | 49 | /* |
54 | * NetLabel NETLINK Setup Functions | 50 | * NetLabel NETLINK Setup Functions |
55 | */ | 51 | */ |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 1f15821c8da4..a3c8e692f493 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -1713,7 +1713,7 @@ static int netlink_seq_show(struct seq_file *seq, void *v) | |||
1713 | return 0; | 1713 | return 0; |
1714 | } | 1714 | } |
1715 | 1715 | ||
1716 | static struct seq_operations netlink_seq_ops = { | 1716 | static const struct seq_operations netlink_seq_ops = { |
1717 | .start = netlink_seq_start, | 1717 | .start = netlink_seq_start, |
1718 | .next = netlink_seq_next, | 1718 | .next = netlink_seq_next, |
1719 | .stop = netlink_seq_stop, | 1719 | .stop = netlink_seq_stop, |
diff --git a/net/netlink/attr.c b/net/netlink/attr.c index c591212793ee..e4d7bed99c2e 100644 --- a/net/netlink/attr.c +++ b/net/netlink/attr.c | |||
@@ -72,6 +72,17 @@ static int validate_nla(struct nlattr *nla, int maxtype, | |||
72 | return -ERANGE; | 72 | return -ERANGE; |
73 | break; | 73 | break; |
74 | 74 | ||
75 | case NLA_NESTED_COMPAT: | ||
76 | if (attrlen < pt->len) | ||
77 | return -ERANGE; | ||
78 | if (attrlen < NLA_ALIGN(pt->len)) | ||
79 | break; | ||
80 | if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN) | ||
81 | return -ERANGE; | ||
82 | nla = nla_data(nla) + NLA_ALIGN(pt->len); | ||
83 | if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN + nla_len(nla)) | ||
84 | return -ERANGE; | ||
85 | break; | ||
75 | default: | 86 | default: |
76 | if (pt->len) | 87 | if (pt->len) |
77 | minlen = pt->len; | 88 | minlen = pt->len; |
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 5d4a26c2aa0c..5d66490dd290 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c | |||
@@ -1328,7 +1328,7 @@ static int nr_info_show(struct seq_file *seq, void *v) | |||
1328 | return 0; | 1328 | return 0; |
1329 | } | 1329 | } |
1330 | 1330 | ||
1331 | static struct seq_operations nr_info_seqops = { | 1331 | static const struct seq_operations nr_info_seqops = { |
1332 | .start = nr_info_start, | 1332 | .start = nr_info_start, |
1333 | .next = nr_info_next, | 1333 | .next = nr_info_next, |
1334 | .stop = nr_info_stop, | 1334 | .stop = nr_info_stop, |
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c index 2f76e062609d..24fe4a66d297 100644 --- a/net/netrom/nr_route.c +++ b/net/netrom/nr_route.c | |||
@@ -922,7 +922,7 @@ static int nr_node_show(struct seq_file *seq, void *v) | |||
922 | return 0; | 922 | return 0; |
923 | } | 923 | } |
924 | 924 | ||
925 | static struct seq_operations nr_node_seqops = { | 925 | static const struct seq_operations nr_node_seqops = { |
926 | .start = nr_node_start, | 926 | .start = nr_node_start, |
927 | .next = nr_node_next, | 927 | .next = nr_node_next, |
928 | .stop = nr_node_stop, | 928 | .stop = nr_node_stop, |
@@ -1006,7 +1006,7 @@ static int nr_neigh_show(struct seq_file *seq, void *v) | |||
1006 | return 0; | 1006 | return 0; |
1007 | } | 1007 | } |
1008 | 1008 | ||
1009 | static struct seq_operations nr_neigh_seqops = { | 1009 | static const struct seq_operations nr_neigh_seqops = { |
1010 | .start = nr_neigh_start, | 1010 | .start = nr_neigh_start, |
1011 | .next = nr_neigh_next, | 1011 | .next = nr_neigh_next, |
1012 | .stop = nr_neigh_stop, | 1012 | .stop = nr_neigh_stop, |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index f8b83014ccca..7c27bd389b7e 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -1928,7 +1928,7 @@ static int packet_seq_show(struct seq_file *seq, void *v) | |||
1928 | return 0; | 1928 | return 0; |
1929 | } | 1929 | } |
1930 | 1930 | ||
1931 | static struct seq_operations packet_seq_ops = { | 1931 | static const struct seq_operations packet_seq_ops = { |
1932 | .start = packet_seq_start, | 1932 | .start = packet_seq_start, |
1933 | .next = packet_seq_next, | 1933 | .next = packet_seq_next, |
1934 | .stop = packet_seq_stop, | 1934 | .stop = packet_seq_stop, |
diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c index e5c840c30284..230e35c59786 100644 --- a/net/rfkill/rfkill-input.c +++ b/net/rfkill/rfkill-input.c | |||
@@ -55,7 +55,7 @@ static void rfkill_task_handler(struct work_struct *work) | |||
55 | 55 | ||
56 | static void rfkill_schedule_toggle(struct rfkill_task *task) | 56 | static void rfkill_schedule_toggle(struct rfkill_task *task) |
57 | { | 57 | { |
58 | unsigned int flags; | 58 | unsigned long flags; |
59 | 59 | ||
60 | spin_lock_irqsave(&task->lock, flags); | 60 | spin_lock_irqsave(&task->lock, flags); |
61 | 61 | ||
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index d476c43d5216..f4d3aba00800 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c | |||
@@ -1454,7 +1454,7 @@ static int rose_info_show(struct seq_file *seq, void *v) | |||
1454 | return 0; | 1454 | return 0; |
1455 | } | 1455 | } |
1456 | 1456 | ||
1457 | static struct seq_operations rose_info_seqops = { | 1457 | static const struct seq_operations rose_info_seqops = { |
1458 | .start = rose_info_start, | 1458 | .start = rose_info_start, |
1459 | .next = rose_info_next, | 1459 | .next = rose_info_next, |
1460 | .stop = rose_info_stop, | 1460 | .stop = rose_info_stop, |
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index 929a784a86d7..bbcbad1da0d0 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c | |||
@@ -1118,7 +1118,7 @@ static int rose_node_show(struct seq_file *seq, void *v) | |||
1118 | return 0; | 1118 | return 0; |
1119 | } | 1119 | } |
1120 | 1120 | ||
1121 | static struct seq_operations rose_node_seqops = { | 1121 | static const struct seq_operations rose_node_seqops = { |
1122 | .start = rose_node_start, | 1122 | .start = rose_node_start, |
1123 | .next = rose_node_next, | 1123 | .next = rose_node_next, |
1124 | .stop = rose_node_stop, | 1124 | .stop = rose_node_stop, |
@@ -1200,7 +1200,7 @@ static int rose_neigh_show(struct seq_file *seq, void *v) | |||
1200 | } | 1200 | } |
1201 | 1201 | ||
1202 | 1202 | ||
1203 | static struct seq_operations rose_neigh_seqops = { | 1203 | static const struct seq_operations rose_neigh_seqops = { |
1204 | .start = rose_neigh_start, | 1204 | .start = rose_neigh_start, |
1205 | .next = rose_neigh_next, | 1205 | .next = rose_neigh_next, |
1206 | .stop = rose_neigh_stop, | 1206 | .stop = rose_neigh_stop, |
@@ -1284,7 +1284,7 @@ static int rose_route_show(struct seq_file *seq, void *v) | |||
1284 | return 0; | 1284 | return 0; |
1285 | } | 1285 | } |
1286 | 1286 | ||
1287 | static struct seq_operations rose_route_seqops = { | 1287 | static const struct seq_operations rose_route_seqops = { |
1288 | .start = rose_route_start, | 1288 | .start = rose_route_start, |
1289 | .next = rose_route_next, | 1289 | .next = rose_route_next, |
1290 | .stop = rose_route_stop, | 1290 | .stop = rose_route_stop, |
diff --git a/net/rxrpc/ar-proc.c b/net/rxrpc/ar-proc.c index 1c0be0e77b16..2e83ce325d15 100644 --- a/net/rxrpc/ar-proc.c +++ b/net/rxrpc/ar-proc.c | |||
@@ -30,31 +30,13 @@ static const char *rxrpc_conn_states[] = { | |||
30 | */ | 30 | */ |
31 | static void *rxrpc_call_seq_start(struct seq_file *seq, loff_t *_pos) | 31 | static void *rxrpc_call_seq_start(struct seq_file *seq, loff_t *_pos) |
32 | { | 32 | { |
33 | struct list_head *_p; | ||
34 | loff_t pos = *_pos; | ||
35 | |||
36 | read_lock(&rxrpc_call_lock); | 33 | read_lock(&rxrpc_call_lock); |
37 | if (!pos) | 34 | return seq_list_start_head(&rxrpc_calls, *_pos); |
38 | return SEQ_START_TOKEN; | ||
39 | pos--; | ||
40 | |||
41 | list_for_each(_p, &rxrpc_calls) | ||
42 | if (!pos--) | ||
43 | break; | ||
44 | |||
45 | return _p != &rxrpc_calls ? _p : NULL; | ||
46 | } | 35 | } |
47 | 36 | ||
48 | static void *rxrpc_call_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 37 | static void *rxrpc_call_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
49 | { | 38 | { |
50 | struct list_head *_p; | 39 | return seq_list_next(v, &rxrpc_calls, pos); |
51 | |||
52 | (*pos)++; | ||
53 | |||
54 | _p = v; | ||
55 | _p = (v == SEQ_START_TOKEN) ? rxrpc_calls.next : _p->next; | ||
56 | |||
57 | return _p != &rxrpc_calls ? _p : NULL; | ||
58 | } | 40 | } |
59 | 41 | ||
60 | static void rxrpc_call_seq_stop(struct seq_file *seq, void *v) | 42 | static void rxrpc_call_seq_stop(struct seq_file *seq, void *v) |
@@ -68,7 +50,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v) | |||
68 | struct rxrpc_call *call; | 50 | struct rxrpc_call *call; |
69 | char lbuff[4 + 4 + 4 + 4 + 5 + 1], rbuff[4 + 4 + 4 + 4 + 5 + 1]; | 51 | char lbuff[4 + 4 + 4 + 4 + 5 + 1], rbuff[4 + 4 + 4 + 4 + 5 + 1]; |
70 | 52 | ||
71 | if (v == SEQ_START_TOKEN) { | 53 | if (v == &rxrpc_calls) { |
72 | seq_puts(seq, | 54 | seq_puts(seq, |
73 | "Proto Local Remote " | 55 | "Proto Local Remote " |
74 | " SvID ConnID CallID End Use State Abort " | 56 | " SvID ConnID CallID End Use State Abort " |
@@ -104,7 +86,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v) | |||
104 | return 0; | 86 | return 0; |
105 | } | 87 | } |
106 | 88 | ||
107 | static struct seq_operations rxrpc_call_seq_ops = { | 89 | static const struct seq_operations rxrpc_call_seq_ops = { |
108 | .start = rxrpc_call_seq_start, | 90 | .start = rxrpc_call_seq_start, |
109 | .next = rxrpc_call_seq_next, | 91 | .next = rxrpc_call_seq_next, |
110 | .stop = rxrpc_call_seq_stop, | 92 | .stop = rxrpc_call_seq_stop, |
@@ -129,32 +111,14 @@ struct file_operations rxrpc_call_seq_fops = { | |||
129 | */ | 111 | */ |
130 | static void *rxrpc_connection_seq_start(struct seq_file *seq, loff_t *_pos) | 112 | static void *rxrpc_connection_seq_start(struct seq_file *seq, loff_t *_pos) |
131 | { | 113 | { |
132 | struct list_head *_p; | ||
133 | loff_t pos = *_pos; | ||
134 | |||
135 | read_lock(&rxrpc_connection_lock); | 114 | read_lock(&rxrpc_connection_lock); |
136 | if (!pos) | 115 | return seq_list_start_head(&rxrpc_connections, *_pos); |
137 | return SEQ_START_TOKEN; | ||
138 | pos--; | ||
139 | |||
140 | list_for_each(_p, &rxrpc_connections) | ||
141 | if (!pos--) | ||
142 | break; | ||
143 | |||
144 | return _p != &rxrpc_connections ? _p : NULL; | ||
145 | } | 116 | } |
146 | 117 | ||
147 | static void *rxrpc_connection_seq_next(struct seq_file *seq, void *v, | 118 | static void *rxrpc_connection_seq_next(struct seq_file *seq, void *v, |
148 | loff_t *pos) | 119 | loff_t *pos) |
149 | { | 120 | { |
150 | struct list_head *_p; | 121 | return seq_list_next(v, &rxrpc_connections, pos); |
151 | |||
152 | (*pos)++; | ||
153 | |||
154 | _p = v; | ||
155 | _p = (v == SEQ_START_TOKEN) ? rxrpc_connections.next : _p->next; | ||
156 | |||
157 | return _p != &rxrpc_connections ? _p : NULL; | ||
158 | } | 122 | } |
159 | 123 | ||
160 | static void rxrpc_connection_seq_stop(struct seq_file *seq, void *v) | 124 | static void rxrpc_connection_seq_stop(struct seq_file *seq, void *v) |
@@ -168,7 +132,7 @@ static int rxrpc_connection_seq_show(struct seq_file *seq, void *v) | |||
168 | struct rxrpc_transport *trans; | 132 | struct rxrpc_transport *trans; |
169 | char lbuff[4 + 4 + 4 + 4 + 5 + 1], rbuff[4 + 4 + 4 + 4 + 5 + 1]; | 133 | char lbuff[4 + 4 + 4 + 4 + 5 + 1], rbuff[4 + 4 + 4 + 4 + 5 + 1]; |
170 | 134 | ||
171 | if (v == SEQ_START_TOKEN) { | 135 | if (v == &rxrpc_connections) { |
172 | seq_puts(seq, | 136 | seq_puts(seq, |
173 | "Proto Local Remote " | 137 | "Proto Local Remote " |
174 | " SvID ConnID Calls End Use State Key " | 138 | " SvID ConnID Calls End Use State Key " |
@@ -206,7 +170,7 @@ static int rxrpc_connection_seq_show(struct seq_file *seq, void *v) | |||
206 | return 0; | 170 | return 0; |
207 | } | 171 | } |
208 | 172 | ||
209 | static struct seq_operations rxrpc_connection_seq_ops = { | 173 | static const struct seq_operations rxrpc_connection_seq_ops = { |
210 | .start = rxrpc_connection_seq_start, | 174 | .start = rxrpc_connection_seq_start, |
211 | .next = rxrpc_connection_seq_next, | 175 | .next = rxrpc_connection_seq_next, |
212 | .stop = rxrpc_connection_seq_stop, | 176 | .stop = rxrpc_connection_seq_stop, |
diff --git a/net/sched/Kconfig b/net/sched/Kconfig index 475df8449be9..d3f7c3f9407a 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig | |||
@@ -111,6 +111,17 @@ config NET_SCH_PRIO | |||
111 | To compile this code as a module, choose M here: the | 111 | To compile this code as a module, choose M here: the |
112 | module will be called sch_prio. | 112 | module will be called sch_prio. |
113 | 113 | ||
114 | config NET_SCH_RR | ||
115 | tristate "Multi Band Round Robin Queuing (RR)" | ||
116 | select NET_SCH_PRIO | ||
117 | ---help--- | ||
118 | Say Y here if you want to use an n-band round robin packet | ||
119 | scheduler. | ||
120 | |||
121 | The module uses sch_prio for its framework and is aliased as | ||
122 | sch_rr, so it will load sch_prio, although it is referred | ||
123 | to using sch_rr. | ||
124 | |||
114 | config NET_SCH_RED | 125 | config NET_SCH_RED |
115 | tristate "Random Early Detection (RED)" | 126 | tristate "Random Early Detection (RED)" |
116 | ---help--- | 127 | ---help--- |
@@ -275,7 +286,6 @@ config CLS_U32_MARK | |||
275 | config NET_CLS_RSVP | 286 | config NET_CLS_RSVP |
276 | tristate "IPv4 Resource Reservation Protocol (RSVP)" | 287 | tristate "IPv4 Resource Reservation Protocol (RSVP)" |
277 | select NET_CLS | 288 | select NET_CLS |
278 | select NET_ESTIMATOR | ||
279 | ---help--- | 289 | ---help--- |
280 | The Resource Reservation Protocol (RSVP) permits end systems to | 290 | The Resource Reservation Protocol (RSVP) permits end systems to |
281 | request a minimum and maximum data flow rate for a connection; this | 291 | request a minimum and maximum data flow rate for a connection; this |
@@ -290,7 +300,6 @@ config NET_CLS_RSVP | |||
290 | config NET_CLS_RSVP6 | 300 | config NET_CLS_RSVP6 |
291 | tristate "IPv6 Resource Reservation Protocol (RSVP6)" | 301 | tristate "IPv6 Resource Reservation Protocol (RSVP6)" |
292 | select NET_CLS | 302 | select NET_CLS |
293 | select NET_ESTIMATOR | ||
294 | ---help--- | 303 | ---help--- |
295 | The Resource Reservation Protocol (RSVP) permits end systems to | 304 | The Resource Reservation Protocol (RSVP) permits end systems to |
296 | request a minimum and maximum data flow rate for a connection; this | 305 | request a minimum and maximum data flow rate for a connection; this |
@@ -382,7 +391,6 @@ config NET_EMATCH_TEXT | |||
382 | 391 | ||
383 | config NET_CLS_ACT | 392 | config NET_CLS_ACT |
384 | bool "Actions" | 393 | bool "Actions" |
385 | select NET_ESTIMATOR | ||
386 | ---help--- | 394 | ---help--- |
387 | Say Y here if you want to use traffic control actions. Actions | 395 | Say Y here if you want to use traffic control actions. Actions |
388 | get attached to classifiers and are invoked after a successful | 396 | get attached to classifiers and are invoked after a successful |
@@ -464,13 +472,12 @@ config NET_ACT_SIMP | |||
464 | 472 | ||
465 | config NET_CLS_POLICE | 473 | config NET_CLS_POLICE |
466 | bool "Traffic Policing (obsolete)" | 474 | bool "Traffic Policing (obsolete)" |
467 | depends on NET_CLS_ACT!=y | 475 | select NET_CLS_ACT |
468 | select NET_ESTIMATOR | 476 | select NET_ACT_POLICE |
469 | ---help--- | 477 | ---help--- |
470 | Say Y here if you want to do traffic policing, i.e. strict | 478 | Say Y here if you want to do traffic policing, i.e. strict |
471 | bandwidth limiting. This option is obsoleted by the traffic | 479 | bandwidth limiting. This option is obsolete and just selects |
472 | policer implemented as action, it stays here for compatibility | 480 | the option replacing it. It will be removed in the future. |
473 | reasons. | ||
474 | 481 | ||
475 | config NET_CLS_IND | 482 | config NET_CLS_IND |
476 | bool "Incoming device classification" | 483 | bool "Incoming device classification" |
@@ -480,14 +487,6 @@ config NET_CLS_IND | |||
480 | classification based on the incoming device. This option is | 487 | classification based on the incoming device. This option is |
481 | likely to disappear in favour of the metadata ematch. | 488 | likely to disappear in favour of the metadata ematch. |
482 | 489 | ||
483 | config NET_ESTIMATOR | ||
484 | bool "Rate estimator" | ||
485 | ---help--- | ||
486 | Say Y here to allow using rate estimators to estimate the current | ||
487 | rate-of-flow for network devices, queues, etc. This module is | ||
488 | automatically selected if needed but can be selected manually for | ||
489 | statistical purposes. | ||
490 | |||
491 | endif # NET_SCHED | 490 | endif # NET_SCHED |
492 | 491 | ||
493 | endmenu | 492 | endmenu |
diff --git a/net/sched/Makefile b/net/sched/Makefile index 020767a204d4..b67c36f65cf2 100644 --- a/net/sched/Makefile +++ b/net/sched/Makefile | |||
@@ -8,7 +8,6 @@ obj-$(CONFIG_NET_SCHED) += sch_api.o sch_blackhole.o | |||
8 | obj-$(CONFIG_NET_CLS) += cls_api.o | 8 | obj-$(CONFIG_NET_CLS) += cls_api.o |
9 | obj-$(CONFIG_NET_CLS_ACT) += act_api.o | 9 | obj-$(CONFIG_NET_CLS_ACT) += act_api.o |
10 | obj-$(CONFIG_NET_ACT_POLICE) += act_police.o | 10 | obj-$(CONFIG_NET_ACT_POLICE) += act_police.o |
11 | obj-$(CONFIG_NET_CLS_POLICE) += act_police.o | ||
12 | obj-$(CONFIG_NET_ACT_GACT) += act_gact.o | 11 | obj-$(CONFIG_NET_ACT_GACT) += act_gact.o |
13 | obj-$(CONFIG_NET_ACT_MIRRED) += act_mirred.o | 12 | obj-$(CONFIG_NET_ACT_MIRRED) += act_mirred.o |
14 | obj-$(CONFIG_NET_ACT_IPT) += act_ipt.o | 13 | obj-$(CONFIG_NET_ACT_IPT) += act_ipt.o |
diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 711dd26c95c3..feef366cad5d 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c | |||
@@ -11,23 +11,13 @@ | |||
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <asm/uaccess.h> | ||
15 | #include <asm/system.h> | ||
16 | #include <linux/bitops.h> | ||
17 | #include <linux/types.h> | 14 | #include <linux/types.h> |
18 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
19 | #include <linux/string.h> | 16 | #include <linux/string.h> |
20 | #include <linux/mm.h> | ||
21 | #include <linux/socket.h> | ||
22 | #include <linux/sockios.h> | ||
23 | #include <linux/in.h> | ||
24 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/netdevice.h> | ||
27 | #include <linux/skbuff.h> | 18 | #include <linux/skbuff.h> |
28 | #include <linux/init.h> | 19 | #include <linux/init.h> |
29 | #include <linux/kmod.h> | 20 | #include <linux/kmod.h> |
30 | #include <net/sock.h> | ||
31 | #include <net/sch_generic.h> | 21 | #include <net/sch_generic.h> |
32 | #include <net/act_api.h> | 22 | #include <net/act_api.h> |
33 | #include <net/netlink.h> | 23 | #include <net/netlink.h> |
@@ -42,10 +32,8 @@ void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo) | |||
42 | write_lock_bh(hinfo->lock); | 32 | write_lock_bh(hinfo->lock); |
43 | *p1p = p->tcfc_next; | 33 | *p1p = p->tcfc_next; |
44 | write_unlock_bh(hinfo->lock); | 34 | write_unlock_bh(hinfo->lock); |
45 | #ifdef CONFIG_NET_ESTIMATOR | ||
46 | gen_kill_estimator(&p->tcfc_bstats, | 35 | gen_kill_estimator(&p->tcfc_bstats, |
47 | &p->tcfc_rate_est); | 36 | &p->tcfc_rate_est); |
48 | #endif | ||
49 | kfree(p); | 37 | kfree(p); |
50 | return; | 38 | return; |
51 | } | 39 | } |
@@ -232,15 +220,12 @@ struct tcf_common *tcf_hash_create(u32 index, struct rtattr *est, struct tc_acti | |||
232 | p->tcfc_bindcnt = 1; | 220 | p->tcfc_bindcnt = 1; |
233 | 221 | ||
234 | spin_lock_init(&p->tcfc_lock); | 222 | spin_lock_init(&p->tcfc_lock); |
235 | p->tcfc_stats_lock = &p->tcfc_lock; | ||
236 | p->tcfc_index = index ? index : tcf_hash_new_index(idx_gen, hinfo); | 223 | p->tcfc_index = index ? index : tcf_hash_new_index(idx_gen, hinfo); |
237 | p->tcfc_tm.install = jiffies; | 224 | p->tcfc_tm.install = jiffies; |
238 | p->tcfc_tm.lastuse = jiffies; | 225 | p->tcfc_tm.lastuse = jiffies; |
239 | #ifdef CONFIG_NET_ESTIMATOR | ||
240 | if (est) | 226 | if (est) |
241 | gen_new_estimator(&p->tcfc_bstats, &p->tcfc_rate_est, | 227 | gen_new_estimator(&p->tcfc_bstats, &p->tcfc_rate_est, |
242 | p->tcfc_stats_lock, est); | 228 | &p->tcfc_lock, est); |
243 | #endif | ||
244 | a->priv = (void *) p; | 229 | a->priv = (void *) p; |
245 | return p; | 230 | return p; |
246 | } | 231 | } |
@@ -599,12 +584,12 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a, | |||
599 | if (compat_mode) { | 584 | if (compat_mode) { |
600 | if (a->type == TCA_OLD_COMPAT) | 585 | if (a->type == TCA_OLD_COMPAT) |
601 | err = gnet_stats_start_copy_compat(skb, 0, | 586 | err = gnet_stats_start_copy_compat(skb, 0, |
602 | TCA_STATS, TCA_XSTATS, h->tcf_stats_lock, &d); | 587 | TCA_STATS, TCA_XSTATS, &h->tcf_lock, &d); |
603 | else | 588 | else |
604 | return 0; | 589 | return 0; |
605 | } else | 590 | } else |
606 | err = gnet_stats_start_copy(skb, TCA_ACT_STATS, | 591 | err = gnet_stats_start_copy(skb, TCA_ACT_STATS, |
607 | h->tcf_stats_lock, &d); | 592 | &h->tcf_lock, &d); |
608 | 593 | ||
609 | if (err < 0) | 594 | if (err < 0) |
610 | goto errout; | 595 | goto errout; |
@@ -614,9 +599,7 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a, | |||
614 | goto errout; | 599 | goto errout; |
615 | 600 | ||
616 | if (gnet_stats_copy_basic(&d, &h->tcf_bstats) < 0 || | 601 | if (gnet_stats_copy_basic(&d, &h->tcf_bstats) < 0 || |
617 | #ifdef CONFIG_NET_ESTIMATOR | ||
618 | gnet_stats_copy_rate_est(&d, &h->tcf_rate_est) < 0 || | 602 | gnet_stats_copy_rate_est(&d, &h->tcf_rate_est) < 0 || |
619 | #endif | ||
620 | gnet_stats_copy_queue(&d, &h->tcf_qstats) < 0) | 603 | gnet_stats_copy_queue(&d, &h->tcf_qstats) < 0) |
621 | goto errout; | 604 | goto errout; |
622 | 605 | ||
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c index 7517f3791541..a9631e426d91 100644 --- a/net/sched/act_gact.c +++ b/net/sched/act_gact.c | |||
@@ -10,26 +10,15 @@ | |||
10 | * | 10 | * |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <asm/uaccess.h> | ||
14 | #include <asm/system.h> | ||
15 | #include <linux/bitops.h> | ||
16 | #include <linux/types.h> | 13 | #include <linux/types.h> |
17 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
18 | #include <linux/string.h> | 15 | #include <linux/string.h> |
19 | #include <linux/mm.h> | ||
20 | #include <linux/socket.h> | ||
21 | #include <linux/sockios.h> | ||
22 | #include <linux/in.h> | ||
23 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/netdevice.h> | ||
26 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
27 | #include <linux/rtnetlink.h> | 18 | #include <linux/rtnetlink.h> |
28 | #include <linux/module.h> | 19 | #include <linux/module.h> |
29 | #include <linux/init.h> | 20 | #include <linux/init.h> |
30 | #include <linux/proc_fs.h> | ||
31 | #include <net/netlink.h> | 21 | #include <net/netlink.h> |
32 | #include <net/sock.h> | ||
33 | #include <net/pkt_sched.h> | 22 | #include <net/pkt_sched.h> |
34 | #include <linux/tc_act/tc_gact.h> | 23 | #include <linux/tc_act/tc_gact.h> |
35 | #include <net/tc_act/tc_gact.h> | 24 | #include <net/tc_act/tc_gact.h> |
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index 00b05f422d45..6b407ece953c 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c | |||
@@ -11,27 +11,15 @@ | |||
11 | * Copyright: Jamal Hadi Salim (2002-4) | 11 | * Copyright: Jamal Hadi Salim (2002-4) |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <asm/uaccess.h> | ||
15 | #include <asm/system.h> | ||
16 | #include <asm/bitops.h> | ||
17 | #include <linux/types.h> | 14 | #include <linux/types.h> |
18 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
19 | #include <linux/string.h> | 16 | #include <linux/string.h> |
20 | #include <linux/mm.h> | ||
21 | #include <linux/socket.h> | ||
22 | #include <linux/sockios.h> | ||
23 | #include <linux/in.h> | ||
24 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/netdevice.h> | ||
27 | #include <linux/skbuff.h> | 18 | #include <linux/skbuff.h> |
28 | #include <linux/rtnetlink.h> | 19 | #include <linux/rtnetlink.h> |
29 | #include <linux/module.h> | 20 | #include <linux/module.h> |
30 | #include <linux/init.h> | 21 | #include <linux/init.h> |
31 | #include <linux/proc_fs.h> | ||
32 | #include <linux/kmod.h> | ||
33 | #include <net/netlink.h> | 22 | #include <net/netlink.h> |
34 | #include <net/sock.h> | ||
35 | #include <net/pkt_sched.h> | 23 | #include <net/pkt_sched.h> |
36 | #include <linux/tc_act/tc_ipt.h> | 24 | #include <linux/tc_act/tc_ipt.h> |
37 | #include <net/tc_act/tc_ipt.h> | 25 | #include <net/tc_act/tc_ipt.h> |
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index de21c92faaa2..579578944ae7 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c | |||
@@ -12,31 +12,19 @@ | |||
12 | * | 12 | * |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <asm/uaccess.h> | ||
16 | #include <asm/system.h> | ||
17 | #include <asm/bitops.h> | ||
18 | #include <linux/types.h> | 15 | #include <linux/types.h> |
19 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
20 | #include <linux/string.h> | 17 | #include <linux/string.h> |
21 | #include <linux/mm.h> | ||
22 | #include <linux/socket.h> | ||
23 | #include <linux/sockios.h> | ||
24 | #include <linux/in.h> | ||
25 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/netdevice.h> | ||
28 | #include <linux/skbuff.h> | 19 | #include <linux/skbuff.h> |
29 | #include <linux/rtnetlink.h> | 20 | #include <linux/rtnetlink.h> |
30 | #include <linux/module.h> | 21 | #include <linux/module.h> |
31 | #include <linux/init.h> | 22 | #include <linux/init.h> |
32 | #include <linux/proc_fs.h> | ||
33 | #include <net/netlink.h> | 23 | #include <net/netlink.h> |
34 | #include <net/sock.h> | ||
35 | #include <net/pkt_sched.h> | 24 | #include <net/pkt_sched.h> |
36 | #include <linux/tc_act/tc_mirred.h> | 25 | #include <linux/tc_act/tc_mirred.h> |
37 | #include <net/tc_act/tc_mirred.h> | 26 | #include <net/tc_act/tc_mirred.h> |
38 | 27 | ||
39 | #include <linux/etherdevice.h> | ||
40 | #include <linux/if_arp.h> | 28 | #include <linux/if_arp.h> |
41 | 29 | ||
42 | #define MIRRED_TAB_MASK 7 | 30 | #define MIRRED_TAB_MASK 7 |
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index 6f8684b5617e..b46fab5fb323 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c | |||
@@ -9,26 +9,15 @@ | |||
9 | * Authors: Jamal Hadi Salim (2002-4) | 9 | * Authors: Jamal Hadi Salim (2002-4) |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <asm/uaccess.h> | ||
13 | #include <asm/system.h> | ||
14 | #include <asm/bitops.h> | ||
15 | #include <linux/types.h> | 12 | #include <linux/types.h> |
16 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
17 | #include <linux/string.h> | 14 | #include <linux/string.h> |
18 | #include <linux/mm.h> | ||
19 | #include <linux/socket.h> | ||
20 | #include <linux/sockios.h> | ||
21 | #include <linux/in.h> | ||
22 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/netdevice.h> | ||
25 | #include <linux/skbuff.h> | 16 | #include <linux/skbuff.h> |
26 | #include <linux/rtnetlink.h> | 17 | #include <linux/rtnetlink.h> |
27 | #include <linux/module.h> | 18 | #include <linux/module.h> |
28 | #include <linux/init.h> | 19 | #include <linux/init.h> |
29 | #include <linux/proc_fs.h> | ||
30 | #include <net/netlink.h> | 20 | #include <net/netlink.h> |
31 | #include <net/sock.h> | ||
32 | #include <net/pkt_sched.h> | 21 | #include <net/pkt_sched.h> |
33 | #include <linux/tc_act/tc_pedit.h> | 22 | #include <linux/tc_act/tc_pedit.h> |
34 | #include <net/tc_act/tc_pedit.h> | 23 | #include <net/tc_act/tc_pedit.h> |
diff --git a/net/sched/act_police.c b/net/sched/act_police.c index 616f465f407e..bf90e60f8411 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c | |||
@@ -10,25 +10,15 @@ | |||
10 | * J Hadi Salim (action changes) | 10 | * J Hadi Salim (action changes) |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <asm/uaccess.h> | ||
14 | #include <asm/system.h> | ||
15 | #include <linux/bitops.h> | ||
16 | #include <linux/module.h> | 13 | #include <linux/module.h> |
17 | #include <linux/types.h> | 14 | #include <linux/types.h> |
18 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
19 | #include <linux/string.h> | 16 | #include <linux/string.h> |
20 | #include <linux/mm.h> | ||
21 | #include <linux/socket.h> | ||
22 | #include <linux/sockios.h> | ||
23 | #include <linux/in.h> | ||
24 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/netdevice.h> | ||
27 | #include <linux/skbuff.h> | 18 | #include <linux/skbuff.h> |
28 | #include <linux/module.h> | 19 | #include <linux/module.h> |
29 | #include <linux/rtnetlink.h> | 20 | #include <linux/rtnetlink.h> |
30 | #include <linux/init.h> | 21 | #include <linux/init.h> |
31 | #include <net/sock.h> | ||
32 | #include <net/act_api.h> | 22 | #include <net/act_api.h> |
33 | #include <net/netlink.h> | 23 | #include <net/netlink.h> |
34 | 24 | ||
@@ -60,7 +50,6 @@ struct tc_police_compat | |||
60 | 50 | ||
61 | /* Each policer is serialized by its individual spinlock */ | 51 | /* Each policer is serialized by its individual spinlock */ |
62 | 52 | ||
63 | #ifdef CONFIG_NET_CLS_ACT | ||
64 | static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb, | 53 | static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb, |
65 | int type, struct tc_action *a) | 54 | int type, struct tc_action *a) |
66 | { | 55 | { |
@@ -106,9 +95,8 @@ rtattr_failure: | |||
106 | nlmsg_trim(skb, r); | 95 | nlmsg_trim(skb, r); |
107 | goto done; | 96 | goto done; |
108 | } | 97 | } |
109 | #endif | ||
110 | 98 | ||
111 | void tcf_police_destroy(struct tcf_police *p) | 99 | static void tcf_police_destroy(struct tcf_police *p) |
112 | { | 100 | { |
113 | unsigned int h = tcf_hash(p->tcf_index, POL_TAB_MASK); | 101 | unsigned int h = tcf_hash(p->tcf_index, POL_TAB_MASK); |
114 | struct tcf_common **p1p; | 102 | struct tcf_common **p1p; |
@@ -118,10 +106,8 @@ void tcf_police_destroy(struct tcf_police *p) | |||
118 | write_lock_bh(&police_lock); | 106 | write_lock_bh(&police_lock); |
119 | *p1p = p->tcf_next; | 107 | *p1p = p->tcf_next; |
120 | write_unlock_bh(&police_lock); | 108 | write_unlock_bh(&police_lock); |
121 | #ifdef CONFIG_NET_ESTIMATOR | ||
122 | gen_kill_estimator(&p->tcf_bstats, | 109 | gen_kill_estimator(&p->tcf_bstats, |
123 | &p->tcf_rate_est); | 110 | &p->tcf_rate_est); |
124 | #endif | ||
125 | if (p->tcfp_R_tab) | 111 | if (p->tcfp_R_tab) |
126 | qdisc_put_rtab(p->tcfp_R_tab); | 112 | qdisc_put_rtab(p->tcfp_R_tab); |
127 | if (p->tcfp_P_tab) | 113 | if (p->tcfp_P_tab) |
@@ -133,7 +119,6 @@ void tcf_police_destroy(struct tcf_police *p) | |||
133 | BUG_TRAP(0); | 119 | BUG_TRAP(0); |
134 | } | 120 | } |
135 | 121 | ||
136 | #ifdef CONFIG_NET_CLS_ACT | ||
137 | static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est, | 122 | static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est, |
138 | struct tc_action *a, int ovr, int bind) | 123 | struct tc_action *a, int ovr, int bind) |
139 | { | 124 | { |
@@ -185,7 +170,6 @@ static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est, | |||
185 | ret = ACT_P_CREATED; | 170 | ret = ACT_P_CREATED; |
186 | police->tcf_refcnt = 1; | 171 | police->tcf_refcnt = 1; |
187 | spin_lock_init(&police->tcf_lock); | 172 | spin_lock_init(&police->tcf_lock); |
188 | police->tcf_stats_lock = &police->tcf_lock; | ||
189 | if (bind) | 173 | if (bind) |
190 | police->tcf_bindcnt = 1; | 174 | police->tcf_bindcnt = 1; |
191 | override: | 175 | override: |
@@ -227,15 +211,13 @@ override: | |||
227 | police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu); | 211 | police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu); |
228 | police->tcf_action = parm->action; | 212 | police->tcf_action = parm->action; |
229 | 213 | ||
230 | #ifdef CONFIG_NET_ESTIMATOR | ||
231 | if (tb[TCA_POLICE_AVRATE-1]) | 214 | if (tb[TCA_POLICE_AVRATE-1]) |
232 | police->tcfp_ewma_rate = | 215 | police->tcfp_ewma_rate = |
233 | *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]); | 216 | *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]); |
234 | if (est) | 217 | if (est) |
235 | gen_replace_estimator(&police->tcf_bstats, | 218 | gen_replace_estimator(&police->tcf_bstats, |
236 | &police->tcf_rate_est, | 219 | &police->tcf_rate_est, |
237 | police->tcf_stats_lock, est); | 220 | &police->tcf_lock, est); |
238 | #endif | ||
239 | 221 | ||
240 | spin_unlock_bh(&police->tcf_lock); | 222 | spin_unlock_bh(&police->tcf_lock); |
241 | if (ret != ACT_P_CREATED) | 223 | if (ret != ACT_P_CREATED) |
@@ -262,10 +244,19 @@ failure: | |||
262 | static int tcf_act_police_cleanup(struct tc_action *a, int bind) | 244 | static int tcf_act_police_cleanup(struct tc_action *a, int bind) |
263 | { | 245 | { |
264 | struct tcf_police *p = a->priv; | 246 | struct tcf_police *p = a->priv; |
247 | int ret = 0; | ||
265 | 248 | ||
266 | if (p != NULL) | 249 | if (p != NULL) { |
267 | return tcf_police_release(p, bind); | 250 | if (bind) |
268 | return 0; | 251 | p->tcf_bindcnt--; |
252 | |||
253 | p->tcf_refcnt--; | ||
254 | if (p->tcf_refcnt <= 0 && !p->tcf_bindcnt) { | ||
255 | tcf_police_destroy(p); | ||
256 | ret = 1; | ||
257 | } | ||
258 | } | ||
259 | return ret; | ||
269 | } | 260 | } |
270 | 261 | ||
271 | static int tcf_act_police(struct sk_buff *skb, struct tc_action *a, | 262 | static int tcf_act_police(struct sk_buff *skb, struct tc_action *a, |
@@ -281,14 +272,12 @@ static int tcf_act_police(struct sk_buff *skb, struct tc_action *a, | |||
281 | police->tcf_bstats.bytes += skb->len; | 272 | police->tcf_bstats.bytes += skb->len; |
282 | police->tcf_bstats.packets++; | 273 | police->tcf_bstats.packets++; |
283 | 274 | ||
284 | #ifdef CONFIG_NET_ESTIMATOR | ||
285 | if (police->tcfp_ewma_rate && | 275 | if (police->tcfp_ewma_rate && |
286 | police->tcf_rate_est.bps >= police->tcfp_ewma_rate) { | 276 | police->tcf_rate_est.bps >= police->tcfp_ewma_rate) { |
287 | police->tcf_qstats.overlimits++; | 277 | police->tcf_qstats.overlimits++; |
288 | spin_unlock(&police->tcf_lock); | 278 | spin_unlock(&police->tcf_lock); |
289 | return police->tcf_action; | 279 | return police->tcf_action; |
290 | } | 280 | } |
291 | #endif | ||
292 | 281 | ||
293 | if (skb->len <= police->tcfp_mtu) { | 282 | if (skb->len <= police->tcfp_mtu) { |
294 | if (police->tcfp_R_tab == NULL) { | 283 | if (police->tcfp_R_tab == NULL) { |
@@ -348,10 +337,8 @@ tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) | |||
348 | if (police->tcfp_result) | 337 | if (police->tcfp_result) |
349 | RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), | 338 | RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), |
350 | &police->tcfp_result); | 339 | &police->tcfp_result); |
351 | #ifdef CONFIG_NET_ESTIMATOR | ||
352 | if (police->tcfp_ewma_rate) | 340 | if (police->tcfp_ewma_rate) |
353 | RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &police->tcfp_ewma_rate); | 341 | RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &police->tcfp_ewma_rate); |
354 | #endif | ||
355 | return skb->len; | 342 | return skb->len; |
356 | 343 | ||
357 | rtattr_failure: | 344 | rtattr_failure: |
@@ -391,240 +378,3 @@ police_cleanup_module(void) | |||
391 | 378 | ||
392 | module_init(police_init_module); | 379 | module_init(police_init_module); |
393 | module_exit(police_cleanup_module); | 380 | module_exit(police_cleanup_module); |
394 | |||
395 | #else /* CONFIG_NET_CLS_ACT */ | ||
396 | |||
397 | static struct tcf_common *tcf_police_lookup(u32 index) | ||
398 | { | ||
399 | struct tcf_hashinfo *hinfo = &police_hash_info; | ||
400 | struct tcf_common *p; | ||
401 | |||
402 | read_lock(hinfo->lock); | ||
403 | for (p = hinfo->htab[tcf_hash(index, hinfo->hmask)]; p; | ||
404 | p = p->tcfc_next) { | ||
405 | if (p->tcfc_index == index) | ||
406 | break; | ||
407 | } | ||
408 | read_unlock(hinfo->lock); | ||
409 | |||
410 | return p; | ||
411 | } | ||
412 | |||
413 | static u32 tcf_police_new_index(void) | ||
414 | { | ||
415 | u32 *idx_gen = &police_idx_gen; | ||
416 | u32 val = *idx_gen; | ||
417 | |||
418 | do { | ||
419 | if (++val == 0) | ||
420 | val = 1; | ||
421 | } while (tcf_police_lookup(val)); | ||
422 | |||
423 | return (*idx_gen = val); | ||
424 | } | ||
425 | |||
426 | struct tcf_police *tcf_police_locate(struct rtattr *rta, struct rtattr *est) | ||
427 | { | ||
428 | unsigned int h; | ||
429 | struct tcf_police *police; | ||
430 | struct rtattr *tb[TCA_POLICE_MAX]; | ||
431 | struct tc_police *parm; | ||
432 | int size; | ||
433 | |||
434 | if (rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0) | ||
435 | return NULL; | ||
436 | |||
437 | if (tb[TCA_POLICE_TBF-1] == NULL) | ||
438 | return NULL; | ||
439 | size = RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]); | ||
440 | if (size != sizeof(*parm) && size != sizeof(struct tc_police_compat)) | ||
441 | return NULL; | ||
442 | |||
443 | parm = RTA_DATA(tb[TCA_POLICE_TBF-1]); | ||
444 | |||
445 | if (parm->index) { | ||
446 | struct tcf_common *pc; | ||
447 | |||
448 | pc = tcf_police_lookup(parm->index); | ||
449 | if (pc) { | ||
450 | police = to_police(pc); | ||
451 | police->tcf_refcnt++; | ||
452 | return police; | ||
453 | } | ||
454 | } | ||
455 | police = kzalloc(sizeof(*police), GFP_KERNEL); | ||
456 | if (unlikely(!police)) | ||
457 | return NULL; | ||
458 | |||
459 | police->tcf_refcnt = 1; | ||
460 | spin_lock_init(&police->tcf_lock); | ||
461 | police->tcf_stats_lock = &police->tcf_lock; | ||
462 | if (parm->rate.rate) { | ||
463 | police->tcfp_R_tab = | ||
464 | qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]); | ||
465 | if (police->tcfp_R_tab == NULL) | ||
466 | goto failure; | ||
467 | if (parm->peakrate.rate) { | ||
468 | police->tcfp_P_tab = | ||
469 | qdisc_get_rtab(&parm->peakrate, | ||
470 | tb[TCA_POLICE_PEAKRATE-1]); | ||
471 | if (police->tcfp_P_tab == NULL) | ||
472 | goto failure; | ||
473 | } | ||
474 | } | ||
475 | if (tb[TCA_POLICE_RESULT-1]) { | ||
476 | if (RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32)) | ||
477 | goto failure; | ||
478 | police->tcfp_result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]); | ||
479 | } | ||
480 | #ifdef CONFIG_NET_ESTIMATOR | ||
481 | if (tb[TCA_POLICE_AVRATE-1]) { | ||
482 | if (RTA_PAYLOAD(tb[TCA_POLICE_AVRATE-1]) != sizeof(u32)) | ||
483 | goto failure; | ||
484 | police->tcfp_ewma_rate = | ||
485 | *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]); | ||
486 | } | ||
487 | #endif | ||
488 | police->tcfp_toks = police->tcfp_burst = parm->burst; | ||
489 | police->tcfp_mtu = parm->mtu; | ||
490 | if (police->tcfp_mtu == 0) { | ||
491 | police->tcfp_mtu = ~0; | ||
492 | if (police->tcfp_R_tab) | ||
493 | police->tcfp_mtu = 255<<police->tcfp_R_tab->rate.cell_log; | ||
494 | } | ||
495 | if (police->tcfp_P_tab) | ||
496 | police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu); | ||
497 | police->tcfp_t_c = psched_get_time(); | ||
498 | police->tcf_index = parm->index ? parm->index : | ||
499 | tcf_police_new_index(); | ||
500 | police->tcf_action = parm->action; | ||
501 | #ifdef CONFIG_NET_ESTIMATOR | ||
502 | if (est) | ||
503 | gen_new_estimator(&police->tcf_bstats, &police->tcf_rate_est, | ||
504 | police->tcf_stats_lock, est); | ||
505 | #endif | ||
506 | h = tcf_hash(police->tcf_index, POL_TAB_MASK); | ||
507 | write_lock_bh(&police_lock); | ||
508 | police->tcf_next = tcf_police_ht[h]; | ||
509 | tcf_police_ht[h] = &police->common; | ||
510 | write_unlock_bh(&police_lock); | ||
511 | return police; | ||
512 | |||
513 | failure: | ||
514 | if (police->tcfp_R_tab) | ||
515 | qdisc_put_rtab(police->tcfp_R_tab); | ||
516 | kfree(police); | ||
517 | return NULL; | ||
518 | } | ||
519 | |||
520 | int tcf_police(struct sk_buff *skb, struct tcf_police *police) | ||
521 | { | ||
522 | psched_time_t now; | ||
523 | long toks; | ||
524 | long ptoks = 0; | ||
525 | |||
526 | spin_lock(&police->tcf_lock); | ||
527 | |||
528 | police->tcf_bstats.bytes += skb->len; | ||
529 | police->tcf_bstats.packets++; | ||
530 | |||
531 | #ifdef CONFIG_NET_ESTIMATOR | ||
532 | if (police->tcfp_ewma_rate && | ||
533 | police->tcf_rate_est.bps >= police->tcfp_ewma_rate) { | ||
534 | police->tcf_qstats.overlimits++; | ||
535 | spin_unlock(&police->tcf_lock); | ||
536 | return police->tcf_action; | ||
537 | } | ||
538 | #endif | ||
539 | if (skb->len <= police->tcfp_mtu) { | ||
540 | if (police->tcfp_R_tab == NULL) { | ||
541 | spin_unlock(&police->tcf_lock); | ||
542 | return police->tcfp_result; | ||
543 | } | ||
544 | |||
545 | now = psched_get_time(); | ||
546 | toks = psched_tdiff_bounded(now, police->tcfp_t_c, | ||
547 | police->tcfp_burst); | ||
548 | if (police->tcfp_P_tab) { | ||
549 | ptoks = toks + police->tcfp_ptoks; | ||
550 | if (ptoks > (long)L2T_P(police, police->tcfp_mtu)) | ||
551 | ptoks = (long)L2T_P(police, police->tcfp_mtu); | ||
552 | ptoks -= L2T_P(police, skb->len); | ||
553 | } | ||
554 | toks += police->tcfp_toks; | ||
555 | if (toks > (long)police->tcfp_burst) | ||
556 | toks = police->tcfp_burst; | ||
557 | toks -= L2T(police, skb->len); | ||
558 | if ((toks|ptoks) >= 0) { | ||
559 | police->tcfp_t_c = now; | ||
560 | police->tcfp_toks = toks; | ||
561 | police->tcfp_ptoks = ptoks; | ||
562 | spin_unlock(&police->tcf_lock); | ||
563 | return police->tcfp_result; | ||
564 | } | ||
565 | } | ||
566 | |||
567 | police->tcf_qstats.overlimits++; | ||
568 | spin_unlock(&police->tcf_lock); | ||
569 | return police->tcf_action; | ||
570 | } | ||
571 | EXPORT_SYMBOL(tcf_police); | ||
572 | |||
573 | int tcf_police_dump(struct sk_buff *skb, struct tcf_police *police) | ||
574 | { | ||
575 | unsigned char *b = skb_tail_pointer(skb); | ||
576 | struct tc_police opt; | ||
577 | |||
578 | opt.index = police->tcf_index; | ||
579 | opt.action = police->tcf_action; | ||
580 | opt.mtu = police->tcfp_mtu; | ||
581 | opt.burst = police->tcfp_burst; | ||
582 | if (police->tcfp_R_tab) | ||
583 | opt.rate = police->tcfp_R_tab->rate; | ||
584 | else | ||
585 | memset(&opt.rate, 0, sizeof(opt.rate)); | ||
586 | if (police->tcfp_P_tab) | ||
587 | opt.peakrate = police->tcfp_P_tab->rate; | ||
588 | else | ||
589 | memset(&opt.peakrate, 0, sizeof(opt.peakrate)); | ||
590 | RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt); | ||
591 | if (police->tcfp_result) | ||
592 | RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), | ||
593 | &police->tcfp_result); | ||
594 | #ifdef CONFIG_NET_ESTIMATOR | ||
595 | if (police->tcfp_ewma_rate) | ||
596 | RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &police->tcfp_ewma_rate); | ||
597 | #endif | ||
598 | return skb->len; | ||
599 | |||
600 | rtattr_failure: | ||
601 | nlmsg_trim(skb, b); | ||
602 | return -1; | ||
603 | } | ||
604 | |||
605 | int tcf_police_dump_stats(struct sk_buff *skb, struct tcf_police *police) | ||
606 | { | ||
607 | struct gnet_dump d; | ||
608 | |||
609 | if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS, | ||
610 | TCA_XSTATS, police->tcf_stats_lock, | ||
611 | &d) < 0) | ||
612 | goto errout; | ||
613 | |||
614 | if (gnet_stats_copy_basic(&d, &police->tcf_bstats) < 0 || | ||
615 | #ifdef CONFIG_NET_ESTIMATOR | ||
616 | gnet_stats_copy_rate_est(&d, &police->tcf_rate_est) < 0 || | ||
617 | #endif | ||
618 | gnet_stats_copy_queue(&d, &police->tcf_qstats) < 0) | ||
619 | goto errout; | ||
620 | |||
621 | if (gnet_stats_finish_copy(&d) < 0) | ||
622 | goto errout; | ||
623 | |||
624 | return 0; | ||
625 | |||
626 | errout: | ||
627 | return -1; | ||
628 | } | ||
629 | |||
630 | #endif /* CONFIG_NET_CLS_ACT */ | ||
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c index 36e1edad5990..fb84ef33d14f 100644 --- a/net/sched/act_simple.c +++ b/net/sched/act_simple.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/netdevice.h> | ||
17 | #include <linux/skbuff.h> | 16 | #include <linux/skbuff.h> |
18 | #include <linux/rtnetlink.h> | 17 | #include <linux/rtnetlink.h> |
19 | #include <net/netlink.h> | 18 | #include <net/netlink.h> |
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index ebf94edf0478..5f0fbca7393f 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
@@ -14,26 +14,16 @@ | |||
14 | * | 14 | * |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <asm/uaccess.h> | ||
18 | #include <asm/system.h> | ||
19 | #include <linux/bitops.h> | ||
20 | #include <linux/module.h> | 17 | #include <linux/module.h> |
21 | #include <linux/types.h> | 18 | #include <linux/types.h> |
22 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
23 | #include <linux/string.h> | 20 | #include <linux/string.h> |
24 | #include <linux/mm.h> | ||
25 | #include <linux/socket.h> | ||
26 | #include <linux/sockios.h> | ||
27 | #include <linux/in.h> | ||
28 | #include <linux/errno.h> | 21 | #include <linux/errno.h> |
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/netdevice.h> | ||
31 | #include <linux/skbuff.h> | 22 | #include <linux/skbuff.h> |
32 | #include <linux/init.h> | 23 | #include <linux/init.h> |
33 | #include <linux/kmod.h> | 24 | #include <linux/kmod.h> |
34 | #include <linux/netlink.h> | 25 | #include <linux/netlink.h> |
35 | #include <net/netlink.h> | 26 | #include <net/netlink.h> |
36 | #include <net/sock.h> | ||
37 | #include <net/pkt_sched.h> | 27 | #include <net/pkt_sched.h> |
38 | #include <net/pkt_cls.h> | 28 | #include <net/pkt_cls.h> |
39 | 29 | ||
@@ -468,11 +458,6 @@ tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts) | |||
468 | tcf_action_destroy(exts->action, TCA_ACT_UNBIND); | 458 | tcf_action_destroy(exts->action, TCA_ACT_UNBIND); |
469 | exts->action = NULL; | 459 | exts->action = NULL; |
470 | } | 460 | } |
471 | #elif defined CONFIG_NET_CLS_POLICE | ||
472 | if (exts->police) { | ||
473 | tcf_police_release(exts->police, TCA_ACT_UNBIND); | ||
474 | exts->police = NULL; | ||
475 | } | ||
476 | #endif | 461 | #endif |
477 | } | 462 | } |
478 | 463 | ||
@@ -506,17 +491,6 @@ tcf_exts_validate(struct tcf_proto *tp, struct rtattr **tb, | |||
506 | exts->action = act; | 491 | exts->action = act; |
507 | } | 492 | } |
508 | } | 493 | } |
509 | #elif defined CONFIG_NET_CLS_POLICE | ||
510 | if (map->police && tb[map->police-1]) { | ||
511 | struct tcf_police *p; | ||
512 | |||
513 | p = tcf_police_locate(tb[map->police-1], rate_tlv); | ||
514 | if (p == NULL) | ||
515 | return -EINVAL; | ||
516 | |||
517 | exts->police = p; | ||
518 | } else if (map->action && tb[map->action-1]) | ||
519 | return -EOPNOTSUPP; | ||
520 | #else | 494 | #else |
521 | if ((map->action && tb[map->action-1]) || | 495 | if ((map->action && tb[map->action-1]) || |
522 | (map->police && tb[map->police-1])) | 496 | (map->police && tb[map->police-1])) |
@@ -539,15 +513,6 @@ tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst, | |||
539 | if (act) | 513 | if (act) |
540 | tcf_action_destroy(act, TCA_ACT_UNBIND); | 514 | tcf_action_destroy(act, TCA_ACT_UNBIND); |
541 | } | 515 | } |
542 | #elif defined CONFIG_NET_CLS_POLICE | ||
543 | if (src->police) { | ||
544 | struct tcf_police *p; | ||
545 | tcf_tree_lock(tp); | ||
546 | p = xchg(&dst->police, src->police); | ||
547 | tcf_tree_unlock(tp); | ||
548 | if (p) | ||
549 | tcf_police_release(p, TCA_ACT_UNBIND); | ||
550 | } | ||
551 | #endif | 516 | #endif |
552 | } | 517 | } |
553 | 518 | ||
@@ -576,17 +541,6 @@ tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts, | |||
576 | p_rta->rta_len = skb_tail_pointer(skb) - (u8 *)p_rta; | 541 | p_rta->rta_len = skb_tail_pointer(skb) - (u8 *)p_rta; |
577 | } | 542 | } |
578 | } | 543 | } |
579 | #elif defined CONFIG_NET_CLS_POLICE | ||
580 | if (map->police && exts->police) { | ||
581 | struct rtattr *p_rta = (struct rtattr *)skb_tail_pointer(skb); | ||
582 | |||
583 | RTA_PUT(skb, map->police, 0, NULL); | ||
584 | |||
585 | if (tcf_police_dump(skb, exts->police) < 0) | ||
586 | goto rtattr_failure; | ||
587 | |||
588 | p_rta->rta_len = skb_tail_pointer(skb) - (u8 *)p_rta; | ||
589 | } | ||
590 | #endif | 544 | #endif |
591 | return 0; | 545 | return 0; |
592 | rtattr_failure: __attribute__ ((unused)) | 546 | rtattr_failure: __attribute__ ((unused)) |
@@ -601,10 +555,6 @@ tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts, | |||
601 | if (exts->action) | 555 | if (exts->action) |
602 | if (tcf_action_copy_stats(skb, exts->action, 1) < 0) | 556 | if (tcf_action_copy_stats(skb, exts->action, 1) < 0) |
603 | goto rtattr_failure; | 557 | goto rtattr_failure; |
604 | #elif defined CONFIG_NET_CLS_POLICE | ||
605 | if (exts->police) | ||
606 | if (tcf_police_dump_stats(skb, exts->police) < 0) | ||
607 | goto rtattr_failure; | ||
608 | #endif | 558 | #endif |
609 | return 0; | 559 | return 0; |
610 | rtattr_failure: __attribute__ ((unused)) | 560 | rtattr_failure: __attribute__ ((unused)) |
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c index c885412d79d5..8dbcf2771a46 100644 --- a/net/sched/cls_basic.c +++ b/net/sched/cls_basic.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/string.h> | 15 | #include <linux/string.h> |
16 | #include <linux/mm.h> | ||
17 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
18 | #include <linux/rtnetlink.h> | 17 | #include <linux/rtnetlink.h> |
19 | #include <linux/skbuff.h> | 18 | #include <linux/skbuff.h> |
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c index bbec4a0d4dcb..8adbd6a37d14 100644 --- a/net/sched/cls_fw.c +++ b/net/sched/cls_fw.c | |||
@@ -19,29 +19,12 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <asm/uaccess.h> | ||
23 | #include <asm/system.h> | ||
24 | #include <linux/bitops.h> | ||
25 | #include <linux/types.h> | 22 | #include <linux/types.h> |
26 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
27 | #include <linux/string.h> | 24 | #include <linux/string.h> |
28 | #include <linux/mm.h> | ||
29 | #include <linux/socket.h> | ||
30 | #include <linux/sockios.h> | ||
31 | #include <linux/in.h> | ||
32 | #include <linux/errno.h> | 25 | #include <linux/errno.h> |
33 | #include <linux/interrupt.h> | ||
34 | #include <linux/if_ether.h> | ||
35 | #include <linux/inet.h> | ||
36 | #include <linux/netdevice.h> | ||
37 | #include <linux/etherdevice.h> | ||
38 | #include <linux/notifier.h> | ||
39 | #include <linux/netfilter.h> | ||
40 | #include <net/ip.h> | ||
41 | #include <net/netlink.h> | ||
42 | #include <net/route.h> | ||
43 | #include <linux/skbuff.h> | 26 | #include <linux/skbuff.h> |
44 | #include <net/sock.h> | 27 | #include <net/netlink.h> |
45 | #include <net/act_api.h> | 28 | #include <net/act_api.h> |
46 | #include <net/pkt_cls.h> | 29 | #include <net/pkt_cls.h> |
47 | 30 | ||
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c index cc941d0ee3a5..0a8409c1d28a 100644 --- a/net/sched/cls_route.c +++ b/net/sched/cls_route.c | |||
@@ -10,28 +10,14 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <asm/uaccess.h> | ||
14 | #include <asm/system.h> | ||
15 | #include <linux/bitops.h> | ||
16 | #include <linux/types.h> | 13 | #include <linux/types.h> |
17 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
18 | #include <linux/string.h> | 15 | #include <linux/string.h> |
19 | #include <linux/mm.h> | ||
20 | #include <linux/socket.h> | ||
21 | #include <linux/sockios.h> | ||
22 | #include <linux/in.h> | ||
23 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/if_ether.h> | ||
26 | #include <linux/inet.h> | ||
27 | #include <linux/netdevice.h> | ||
28 | #include <linux/etherdevice.h> | ||
29 | #include <linux/notifier.h> | ||
30 | #include <net/ip.h> | ||
31 | #include <net/netlink.h> | ||
32 | #include <net/route.h> | ||
33 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
34 | #include <net/sock.h> | 18 | #include <net/dst.h> |
19 | #include <net/route.h> | ||
20 | #include <net/netlink.h> | ||
35 | #include <net/act_api.h> | 21 | #include <net/act_api.h> |
36 | #include <net/pkt_cls.h> | 22 | #include <net/pkt_cls.h> |
37 | 23 | ||
diff --git a/net/sched/cls_rsvp.c b/net/sched/cls_rsvp.c index 0a683c07c648..cbb5e0d600f3 100644 --- a/net/sched/cls_rsvp.c +++ b/net/sched/cls_rsvp.c | |||
@@ -10,27 +10,12 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <asm/uaccess.h> | ||
14 | #include <asm/system.h> | ||
15 | #include <linux/bitops.h> | ||
16 | #include <linux/types.h> | 13 | #include <linux/types.h> |
17 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
18 | #include <linux/string.h> | 15 | #include <linux/string.h> |
19 | #include <linux/mm.h> | ||
20 | #include <linux/socket.h> | ||
21 | #include <linux/sockios.h> | ||
22 | #include <linux/in.h> | ||
23 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/if_ether.h> | ||
26 | #include <linux/inet.h> | ||
27 | #include <linux/netdevice.h> | ||
28 | #include <linux/etherdevice.h> | ||
29 | #include <linux/notifier.h> | ||
30 | #include <net/ip.h> | ||
31 | #include <net/route.h> | ||
32 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
33 | #include <net/sock.h> | 18 | #include <net/ip.h> |
34 | #include <net/netlink.h> | 19 | #include <net/netlink.h> |
35 | #include <net/act_api.h> | 20 | #include <net/act_api.h> |
36 | #include <net/pkt_cls.h> | 21 | #include <net/pkt_cls.h> |
diff --git a/net/sched/cls_rsvp6.c b/net/sched/cls_rsvp6.c index 93b6abed57db..dd08aea2aee5 100644 --- a/net/sched/cls_rsvp6.c +++ b/net/sched/cls_rsvp6.c | |||
@@ -10,28 +10,12 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <asm/uaccess.h> | ||
14 | #include <asm/system.h> | ||
15 | #include <linux/bitops.h> | ||
16 | #include <linux/types.h> | 13 | #include <linux/types.h> |
17 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
18 | #include <linux/string.h> | 15 | #include <linux/string.h> |
19 | #include <linux/mm.h> | ||
20 | #include <linux/socket.h> | ||
21 | #include <linux/sockios.h> | ||
22 | #include <linux/in.h> | ||
23 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/if_ether.h> | ||
26 | #include <linux/inet.h> | ||
27 | #include <linux/netdevice.h> | ||
28 | #include <linux/etherdevice.h> | ||
29 | #include <linux/notifier.h> | ||
30 | #include <net/ip.h> | ||
31 | #include <linux/ipv6.h> | 17 | #include <linux/ipv6.h> |
32 | #include <net/route.h> | ||
33 | #include <linux/skbuff.h> | 18 | #include <linux/skbuff.h> |
34 | #include <net/sock.h> | ||
35 | #include <net/act_api.h> | 19 | #include <net/act_api.h> |
36 | #include <net/pkt_cls.h> | 20 | #include <net/pkt_cls.h> |
37 | #include <net/netlink.h> | 21 | #include <net/netlink.h> |
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index 47ac0c556429..2314820a080a 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c | |||
@@ -9,12 +9,9 @@ | |||
9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
10 | #include <linux/skbuff.h> | 10 | #include <linux/skbuff.h> |
11 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
12 | #include <linux/netdevice.h> | ||
13 | #include <net/ip.h> | ||
14 | #include <net/act_api.h> | 12 | #include <net/act_api.h> |
15 | #include <net/netlink.h> | 13 | #include <net/netlink.h> |
16 | #include <net/pkt_cls.h> | 14 | #include <net/pkt_cls.h> |
17 | #include <net/route.h> | ||
18 | 15 | ||
19 | 16 | ||
20 | /* | 17 | /* |
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index c7a347bd6d70..8dbe36912ecb 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c | |||
@@ -30,30 +30,14 @@ | |||
30 | * nfmark match added by Catalin(ux aka Dino) BOIE <catab at umbrella.ro> | 30 | * nfmark match added by Catalin(ux aka Dino) BOIE <catab at umbrella.ro> |
31 | */ | 31 | */ |
32 | 32 | ||
33 | #include <asm/uaccess.h> | ||
34 | #include <asm/system.h> | ||
35 | #include <linux/bitops.h> | ||
36 | #include <linux/module.h> | 33 | #include <linux/module.h> |
37 | #include <linux/types.h> | 34 | #include <linux/types.h> |
38 | #include <linux/kernel.h> | 35 | #include <linux/kernel.h> |
39 | #include <linux/string.h> | 36 | #include <linux/string.h> |
40 | #include <linux/mm.h> | ||
41 | #include <linux/socket.h> | ||
42 | #include <linux/sockios.h> | ||
43 | #include <linux/in.h> | ||
44 | #include <linux/errno.h> | 37 | #include <linux/errno.h> |
45 | #include <linux/interrupt.h> | ||
46 | #include <linux/if_ether.h> | ||
47 | #include <linux/inet.h> | ||
48 | #include <linux/netdevice.h> | ||
49 | #include <linux/etherdevice.h> | ||
50 | #include <linux/notifier.h> | ||
51 | #include <linux/rtnetlink.h> | 38 | #include <linux/rtnetlink.h> |
52 | #include <net/ip.h> | ||
53 | #include <net/netlink.h> | ||
54 | #include <net/route.h> | ||
55 | #include <linux/skbuff.h> | 39 | #include <linux/skbuff.h> |
56 | #include <net/sock.h> | 40 | #include <net/netlink.h> |
57 | #include <net/act_api.h> | 41 | #include <net/act_api.h> |
58 | #include <net/pkt_cls.h> | 42 | #include <net/pkt_cls.h> |
59 | 43 | ||
@@ -798,9 +782,6 @@ static int __init init_u32(void) | |||
798 | #ifdef CONFIG_CLS_U32_PERF | 782 | #ifdef CONFIG_CLS_U32_PERF |
799 | printk(" Performance counters on\n"); | 783 | printk(" Performance counters on\n"); |
800 | #endif | 784 | #endif |
801 | #ifdef CONFIG_NET_CLS_POLICE | ||
802 | printk(" OLD policer on \n"); | ||
803 | #endif | ||
804 | #ifdef CONFIG_NET_CLS_IND | 785 | #ifdef CONFIG_NET_CLS_IND |
805 | printk(" input device check on \n"); | 786 | printk(" input device check on \n"); |
806 | #endif | 787 | #endif |
diff --git a/net/sched/em_cmp.c b/net/sched/em_cmp.c index 8d6dacd81900..cc49c932641d 100644 --- a/net/sched/em_cmp.c +++ b/net/sched/em_cmp.c | |||
@@ -98,3 +98,4 @@ MODULE_LICENSE("GPL"); | |||
98 | module_init(init_em_cmp); | 98 | module_init(init_em_cmp); |
99 | module_exit(exit_em_cmp); | 99 | module_exit(exit_em_cmp); |
100 | 100 | ||
101 | MODULE_ALIAS_TCF_EMATCH(TCF_EM_CMP); | ||
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c index 60acf8cdb27b..650f09c8bd6a 100644 --- a/net/sched/em_meta.c +++ b/net/sched/em_meta.c | |||
@@ -848,3 +848,5 @@ MODULE_LICENSE("GPL"); | |||
848 | 848 | ||
849 | module_init(init_em_meta); | 849 | module_init(init_em_meta); |
850 | module_exit(exit_em_meta); | 850 | module_exit(exit_em_meta); |
851 | |||
852 | MODULE_ALIAS_TCF_EMATCH(TCF_EM_META); | ||
diff --git a/net/sched/em_nbyte.c b/net/sched/em_nbyte.c index b4b36efce292..370a1b2ea317 100644 --- a/net/sched/em_nbyte.c +++ b/net/sched/em_nbyte.c | |||
@@ -76,3 +76,5 @@ MODULE_LICENSE("GPL"); | |||
76 | 76 | ||
77 | module_init(init_em_nbyte); | 77 | module_init(init_em_nbyte); |
78 | module_exit(exit_em_nbyte); | 78 | module_exit(exit_em_nbyte); |
79 | |||
80 | MODULE_ALIAS_TCF_EMATCH(TCF_EM_NBYTE); | ||
diff --git a/net/sched/em_text.c b/net/sched/em_text.c index e8f46169449d..d5cd86efb7d0 100644 --- a/net/sched/em_text.c +++ b/net/sched/em_text.c | |||
@@ -150,3 +150,5 @@ MODULE_LICENSE("GPL"); | |||
150 | 150 | ||
151 | module_init(init_em_text); | 151 | module_init(init_em_text); |
152 | module_exit(exit_em_text); | 152 | module_exit(exit_em_text); |
153 | |||
154 | MODULE_ALIAS_TCF_EMATCH(TCF_EM_TEXT); | ||
diff --git a/net/sched/em_u32.c b/net/sched/em_u32.c index 0a2a7fe08de3..112796e4a7c4 100644 --- a/net/sched/em_u32.c +++ b/net/sched/em_u32.c | |||
@@ -60,3 +60,5 @@ MODULE_LICENSE("GPL"); | |||
60 | 60 | ||
61 | module_init(init_em_u32); | 61 | module_init(init_em_u32); |
62 | module_exit(exit_em_u32); | 62 | module_exit(exit_em_u32); |
63 | |||
64 | MODULE_ALIAS_TCF_EMATCH(TCF_EM_U32); | ||
diff --git a/net/sched/ematch.c b/net/sched/ematch.c index 63146d339d81..f3a104e323bd 100644 --- a/net/sched/ematch.c +++ b/net/sched/ematch.c | |||
@@ -84,9 +84,7 @@ | |||
84 | #include <linux/module.h> | 84 | #include <linux/module.h> |
85 | #include <linux/types.h> | 85 | #include <linux/types.h> |
86 | #include <linux/kernel.h> | 86 | #include <linux/kernel.h> |
87 | #include <linux/mm.h> | ||
88 | #include <linux/errno.h> | 87 | #include <linux/errno.h> |
89 | #include <linux/interrupt.h> | ||
90 | #include <linux/rtnetlink.h> | 88 | #include <linux/rtnetlink.h> |
91 | #include <linux/skbuff.h> | 89 | #include <linux/skbuff.h> |
92 | #include <net/pkt_cls.h> | 90 | #include <net/pkt_cls.h> |
@@ -224,6 +222,19 @@ static int tcf_em_validate(struct tcf_proto *tp, | |||
224 | 222 | ||
225 | if (em->ops == NULL) { | 223 | if (em->ops == NULL) { |
226 | err = -ENOENT; | 224 | err = -ENOENT; |
225 | #ifdef CONFIG_KMOD | ||
226 | __rtnl_unlock(); | ||
227 | request_module("ematch-kind-%u", em_hdr->kind); | ||
228 | rtnl_lock(); | ||
229 | em->ops = tcf_em_lookup(em_hdr->kind); | ||
230 | if (em->ops) { | ||
231 | /* We dropped the RTNL mutex in order to | ||
232 | * perform the module load. Tell the caller | ||
233 | * to replay the request. */ | ||
234 | module_put(em->ops->owner); | ||
235 | err = -EAGAIN; | ||
236 | } | ||
237 | #endif | ||
227 | goto errout; | 238 | goto errout; |
228 | } | 239 | } |
229 | 240 | ||
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index bec600af03ca..13c09bc32aa3 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -19,30 +19,18 @@ | |||
19 | #include <linux/types.h> | 19 | #include <linux/types.h> |
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/string.h> | 21 | #include <linux/string.h> |
22 | #include <linux/mm.h> | ||
23 | #include <linux/socket.h> | ||
24 | #include <linux/sockios.h> | ||
25 | #include <linux/in.h> | ||
26 | #include <linux/errno.h> | 22 | #include <linux/errno.h> |
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/netdevice.h> | ||
29 | #include <linux/skbuff.h> | 23 | #include <linux/skbuff.h> |
30 | #include <linux/init.h> | 24 | #include <linux/init.h> |
31 | #include <linux/proc_fs.h> | 25 | #include <linux/proc_fs.h> |
32 | #include <linux/seq_file.h> | 26 | #include <linux/seq_file.h> |
33 | #include <linux/kmod.h> | 27 | #include <linux/kmod.h> |
34 | #include <linux/list.h> | 28 | #include <linux/list.h> |
35 | #include <linux/bitops.h> | ||
36 | #include <linux/hrtimer.h> | 29 | #include <linux/hrtimer.h> |
37 | 30 | ||
38 | #include <net/netlink.h> | 31 | #include <net/netlink.h> |
39 | #include <net/sock.h> | ||
40 | #include <net/pkt_sched.h> | 32 | #include <net/pkt_sched.h> |
41 | 33 | ||
42 | #include <asm/processor.h> | ||
43 | #include <asm/uaccess.h> | ||
44 | #include <asm/system.h> | ||
45 | |||
46 | static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n, u32 clid, | 34 | static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n, u32 clid, |
47 | struct Qdisc *old, struct Qdisc *new); | 35 | struct Qdisc *old, struct Qdisc *new); |
48 | static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n, | 36 | static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n, |
@@ -290,11 +278,7 @@ static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer) | |||
290 | 278 | ||
291 | wd->qdisc->flags &= ~TCQ_F_THROTTLED; | 279 | wd->qdisc->flags &= ~TCQ_F_THROTTLED; |
292 | smp_wmb(); | 280 | smp_wmb(); |
293 | if (spin_trylock(&dev->queue_lock)) { | 281 | netif_schedule(dev); |
294 | qdisc_run(dev); | ||
295 | spin_unlock(&dev->queue_lock); | ||
296 | } else | ||
297 | netif_schedule(dev); | ||
298 | 282 | ||
299 | return HRTIMER_NORESTART; | 283 | return HRTIMER_NORESTART; |
300 | } | 284 | } |
@@ -515,7 +499,6 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp) | |||
515 | sch->handle = handle; | 499 | sch->handle = handle; |
516 | 500 | ||
517 | if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) { | 501 | if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) { |
518 | #ifdef CONFIG_NET_ESTIMATOR | ||
519 | if (tca[TCA_RATE-1]) { | 502 | if (tca[TCA_RATE-1]) { |
520 | err = gen_new_estimator(&sch->bstats, &sch->rate_est, | 503 | err = gen_new_estimator(&sch->bstats, &sch->rate_est, |
521 | sch->stats_lock, | 504 | sch->stats_lock, |
@@ -531,7 +514,6 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp) | |||
531 | goto err_out3; | 514 | goto err_out3; |
532 | } | 515 | } |
533 | } | 516 | } |
534 | #endif | ||
535 | qdisc_lock_tree(dev); | 517 | qdisc_lock_tree(dev); |
536 | list_add_tail(&sch->list, &dev->qdisc_list); | 518 | list_add_tail(&sch->list, &dev->qdisc_list); |
537 | qdisc_unlock_tree(dev); | 519 | qdisc_unlock_tree(dev); |
@@ -559,11 +541,9 @@ static int qdisc_change(struct Qdisc *sch, struct rtattr **tca) | |||
559 | if (err) | 541 | if (err) |
560 | return err; | 542 | return err; |
561 | } | 543 | } |
562 | #ifdef CONFIG_NET_ESTIMATOR | ||
563 | if (tca[TCA_RATE-1]) | 544 | if (tca[TCA_RATE-1]) |
564 | gen_replace_estimator(&sch->bstats, &sch->rate_est, | 545 | gen_replace_estimator(&sch->bstats, &sch->rate_est, |
565 | sch->stats_lock, tca[TCA_RATE-1]); | 546 | sch->stats_lock, tca[TCA_RATE-1]); |
566 | #endif | ||
567 | return 0; | 547 | return 0; |
568 | } | 548 | } |
569 | 549 | ||
@@ -839,9 +819,7 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid, | |||
839 | goto rtattr_failure; | 819 | goto rtattr_failure; |
840 | 820 | ||
841 | if (gnet_stats_copy_basic(&d, &q->bstats) < 0 || | 821 | if (gnet_stats_copy_basic(&d, &q->bstats) < 0 || |
842 | #ifdef CONFIG_NET_ESTIMATOR | ||
843 | gnet_stats_copy_rate_est(&d, &q->rate_est) < 0 || | 822 | gnet_stats_copy_rate_est(&d, &q->rate_est) < 0 || |
844 | #endif | ||
845 | gnet_stats_copy_queue(&d, &q->qstats) < 0) | 823 | gnet_stats_copy_queue(&d, &q->qstats) < 0) |
846 | goto rtattr_failure; | 824 | goto rtattr_failure; |
847 | 825 | ||
@@ -1167,47 +1145,57 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) | |||
1167 | to this qdisc, (optionally) tests for protocol and asks | 1145 | to this qdisc, (optionally) tests for protocol and asks |
1168 | specific classifiers. | 1146 | specific classifiers. |
1169 | */ | 1147 | */ |
1148 | int tc_classify_compat(struct sk_buff *skb, struct tcf_proto *tp, | ||
1149 | struct tcf_result *res) | ||
1150 | { | ||
1151 | __be16 protocol = skb->protocol; | ||
1152 | int err = 0; | ||
1153 | |||
1154 | for (; tp; tp = tp->next) { | ||
1155 | if ((tp->protocol == protocol || | ||
1156 | tp->protocol == htons(ETH_P_ALL)) && | ||
1157 | (err = tp->classify(skb, tp, res)) >= 0) { | ||
1158 | #ifdef CONFIG_NET_CLS_ACT | ||
1159 | if (err != TC_ACT_RECLASSIFY && skb->tc_verd) | ||
1160 | skb->tc_verd = SET_TC_VERD(skb->tc_verd, 0); | ||
1161 | #endif | ||
1162 | return err; | ||
1163 | } | ||
1164 | } | ||
1165 | return -1; | ||
1166 | } | ||
1167 | EXPORT_SYMBOL(tc_classify_compat); | ||
1168 | |||
1170 | int tc_classify(struct sk_buff *skb, struct tcf_proto *tp, | 1169 | int tc_classify(struct sk_buff *skb, struct tcf_proto *tp, |
1171 | struct tcf_result *res) | 1170 | struct tcf_result *res) |
1172 | { | 1171 | { |
1173 | int err = 0; | 1172 | int err = 0; |
1174 | __be16 protocol = skb->protocol; | 1173 | __be16 protocol; |
1175 | #ifdef CONFIG_NET_CLS_ACT | 1174 | #ifdef CONFIG_NET_CLS_ACT |
1176 | struct tcf_proto *otp = tp; | 1175 | struct tcf_proto *otp = tp; |
1177 | reclassify: | 1176 | reclassify: |
1178 | #endif | 1177 | #endif |
1179 | protocol = skb->protocol; | 1178 | protocol = skb->protocol; |
1180 | 1179 | ||
1181 | for ( ; tp; tp = tp->next) { | 1180 | err = tc_classify_compat(skb, tp, res); |
1182 | if ((tp->protocol == protocol || | ||
1183 | tp->protocol == htons(ETH_P_ALL)) && | ||
1184 | (err = tp->classify(skb, tp, res)) >= 0) { | ||
1185 | #ifdef CONFIG_NET_CLS_ACT | 1181 | #ifdef CONFIG_NET_CLS_ACT |
1186 | if ( TC_ACT_RECLASSIFY == err) { | 1182 | if (err == TC_ACT_RECLASSIFY) { |
1187 | __u32 verd = (__u32) G_TC_VERD(skb->tc_verd); | 1183 | u32 verd = G_TC_VERD(skb->tc_verd); |
1188 | tp = otp; | 1184 | tp = otp; |
1189 | 1185 | ||
1190 | if (MAX_REC_LOOP < verd++) { | 1186 | if (verd++ >= MAX_REC_LOOP) { |
1191 | printk("rule prio %d protocol %02x reclassify is buggy packet dropped\n", | 1187 | printk("rule prio %u protocol %02x reclassify loop, " |
1192 | tp->prio&0xffff, ntohs(tp->protocol)); | 1188 | "packet dropped\n", |
1193 | return TC_ACT_SHOT; | 1189 | tp->prio&0xffff, ntohs(tp->protocol)); |
1194 | } | 1190 | return TC_ACT_SHOT; |
1195 | skb->tc_verd = SET_TC_VERD(skb->tc_verd,verd); | ||
1196 | goto reclassify; | ||
1197 | } else { | ||
1198 | if (skb->tc_verd) | ||
1199 | skb->tc_verd = SET_TC_VERD(skb->tc_verd,0); | ||
1200 | return err; | ||
1201 | } | ||
1202 | #else | ||
1203 | |||
1204 | return err; | ||
1205 | #endif | ||
1206 | } | 1191 | } |
1207 | 1192 | skb->tc_verd = SET_TC_VERD(skb->tc_verd, verd); | |
1193 | goto reclassify; | ||
1208 | } | 1194 | } |
1209 | return -1; | 1195 | #endif |
1196 | return err; | ||
1210 | } | 1197 | } |
1198 | EXPORT_SYMBOL(tc_classify); | ||
1211 | 1199 | ||
1212 | void tcf_destroy(struct tcf_proto *tp) | 1200 | void tcf_destroy(struct tcf_proto *tp) |
1213 | { | 1201 | { |
@@ -1274,4 +1262,3 @@ EXPORT_SYMBOL(qdisc_get_rtab); | |||
1274 | EXPORT_SYMBOL(qdisc_put_rtab); | 1262 | EXPORT_SYMBOL(qdisc_put_rtab); |
1275 | EXPORT_SYMBOL(register_qdisc); | 1263 | EXPORT_SYMBOL(register_qdisc); |
1276 | EXPORT_SYMBOL(unregister_qdisc); | 1264 | EXPORT_SYMBOL(unregister_qdisc); |
1277 | EXPORT_SYMBOL(tc_classify); | ||
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index d1c383fca82c..417ec8fb7f1a 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c | |||
@@ -2,24 +2,19 @@ | |||
2 | 2 | ||
3 | /* Written 1998-2000 by Werner Almesberger, EPFL ICA */ | 3 | /* Written 1998-2000 by Werner Almesberger, EPFL ICA */ |
4 | 4 | ||
5 | |||
6 | #include <linux/module.h> | 5 | #include <linux/module.h> |
7 | #include <linux/init.h> | 6 | #include <linux/init.h> |
8 | #include <linux/string.h> | 7 | #include <linux/string.h> |
9 | #include <linux/errno.h> | 8 | #include <linux/errno.h> |
10 | #include <linux/skbuff.h> | 9 | #include <linux/skbuff.h> |
11 | #include <linux/interrupt.h> | ||
12 | #include <linux/atmdev.h> | 10 | #include <linux/atmdev.h> |
13 | #include <linux/atmclip.h> | 11 | #include <linux/atmclip.h> |
14 | #include <linux/netdevice.h> | ||
15 | #include <linux/rtnetlink.h> | 12 | #include <linux/rtnetlink.h> |
16 | #include <linux/file.h> /* for fput */ | 13 | #include <linux/file.h> /* for fput */ |
17 | #include <net/netlink.h> | 14 | #include <net/netlink.h> |
18 | #include <net/pkt_sched.h> | 15 | #include <net/pkt_sched.h> |
19 | #include <net/sock.h> | ||
20 | |||
21 | 16 | ||
22 | extern struct socket *sockfd_lookup(int fd, int *err); /* @@@ fix this */ | 17 | extern struct socket *sockfd_lookup(int fd, int *err); /* @@@ fix this */ |
23 | 18 | ||
24 | #if 0 /* control */ | 19 | #if 0 /* control */ |
25 | #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args) | 20 | #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args) |
@@ -33,7 +28,6 @@ extern struct socket *sockfd_lookup(int fd, int *err); /* @@@ fix this */ | |||
33 | #define D2PRINTK(format,args...) | 28 | #define D2PRINTK(format,args...) |
34 | #endif | 29 | #endif |
35 | 30 | ||
36 | |||
37 | /* | 31 | /* |
38 | * The ATM queuing discipline provides a framework for invoking classifiers | 32 | * The ATM queuing discipline provides a framework for invoking classifiers |
39 | * (aka "filters"), which in turn select classes of this queuing discipline. | 33 | * (aka "filters"), which in turn select classes of this queuing discipline. |
@@ -55,23 +49,21 @@ extern struct socket *sockfd_lookup(int fd, int *err); /* @@@ fix this */ | |||
55 | * - should lock the flow while there is data in the queue (?) | 49 | * - should lock the flow while there is data in the queue (?) |
56 | */ | 50 | */ |
57 | 51 | ||
58 | |||
59 | #define PRIV(sch) qdisc_priv(sch) | 52 | #define PRIV(sch) qdisc_priv(sch) |
60 | #define VCC2FLOW(vcc) ((struct atm_flow_data *) ((vcc)->user_back)) | 53 | #define VCC2FLOW(vcc) ((struct atm_flow_data *) ((vcc)->user_back)) |
61 | 54 | ||
62 | |||
63 | struct atm_flow_data { | 55 | struct atm_flow_data { |
64 | struct Qdisc *q; /* FIFO, TBF, etc. */ | 56 | struct Qdisc *q; /* FIFO, TBF, etc. */ |
65 | struct tcf_proto *filter_list; | 57 | struct tcf_proto *filter_list; |
66 | struct atm_vcc *vcc; /* VCC; NULL if VCC is closed */ | 58 | struct atm_vcc *vcc; /* VCC; NULL if VCC is closed */ |
67 | void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb); /* chaining */ | 59 | void (*old_pop)(struct atm_vcc *vcc, |
60 | struct sk_buff * skb); /* chaining */ | ||
68 | struct atm_qdisc_data *parent; /* parent qdisc */ | 61 | struct atm_qdisc_data *parent; /* parent qdisc */ |
69 | struct socket *sock; /* for closing */ | 62 | struct socket *sock; /* for closing */ |
70 | u32 classid; /* x:y type ID */ | 63 | u32 classid; /* x:y type ID */ |
71 | int ref; /* reference count */ | 64 | int ref; /* reference count */ |
72 | struct gnet_stats_basic bstats; | 65 | struct gnet_stats_basic bstats; |
73 | struct gnet_stats_queue qstats; | 66 | struct gnet_stats_queue qstats; |
74 | spinlock_t *stats_lock; | ||
75 | struct atm_flow_data *next; | 67 | struct atm_flow_data *next; |
76 | struct atm_flow_data *excess; /* flow for excess traffic; | 68 | struct atm_flow_data *excess; /* flow for excess traffic; |
77 | NULL to set CLP instead */ | 69 | NULL to set CLP instead */ |
@@ -86,76 +78,74 @@ struct atm_qdisc_data { | |||
86 | struct tasklet_struct task; /* requeue tasklet */ | 78 | struct tasklet_struct task; /* requeue tasklet */ |
87 | }; | 79 | }; |
88 | 80 | ||
89 | |||
90 | /* ------------------------- Class/flow operations ------------------------- */ | 81 | /* ------------------------- Class/flow operations ------------------------- */ |
91 | 82 | ||
92 | 83 | static int find_flow(struct atm_qdisc_data *qdisc, struct atm_flow_data *flow) | |
93 | static int find_flow(struct atm_qdisc_data *qdisc,struct atm_flow_data *flow) | ||
94 | { | 84 | { |
95 | struct atm_flow_data *walk; | 85 | struct atm_flow_data *walk; |
96 | 86 | ||
97 | DPRINTK("find_flow(qdisc %p,flow %p)\n",qdisc,flow); | 87 | DPRINTK("find_flow(qdisc %p,flow %p)\n", qdisc, flow); |
98 | for (walk = qdisc->flows; walk; walk = walk->next) | 88 | for (walk = qdisc->flows; walk; walk = walk->next) |
99 | if (walk == flow) return 1; | 89 | if (walk == flow) |
90 | return 1; | ||
100 | DPRINTK("find_flow: not found\n"); | 91 | DPRINTK("find_flow: not found\n"); |
101 | return 0; | 92 | return 0; |
102 | } | 93 | } |
103 | 94 | ||
104 | 95 | static inline struct atm_flow_data *lookup_flow(struct Qdisc *sch, u32 classid) | |
105 | static __inline__ struct atm_flow_data *lookup_flow(struct Qdisc *sch, | ||
106 | u32 classid) | ||
107 | { | 96 | { |
108 | struct atm_qdisc_data *p = PRIV(sch); | 97 | struct atm_qdisc_data *p = PRIV(sch); |
109 | struct atm_flow_data *flow; | 98 | struct atm_flow_data *flow; |
110 | 99 | ||
111 | for (flow = p->flows; flow; flow = flow->next) | 100 | for (flow = p->flows; flow; flow = flow->next) |
112 | if (flow->classid == classid) break; | 101 | if (flow->classid == classid) |
102 | break; | ||
113 | return flow; | 103 | return flow; |
114 | } | 104 | } |
115 | 105 | ||
116 | 106 | static int atm_tc_graft(struct Qdisc *sch, unsigned long arg, | |
117 | static int atm_tc_graft(struct Qdisc *sch,unsigned long arg, | 107 | struct Qdisc *new, struct Qdisc **old) |
118 | struct Qdisc *new,struct Qdisc **old) | ||
119 | { | 108 | { |
120 | struct atm_qdisc_data *p = PRIV(sch); | 109 | struct atm_qdisc_data *p = PRIV(sch); |
121 | struct atm_flow_data *flow = (struct atm_flow_data *) arg; | 110 | struct atm_flow_data *flow = (struct atm_flow_data *)arg; |
122 | 111 | ||
123 | DPRINTK("atm_tc_graft(sch %p,[qdisc %p],flow %p,new %p,old %p)\n",sch, | 112 | DPRINTK("atm_tc_graft(sch %p,[qdisc %p],flow %p,new %p,old %p)\n", |
124 | p,flow,new,old); | 113 | sch, p, flow, new, old); |
125 | if (!find_flow(p,flow)) return -EINVAL; | 114 | if (!find_flow(p, flow)) |
126 | if (!new) new = &noop_qdisc; | 115 | return -EINVAL; |
127 | *old = xchg(&flow->q,new); | 116 | if (!new) |
128 | if (*old) qdisc_reset(*old); | 117 | new = &noop_qdisc; |
118 | *old = xchg(&flow->q, new); | ||
119 | if (*old) | ||
120 | qdisc_reset(*old); | ||
129 | return 0; | 121 | return 0; |
130 | } | 122 | } |
131 | 123 | ||
132 | 124 | static struct Qdisc *atm_tc_leaf(struct Qdisc *sch, unsigned long cl) | |
133 | static struct Qdisc *atm_tc_leaf(struct Qdisc *sch,unsigned long cl) | ||
134 | { | 125 | { |
135 | struct atm_flow_data *flow = (struct atm_flow_data *) cl; | 126 | struct atm_flow_data *flow = (struct atm_flow_data *)cl; |
136 | 127 | ||
137 | DPRINTK("atm_tc_leaf(sch %p,flow %p)\n",sch,flow); | 128 | DPRINTK("atm_tc_leaf(sch %p,flow %p)\n", sch, flow); |
138 | return flow ? flow->q : NULL; | 129 | return flow ? flow->q : NULL; |
139 | } | 130 | } |
140 | 131 | ||
141 | 132 | static unsigned long atm_tc_get(struct Qdisc *sch, u32 classid) | |
142 | static unsigned long atm_tc_get(struct Qdisc *sch,u32 classid) | ||
143 | { | 133 | { |
144 | struct atm_qdisc_data *p __attribute__((unused)) = PRIV(sch); | 134 | struct atm_qdisc_data *p __maybe_unused = PRIV(sch); |
145 | struct atm_flow_data *flow; | 135 | struct atm_flow_data *flow; |
146 | 136 | ||
147 | DPRINTK("atm_tc_get(sch %p,[qdisc %p],classid %x)\n",sch,p,classid); | 137 | DPRINTK("atm_tc_get(sch %p,[qdisc %p],classid %x)\n", sch, p, classid); |
148 | flow = lookup_flow(sch,classid); | 138 | flow = lookup_flow(sch, classid); |
149 | if (flow) flow->ref++; | 139 | if (flow) |
150 | DPRINTK("atm_tc_get: flow %p\n",flow); | 140 | flow->ref++; |
151 | return (unsigned long) flow; | 141 | DPRINTK("atm_tc_get: flow %p\n", flow); |
142 | return (unsigned long)flow; | ||
152 | } | 143 | } |
153 | 144 | ||
154 | |||
155 | static unsigned long atm_tc_bind_filter(struct Qdisc *sch, | 145 | static unsigned long atm_tc_bind_filter(struct Qdisc *sch, |
156 | unsigned long parent, u32 classid) | 146 | unsigned long parent, u32 classid) |
157 | { | 147 | { |
158 | return atm_tc_get(sch,classid); | 148 | return atm_tc_get(sch, classid); |
159 | } | 149 | } |
160 | 150 | ||
161 | /* | 151 | /* |
@@ -163,72 +153,75 @@ static unsigned long atm_tc_bind_filter(struct Qdisc *sch, | |||
163 | * requested (atm_tc_destroy, etc.). The assumption here is that we never drop | 153 | * requested (atm_tc_destroy, etc.). The assumption here is that we never drop |
164 | * anything that still seems to be in use. | 154 | * anything that still seems to be in use. |
165 | */ | 155 | */ |
166 | |||
167 | static void atm_tc_put(struct Qdisc *sch, unsigned long cl) | 156 | static void atm_tc_put(struct Qdisc *sch, unsigned long cl) |
168 | { | 157 | { |
169 | struct atm_qdisc_data *p = PRIV(sch); | 158 | struct atm_qdisc_data *p = PRIV(sch); |
170 | struct atm_flow_data *flow = (struct atm_flow_data *) cl; | 159 | struct atm_flow_data *flow = (struct atm_flow_data *)cl; |
171 | struct atm_flow_data **prev; | 160 | struct atm_flow_data **prev; |
172 | 161 | ||
173 | DPRINTK("atm_tc_put(sch %p,[qdisc %p],flow %p)\n",sch,p,flow); | 162 | DPRINTK("atm_tc_put(sch %p,[qdisc %p],flow %p)\n", sch, p, flow); |
174 | if (--flow->ref) return; | 163 | if (--flow->ref) |
164 | return; | ||
175 | DPRINTK("atm_tc_put: destroying\n"); | 165 | DPRINTK("atm_tc_put: destroying\n"); |
176 | for (prev = &p->flows; *prev; prev = &(*prev)->next) | 166 | for (prev = &p->flows; *prev; prev = &(*prev)->next) |
177 | if (*prev == flow) break; | 167 | if (*prev == flow) |
168 | break; | ||
178 | if (!*prev) { | 169 | if (!*prev) { |
179 | printk(KERN_CRIT "atm_tc_put: class %p not found\n",flow); | 170 | printk(KERN_CRIT "atm_tc_put: class %p not found\n", flow); |
180 | return; | 171 | return; |
181 | } | 172 | } |
182 | *prev = flow->next; | 173 | *prev = flow->next; |
183 | DPRINTK("atm_tc_put: qdisc %p\n",flow->q); | 174 | DPRINTK("atm_tc_put: qdisc %p\n", flow->q); |
184 | qdisc_destroy(flow->q); | 175 | qdisc_destroy(flow->q); |
185 | tcf_destroy_chain(flow->filter_list); | 176 | tcf_destroy_chain(flow->filter_list); |
186 | if (flow->sock) { | 177 | if (flow->sock) { |
187 | DPRINTK("atm_tc_put: f_count %d\n", | 178 | DPRINTK("atm_tc_put: f_count %d\n", |
188 | file_count(flow->sock->file)); | 179 | file_count(flow->sock->file)); |
189 | flow->vcc->pop = flow->old_pop; | 180 | flow->vcc->pop = flow->old_pop; |
190 | sockfd_put(flow->sock); | 181 | sockfd_put(flow->sock); |
191 | } | 182 | } |
192 | if (flow->excess) atm_tc_put(sch,(unsigned long) flow->excess); | 183 | if (flow->excess) |
193 | if (flow != &p->link) kfree(flow); | 184 | atm_tc_put(sch, (unsigned long)flow->excess); |
185 | if (flow != &p->link) | ||
186 | kfree(flow); | ||
194 | /* | 187 | /* |
195 | * If flow == &p->link, the qdisc no longer works at this point and | 188 | * If flow == &p->link, the qdisc no longer works at this point and |
196 | * needs to be removed. (By the caller of atm_tc_put.) | 189 | * needs to be removed. (By the caller of atm_tc_put.) |
197 | */ | 190 | */ |
198 | } | 191 | } |
199 | 192 | ||
200 | 193 | static void sch_atm_pop(struct atm_vcc *vcc, struct sk_buff *skb) | |
201 | static void sch_atm_pop(struct atm_vcc *vcc,struct sk_buff *skb) | ||
202 | { | 194 | { |
203 | struct atm_qdisc_data *p = VCC2FLOW(vcc)->parent; | 195 | struct atm_qdisc_data *p = VCC2FLOW(vcc)->parent; |
204 | 196 | ||
205 | D2PRINTK("sch_atm_pop(vcc %p,skb %p,[qdisc %p])\n",vcc,skb,p); | 197 | D2PRINTK("sch_atm_pop(vcc %p,skb %p,[qdisc %p])\n", vcc, skb, p); |
206 | VCC2FLOW(vcc)->old_pop(vcc,skb); | 198 | VCC2FLOW(vcc)->old_pop(vcc, skb); |
207 | tasklet_schedule(&p->task); | 199 | tasklet_schedule(&p->task); |
208 | } | 200 | } |
209 | 201 | ||
210 | static const u8 llc_oui_ip[] = { | 202 | static const u8 llc_oui_ip[] = { |
211 | 0xaa, /* DSAP: non-ISO */ | 203 | 0xaa, /* DSAP: non-ISO */ |
212 | 0xaa, /* SSAP: non-ISO */ | 204 | 0xaa, /* SSAP: non-ISO */ |
213 | 0x03, /* Ctrl: Unnumbered Information Command PDU */ | 205 | 0x03, /* Ctrl: Unnumbered Information Command PDU */ |
214 | 0x00, /* OUI: EtherType */ | 206 | 0x00, /* OUI: EtherType */ |
215 | 0x00, 0x00, | 207 | 0x00, 0x00, |
216 | 0x08, 0x00 }; /* Ethertype IP (0800) */ | 208 | 0x08, 0x00 |
209 | }; /* Ethertype IP (0800) */ | ||
217 | 210 | ||
218 | static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent, | 211 | static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent, |
219 | struct rtattr **tca, unsigned long *arg) | 212 | struct rtattr **tca, unsigned long *arg) |
220 | { | 213 | { |
221 | struct atm_qdisc_data *p = PRIV(sch); | 214 | struct atm_qdisc_data *p = PRIV(sch); |
222 | struct atm_flow_data *flow = (struct atm_flow_data *) *arg; | 215 | struct atm_flow_data *flow = (struct atm_flow_data *)*arg; |
223 | struct atm_flow_data *excess = NULL; | 216 | struct atm_flow_data *excess = NULL; |
224 | struct rtattr *opt = tca[TCA_OPTIONS-1]; | 217 | struct rtattr *opt = tca[TCA_OPTIONS - 1]; |
225 | struct rtattr *tb[TCA_ATM_MAX]; | 218 | struct rtattr *tb[TCA_ATM_MAX]; |
226 | struct socket *sock; | 219 | struct socket *sock; |
227 | int fd,error,hdr_len; | 220 | int fd, error, hdr_len; |
228 | void *hdr; | 221 | void *hdr; |
229 | 222 | ||
230 | DPRINTK("atm_tc_change(sch %p,[qdisc %p],classid %x,parent %x," | 223 | DPRINTK("atm_tc_change(sch %p,[qdisc %p],classid %x,parent %x," |
231 | "flow %p,opt %p)\n",sch,p,classid,parent,flow,opt); | 224 | "flow %p,opt %p)\n", sch, p, classid, parent, flow, opt); |
232 | /* | 225 | /* |
233 | * The concept of parents doesn't apply for this qdisc. | 226 | * The concept of parents doesn't apply for this qdisc. |
234 | */ | 227 | */ |
@@ -241,33 +234,36 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent, | |||
241 | * class needs to be removed and a new one added. (This may be changed | 234 | * class needs to be removed and a new one added. (This may be changed |
242 | * later.) | 235 | * later.) |
243 | */ | 236 | */ |
244 | if (flow) return -EBUSY; | 237 | if (flow) |
238 | return -EBUSY; | ||
245 | if (opt == NULL || rtattr_parse_nested(tb, TCA_ATM_MAX, opt)) | 239 | if (opt == NULL || rtattr_parse_nested(tb, TCA_ATM_MAX, opt)) |
246 | return -EINVAL; | 240 | return -EINVAL; |
247 | if (!tb[TCA_ATM_FD-1] || RTA_PAYLOAD(tb[TCA_ATM_FD-1]) < sizeof(fd)) | 241 | if (!tb[TCA_ATM_FD - 1] || RTA_PAYLOAD(tb[TCA_ATM_FD - 1]) < sizeof(fd)) |
248 | return -EINVAL; | 242 | return -EINVAL; |
249 | fd = *(int *) RTA_DATA(tb[TCA_ATM_FD-1]); | 243 | fd = *(int *)RTA_DATA(tb[TCA_ATM_FD - 1]); |
250 | DPRINTK("atm_tc_change: fd %d\n",fd); | 244 | DPRINTK("atm_tc_change: fd %d\n", fd); |
251 | if (tb[TCA_ATM_HDR-1]) { | 245 | if (tb[TCA_ATM_HDR - 1]) { |
252 | hdr_len = RTA_PAYLOAD(tb[TCA_ATM_HDR-1]); | 246 | hdr_len = RTA_PAYLOAD(tb[TCA_ATM_HDR - 1]); |
253 | hdr = RTA_DATA(tb[TCA_ATM_HDR-1]); | 247 | hdr = RTA_DATA(tb[TCA_ATM_HDR - 1]); |
254 | } | 248 | } else { |
255 | else { | ||
256 | hdr_len = RFC1483LLC_LEN; | 249 | hdr_len = RFC1483LLC_LEN; |
257 | hdr = NULL; /* default LLC/SNAP for IP */ | 250 | hdr = NULL; /* default LLC/SNAP for IP */ |
258 | } | 251 | } |
259 | if (!tb[TCA_ATM_EXCESS-1]) excess = NULL; | 252 | if (!tb[TCA_ATM_EXCESS - 1]) |
253 | excess = NULL; | ||
260 | else { | 254 | else { |
261 | if (RTA_PAYLOAD(tb[TCA_ATM_EXCESS-1]) != sizeof(u32)) | 255 | if (RTA_PAYLOAD(tb[TCA_ATM_EXCESS - 1]) != sizeof(u32)) |
262 | return -EINVAL; | 256 | return -EINVAL; |
263 | excess = (struct atm_flow_data *) atm_tc_get(sch, | 257 | excess = (struct atm_flow_data *) |
264 | *(u32 *) RTA_DATA(tb[TCA_ATM_EXCESS-1])); | 258 | atm_tc_get(sch, *(u32 *)RTA_DATA(tb[TCA_ATM_EXCESS - 1])); |
265 | if (!excess) return -ENOENT; | 259 | if (!excess) |
260 | return -ENOENT; | ||
266 | } | 261 | } |
267 | DPRINTK("atm_tc_change: type %d, payload %d, hdr_len %d\n", | 262 | DPRINTK("atm_tc_change: type %d, payload %d, hdr_len %d\n", |
268 | opt->rta_type,RTA_PAYLOAD(opt),hdr_len); | 263 | opt->rta_type, RTA_PAYLOAD(opt), hdr_len); |
269 | if (!(sock = sockfd_lookup(fd,&error))) return error; /* f_count++ */ | 264 | if (!(sock = sockfd_lookup(fd, &error))) |
270 | DPRINTK("atm_tc_change: f_count %d\n",file_count(sock->file)); | 265 | return error; /* f_count++ */ |
266 | DPRINTK("atm_tc_change: f_count %d\n", file_count(sock->file)); | ||
271 | if (sock->ops->family != PF_ATMSVC && sock->ops->family != PF_ATMPVC) { | 267 | if (sock->ops->family != PF_ATMSVC && sock->ops->family != PF_ATMPVC) { |
272 | error = -EPROTOTYPE; | 268 | error = -EPROTOTYPE; |
273 | goto err_out; | 269 | goto err_out; |
@@ -280,37 +276,37 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent, | |||
280 | error = -EINVAL; | 276 | error = -EINVAL; |
281 | goto err_out; | 277 | goto err_out; |
282 | } | 278 | } |
283 | if (find_flow(p,flow)) { | 279 | if (find_flow(p, flow)) { |
284 | error = -EEXIST; | 280 | error = -EEXIST; |
285 | goto err_out; | 281 | goto err_out; |
286 | } | 282 | } |
287 | } | 283 | } else { |
288 | else { | ||
289 | int i; | 284 | int i; |
290 | unsigned long cl; | 285 | unsigned long cl; |
291 | 286 | ||
292 | for (i = 1; i < 0x8000; i++) { | 287 | for (i = 1; i < 0x8000; i++) { |
293 | classid = TC_H_MAKE(sch->handle,0x8000 | i); | 288 | classid = TC_H_MAKE(sch->handle, 0x8000 | i); |
294 | if (!(cl = atm_tc_get(sch,classid))) break; | 289 | if (!(cl = atm_tc_get(sch, classid))) |
295 | atm_tc_put(sch,cl); | 290 | break; |
291 | atm_tc_put(sch, cl); | ||
296 | } | 292 | } |
297 | } | 293 | } |
298 | DPRINTK("atm_tc_change: new id %x\n",classid); | 294 | DPRINTK("atm_tc_change: new id %x\n", classid); |
299 | flow = kmalloc(sizeof(struct atm_flow_data)+hdr_len,GFP_KERNEL); | 295 | flow = kmalloc(sizeof(struct atm_flow_data) + hdr_len, GFP_KERNEL); |
300 | DPRINTK("atm_tc_change: flow %p\n",flow); | 296 | DPRINTK("atm_tc_change: flow %p\n", flow); |
301 | if (!flow) { | 297 | if (!flow) { |
302 | error = -ENOBUFS; | 298 | error = -ENOBUFS; |
303 | goto err_out; | 299 | goto err_out; |
304 | } | 300 | } |
305 | memset(flow,0,sizeof(*flow)); | 301 | memset(flow, 0, sizeof(*flow)); |
306 | flow->filter_list = NULL; | 302 | flow->filter_list = NULL; |
307 | if (!(flow->q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops,classid))) | 303 | if (!(flow->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid))) |
308 | flow->q = &noop_qdisc; | 304 | flow->q = &noop_qdisc; |
309 | DPRINTK("atm_tc_change: qdisc %p\n",flow->q); | 305 | DPRINTK("atm_tc_change: qdisc %p\n", flow->q); |
310 | flow->sock = sock; | 306 | flow->sock = sock; |
311 | flow->vcc = ATM_SD(sock); /* speedup */ | 307 | flow->vcc = ATM_SD(sock); /* speedup */ |
312 | flow->vcc->user_back = flow; | 308 | flow->vcc->user_back = flow; |
313 | DPRINTK("atm_tc_change: vcc %p\n",flow->vcc); | 309 | DPRINTK("atm_tc_change: vcc %p\n", flow->vcc); |
314 | flow->old_pop = flow->vcc->pop; | 310 | flow->old_pop = flow->vcc->pop; |
315 | flow->parent = p; | 311 | flow->parent = p; |
316 | flow->vcc->pop = sch_atm_pop; | 312 | flow->vcc->pop = sch_atm_pop; |
@@ -321,50 +317,53 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent, | |||
321 | p->link.next = flow; | 317 | p->link.next = flow; |
322 | flow->hdr_len = hdr_len; | 318 | flow->hdr_len = hdr_len; |
323 | if (hdr) | 319 | if (hdr) |
324 | memcpy(flow->hdr,hdr,hdr_len); | 320 | memcpy(flow->hdr, hdr, hdr_len); |
325 | else | 321 | else |
326 | memcpy(flow->hdr,llc_oui_ip,sizeof(llc_oui_ip)); | 322 | memcpy(flow->hdr, llc_oui_ip, sizeof(llc_oui_ip)); |
327 | *arg = (unsigned long) flow; | 323 | *arg = (unsigned long)flow; |
328 | return 0; | 324 | return 0; |
329 | err_out: | 325 | err_out: |
330 | if (excess) atm_tc_put(sch,(unsigned long) excess); | 326 | if (excess) |
327 | atm_tc_put(sch, (unsigned long)excess); | ||
331 | sockfd_put(sock); | 328 | sockfd_put(sock); |
332 | return error; | 329 | return error; |
333 | } | 330 | } |
334 | 331 | ||
335 | 332 | static int atm_tc_delete(struct Qdisc *sch, unsigned long arg) | |
336 | static int atm_tc_delete(struct Qdisc *sch,unsigned long arg) | ||
337 | { | 333 | { |
338 | struct atm_qdisc_data *p = PRIV(sch); | 334 | struct atm_qdisc_data *p = PRIV(sch); |
339 | struct atm_flow_data *flow = (struct atm_flow_data *) arg; | 335 | struct atm_flow_data *flow = (struct atm_flow_data *)arg; |
340 | 336 | ||
341 | DPRINTK("atm_tc_delete(sch %p,[qdisc %p],flow %p)\n",sch,p,flow); | 337 | DPRINTK("atm_tc_delete(sch %p,[qdisc %p],flow %p)\n", sch, p, flow); |
342 | if (!find_flow(PRIV(sch),flow)) return -EINVAL; | 338 | if (!find_flow(PRIV(sch), flow)) |
343 | if (flow->filter_list || flow == &p->link) return -EBUSY; | 339 | return -EINVAL; |
340 | if (flow->filter_list || flow == &p->link) | ||
341 | return -EBUSY; | ||
344 | /* | 342 | /* |
345 | * Reference count must be 2: one for "keepalive" (set at class | 343 | * Reference count must be 2: one for "keepalive" (set at class |
346 | * creation), and one for the reference held when calling delete. | 344 | * creation), and one for the reference held when calling delete. |
347 | */ | 345 | */ |
348 | if (flow->ref < 2) { | 346 | if (flow->ref < 2) { |
349 | printk(KERN_ERR "atm_tc_delete: flow->ref == %d\n",flow->ref); | 347 | printk(KERN_ERR "atm_tc_delete: flow->ref == %d\n", flow->ref); |
350 | return -EINVAL; | 348 | return -EINVAL; |
351 | } | 349 | } |
352 | if (flow->ref > 2) return -EBUSY; /* catch references via excess, etc.*/ | 350 | if (flow->ref > 2) |
353 | atm_tc_put(sch,arg); | 351 | return -EBUSY; /* catch references via excess, etc. */ |
352 | atm_tc_put(sch, arg); | ||
354 | return 0; | 353 | return 0; |
355 | } | 354 | } |
356 | 355 | ||
357 | 356 | static void atm_tc_walk(struct Qdisc *sch, struct qdisc_walker *walker) | |
358 | static void atm_tc_walk(struct Qdisc *sch,struct qdisc_walker *walker) | ||
359 | { | 357 | { |
360 | struct atm_qdisc_data *p = PRIV(sch); | 358 | struct atm_qdisc_data *p = PRIV(sch); |
361 | struct atm_flow_data *flow; | 359 | struct atm_flow_data *flow; |
362 | 360 | ||
363 | DPRINTK("atm_tc_walk(sch %p,[qdisc %p],walker %p)\n",sch,p,walker); | 361 | DPRINTK("atm_tc_walk(sch %p,[qdisc %p],walker %p)\n", sch, p, walker); |
364 | if (walker->stop) return; | 362 | if (walker->stop) |
363 | return; | ||
365 | for (flow = p->flows; flow; flow = flow->next) { | 364 | for (flow = p->flows; flow; flow = flow->next) { |
366 | if (walker->count >= walker->skip) | 365 | if (walker->count >= walker->skip) |
367 | if (walker->fn(sch,(unsigned long) flow,walker) < 0) { | 366 | if (walker->fn(sch, (unsigned long)flow, walker) < 0) { |
368 | walker->stop = 1; | 367 | walker->stop = 1; |
369 | break; | 368 | break; |
370 | } | 369 | } |
@@ -372,73 +371,71 @@ static void atm_tc_walk(struct Qdisc *sch,struct qdisc_walker *walker) | |||
372 | } | 371 | } |
373 | } | 372 | } |
374 | 373 | ||
375 | 374 | static struct tcf_proto **atm_tc_find_tcf(struct Qdisc *sch, unsigned long cl) | |
376 | static struct tcf_proto **atm_tc_find_tcf(struct Qdisc *sch,unsigned long cl) | ||
377 | { | 375 | { |
378 | struct atm_qdisc_data *p = PRIV(sch); | 376 | struct atm_qdisc_data *p = PRIV(sch); |
379 | struct atm_flow_data *flow = (struct atm_flow_data *) cl; | 377 | struct atm_flow_data *flow = (struct atm_flow_data *)cl; |
380 | 378 | ||
381 | DPRINTK("atm_tc_find_tcf(sch %p,[qdisc %p],flow %p)\n",sch,p,flow); | 379 | DPRINTK("atm_tc_find_tcf(sch %p,[qdisc %p],flow %p)\n", sch, p, flow); |
382 | return flow ? &flow->filter_list : &p->link.filter_list; | 380 | return flow ? &flow->filter_list : &p->link.filter_list; |
383 | } | 381 | } |
384 | 382 | ||
385 | |||
386 | /* --------------------------- Qdisc operations ---------------------------- */ | 383 | /* --------------------------- Qdisc operations ---------------------------- */ |
387 | 384 | ||
388 | 385 | static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |
389 | static int atm_tc_enqueue(struct sk_buff *skb,struct Qdisc *sch) | ||
390 | { | 386 | { |
391 | struct atm_qdisc_data *p = PRIV(sch); | 387 | struct atm_qdisc_data *p = PRIV(sch); |
392 | struct atm_flow_data *flow = NULL ; /* @@@ */ | 388 | struct atm_flow_data *flow = NULL; /* @@@ */ |
393 | struct tcf_result res; | 389 | struct tcf_result res; |
394 | int result; | 390 | int result; |
395 | int ret = NET_XMIT_POLICED; | 391 | int ret = NET_XMIT_POLICED; |
396 | 392 | ||
397 | D2PRINTK("atm_tc_enqueue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p); | 393 | D2PRINTK("atm_tc_enqueue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p); |
398 | result = TC_POLICE_OK; /* be nice to gcc */ | 394 | result = TC_POLICE_OK; /* be nice to gcc */ |
399 | if (TC_H_MAJ(skb->priority) != sch->handle || | 395 | if (TC_H_MAJ(skb->priority) != sch->handle || |
400 | !(flow = (struct atm_flow_data *) atm_tc_get(sch,skb->priority))) | 396 | !(flow = (struct atm_flow_data *)atm_tc_get(sch, skb->priority))) |
401 | for (flow = p->flows; flow; flow = flow->next) | 397 | for (flow = p->flows; flow; flow = flow->next) |
402 | if (flow->filter_list) { | 398 | if (flow->filter_list) { |
403 | result = tc_classify(skb,flow->filter_list, | 399 | result = tc_classify_compat(skb, |
404 | &res); | 400 | flow->filter_list, |
405 | if (result < 0) continue; | 401 | &res); |
406 | flow = (struct atm_flow_data *) res.class; | 402 | if (result < 0) |
407 | if (!flow) flow = lookup_flow(sch,res.classid); | 403 | continue; |
404 | flow = (struct atm_flow_data *)res.class; | ||
405 | if (!flow) | ||
406 | flow = lookup_flow(sch, res.classid); | ||
408 | break; | 407 | break; |
409 | } | 408 | } |
410 | if (!flow) flow = &p->link; | 409 | if (!flow) |
410 | flow = &p->link; | ||
411 | else { | 411 | else { |
412 | if (flow->vcc) | 412 | if (flow->vcc) |
413 | ATM_SKB(skb)->atm_options = flow->vcc->atm_options; | 413 | ATM_SKB(skb)->atm_options = flow->vcc->atm_options; |
414 | /*@@@ looks good ... but it's not supposed to work :-)*/ | 414 | /*@@@ looks good ... but it's not supposed to work :-) */ |
415 | #ifdef CONFIG_NET_CLS_POLICE | 415 | #ifdef CONFIG_NET_CLS_ACT |
416 | switch (result) { | 416 | switch (result) { |
417 | case TC_POLICE_SHOT: | 417 | case TC_ACT_QUEUED: |
418 | kfree_skb(skb); | 418 | case TC_ACT_STOLEN: |
419 | break; | 419 | kfree_skb(skb); |
420 | case TC_POLICE_RECLASSIFY: | 420 | return NET_XMIT_SUCCESS; |
421 | if (flow->excess) flow = flow->excess; | 421 | case TC_ACT_SHOT: |
422 | else { | 422 | kfree_skb(skb); |
423 | ATM_SKB(skb)->atm_options |= | 423 | goto drop; |
424 | ATM_ATMOPT_CLP; | 424 | case TC_POLICE_RECLASSIFY: |
425 | break; | 425 | if (flow->excess) |
426 | } | 426 | flow = flow->excess; |
427 | /* fall through */ | 427 | else |
428 | case TC_POLICE_OK: | 428 | ATM_SKB(skb)->atm_options |= ATM_ATMOPT_CLP; |
429 | /* fall through */ | 429 | break; |
430 | default: | ||
431 | break; | ||
432 | } | 430 | } |
433 | #endif | 431 | #endif |
434 | } | 432 | } |
435 | if ( | 433 | |
436 | #ifdef CONFIG_NET_CLS_POLICE | 434 | if ((ret = flow->q->enqueue(skb, flow->q)) != 0) { |
437 | result == TC_POLICE_SHOT || | 435 | drop: __maybe_unused |
438 | #endif | ||
439 | (ret = flow->q->enqueue(skb,flow->q)) != 0) { | ||
440 | sch->qstats.drops++; | 436 | sch->qstats.drops++; |
441 | if (flow) flow->qstats.drops++; | 437 | if (flow) |
438 | flow->qstats.drops++; | ||
442 | return ret; | 439 | return ret; |
443 | } | 440 | } |
444 | sch->bstats.bytes += skb->len; | 441 | sch->bstats.bytes += skb->len; |
@@ -462,7 +459,6 @@ static int atm_tc_enqueue(struct sk_buff *skb,struct Qdisc *sch) | |||
462 | return NET_XMIT_BYPASS; | 459 | return NET_XMIT_BYPASS; |
463 | } | 460 | } |
464 | 461 | ||
465 | |||
466 | /* | 462 | /* |
467 | * Dequeue packets and send them over ATM. Note that we quite deliberately | 463 | * Dequeue packets and send them over ATM. Note that we quite deliberately |
468 | * avoid checking net_device's flow control here, simply because sch_atm | 464 | * avoid checking net_device's flow control here, simply because sch_atm |
@@ -470,167 +466,163 @@ static int atm_tc_enqueue(struct sk_buff *skb,struct Qdisc *sch) | |||
470 | * non-ATM interfaces. | 466 | * non-ATM interfaces. |
471 | */ | 467 | */ |
472 | 468 | ||
473 | |||
474 | static void sch_atm_dequeue(unsigned long data) | 469 | static void sch_atm_dequeue(unsigned long data) |
475 | { | 470 | { |
476 | struct Qdisc *sch = (struct Qdisc *) data; | 471 | struct Qdisc *sch = (struct Qdisc *)data; |
477 | struct atm_qdisc_data *p = PRIV(sch); | 472 | struct atm_qdisc_data *p = PRIV(sch); |
478 | struct atm_flow_data *flow; | 473 | struct atm_flow_data *flow; |
479 | struct sk_buff *skb; | 474 | struct sk_buff *skb; |
480 | 475 | ||
481 | D2PRINTK("sch_atm_dequeue(sch %p,[qdisc %p])\n",sch,p); | 476 | D2PRINTK("sch_atm_dequeue(sch %p,[qdisc %p])\n", sch, p); |
482 | for (flow = p->link.next; flow; flow = flow->next) | 477 | for (flow = p->link.next; flow; flow = flow->next) |
483 | /* | 478 | /* |
484 | * If traffic is properly shaped, this won't generate nasty | 479 | * If traffic is properly shaped, this won't generate nasty |
485 | * little bursts. Otherwise, it may ... (but that's okay) | 480 | * little bursts. Otherwise, it may ... (but that's okay) |
486 | */ | 481 | */ |
487 | while ((skb = flow->q->dequeue(flow->q))) { | 482 | while ((skb = flow->q->dequeue(flow->q))) { |
488 | if (!atm_may_send(flow->vcc,skb->truesize)) { | 483 | if (!atm_may_send(flow->vcc, skb->truesize)) { |
489 | (void) flow->q->ops->requeue(skb,flow->q); | 484 | (void)flow->q->ops->requeue(skb, flow->q); |
490 | break; | 485 | break; |
491 | } | 486 | } |
492 | D2PRINTK("atm_tc_dequeue: sending on class %p\n",flow); | 487 | D2PRINTK("atm_tc_dequeue: sending on class %p\n", flow); |
493 | /* remove any LL header somebody else has attached */ | 488 | /* remove any LL header somebody else has attached */ |
494 | skb_pull(skb, skb_network_offset(skb)); | 489 | skb_pull(skb, skb_network_offset(skb)); |
495 | if (skb_headroom(skb) < flow->hdr_len) { | 490 | if (skb_headroom(skb) < flow->hdr_len) { |
496 | struct sk_buff *new; | 491 | struct sk_buff *new; |
497 | 492 | ||
498 | new = skb_realloc_headroom(skb,flow->hdr_len); | 493 | new = skb_realloc_headroom(skb, flow->hdr_len); |
499 | dev_kfree_skb(skb); | 494 | dev_kfree_skb(skb); |
500 | if (!new) continue; | 495 | if (!new) |
496 | continue; | ||
501 | skb = new; | 497 | skb = new; |
502 | } | 498 | } |
503 | D2PRINTK("sch_atm_dequeue: ip %p, data %p\n", | 499 | D2PRINTK("sch_atm_dequeue: ip %p, data %p\n", |
504 | skb_network_header(skb), skb->data); | 500 | skb_network_header(skb), skb->data); |
505 | ATM_SKB(skb)->vcc = flow->vcc; | 501 | ATM_SKB(skb)->vcc = flow->vcc; |
506 | memcpy(skb_push(skb,flow->hdr_len),flow->hdr, | 502 | memcpy(skb_push(skb, flow->hdr_len), flow->hdr, |
507 | flow->hdr_len); | 503 | flow->hdr_len); |
508 | atomic_add(skb->truesize, | 504 | atomic_add(skb->truesize, |
509 | &sk_atm(flow->vcc)->sk_wmem_alloc); | 505 | &sk_atm(flow->vcc)->sk_wmem_alloc); |
510 | /* atm.atm_options are already set by atm_tc_enqueue */ | 506 | /* atm.atm_options are already set by atm_tc_enqueue */ |
511 | (void) flow->vcc->send(flow->vcc,skb); | 507 | flow->vcc->send(flow->vcc, skb); |
512 | } | 508 | } |
513 | } | 509 | } |
514 | 510 | ||
515 | |||
516 | static struct sk_buff *atm_tc_dequeue(struct Qdisc *sch) | 511 | static struct sk_buff *atm_tc_dequeue(struct Qdisc *sch) |
517 | { | 512 | { |
518 | struct atm_qdisc_data *p = PRIV(sch); | 513 | struct atm_qdisc_data *p = PRIV(sch); |
519 | struct sk_buff *skb; | 514 | struct sk_buff *skb; |
520 | 515 | ||
521 | D2PRINTK("atm_tc_dequeue(sch %p,[qdisc %p])\n",sch,p); | 516 | D2PRINTK("atm_tc_dequeue(sch %p,[qdisc %p])\n", sch, p); |
522 | tasklet_schedule(&p->task); | 517 | tasklet_schedule(&p->task); |
523 | skb = p->link.q->dequeue(p->link.q); | 518 | skb = p->link.q->dequeue(p->link.q); |
524 | if (skb) sch->q.qlen--; | 519 | if (skb) |
520 | sch->q.qlen--; | ||
525 | return skb; | 521 | return skb; |
526 | } | 522 | } |
527 | 523 | ||
528 | 524 | static int atm_tc_requeue(struct sk_buff *skb, struct Qdisc *sch) | |
529 | static int atm_tc_requeue(struct sk_buff *skb,struct Qdisc *sch) | ||
530 | { | 525 | { |
531 | struct atm_qdisc_data *p = PRIV(sch); | 526 | struct atm_qdisc_data *p = PRIV(sch); |
532 | int ret; | 527 | int ret; |
533 | 528 | ||
534 | D2PRINTK("atm_tc_requeue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p); | 529 | D2PRINTK("atm_tc_requeue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p); |
535 | ret = p->link.q->ops->requeue(skb,p->link.q); | 530 | ret = p->link.q->ops->requeue(skb, p->link.q); |
536 | if (!ret) { | 531 | if (!ret) { |
537 | sch->q.qlen++; | 532 | sch->q.qlen++; |
538 | sch->qstats.requeues++; | 533 | sch->qstats.requeues++; |
539 | } else { | 534 | } else { |
540 | sch->qstats.drops++; | 535 | sch->qstats.drops++; |
541 | p->link.qstats.drops++; | 536 | p->link.qstats.drops++; |
542 | } | 537 | } |
543 | return ret; | 538 | return ret; |
544 | } | 539 | } |
545 | 540 | ||
546 | |||
547 | static unsigned int atm_tc_drop(struct Qdisc *sch) | 541 | static unsigned int atm_tc_drop(struct Qdisc *sch) |
548 | { | 542 | { |
549 | struct atm_qdisc_data *p = PRIV(sch); | 543 | struct atm_qdisc_data *p = PRIV(sch); |
550 | struct atm_flow_data *flow; | 544 | struct atm_flow_data *flow; |
551 | unsigned int len; | 545 | unsigned int len; |
552 | 546 | ||
553 | DPRINTK("atm_tc_drop(sch %p,[qdisc %p])\n",sch,p); | 547 | DPRINTK("atm_tc_drop(sch %p,[qdisc %p])\n", sch, p); |
554 | for (flow = p->flows; flow; flow = flow->next) | 548 | for (flow = p->flows; flow; flow = flow->next) |
555 | if (flow->q->ops->drop && (len = flow->q->ops->drop(flow->q))) | 549 | if (flow->q->ops->drop && (len = flow->q->ops->drop(flow->q))) |
556 | return len; | 550 | return len; |
557 | return 0; | 551 | return 0; |
558 | } | 552 | } |
559 | 553 | ||
560 | 554 | static int atm_tc_init(struct Qdisc *sch, struct rtattr *opt) | |
561 | static int atm_tc_init(struct Qdisc *sch,struct rtattr *opt) | ||
562 | { | 555 | { |
563 | struct atm_qdisc_data *p = PRIV(sch); | 556 | struct atm_qdisc_data *p = PRIV(sch); |
564 | 557 | ||
565 | DPRINTK("atm_tc_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt); | 558 | DPRINTK("atm_tc_init(sch %p,[qdisc %p],opt %p)\n", sch, p, opt); |
566 | p->flows = &p->link; | 559 | p->flows = &p->link; |
567 | if(!(p->link.q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops, | 560 | if (!(p->link.q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, |
568 | sch->handle))) | 561 | sch->handle))) |
569 | p->link.q = &noop_qdisc; | 562 | p->link.q = &noop_qdisc; |
570 | DPRINTK("atm_tc_init: link (%p) qdisc %p\n",&p->link,p->link.q); | 563 | DPRINTK("atm_tc_init: link (%p) qdisc %p\n", &p->link, p->link.q); |
571 | p->link.filter_list = NULL; | 564 | p->link.filter_list = NULL; |
572 | p->link.vcc = NULL; | 565 | p->link.vcc = NULL; |
573 | p->link.sock = NULL; | 566 | p->link.sock = NULL; |
574 | p->link.classid = sch->handle; | 567 | p->link.classid = sch->handle; |
575 | p->link.ref = 1; | 568 | p->link.ref = 1; |
576 | p->link.next = NULL; | 569 | p->link.next = NULL; |
577 | tasklet_init(&p->task,sch_atm_dequeue,(unsigned long) sch); | 570 | tasklet_init(&p->task, sch_atm_dequeue, (unsigned long)sch); |
578 | return 0; | 571 | return 0; |
579 | } | 572 | } |
580 | 573 | ||
581 | |||
582 | static void atm_tc_reset(struct Qdisc *sch) | 574 | static void atm_tc_reset(struct Qdisc *sch) |
583 | { | 575 | { |
584 | struct atm_qdisc_data *p = PRIV(sch); | 576 | struct atm_qdisc_data *p = PRIV(sch); |
585 | struct atm_flow_data *flow; | 577 | struct atm_flow_data *flow; |
586 | 578 | ||
587 | DPRINTK("atm_tc_reset(sch %p,[qdisc %p])\n",sch,p); | 579 | DPRINTK("atm_tc_reset(sch %p,[qdisc %p])\n", sch, p); |
588 | for (flow = p->flows; flow; flow = flow->next) qdisc_reset(flow->q); | 580 | for (flow = p->flows; flow; flow = flow->next) |
581 | qdisc_reset(flow->q); | ||
589 | sch->q.qlen = 0; | 582 | sch->q.qlen = 0; |
590 | } | 583 | } |
591 | 584 | ||
592 | |||
593 | static void atm_tc_destroy(struct Qdisc *sch) | 585 | static void atm_tc_destroy(struct Qdisc *sch) |
594 | { | 586 | { |
595 | struct atm_qdisc_data *p = PRIV(sch); | 587 | struct atm_qdisc_data *p = PRIV(sch); |
596 | struct atm_flow_data *flow; | 588 | struct atm_flow_data *flow; |
597 | 589 | ||
598 | DPRINTK("atm_tc_destroy(sch %p,[qdisc %p])\n",sch,p); | 590 | DPRINTK("atm_tc_destroy(sch %p,[qdisc %p])\n", sch, p); |
599 | /* races ? */ | 591 | /* races ? */ |
600 | while ((flow = p->flows)) { | 592 | while ((flow = p->flows)) { |
601 | tcf_destroy_chain(flow->filter_list); | 593 | tcf_destroy_chain(flow->filter_list); |
602 | flow->filter_list = NULL; | 594 | flow->filter_list = NULL; |
603 | if (flow->ref > 1) | 595 | if (flow->ref > 1) |
604 | printk(KERN_ERR "atm_destroy: %p->ref = %d\n",flow, | 596 | printk(KERN_ERR "atm_destroy: %p->ref = %d\n", flow, |
605 | flow->ref); | 597 | flow->ref); |
606 | atm_tc_put(sch,(unsigned long) flow); | 598 | atm_tc_put(sch, (unsigned long)flow); |
607 | if (p->flows == flow) { | 599 | if (p->flows == flow) { |
608 | printk(KERN_ERR "atm_destroy: putting flow %p didn't " | 600 | printk(KERN_ERR "atm_destroy: putting flow %p didn't " |
609 | "kill it\n",flow); | 601 | "kill it\n", flow); |
610 | p->flows = flow->next; /* brute force */ | 602 | p->flows = flow->next; /* brute force */ |
611 | break; | 603 | break; |
612 | } | 604 | } |
613 | } | 605 | } |
614 | tasklet_kill(&p->task); | 606 | tasklet_kill(&p->task); |
615 | } | 607 | } |
616 | 608 | ||
617 | |||
618 | static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl, | 609 | static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl, |
619 | struct sk_buff *skb, struct tcmsg *tcm) | 610 | struct sk_buff *skb, struct tcmsg *tcm) |
620 | { | 611 | { |
621 | struct atm_qdisc_data *p = PRIV(sch); | 612 | struct atm_qdisc_data *p = PRIV(sch); |
622 | struct atm_flow_data *flow = (struct atm_flow_data *) cl; | 613 | struct atm_flow_data *flow = (struct atm_flow_data *)cl; |
623 | unsigned char *b = skb_tail_pointer(skb); | 614 | unsigned char *b = skb_tail_pointer(skb); |
624 | struct rtattr *rta; | 615 | struct rtattr *rta; |
625 | 616 | ||
626 | DPRINTK("atm_tc_dump_class(sch %p,[qdisc %p],flow %p,skb %p,tcm %p)\n", | 617 | DPRINTK("atm_tc_dump_class(sch %p,[qdisc %p],flow %p,skb %p,tcm %p)\n", |
627 | sch,p,flow,skb,tcm); | 618 | sch, p, flow, skb, tcm); |
628 | if (!find_flow(p,flow)) return -EINVAL; | 619 | if (!find_flow(p, flow)) |
620 | return -EINVAL; | ||
629 | tcm->tcm_handle = flow->classid; | 621 | tcm->tcm_handle = flow->classid; |
630 | tcm->tcm_info = flow->q->handle; | 622 | tcm->tcm_info = flow->q->handle; |
631 | rta = (struct rtattr *) b; | 623 | rta = (struct rtattr *)b; |
632 | RTA_PUT(skb,TCA_OPTIONS,0,NULL); | 624 | RTA_PUT(skb, TCA_OPTIONS, 0, NULL); |
633 | RTA_PUT(skb,TCA_ATM_HDR,flow->hdr_len,flow->hdr); | 625 | RTA_PUT(skb, TCA_ATM_HDR, flow->hdr_len, flow->hdr); |
634 | if (flow->vcc) { | 626 | if (flow->vcc) { |
635 | struct sockaddr_atmpvc pvc; | 627 | struct sockaddr_atmpvc pvc; |
636 | int state; | 628 | int state; |
@@ -639,16 +631,16 @@ static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl, | |||
639 | pvc.sap_addr.itf = flow->vcc->dev ? flow->vcc->dev->number : -1; | 631 | pvc.sap_addr.itf = flow->vcc->dev ? flow->vcc->dev->number : -1; |
640 | pvc.sap_addr.vpi = flow->vcc->vpi; | 632 | pvc.sap_addr.vpi = flow->vcc->vpi; |
641 | pvc.sap_addr.vci = flow->vcc->vci; | 633 | pvc.sap_addr.vci = flow->vcc->vci; |
642 | RTA_PUT(skb,TCA_ATM_ADDR,sizeof(pvc),&pvc); | 634 | RTA_PUT(skb, TCA_ATM_ADDR, sizeof(pvc), &pvc); |
643 | state = ATM_VF2VS(flow->vcc->flags); | 635 | state = ATM_VF2VS(flow->vcc->flags); |
644 | RTA_PUT(skb,TCA_ATM_STATE,sizeof(state),&state); | 636 | RTA_PUT(skb, TCA_ATM_STATE, sizeof(state), &state); |
645 | } | 637 | } |
646 | if (flow->excess) | 638 | if (flow->excess) |
647 | RTA_PUT(skb,TCA_ATM_EXCESS,sizeof(u32),&flow->classid); | 639 | RTA_PUT(skb, TCA_ATM_EXCESS, sizeof(u32), &flow->classid); |
648 | else { | 640 | else { |
649 | static u32 zero; | 641 | static u32 zero; |
650 | 642 | ||
651 | RTA_PUT(skb,TCA_ATM_EXCESS,sizeof(zero),&zero); | 643 | RTA_PUT(skb, TCA_ATM_EXCESS, sizeof(zero), &zero); |
652 | } | 644 | } |
653 | rta->rta_len = skb_tail_pointer(skb) - b; | 645 | rta->rta_len = skb_tail_pointer(skb) - b; |
654 | return skb->len; | 646 | return skb->len; |
@@ -659,9 +651,9 @@ rtattr_failure: | |||
659 | } | 651 | } |
660 | static int | 652 | static int |
661 | atm_tc_dump_class_stats(struct Qdisc *sch, unsigned long arg, | 653 | atm_tc_dump_class_stats(struct Qdisc *sch, unsigned long arg, |
662 | struct gnet_dump *d) | 654 | struct gnet_dump *d) |
663 | { | 655 | { |
664 | struct atm_flow_data *flow = (struct atm_flow_data *) arg; | 656 | struct atm_flow_data *flow = (struct atm_flow_data *)arg; |
665 | 657 | ||
666 | flow->qstats.qlen = flow->q->q.qlen; | 658 | flow->qstats.qlen = flow->q->q.qlen; |
667 | 659 | ||
@@ -678,38 +670,35 @@ static int atm_tc_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
678 | } | 670 | } |
679 | 671 | ||
680 | static struct Qdisc_class_ops atm_class_ops = { | 672 | static struct Qdisc_class_ops atm_class_ops = { |
681 | .graft = atm_tc_graft, | 673 | .graft = atm_tc_graft, |
682 | .leaf = atm_tc_leaf, | 674 | .leaf = atm_tc_leaf, |
683 | .get = atm_tc_get, | 675 | .get = atm_tc_get, |
684 | .put = atm_tc_put, | 676 | .put = atm_tc_put, |
685 | .change = atm_tc_change, | 677 | .change = atm_tc_change, |
686 | .delete = atm_tc_delete, | 678 | .delete = atm_tc_delete, |
687 | .walk = atm_tc_walk, | 679 | .walk = atm_tc_walk, |
688 | .tcf_chain = atm_tc_find_tcf, | 680 | .tcf_chain = atm_tc_find_tcf, |
689 | .bind_tcf = atm_tc_bind_filter, | 681 | .bind_tcf = atm_tc_bind_filter, |
690 | .unbind_tcf = atm_tc_put, | 682 | .unbind_tcf = atm_tc_put, |
691 | .dump = atm_tc_dump_class, | 683 | .dump = atm_tc_dump_class, |
692 | .dump_stats = atm_tc_dump_class_stats, | 684 | .dump_stats = atm_tc_dump_class_stats, |
693 | }; | 685 | }; |
694 | 686 | ||
695 | static struct Qdisc_ops atm_qdisc_ops = { | 687 | static struct Qdisc_ops atm_qdisc_ops = { |
696 | .next = NULL, | 688 | .cl_ops = &atm_class_ops, |
697 | .cl_ops = &atm_class_ops, | 689 | .id = "atm", |
698 | .id = "atm", | 690 | .priv_size = sizeof(struct atm_qdisc_data), |
699 | .priv_size = sizeof(struct atm_qdisc_data), | 691 | .enqueue = atm_tc_enqueue, |
700 | .enqueue = atm_tc_enqueue, | 692 | .dequeue = atm_tc_dequeue, |
701 | .dequeue = atm_tc_dequeue, | 693 | .requeue = atm_tc_requeue, |
702 | .requeue = atm_tc_requeue, | 694 | .drop = atm_tc_drop, |
703 | .drop = atm_tc_drop, | 695 | .init = atm_tc_init, |
704 | .init = atm_tc_init, | 696 | .reset = atm_tc_reset, |
705 | .reset = atm_tc_reset, | 697 | .destroy = atm_tc_destroy, |
706 | .destroy = atm_tc_destroy, | 698 | .dump = atm_tc_dump, |
707 | .change = NULL, | 699 | .owner = THIS_MODULE, |
708 | .dump = atm_tc_dump, | ||
709 | .owner = THIS_MODULE, | ||
710 | }; | 700 | }; |
711 | 701 | ||
712 | |||
713 | static int __init atm_init(void) | 702 | static int __init atm_init(void) |
714 | { | 703 | { |
715 | return register_qdisc(&atm_qdisc_ops); | 704 | return register_qdisc(&atm_qdisc_ops); |
diff --git a/net/sched/sch_blackhole.c b/net/sched/sch_blackhole.c index cb0c456aa349..f914fc43a124 100644 --- a/net/sched/sch_blackhole.c +++ b/net/sched/sch_blackhole.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/netdevice.h> | ||
18 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
19 | #include <net/pkt_sched.h> | 18 | #include <net/pkt_sched.h> |
20 | 19 | ||
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index ee2d5967d109..e38c2839b25c 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c | |||
@@ -11,28 +11,12 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <asm/uaccess.h> | ||
15 | #include <asm/system.h> | ||
16 | #include <linux/bitops.h> | ||
17 | #include <linux/types.h> | 14 | #include <linux/types.h> |
18 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
19 | #include <linux/string.h> | 16 | #include <linux/string.h> |
20 | #include <linux/mm.h> | ||
21 | #include <linux/socket.h> | ||
22 | #include <linux/sockios.h> | ||
23 | #include <linux/in.h> | ||
24 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/if_ether.h> | ||
27 | #include <linux/inet.h> | ||
28 | #include <linux/netdevice.h> | ||
29 | #include <linux/etherdevice.h> | ||
30 | #include <linux/notifier.h> | ||
31 | #include <net/ip.h> | ||
32 | #include <net/netlink.h> | ||
33 | #include <net/route.h> | ||
34 | #include <linux/skbuff.h> | 18 | #include <linux/skbuff.h> |
35 | #include <net/sock.h> | 19 | #include <net/netlink.h> |
36 | #include <net/pkt_sched.h> | 20 | #include <net/pkt_sched.h> |
37 | 21 | ||
38 | 22 | ||
@@ -98,7 +82,7 @@ struct cbq_class | |||
98 | unsigned char priority2; /* priority to be used after overlimit */ | 82 | unsigned char priority2; /* priority to be used after overlimit */ |
99 | unsigned char ewma_log; /* time constant for idle time calculation */ | 83 | unsigned char ewma_log; /* time constant for idle time calculation */ |
100 | unsigned char ovl_strategy; | 84 | unsigned char ovl_strategy; |
101 | #ifdef CONFIG_NET_CLS_POLICE | 85 | #ifdef CONFIG_NET_CLS_ACT |
102 | unsigned char police; | 86 | unsigned char police; |
103 | #endif | 87 | #endif |
104 | 88 | ||
@@ -148,7 +132,6 @@ struct cbq_class | |||
148 | struct gnet_stats_basic bstats; | 132 | struct gnet_stats_basic bstats; |
149 | struct gnet_stats_queue qstats; | 133 | struct gnet_stats_queue qstats; |
150 | struct gnet_stats_rate_est rate_est; | 134 | struct gnet_stats_rate_est rate_est; |
151 | spinlock_t *stats_lock; | ||
152 | struct tc_cbq_xstats xstats; | 135 | struct tc_cbq_xstats xstats; |
153 | 136 | ||
154 | struct tcf_proto *filter_list; | 137 | struct tcf_proto *filter_list; |
@@ -171,7 +154,7 @@ struct cbq_sched_data | |||
171 | struct cbq_class *active[TC_CBQ_MAXPRIO+1]; /* List of all classes | 154 | struct cbq_class *active[TC_CBQ_MAXPRIO+1]; /* List of all classes |
172 | with backlog */ | 155 | with backlog */ |
173 | 156 | ||
174 | #ifdef CONFIG_NET_CLS_POLICE | 157 | #ifdef CONFIG_NET_CLS_ACT |
175 | struct cbq_class *rx_class; | 158 | struct cbq_class *rx_class; |
176 | #endif | 159 | #endif |
177 | struct cbq_class *tx_class; | 160 | struct cbq_class *tx_class; |
@@ -213,7 +196,7 @@ cbq_class_lookup(struct cbq_sched_data *q, u32 classid) | |||
213 | return NULL; | 196 | return NULL; |
214 | } | 197 | } |
215 | 198 | ||
216 | #ifdef CONFIG_NET_CLS_POLICE | 199 | #ifdef CONFIG_NET_CLS_ACT |
217 | 200 | ||
218 | static struct cbq_class * | 201 | static struct cbq_class * |
219 | cbq_reclassify(struct sk_buff *skb, struct cbq_class *this) | 202 | cbq_reclassify(struct sk_buff *skb, struct cbq_class *this) |
@@ -264,7 +247,8 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) | |||
264 | /* | 247 | /* |
265 | * Step 2+n. Apply classifier. | 248 | * Step 2+n. Apply classifier. |
266 | */ | 249 | */ |
267 | if (!head->filter_list || (result = tc_classify(skb, head->filter_list, &res)) < 0) | 250 | if (!head->filter_list || |
251 | (result = tc_classify_compat(skb, head->filter_list, &res)) < 0) | ||
268 | goto fallback; | 252 | goto fallback; |
269 | 253 | ||
270 | if ((cl = (void*)res.class) == NULL) { | 254 | if ((cl = (void*)res.class) == NULL) { |
@@ -284,15 +268,8 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) | |||
284 | *qerr = NET_XMIT_SUCCESS; | 268 | *qerr = NET_XMIT_SUCCESS; |
285 | case TC_ACT_SHOT: | 269 | case TC_ACT_SHOT: |
286 | return NULL; | 270 | return NULL; |
287 | } | 271 | case TC_ACT_RECLASSIFY: |
288 | #elif defined(CONFIG_NET_CLS_POLICE) | ||
289 | switch (result) { | ||
290 | case TC_POLICE_RECLASSIFY: | ||
291 | return cbq_reclassify(skb, cl); | 272 | return cbq_reclassify(skb, cl); |
292 | case TC_POLICE_SHOT: | ||
293 | return NULL; | ||
294 | default: | ||
295 | break; | ||
296 | } | 273 | } |
297 | #endif | 274 | #endif |
298 | if (cl->level == 0) | 275 | if (cl->level == 0) |
@@ -406,7 +383,7 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
406 | int ret; | 383 | int ret; |
407 | struct cbq_class *cl = cbq_classify(skb, sch, &ret); | 384 | struct cbq_class *cl = cbq_classify(skb, sch, &ret); |
408 | 385 | ||
409 | #ifdef CONFIG_NET_CLS_POLICE | 386 | #ifdef CONFIG_NET_CLS_ACT |
410 | q->rx_class = cl; | 387 | q->rx_class = cl; |
411 | #endif | 388 | #endif |
412 | if (cl == NULL) { | 389 | if (cl == NULL) { |
@@ -416,7 +393,7 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
416 | return ret; | 393 | return ret; |
417 | } | 394 | } |
418 | 395 | ||
419 | #ifdef CONFIG_NET_CLS_POLICE | 396 | #ifdef CONFIG_NET_CLS_ACT |
420 | cl->q->__parent = sch; | 397 | cl->q->__parent = sch; |
421 | #endif | 398 | #endif |
422 | if ((ret = cl->q->enqueue(skb, cl->q)) == NET_XMIT_SUCCESS) { | 399 | if ((ret = cl->q->enqueue(skb, cl->q)) == NET_XMIT_SUCCESS) { |
@@ -451,7 +428,7 @@ cbq_requeue(struct sk_buff *skb, struct Qdisc *sch) | |||
451 | 428 | ||
452 | cbq_mark_toplevel(q, cl); | 429 | cbq_mark_toplevel(q, cl); |
453 | 430 | ||
454 | #ifdef CONFIG_NET_CLS_POLICE | 431 | #ifdef CONFIG_NET_CLS_ACT |
455 | q->rx_class = cl; | 432 | q->rx_class = cl; |
456 | cl->q->__parent = sch; | 433 | cl->q->__parent = sch; |
457 | #endif | 434 | #endif |
@@ -686,9 +663,7 @@ static enum hrtimer_restart cbq_undelay(struct hrtimer *timer) | |||
686 | return HRTIMER_NORESTART; | 663 | return HRTIMER_NORESTART; |
687 | } | 664 | } |
688 | 665 | ||
689 | 666 | #ifdef CONFIG_NET_CLS_ACT | |
690 | #ifdef CONFIG_NET_CLS_POLICE | ||
691 | |||
692 | static int cbq_reshape_fail(struct sk_buff *skb, struct Qdisc *child) | 667 | static int cbq_reshape_fail(struct sk_buff *skb, struct Qdisc *child) |
693 | { | 668 | { |
694 | int len = skb->len; | 669 | int len = skb->len; |
@@ -1381,7 +1356,7 @@ static int cbq_set_overlimit(struct cbq_class *cl, struct tc_cbq_ovl *ovl) | |||
1381 | return 0; | 1356 | return 0; |
1382 | } | 1357 | } |
1383 | 1358 | ||
1384 | #ifdef CONFIG_NET_CLS_POLICE | 1359 | #ifdef CONFIG_NET_CLS_ACT |
1385 | static int cbq_set_police(struct cbq_class *cl, struct tc_cbq_police *p) | 1360 | static int cbq_set_police(struct cbq_class *cl, struct tc_cbq_police *p) |
1386 | { | 1361 | { |
1387 | cl->police = p->police; | 1362 | cl->police = p->police; |
@@ -1442,7 +1417,6 @@ static int cbq_init(struct Qdisc *sch, struct rtattr *opt) | |||
1442 | q->link.ewma_log = TC_CBQ_DEF_EWMA; | 1417 | q->link.ewma_log = TC_CBQ_DEF_EWMA; |
1443 | q->link.avpkt = q->link.allot/2; | 1418 | q->link.avpkt = q->link.allot/2; |
1444 | q->link.minidle = -0x7FFFFFFF; | 1419 | q->link.minidle = -0x7FFFFFFF; |
1445 | q->link.stats_lock = &sch->dev->queue_lock; | ||
1446 | 1420 | ||
1447 | qdisc_watchdog_init(&q->watchdog, sch); | 1421 | qdisc_watchdog_init(&q->watchdog, sch); |
1448 | hrtimer_init(&q->delay_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); | 1422 | hrtimer_init(&q->delay_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); |
@@ -1550,7 +1524,7 @@ rtattr_failure: | |||
1550 | return -1; | 1524 | return -1; |
1551 | } | 1525 | } |
1552 | 1526 | ||
1553 | #ifdef CONFIG_NET_CLS_POLICE | 1527 | #ifdef CONFIG_NET_CLS_ACT |
1554 | static __inline__ int cbq_dump_police(struct sk_buff *skb, struct cbq_class *cl) | 1528 | static __inline__ int cbq_dump_police(struct sk_buff *skb, struct cbq_class *cl) |
1555 | { | 1529 | { |
1556 | unsigned char *b = skb_tail_pointer(skb); | 1530 | unsigned char *b = skb_tail_pointer(skb); |
@@ -1576,7 +1550,7 @@ static int cbq_dump_attr(struct sk_buff *skb, struct cbq_class *cl) | |||
1576 | cbq_dump_rate(skb, cl) < 0 || | 1550 | cbq_dump_rate(skb, cl) < 0 || |
1577 | cbq_dump_wrr(skb, cl) < 0 || | 1551 | cbq_dump_wrr(skb, cl) < 0 || |
1578 | cbq_dump_ovl(skb, cl) < 0 || | 1552 | cbq_dump_ovl(skb, cl) < 0 || |
1579 | #ifdef CONFIG_NET_CLS_POLICE | 1553 | #ifdef CONFIG_NET_CLS_ACT |
1580 | cbq_dump_police(skb, cl) < 0 || | 1554 | cbq_dump_police(skb, cl) < 0 || |
1581 | #endif | 1555 | #endif |
1582 | cbq_dump_fopt(skb, cl) < 0) | 1556 | cbq_dump_fopt(skb, cl) < 0) |
@@ -1653,9 +1627,7 @@ cbq_dump_class_stats(struct Qdisc *sch, unsigned long arg, | |||
1653 | cl->xstats.undertime = cl->undertime - q->now; | 1627 | cl->xstats.undertime = cl->undertime - q->now; |
1654 | 1628 | ||
1655 | if (gnet_stats_copy_basic(d, &cl->bstats) < 0 || | 1629 | if (gnet_stats_copy_basic(d, &cl->bstats) < 0 || |
1656 | #ifdef CONFIG_NET_ESTIMATOR | ||
1657 | gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 || | 1630 | gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 || |
1658 | #endif | ||
1659 | gnet_stats_copy_queue(d, &cl->qstats) < 0) | 1631 | gnet_stats_copy_queue(d, &cl->qstats) < 0) |
1660 | return -1; | 1632 | return -1; |
1661 | 1633 | ||
@@ -1673,7 +1645,7 @@ static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, | |||
1673 | cl->classid)) == NULL) | 1645 | cl->classid)) == NULL) |
1674 | return -ENOBUFS; | 1646 | return -ENOBUFS; |
1675 | } else { | 1647 | } else { |
1676 | #ifdef CONFIG_NET_CLS_POLICE | 1648 | #ifdef CONFIG_NET_CLS_ACT |
1677 | if (cl->police == TC_POLICE_RECLASSIFY) | 1649 | if (cl->police == TC_POLICE_RECLASSIFY) |
1678 | new->reshape_fail = cbq_reshape_fail; | 1650 | new->reshape_fail = cbq_reshape_fail; |
1679 | #endif | 1651 | #endif |
@@ -1726,9 +1698,7 @@ static void cbq_destroy_class(struct Qdisc *sch, struct cbq_class *cl) | |||
1726 | tcf_destroy_chain(cl->filter_list); | 1698 | tcf_destroy_chain(cl->filter_list); |
1727 | qdisc_destroy(cl->q); | 1699 | qdisc_destroy(cl->q); |
1728 | qdisc_put_rtab(cl->R_tab); | 1700 | qdisc_put_rtab(cl->R_tab); |
1729 | #ifdef CONFIG_NET_ESTIMATOR | ||
1730 | gen_kill_estimator(&cl->bstats, &cl->rate_est); | 1701 | gen_kill_estimator(&cl->bstats, &cl->rate_est); |
1731 | #endif | ||
1732 | if (cl != &q->link) | 1702 | if (cl != &q->link) |
1733 | kfree(cl); | 1703 | kfree(cl); |
1734 | } | 1704 | } |
@@ -1740,7 +1710,7 @@ cbq_destroy(struct Qdisc* sch) | |||
1740 | struct cbq_class *cl; | 1710 | struct cbq_class *cl; |
1741 | unsigned h; | 1711 | unsigned h; |
1742 | 1712 | ||
1743 | #ifdef CONFIG_NET_CLS_POLICE | 1713 | #ifdef CONFIG_NET_CLS_ACT |
1744 | q->rx_class = NULL; | 1714 | q->rx_class = NULL; |
1745 | #endif | 1715 | #endif |
1746 | /* | 1716 | /* |
@@ -1769,7 +1739,7 @@ static void cbq_put(struct Qdisc *sch, unsigned long arg) | |||
1769 | struct cbq_class *cl = (struct cbq_class*)arg; | 1739 | struct cbq_class *cl = (struct cbq_class*)arg; |
1770 | 1740 | ||
1771 | if (--cl->refcnt == 0) { | 1741 | if (--cl->refcnt == 0) { |
1772 | #ifdef CONFIG_NET_CLS_POLICE | 1742 | #ifdef CONFIG_NET_CLS_ACT |
1773 | struct cbq_sched_data *q = qdisc_priv(sch); | 1743 | struct cbq_sched_data *q = qdisc_priv(sch); |
1774 | 1744 | ||
1775 | spin_lock_bh(&sch->dev->queue_lock); | 1745 | spin_lock_bh(&sch->dev->queue_lock); |
@@ -1817,7 +1787,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t | |||
1817 | RTA_PAYLOAD(tb[TCA_CBQ_WRROPT-1]) < sizeof(struct tc_cbq_wrropt)) | 1787 | RTA_PAYLOAD(tb[TCA_CBQ_WRROPT-1]) < sizeof(struct tc_cbq_wrropt)) |
1818 | return -EINVAL; | 1788 | return -EINVAL; |
1819 | 1789 | ||
1820 | #ifdef CONFIG_NET_CLS_POLICE | 1790 | #ifdef CONFIG_NET_CLS_ACT |
1821 | if (tb[TCA_CBQ_POLICE-1] && | 1791 | if (tb[TCA_CBQ_POLICE-1] && |
1822 | RTA_PAYLOAD(tb[TCA_CBQ_POLICE-1]) < sizeof(struct tc_cbq_police)) | 1792 | RTA_PAYLOAD(tb[TCA_CBQ_POLICE-1]) < sizeof(struct tc_cbq_police)) |
1823 | return -EINVAL; | 1793 | return -EINVAL; |
@@ -1860,7 +1830,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t | |||
1860 | if (tb[TCA_CBQ_OVL_STRATEGY-1]) | 1830 | if (tb[TCA_CBQ_OVL_STRATEGY-1]) |
1861 | cbq_set_overlimit(cl, RTA_DATA(tb[TCA_CBQ_OVL_STRATEGY-1])); | 1831 | cbq_set_overlimit(cl, RTA_DATA(tb[TCA_CBQ_OVL_STRATEGY-1])); |
1862 | 1832 | ||
1863 | #ifdef CONFIG_NET_CLS_POLICE | 1833 | #ifdef CONFIG_NET_CLS_ACT |
1864 | if (tb[TCA_CBQ_POLICE-1]) | 1834 | if (tb[TCA_CBQ_POLICE-1]) |
1865 | cbq_set_police(cl, RTA_DATA(tb[TCA_CBQ_POLICE-1])); | 1835 | cbq_set_police(cl, RTA_DATA(tb[TCA_CBQ_POLICE-1])); |
1866 | #endif | 1836 | #endif |
@@ -1873,11 +1843,10 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t | |||
1873 | 1843 | ||
1874 | sch_tree_unlock(sch); | 1844 | sch_tree_unlock(sch); |
1875 | 1845 | ||
1876 | #ifdef CONFIG_NET_ESTIMATOR | ||
1877 | if (tca[TCA_RATE-1]) | 1846 | if (tca[TCA_RATE-1]) |
1878 | gen_replace_estimator(&cl->bstats, &cl->rate_est, | 1847 | gen_replace_estimator(&cl->bstats, &cl->rate_est, |
1879 | cl->stats_lock, tca[TCA_RATE-1]); | 1848 | &sch->dev->queue_lock, |
1880 | #endif | 1849 | tca[TCA_RATE-1]); |
1881 | return 0; | 1850 | return 0; |
1882 | } | 1851 | } |
1883 | 1852 | ||
@@ -1935,7 +1904,6 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t | |||
1935 | cl->allot = parent->allot; | 1904 | cl->allot = parent->allot; |
1936 | cl->quantum = cl->allot; | 1905 | cl->quantum = cl->allot; |
1937 | cl->weight = cl->R_tab->rate.rate; | 1906 | cl->weight = cl->R_tab->rate.rate; |
1938 | cl->stats_lock = &sch->dev->queue_lock; | ||
1939 | 1907 | ||
1940 | sch_tree_lock(sch); | 1908 | sch_tree_lock(sch); |
1941 | cbq_link_class(cl); | 1909 | cbq_link_class(cl); |
@@ -1955,7 +1923,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t | |||
1955 | cl->overlimit = cbq_ovl_classic; | 1923 | cl->overlimit = cbq_ovl_classic; |
1956 | if (tb[TCA_CBQ_OVL_STRATEGY-1]) | 1924 | if (tb[TCA_CBQ_OVL_STRATEGY-1]) |
1957 | cbq_set_overlimit(cl, RTA_DATA(tb[TCA_CBQ_OVL_STRATEGY-1])); | 1925 | cbq_set_overlimit(cl, RTA_DATA(tb[TCA_CBQ_OVL_STRATEGY-1])); |
1958 | #ifdef CONFIG_NET_CLS_POLICE | 1926 | #ifdef CONFIG_NET_CLS_ACT |
1959 | if (tb[TCA_CBQ_POLICE-1]) | 1927 | if (tb[TCA_CBQ_POLICE-1]) |
1960 | cbq_set_police(cl, RTA_DATA(tb[TCA_CBQ_POLICE-1])); | 1928 | cbq_set_police(cl, RTA_DATA(tb[TCA_CBQ_POLICE-1])); |
1961 | #endif | 1929 | #endif |
@@ -1963,11 +1931,9 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t | |||
1963 | cbq_set_fopt(cl, RTA_DATA(tb[TCA_CBQ_FOPT-1])); | 1931 | cbq_set_fopt(cl, RTA_DATA(tb[TCA_CBQ_FOPT-1])); |
1964 | sch_tree_unlock(sch); | 1932 | sch_tree_unlock(sch); |
1965 | 1933 | ||
1966 | #ifdef CONFIG_NET_ESTIMATOR | ||
1967 | if (tca[TCA_RATE-1]) | 1934 | if (tca[TCA_RATE-1]) |
1968 | gen_new_estimator(&cl->bstats, &cl->rate_est, | 1935 | gen_new_estimator(&cl->bstats, &cl->rate_est, |
1969 | cl->stats_lock, tca[TCA_RATE-1]); | 1936 | &sch->dev->queue_lock, tca[TCA_RATE-1]); |
1970 | #endif | ||
1971 | 1937 | ||
1972 | *arg = (unsigned long)cl; | 1938 | *arg = (unsigned long)cl; |
1973 | return 0; | 1939 | return 0; |
@@ -2001,7 +1967,7 @@ static int cbq_delete(struct Qdisc *sch, unsigned long arg) | |||
2001 | q->tx_class = NULL; | 1967 | q->tx_class = NULL; |
2002 | q->tx_borrowed = NULL; | 1968 | q->tx_borrowed = NULL; |
2003 | } | 1969 | } |
2004 | #ifdef CONFIG_NET_CLS_POLICE | 1970 | #ifdef CONFIG_NET_CLS_ACT |
2005 | if (q->rx_class == cl) | 1971 | if (q->rx_class == cl) |
2006 | q->rx_class = NULL; | 1972 | q->rx_class = NULL; |
2007 | #endif | 1973 | #endif |
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index 3c6fd181263f..60f89199e3da 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c | |||
@@ -9,7 +9,6 @@ | |||
9 | #include <linux/string.h> | 9 | #include <linux/string.h> |
10 | #include <linux/errno.h> | 10 | #include <linux/errno.h> |
11 | #include <linux/skbuff.h> | 11 | #include <linux/skbuff.h> |
12 | #include <linux/netdevice.h> /* for pkt_sched */ | ||
13 | #include <linux/rtnetlink.h> | 12 | #include <linux/rtnetlink.h> |
14 | #include <net/pkt_sched.h> | 13 | #include <net/pkt_sched.h> |
15 | #include <net/dsfield.h> | 14 | #include <net/dsfield.h> |
@@ -238,25 +237,23 @@ static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch) | |||
238 | D2PRINTK("result %d class 0x%04x\n", result, res.classid); | 237 | D2PRINTK("result %d class 0x%04x\n", result, res.classid); |
239 | 238 | ||
240 | switch (result) { | 239 | switch (result) { |
241 | #ifdef CONFIG_NET_CLS_POLICE | 240 | #ifdef CONFIG_NET_CLS_ACT |
242 | case TC_POLICE_SHOT: | 241 | case TC_ACT_QUEUED: |
243 | kfree_skb(skb); | 242 | case TC_ACT_STOLEN: |
244 | sch->qstats.drops++; | 243 | kfree_skb(skb); |
245 | return NET_XMIT_POLICED; | 244 | return NET_XMIT_SUCCESS; |
246 | #if 0 | 245 | case TC_ACT_SHOT: |
247 | case TC_POLICE_RECLASSIFY: | 246 | kfree_skb(skb); |
248 | /* FIXME: what to do here ??? */ | 247 | sch->qstats.drops++; |
248 | return NET_XMIT_BYPASS; | ||
249 | #endif | 249 | #endif |
250 | #endif | 250 | case TC_ACT_OK: |
251 | case TC_POLICE_OK: | 251 | skb->tc_index = TC_H_MIN(res.classid); |
252 | skb->tc_index = TC_H_MIN(res.classid); | 252 | break; |
253 | break; | 253 | default: |
254 | case TC_POLICE_UNSPEC: | 254 | if (p->default_index != NO_DEFAULT_INDEX) |
255 | /* fall through */ | 255 | skb->tc_index = p->default_index; |
256 | default: | 256 | break; |
257 | if (p->default_index != NO_DEFAULT_INDEX) | ||
258 | skb->tc_index = p->default_index; | ||
259 | break; | ||
260 | } | 257 | } |
261 | } | 258 | } |
262 | 259 | ||
diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c index c2689f4ba8de..c264308f17c1 100644 --- a/net/sched/sch_fifo.c +++ b/net/sched/sch_fifo.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
16 | #include <linux/netdevice.h> | ||
17 | #include <linux/skbuff.h> | 16 | #include <linux/skbuff.h> |
18 | #include <net/pkt_sched.h> | 17 | #include <net/pkt_sched.h> |
19 | 18 | ||
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index f4d34480a093..c81649cf0b9e 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -11,27 +11,19 @@ | |||
11 | * - Ingress support | 11 | * - Ingress support |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <asm/uaccess.h> | ||
15 | #include <asm/system.h> | ||
16 | #include <linux/bitops.h> | 14 | #include <linux/bitops.h> |
17 | #include <linux/module.h> | 15 | #include <linux/module.h> |
18 | #include <linux/types.h> | 16 | #include <linux/types.h> |
19 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
20 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
21 | #include <linux/string.h> | 19 | #include <linux/string.h> |
22 | #include <linux/mm.h> | ||
23 | #include <linux/socket.h> | ||
24 | #include <linux/sockios.h> | ||
25 | #include <linux/in.h> | ||
26 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/netdevice.h> | 21 | #include <linux/netdevice.h> |
29 | #include <linux/skbuff.h> | 22 | #include <linux/skbuff.h> |
30 | #include <linux/rtnetlink.h> | 23 | #include <linux/rtnetlink.h> |
31 | #include <linux/init.h> | 24 | #include <linux/init.h> |
32 | #include <linux/rcupdate.h> | 25 | #include <linux/rcupdate.h> |
33 | #include <linux/list.h> | 26 | #include <linux/list.h> |
34 | #include <net/sock.h> | ||
35 | #include <net/pkt_sched.h> | 27 | #include <net/pkt_sched.h> |
36 | 28 | ||
37 | /* Main transmission queue. */ | 29 | /* Main transmission queue. */ |
@@ -59,122 +51,143 @@ void qdisc_unlock_tree(struct net_device *dev) | |||
59 | spin_unlock_bh(&dev->queue_lock); | 51 | spin_unlock_bh(&dev->queue_lock); |
60 | } | 52 | } |
61 | 53 | ||
62 | /* | 54 | static inline int qdisc_qlen(struct Qdisc *q) |
63 | dev->queue_lock serializes queue accesses for this device | 55 | { |
64 | AND dev->qdisc pointer itself. | 56 | return q->q.qlen; |
57 | } | ||
65 | 58 | ||
66 | netif_tx_lock serializes accesses to device driver. | 59 | static inline int dev_requeue_skb(struct sk_buff *skb, struct net_device *dev, |
60 | struct Qdisc *q) | ||
61 | { | ||
62 | if (unlikely(skb->next)) | ||
63 | dev->gso_skb = skb; | ||
64 | else | ||
65 | q->ops->requeue(skb, q); | ||
67 | 66 | ||
68 | dev->queue_lock and netif_tx_lock are mutually exclusive, | 67 | netif_schedule(dev); |
69 | if one is grabbed, another must be free. | 68 | return 0; |
70 | */ | 69 | } |
71 | 70 | ||
71 | static inline struct sk_buff *dev_dequeue_skb(struct net_device *dev, | ||
72 | struct Qdisc *q) | ||
73 | { | ||
74 | struct sk_buff *skb; | ||
72 | 75 | ||
73 | /* Kick device. | 76 | if ((skb = dev->gso_skb)) |
77 | dev->gso_skb = NULL; | ||
78 | else | ||
79 | skb = q->dequeue(q); | ||
74 | 80 | ||
75 | Returns: 0 - queue is empty or throttled. | 81 | return skb; |
76 | >0 - queue is not empty. | 82 | } |
77 | 83 | ||
78 | NOTE: Called under dev->queue_lock with locally disabled BH. | 84 | static inline int handle_dev_cpu_collision(struct sk_buff *skb, |
79 | */ | 85 | struct net_device *dev, |
86 | struct Qdisc *q) | ||
87 | { | ||
88 | int ret; | ||
80 | 89 | ||
90 | if (unlikely(dev->xmit_lock_owner == smp_processor_id())) { | ||
91 | /* | ||
92 | * Same CPU holding the lock. It may be a transient | ||
93 | * configuration error, when hard_start_xmit() recurses. We | ||
94 | * detect it by checking xmit owner and drop the packet when | ||
95 | * deadloop is detected. Return OK to try the next skb. | ||
96 | */ | ||
97 | kfree_skb(skb); | ||
98 | if (net_ratelimit()) | ||
99 | printk(KERN_WARNING "Dead loop on netdevice %s, " | ||
100 | "fix it urgently!\n", dev->name); | ||
101 | ret = qdisc_qlen(q); | ||
102 | } else { | ||
103 | /* | ||
104 | * Another cpu is holding lock, requeue & delay xmits for | ||
105 | * some time. | ||
106 | */ | ||
107 | __get_cpu_var(netdev_rx_stat).cpu_collision++; | ||
108 | ret = dev_requeue_skb(skb, dev, q); | ||
109 | } | ||
110 | |||
111 | return ret; | ||
112 | } | ||
113 | |||
114 | /* | ||
115 | * NOTE: Called under dev->queue_lock with locally disabled BH. | ||
116 | * | ||
117 | * __LINK_STATE_QDISC_RUNNING guarantees only one CPU can process this | ||
118 | * device at a time. dev->queue_lock serializes queue accesses for | ||
119 | * this device AND dev->qdisc pointer itself. | ||
120 | * | ||
121 | * netif_tx_lock serializes accesses to device driver. | ||
122 | * | ||
123 | * dev->queue_lock and netif_tx_lock are mutually exclusive, | ||
124 | * if one is grabbed, another must be free. | ||
125 | * | ||
126 | * Note, that this procedure can be called by a watchdog timer | ||
127 | * | ||
128 | * Returns to the caller: | ||
129 | * 0 - queue is empty or throttled. | ||
130 | * >0 - queue is not empty. | ||
131 | * | ||
132 | */ | ||
81 | static inline int qdisc_restart(struct net_device *dev) | 133 | static inline int qdisc_restart(struct net_device *dev) |
82 | { | 134 | { |
83 | struct Qdisc *q = dev->qdisc; | 135 | struct Qdisc *q = dev->qdisc; |
84 | struct sk_buff *skb; | 136 | struct sk_buff *skb; |
137 | unsigned lockless; | ||
138 | int ret; | ||
85 | 139 | ||
86 | /* Dequeue packet */ | 140 | /* Dequeue packet */ |
87 | if (((skb = dev->gso_skb)) || ((skb = q->dequeue(q)))) { | 141 | if (unlikely((skb = dev_dequeue_skb(dev, q)) == NULL)) |
88 | unsigned nolock = (dev->features & NETIF_F_LLTX); | 142 | return 0; |
143 | |||
144 | /* | ||
145 | * When the driver has LLTX set, it does its own locking in | ||
146 | * start_xmit. These checks are worth it because even uncongested | ||
147 | * locks can be quite expensive. The driver can do a trylock, as | ||
148 | * is being done here; in case of lock contention it should return | ||
149 | * NETDEV_TX_LOCKED and the packet will be requeued. | ||
150 | */ | ||
151 | lockless = (dev->features & NETIF_F_LLTX); | ||
89 | 152 | ||
90 | dev->gso_skb = NULL; | 153 | if (!lockless && !netif_tx_trylock(dev)) { |
154 | /* Another CPU grabbed the driver tx lock */ | ||
155 | return handle_dev_cpu_collision(skb, dev, q); | ||
156 | } | ||
91 | 157 | ||
92 | /* | 158 | /* And release queue */ |
93 | * When the driver has LLTX set it does its own locking | 159 | spin_unlock(&dev->queue_lock); |
94 | * in start_xmit. No need to add additional overhead by | ||
95 | * locking again. These checks are worth it because | ||
96 | * even uncongested locks can be quite expensive. | ||
97 | * The driver can do trylock like here too, in case | ||
98 | * of lock congestion it should return -1 and the packet | ||
99 | * will be requeued. | ||
100 | */ | ||
101 | if (!nolock) { | ||
102 | if (!netif_tx_trylock(dev)) { | ||
103 | collision: | ||
104 | /* So, someone grabbed the driver. */ | ||
105 | |||
106 | /* It may be transient configuration error, | ||
107 | when hard_start_xmit() recurses. We detect | ||
108 | it by checking xmit owner and drop the | ||
109 | packet when deadloop is detected. | ||
110 | */ | ||
111 | if (dev->xmit_lock_owner == smp_processor_id()) { | ||
112 | kfree_skb(skb); | ||
113 | if (net_ratelimit()) | ||
114 | printk(KERN_DEBUG "Dead loop on netdevice %s, fix it urgently!\n", dev->name); | ||
115 | goto out; | ||
116 | } | ||
117 | __get_cpu_var(netdev_rx_stat).cpu_collision++; | ||
118 | goto requeue; | ||
119 | } | ||
120 | } | ||
121 | 160 | ||
122 | { | 161 | ret = dev_hard_start_xmit(skb, dev); |
123 | /* And release queue */ | ||
124 | spin_unlock(&dev->queue_lock); | ||
125 | |||
126 | if (!netif_queue_stopped(dev)) { | ||
127 | int ret; | ||
128 | |||
129 | ret = dev_hard_start_xmit(skb, dev); | ||
130 | if (ret == NETDEV_TX_OK) { | ||
131 | if (!nolock) { | ||
132 | netif_tx_unlock(dev); | ||
133 | } | ||
134 | spin_lock(&dev->queue_lock); | ||
135 | q = dev->qdisc; | ||
136 | goto out; | ||
137 | } | ||
138 | if (ret == NETDEV_TX_LOCKED && nolock) { | ||
139 | spin_lock(&dev->queue_lock); | ||
140 | q = dev->qdisc; | ||
141 | goto collision; | ||
142 | } | ||
143 | } | ||
144 | 162 | ||
145 | /* NETDEV_TX_BUSY - we need to requeue */ | 163 | if (!lockless) |
146 | /* Release the driver */ | 164 | netif_tx_unlock(dev); |
147 | if (!nolock) { | ||
148 | netif_tx_unlock(dev); | ||
149 | } | ||
150 | spin_lock(&dev->queue_lock); | ||
151 | q = dev->qdisc; | ||
152 | } | ||
153 | 165 | ||
154 | /* Device kicked us out :( | 166 | spin_lock(&dev->queue_lock); |
155 | This is possible in three cases: | 167 | q = dev->qdisc; |
156 | 168 | ||
157 | 0. driver is locked | 169 | switch (ret) { |
158 | 1. fastroute is enabled | 170 | case NETDEV_TX_OK: |
159 | 2. device cannot determine busy state | 171 | /* Driver sent out skb successfully */ |
160 | before start of transmission (f.e. dialout) | 172 | ret = qdisc_qlen(q); |
161 | 3. device is buggy (ppp) | 173 | break; |
162 | */ | ||
163 | 174 | ||
164 | requeue: | 175 | case NETDEV_TX_LOCKED: |
165 | if (unlikely(q == &noop_qdisc)) | 176 | /* Driver try lock failed */ |
166 | kfree_skb(skb); | 177 | ret = handle_dev_cpu_collision(skb, dev, q); |
167 | else if (skb->next) | 178 | break; |
168 | dev->gso_skb = skb; | 179 | |
169 | else | 180 | default: |
170 | q->ops->requeue(skb, q); | 181 | /* Driver returned NETDEV_TX_BUSY - requeue skb */ |
171 | netif_schedule(dev); | 182 | if (unlikely (ret != NETDEV_TX_BUSY && net_ratelimit())) |
183 | printk(KERN_WARNING "BUG %s code %d qlen %d\n", | ||
184 | dev->name, ret, q->q.qlen); | ||
185 | |||
186 | ret = dev_requeue_skb(skb, dev, q); | ||
187 | break; | ||
172 | } | 188 | } |
173 | return 0; | ||
174 | 189 | ||
175 | out: | 190 | return ret; |
176 | BUG_ON((int) q->q.qlen < 0); | ||
177 | return q->q.qlen; | ||
178 | } | 191 | } |
179 | 192 | ||
180 | void __qdisc_run(struct net_device *dev) | 193 | void __qdisc_run(struct net_device *dev) |
@@ -493,9 +506,7 @@ void qdisc_destroy(struct Qdisc *qdisc) | |||
493 | return; | 506 | return; |
494 | 507 | ||
495 | list_del(&qdisc->list); | 508 | list_del(&qdisc->list); |
496 | #ifdef CONFIG_NET_ESTIMATOR | ||
497 | gen_kill_estimator(&qdisc->bstats, &qdisc->rate_est); | 509 | gen_kill_estimator(&qdisc->bstats, &qdisc->rate_est); |
498 | #endif | ||
499 | if (ops->reset) | 510 | if (ops->reset) |
500 | ops->reset(qdisc); | 511 | ops->reset(qdisc); |
501 | if (ops->destroy) | 512 | if (ops->destroy) |
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index fa1b4fe7a5fd..3cc6dda02e2e 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/types.h> | 22 | #include <linux/types.h> |
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/netdevice.h> | ||
25 | #include <linux/skbuff.h> | 24 | #include <linux/skbuff.h> |
26 | #include <net/pkt_sched.h> | 25 | #include <net/pkt_sched.h> |
27 | #include <net/red.h> | 26 | #include <net/red.h> |
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 9d124c4ee3a7..55e7e4530f43 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c | |||
@@ -53,7 +53,6 @@ | |||
53 | #include <linux/module.h> | 53 | #include <linux/module.h> |
54 | #include <linux/types.h> | 54 | #include <linux/types.h> |
55 | #include <linux/errno.h> | 55 | #include <linux/errno.h> |
56 | #include <linux/jiffies.h> | ||
57 | #include <linux/compiler.h> | 56 | #include <linux/compiler.h> |
58 | #include <linux/spinlock.h> | 57 | #include <linux/spinlock.h> |
59 | #include <linux/skbuff.h> | 58 | #include <linux/skbuff.h> |
@@ -62,13 +61,11 @@ | |||
62 | #include <linux/list.h> | 61 | #include <linux/list.h> |
63 | #include <linux/rbtree.h> | 62 | #include <linux/rbtree.h> |
64 | #include <linux/init.h> | 63 | #include <linux/init.h> |
65 | #include <linux/netdevice.h> | ||
66 | #include <linux/rtnetlink.h> | 64 | #include <linux/rtnetlink.h> |
67 | #include <linux/pkt_sched.h> | 65 | #include <linux/pkt_sched.h> |
68 | #include <net/netlink.h> | 66 | #include <net/netlink.h> |
69 | #include <net/pkt_sched.h> | 67 | #include <net/pkt_sched.h> |
70 | #include <net/pkt_cls.h> | 68 | #include <net/pkt_cls.h> |
71 | #include <asm/system.h> | ||
72 | #include <asm/div64.h> | 69 | #include <asm/div64.h> |
73 | 70 | ||
74 | /* | 71 | /* |
@@ -122,7 +119,6 @@ struct hfsc_class | |||
122 | struct gnet_stats_basic bstats; | 119 | struct gnet_stats_basic bstats; |
123 | struct gnet_stats_queue qstats; | 120 | struct gnet_stats_queue qstats; |
124 | struct gnet_stats_rate_est rate_est; | 121 | struct gnet_stats_rate_est rate_est; |
125 | spinlock_t *stats_lock; | ||
126 | unsigned int level; /* class level in hierarchy */ | 122 | unsigned int level; /* class level in hierarchy */ |
127 | struct tcf_proto *filter_list; /* filter list */ | 123 | struct tcf_proto *filter_list; /* filter list */ |
128 | unsigned int filter_cnt; /* filter count */ | 124 | unsigned int filter_cnt; /* filter count */ |
@@ -1054,11 +1050,10 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | |||
1054 | } | 1050 | } |
1055 | sch_tree_unlock(sch); | 1051 | sch_tree_unlock(sch); |
1056 | 1052 | ||
1057 | #ifdef CONFIG_NET_ESTIMATOR | ||
1058 | if (tca[TCA_RATE-1]) | 1053 | if (tca[TCA_RATE-1]) |
1059 | gen_replace_estimator(&cl->bstats, &cl->rate_est, | 1054 | gen_replace_estimator(&cl->bstats, &cl->rate_est, |
1060 | cl->stats_lock, tca[TCA_RATE-1]); | 1055 | &sch->dev->queue_lock, |
1061 | #endif | 1056 | tca[TCA_RATE-1]); |
1062 | return 0; | 1057 | return 0; |
1063 | } | 1058 | } |
1064 | 1059 | ||
@@ -1098,7 +1093,6 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | |||
1098 | cl->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid); | 1093 | cl->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid); |
1099 | if (cl->qdisc == NULL) | 1094 | if (cl->qdisc == NULL) |
1100 | cl->qdisc = &noop_qdisc; | 1095 | cl->qdisc = &noop_qdisc; |
1101 | cl->stats_lock = &sch->dev->queue_lock; | ||
1102 | INIT_LIST_HEAD(&cl->children); | 1096 | INIT_LIST_HEAD(&cl->children); |
1103 | cl->vt_tree = RB_ROOT; | 1097 | cl->vt_tree = RB_ROOT; |
1104 | cl->cf_tree = RB_ROOT; | 1098 | cl->cf_tree = RB_ROOT; |
@@ -1112,11 +1106,9 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | |||
1112 | cl->cl_pcvtoff = parent->cl_cvtoff; | 1106 | cl->cl_pcvtoff = parent->cl_cvtoff; |
1113 | sch_tree_unlock(sch); | 1107 | sch_tree_unlock(sch); |
1114 | 1108 | ||
1115 | #ifdef CONFIG_NET_ESTIMATOR | ||
1116 | if (tca[TCA_RATE-1]) | 1109 | if (tca[TCA_RATE-1]) |
1117 | gen_new_estimator(&cl->bstats, &cl->rate_est, | 1110 | gen_new_estimator(&cl->bstats, &cl->rate_est, |
1118 | cl->stats_lock, tca[TCA_RATE-1]); | 1111 | &sch->dev->queue_lock, tca[TCA_RATE-1]); |
1119 | #endif | ||
1120 | *arg = (unsigned long)cl; | 1112 | *arg = (unsigned long)cl; |
1121 | return 0; | 1113 | return 0; |
1122 | } | 1114 | } |
@@ -1128,9 +1120,7 @@ hfsc_destroy_class(struct Qdisc *sch, struct hfsc_class *cl) | |||
1128 | 1120 | ||
1129 | tcf_destroy_chain(cl->filter_list); | 1121 | tcf_destroy_chain(cl->filter_list); |
1130 | qdisc_destroy(cl->qdisc); | 1122 | qdisc_destroy(cl->qdisc); |
1131 | #ifdef CONFIG_NET_ESTIMATOR | ||
1132 | gen_kill_estimator(&cl->bstats, &cl->rate_est); | 1123 | gen_kill_estimator(&cl->bstats, &cl->rate_est); |
1133 | #endif | ||
1134 | if (cl != &q->root) | 1124 | if (cl != &q->root) |
1135 | kfree(cl); | 1125 | kfree(cl); |
1136 | } | 1126 | } |
@@ -1184,9 +1174,6 @@ hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) | |||
1184 | case TC_ACT_SHOT: | 1174 | case TC_ACT_SHOT: |
1185 | return NULL; | 1175 | return NULL; |
1186 | } | 1176 | } |
1187 | #elif defined(CONFIG_NET_CLS_POLICE) | ||
1188 | if (result == TC_POLICE_SHOT) | ||
1189 | return NULL; | ||
1190 | #endif | 1177 | #endif |
1191 | if ((cl = (struct hfsc_class *)res.class) == NULL) { | 1178 | if ((cl = (struct hfsc_class *)res.class) == NULL) { |
1192 | if ((cl = hfsc_find_class(res.classid, sch)) == NULL) | 1179 | if ((cl = hfsc_find_class(res.classid, sch)) == NULL) |
@@ -1384,9 +1371,7 @@ hfsc_dump_class_stats(struct Qdisc *sch, unsigned long arg, | |||
1384 | xstats.rtwork = cl->cl_cumul; | 1371 | xstats.rtwork = cl->cl_cumul; |
1385 | 1372 | ||
1386 | if (gnet_stats_copy_basic(d, &cl->bstats) < 0 || | 1373 | if (gnet_stats_copy_basic(d, &cl->bstats) < 0 || |
1387 | #ifdef CONFIG_NET_ESTIMATOR | ||
1388 | gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 || | 1374 | gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 || |
1389 | #endif | ||
1390 | gnet_stats_copy_queue(d, &cl->qstats) < 0) | 1375 | gnet_stats_copy_queue(d, &cl->qstats) < 0) |
1391 | return -1; | 1376 | return -1; |
1392 | 1377 | ||
@@ -1448,8 +1433,6 @@ hfsc_init_qdisc(struct Qdisc *sch, struct rtattr *opt) | |||
1448 | return -EINVAL; | 1433 | return -EINVAL; |
1449 | qopt = RTA_DATA(opt); | 1434 | qopt = RTA_DATA(opt); |
1450 | 1435 | ||
1451 | sch->stats_lock = &sch->dev->queue_lock; | ||
1452 | |||
1453 | q->defcls = qopt->defcls; | 1436 | q->defcls = qopt->defcls; |
1454 | for (i = 0; i < HFSC_HSIZE; i++) | 1437 | for (i = 0; i < HFSC_HSIZE; i++) |
1455 | INIT_LIST_HEAD(&q->clhash[i]); | 1438 | INIT_LIST_HEAD(&q->clhash[i]); |
@@ -1464,7 +1447,6 @@ hfsc_init_qdisc(struct Qdisc *sch, struct rtattr *opt) | |||
1464 | sch->handle); | 1447 | sch->handle); |
1465 | if (q->root.qdisc == NULL) | 1448 | if (q->root.qdisc == NULL) |
1466 | q->root.qdisc = &noop_qdisc; | 1449 | q->root.qdisc = &noop_qdisc; |
1467 | q->root.stats_lock = &sch->dev->queue_lock; | ||
1468 | INIT_LIST_HEAD(&q->root.children); | 1450 | INIT_LIST_HEAD(&q->root.children); |
1469 | q->root.vt_tree = RB_ROOT; | 1451 | q->root.vt_tree = RB_ROOT; |
1470 | q->root.cf_tree = RB_ROOT; | 1452 | q->root.cf_tree = RB_ROOT; |
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 035788c5b7f8..246a2f9765f1 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
@@ -28,32 +28,16 @@ | |||
28 | * $Id: sch_htb.c,v 1.25 2003/12/07 11:08:25 devik Exp devik $ | 28 | * $Id: sch_htb.c,v 1.25 2003/12/07 11:08:25 devik Exp devik $ |
29 | */ | 29 | */ |
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <asm/uaccess.h> | ||
32 | #include <asm/system.h> | ||
33 | #include <linux/bitops.h> | ||
34 | #include <linux/types.h> | 31 | #include <linux/types.h> |
35 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
36 | #include <linux/string.h> | 33 | #include <linux/string.h> |
37 | #include <linux/mm.h> | ||
38 | #include <linux/socket.h> | ||
39 | #include <linux/sockios.h> | ||
40 | #include <linux/in.h> | ||
41 | #include <linux/errno.h> | 34 | #include <linux/errno.h> |
42 | #include <linux/interrupt.h> | ||
43 | #include <linux/if_ether.h> | ||
44 | #include <linux/inet.h> | ||
45 | #include <linux/netdevice.h> | ||
46 | #include <linux/etherdevice.h> | ||
47 | #include <linux/notifier.h> | ||
48 | #include <net/ip.h> | ||
49 | #include <net/route.h> | ||
50 | #include <linux/skbuff.h> | 35 | #include <linux/skbuff.h> |
51 | #include <linux/list.h> | 36 | #include <linux/list.h> |
52 | #include <linux/compiler.h> | 37 | #include <linux/compiler.h> |
38 | #include <linux/rbtree.h> | ||
53 | #include <net/netlink.h> | 39 | #include <net/netlink.h> |
54 | #include <net/sock.h> | ||
55 | #include <net/pkt_sched.h> | 40 | #include <net/pkt_sched.h> |
56 | #include <linux/rbtree.h> | ||
57 | 41 | ||
58 | /* HTB algorithm. | 42 | /* HTB algorithm. |
59 | Author: devik@cdi.cz | 43 | Author: devik@cdi.cz |
@@ -69,8 +53,6 @@ | |||
69 | */ | 53 | */ |
70 | 54 | ||
71 | #define HTB_HSIZE 16 /* classid hash size */ | 55 | #define HTB_HSIZE 16 /* classid hash size */ |
72 | #define HTB_EWMAC 2 /* rate average over HTB_EWMAC*HTB_HSIZE sec */ | ||
73 | #define HTB_RATECM 1 /* whether to use rate computer */ | ||
74 | #define HTB_HYSTERESIS 1 /* whether to use mode hysteresis for speedup */ | 56 | #define HTB_HYSTERESIS 1 /* whether to use mode hysteresis for speedup */ |
75 | #define HTB_VER 0x30011 /* major must be matched with number suplied by TC as version */ | 57 | #define HTB_VER 0x30011 /* major must be matched with number suplied by TC as version */ |
76 | 58 | ||
@@ -95,12 +77,6 @@ struct htb_class { | |||
95 | struct tc_htb_xstats xstats; /* our special stats */ | 77 | struct tc_htb_xstats xstats; /* our special stats */ |
96 | int refcnt; /* usage count of this class */ | 78 | int refcnt; /* usage count of this class */ |
97 | 79 | ||
98 | #ifdef HTB_RATECM | ||
99 | /* rate measurement counters */ | ||
100 | unsigned long rate_bytes, sum_bytes; | ||
101 | unsigned long rate_packets, sum_packets; | ||
102 | #endif | ||
103 | |||
104 | /* topology */ | 80 | /* topology */ |
105 | int level; /* our level (see above) */ | 81 | int level; /* our level (see above) */ |
106 | struct htb_class *parent; /* parent class */ | 82 | struct htb_class *parent; /* parent class */ |
@@ -153,15 +129,12 @@ struct htb_class { | |||
153 | /* of un.leaf originals should be done. */ | 129 | /* of un.leaf originals should be done. */ |
154 | }; | 130 | }; |
155 | 131 | ||
156 | /* TODO: maybe compute rate when size is too large .. or drop ? */ | ||
157 | static inline long L2T(struct htb_class *cl, struct qdisc_rate_table *rate, | 132 | static inline long L2T(struct htb_class *cl, struct qdisc_rate_table *rate, |
158 | int size) | 133 | int size) |
159 | { | 134 | { |
160 | int slot = size >> rate->rate.cell_log; | 135 | int slot = size >> rate->rate.cell_log; |
161 | if (slot > 255) { | 136 | if (slot > 255) |
162 | cl->xstats.giants++; | 137 | return (rate->data[255]*(slot >> 8) + rate->data[slot & 0xFF]); |
163 | slot = 255; | ||
164 | } | ||
165 | return rate->data[slot]; | 138 | return rate->data[slot]; |
166 | } | 139 | } |
167 | 140 | ||
@@ -194,10 +167,6 @@ struct htb_sched { | |||
194 | int rate2quantum; /* quant = rate / rate2quantum */ | 167 | int rate2quantum; /* quant = rate / rate2quantum */ |
195 | psched_time_t now; /* cached dequeue time */ | 168 | psched_time_t now; /* cached dequeue time */ |
196 | struct qdisc_watchdog watchdog; | 169 | struct qdisc_watchdog watchdog; |
197 | #ifdef HTB_RATECM | ||
198 | struct timer_list rttim; /* rate computer timer */ | ||
199 | int recmp_bucket; /* which hash bucket to recompute next */ | ||
200 | #endif | ||
201 | 170 | ||
202 | /* non shaped skbs; let them go directly thru */ | 171 | /* non shaped skbs; let them go directly thru */ |
203 | struct sk_buff_head direct_queue; | 172 | struct sk_buff_head direct_queue; |
@@ -280,9 +249,6 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, | |||
280 | case TC_ACT_SHOT: | 249 | case TC_ACT_SHOT: |
281 | return NULL; | 250 | return NULL; |
282 | } | 251 | } |
283 | #elif defined(CONFIG_NET_CLS_POLICE) | ||
284 | if (result == TC_POLICE_SHOT) | ||
285 | return HTB_DIRECT; | ||
286 | #endif | 252 | #endif |
287 | if ((cl = (void *)res.class) == NULL) { | 253 | if ((cl = (void *)res.class) == NULL) { |
288 | if (res.classid == sch->handle) | 254 | if (res.classid == sch->handle) |
@@ -634,13 +600,14 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
634 | cl->qstats.drops++; | 600 | cl->qstats.drops++; |
635 | return NET_XMIT_DROP; | 601 | return NET_XMIT_DROP; |
636 | } else { | 602 | } else { |
637 | cl->bstats.packets++; | 603 | cl->bstats.packets += |
604 | skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1; | ||
638 | cl->bstats.bytes += skb->len; | 605 | cl->bstats.bytes += skb->len; |
639 | htb_activate(q, cl); | 606 | htb_activate(q, cl); |
640 | } | 607 | } |
641 | 608 | ||
642 | sch->q.qlen++; | 609 | sch->q.qlen++; |
643 | sch->bstats.packets++; | 610 | sch->bstats.packets += skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1; |
644 | sch->bstats.bytes += skb->len; | 611 | sch->bstats.bytes += skb->len; |
645 | return NET_XMIT_SUCCESS; | 612 | return NET_XMIT_SUCCESS; |
646 | } | 613 | } |
@@ -677,34 +644,6 @@ static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch) | |||
677 | return NET_XMIT_SUCCESS; | 644 | return NET_XMIT_SUCCESS; |
678 | } | 645 | } |
679 | 646 | ||
680 | #ifdef HTB_RATECM | ||
681 | #define RT_GEN(D,R) R+=D-(R/HTB_EWMAC);D=0 | ||
682 | static void htb_rate_timer(unsigned long arg) | ||
683 | { | ||
684 | struct Qdisc *sch = (struct Qdisc *)arg; | ||
685 | struct htb_sched *q = qdisc_priv(sch); | ||
686 | struct hlist_node *p; | ||
687 | struct htb_class *cl; | ||
688 | |||
689 | |||
690 | /* lock queue so that we can muck with it */ | ||
691 | spin_lock_bh(&sch->dev->queue_lock); | ||
692 | |||
693 | q->rttim.expires = jiffies + HZ; | ||
694 | add_timer(&q->rttim); | ||
695 | |||
696 | /* scan and recompute one bucket at time */ | ||
697 | if (++q->recmp_bucket >= HTB_HSIZE) | ||
698 | q->recmp_bucket = 0; | ||
699 | |||
700 | hlist_for_each_entry(cl,p, q->hash + q->recmp_bucket, hlist) { | ||
701 | RT_GEN(cl->sum_bytes, cl->rate_bytes); | ||
702 | RT_GEN(cl->sum_packets, cl->rate_packets); | ||
703 | } | ||
704 | spin_unlock_bh(&sch->dev->queue_lock); | ||
705 | } | ||
706 | #endif | ||
707 | |||
708 | /** | 647 | /** |
709 | * htb_charge_class - charges amount "bytes" to leaf and ancestors | 648 | * htb_charge_class - charges amount "bytes" to leaf and ancestors |
710 | * | 649 | * |
@@ -717,8 +656,9 @@ static void htb_rate_timer(unsigned long arg) | |||
717 | * In such case we remove class from event queue first. | 656 | * In such case we remove class from event queue first. |
718 | */ | 657 | */ |
719 | static void htb_charge_class(struct htb_sched *q, struct htb_class *cl, | 658 | static void htb_charge_class(struct htb_sched *q, struct htb_class *cl, |
720 | int level, int bytes) | 659 | int level, struct sk_buff *skb) |
721 | { | 660 | { |
661 | int bytes = skb->len; | ||
722 | long toks, diff; | 662 | long toks, diff; |
723 | enum htb_cmode old_mode; | 663 | enum htb_cmode old_mode; |
724 | 664 | ||
@@ -750,16 +690,12 @@ static void htb_charge_class(struct htb_sched *q, struct htb_class *cl, | |||
750 | if (cl->cmode != HTB_CAN_SEND) | 690 | if (cl->cmode != HTB_CAN_SEND) |
751 | htb_add_to_wait_tree(q, cl, diff); | 691 | htb_add_to_wait_tree(q, cl, diff); |
752 | } | 692 | } |
753 | #ifdef HTB_RATECM | ||
754 | /* update rate counters */ | ||
755 | cl->sum_bytes += bytes; | ||
756 | cl->sum_packets++; | ||
757 | #endif | ||
758 | 693 | ||
759 | /* update byte stats except for leaves which are already updated */ | 694 | /* update byte stats except for leaves which are already updated */ |
760 | if (cl->level) { | 695 | if (cl->level) { |
761 | cl->bstats.bytes += bytes; | 696 | cl->bstats.bytes += bytes; |
762 | cl->bstats.packets++; | 697 | cl->bstats.packets += skb_is_gso(skb)? |
698 | skb_shinfo(skb)->gso_segs:1; | ||
763 | } | 699 | } |
764 | cl = cl->parent; | 700 | cl = cl->parent; |
765 | } | 701 | } |
@@ -943,7 +879,7 @@ next: | |||
943 | gives us slightly better performance */ | 879 | gives us slightly better performance */ |
944 | if (!cl->un.leaf.q->q.qlen) | 880 | if (!cl->un.leaf.q->q.qlen) |
945 | htb_deactivate(q, cl); | 881 | htb_deactivate(q, cl); |
946 | htb_charge_class(q, cl, level, skb->len); | 882 | htb_charge_class(q, cl, level, skb); |
947 | } | 883 | } |
948 | return skb; | 884 | return skb; |
949 | } | 885 | } |
@@ -1095,13 +1031,6 @@ static int htb_init(struct Qdisc *sch, struct rtattr *opt) | |||
1095 | if (q->direct_qlen < 2) /* some devices have zero tx_queue_len */ | 1031 | if (q->direct_qlen < 2) /* some devices have zero tx_queue_len */ |
1096 | q->direct_qlen = 2; | 1032 | q->direct_qlen = 2; |
1097 | 1033 | ||
1098 | #ifdef HTB_RATECM | ||
1099 | init_timer(&q->rttim); | ||
1100 | q->rttim.function = htb_rate_timer; | ||
1101 | q->rttim.data = (unsigned long)sch; | ||
1102 | q->rttim.expires = jiffies + HZ; | ||
1103 | add_timer(&q->rttim); | ||
1104 | #endif | ||
1105 | if ((q->rate2quantum = gopt->rate2quantum) < 1) | 1034 | if ((q->rate2quantum = gopt->rate2quantum) < 1) |
1106 | q->rate2quantum = 1; | 1035 | q->rate2quantum = 1; |
1107 | q->defcls = gopt->defcls; | 1036 | q->defcls = gopt->defcls; |
@@ -1175,11 +1104,6 @@ htb_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d) | |||
1175 | { | 1104 | { |
1176 | struct htb_class *cl = (struct htb_class *)arg; | 1105 | struct htb_class *cl = (struct htb_class *)arg; |
1177 | 1106 | ||
1178 | #ifdef HTB_RATECM | ||
1179 | cl->rate_est.bps = cl->rate_bytes / (HTB_EWMAC * HTB_HSIZE); | ||
1180 | cl->rate_est.pps = cl->rate_packets / (HTB_EWMAC * HTB_HSIZE); | ||
1181 | #endif | ||
1182 | |||
1183 | if (!cl->level && cl->un.leaf.q) | 1107 | if (!cl->level && cl->un.leaf.q) |
1184 | cl->qstats.qlen = cl->un.leaf.q->q.qlen; | 1108 | cl->qstats.qlen = cl->un.leaf.q->q.qlen; |
1185 | cl->xstats.tokens = cl->tokens; | 1109 | cl->xstats.tokens = cl->tokens; |
@@ -1277,6 +1201,7 @@ static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl) | |||
1277 | BUG_TRAP(cl->un.leaf.q); | 1201 | BUG_TRAP(cl->un.leaf.q); |
1278 | qdisc_destroy(cl->un.leaf.q); | 1202 | qdisc_destroy(cl->un.leaf.q); |
1279 | } | 1203 | } |
1204 | gen_kill_estimator(&cl->bstats, &cl->rate_est); | ||
1280 | qdisc_put_rtab(cl->rate); | 1205 | qdisc_put_rtab(cl->rate); |
1281 | qdisc_put_rtab(cl->ceil); | 1206 | qdisc_put_rtab(cl->ceil); |
1282 | 1207 | ||
@@ -1305,9 +1230,6 @@ static void htb_destroy(struct Qdisc *sch) | |||
1305 | struct htb_sched *q = qdisc_priv(sch); | 1230 | struct htb_sched *q = qdisc_priv(sch); |
1306 | 1231 | ||
1307 | qdisc_watchdog_cancel(&q->watchdog); | 1232 | qdisc_watchdog_cancel(&q->watchdog); |
1308 | #ifdef HTB_RATECM | ||
1309 | del_timer_sync(&q->rttim); | ||
1310 | #endif | ||
1311 | /* This line used to be after htb_destroy_class call below | 1233 | /* This line used to be after htb_destroy_class call below |
1312 | and surprisingly it worked in 2.4. But it must precede it | 1234 | and surprisingly it worked in 2.4. But it must precede it |
1313 | because filter need its target class alive to be able to call | 1235 | because filter need its target class alive to be able to call |
@@ -1403,6 +1325,20 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1403 | if (!cl) { /* new class */ | 1325 | if (!cl) { /* new class */ |
1404 | struct Qdisc *new_q; | 1326 | struct Qdisc *new_q; |
1405 | int prio; | 1327 | int prio; |
1328 | struct { | ||
1329 | struct rtattr rta; | ||
1330 | struct gnet_estimator opt; | ||
1331 | } est = { | ||
1332 | .rta = { | ||
1333 | .rta_len = RTA_LENGTH(sizeof(est.opt)), | ||
1334 | .rta_type = TCA_RATE, | ||
1335 | }, | ||
1336 | .opt = { | ||
1337 | /* 4s interval, 16s averaging constant */ | ||
1338 | .interval = 2, | ||
1339 | .ewma_log = 2, | ||
1340 | }, | ||
1341 | }; | ||
1406 | 1342 | ||
1407 | /* check for valid classid */ | 1343 | /* check for valid classid */ |
1408 | if (!classid || TC_H_MAJ(classid ^ sch->handle) | 1344 | if (!classid || TC_H_MAJ(classid ^ sch->handle) |
@@ -1418,6 +1354,9 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1418 | if ((cl = kzalloc(sizeof(*cl), GFP_KERNEL)) == NULL) | 1354 | if ((cl = kzalloc(sizeof(*cl), GFP_KERNEL)) == NULL) |
1419 | goto failure; | 1355 | goto failure; |
1420 | 1356 | ||
1357 | gen_new_estimator(&cl->bstats, &cl->rate_est, | ||
1358 | &sch->dev->queue_lock, | ||
1359 | tca[TCA_RATE-1] ? : &est.rta); | ||
1421 | cl->refcnt = 1; | 1360 | cl->refcnt = 1; |
1422 | INIT_LIST_HEAD(&cl->sibling); | 1361 | INIT_LIST_HEAD(&cl->sibling); |
1423 | INIT_HLIST_NODE(&cl->hlist); | 1362 | INIT_HLIST_NODE(&cl->hlist); |
@@ -1469,8 +1408,13 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1469 | hlist_add_head(&cl->hlist, q->hash + htb_hash(classid)); | 1408 | hlist_add_head(&cl->hlist, q->hash + htb_hash(classid)); |
1470 | list_add_tail(&cl->sibling, | 1409 | list_add_tail(&cl->sibling, |
1471 | parent ? &parent->children : &q->root); | 1410 | parent ? &parent->children : &q->root); |
1472 | } else | 1411 | } else { |
1412 | if (tca[TCA_RATE-1]) | ||
1413 | gen_replace_estimator(&cl->bstats, &cl->rate_est, | ||
1414 | &sch->dev->queue_lock, | ||
1415 | tca[TCA_RATE-1]); | ||
1473 | sch_tree_lock(sch); | 1416 | sch_tree_lock(sch); |
1417 | } | ||
1474 | 1418 | ||
1475 | /* it used to be a nasty bug here, we have to check that node | 1419 | /* it used to be a nasty bug here, we have to check that node |
1476 | is really leaf before changing cl->un.leaf ! */ | 1420 | is really leaf before changing cl->un.leaf ! */ |
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c index f8b9f1cdf738..51f16b0af198 100644 --- a/net/sched/sch_ingress.c +++ b/net/sched/sch_ingress.c | |||
@@ -9,21 +9,14 @@ | |||
9 | 9 | ||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/types.h> | 11 | #include <linux/types.h> |
12 | #include <linux/list.h> | ||
12 | #include <linux/skbuff.h> | 13 | #include <linux/skbuff.h> |
13 | #include <linux/netdevice.h> | ||
14 | #include <linux/rtnetlink.h> | 14 | #include <linux/rtnetlink.h> |
15 | #include <linux/netfilter_ipv4.h> | 15 | #include <linux/netfilter_ipv4.h> |
16 | #include <linux/netfilter_ipv6.h> | 16 | #include <linux/netfilter_ipv6.h> |
17 | #include <linux/netfilter.h> | 17 | #include <linux/netfilter.h> |
18 | #include <linux/smp.h> | ||
19 | #include <net/netlink.h> | 18 | #include <net/netlink.h> |
20 | #include <net/pkt_sched.h> | 19 | #include <net/pkt_sched.h> |
21 | #include <asm/byteorder.h> | ||
22 | #include <asm/uaccess.h> | ||
23 | #include <linux/kmod.h> | ||
24 | #include <linux/stat.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/list.h> | ||
27 | 20 | ||
28 | 21 | ||
29 | #undef DEBUG_INGRESS | 22 | #undef DEBUG_INGRESS |
@@ -171,31 +164,12 @@ static int ingress_enqueue(struct sk_buff *skb,struct Qdisc *sch) | |||
171 | result = TC_ACT_OK; | 164 | result = TC_ACT_OK; |
172 | break; | 165 | break; |
173 | } | 166 | } |
174 | /* backward compat */ | ||
175 | #else | ||
176 | #ifdef CONFIG_NET_CLS_POLICE | ||
177 | switch (result) { | ||
178 | case TC_POLICE_SHOT: | ||
179 | result = NF_DROP; | ||
180 | sch->qstats.drops++; | ||
181 | break; | ||
182 | case TC_POLICE_RECLASSIFY: /* DSCP remarking here ? */ | ||
183 | case TC_POLICE_OK: | ||
184 | case TC_POLICE_UNSPEC: | ||
185 | default: | ||
186 | sch->bstats.packets++; | ||
187 | sch->bstats.bytes += skb->len; | ||
188 | result = NF_ACCEPT; | ||
189 | break; | ||
190 | } | ||
191 | |||
192 | #else | 167 | #else |
193 | D2PRINTK("Overriding result to ACCEPT\n"); | 168 | D2PRINTK("Overriding result to ACCEPT\n"); |
194 | result = NF_ACCEPT; | 169 | result = NF_ACCEPT; |
195 | sch->bstats.packets++; | 170 | sch->bstats.packets++; |
196 | sch->bstats.bytes += skb->len; | 171 | sch->bstats.bytes += skb->len; |
197 | #endif | 172 | #endif |
198 | #endif | ||
199 | 173 | ||
200 | return result; | 174 | return result; |
201 | } | 175 | } |
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 5d9d8bc9cc3a..9e5e87e81f00 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c | |||
@@ -14,11 +14,9 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/bitops.h> | ||
18 | #include <linux/types.h> | 17 | #include <linux/types.h> |
19 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
20 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
21 | #include <linux/netdevice.h> | ||
22 | #include <linux/skbuff.h> | 20 | #include <linux/skbuff.h> |
23 | #include <linux/rtnetlink.h> | 21 | #include <linux/rtnetlink.h> |
24 | 22 | ||
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index 6d7542c26e47..2d8c08493d6e 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c | |||
@@ -12,37 +12,23 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <asm/uaccess.h> | ||
16 | #include <asm/system.h> | ||
17 | #include <linux/bitops.h> | ||
18 | #include <linux/types.h> | 15 | #include <linux/types.h> |
19 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
20 | #include <linux/string.h> | 17 | #include <linux/string.h> |
21 | #include <linux/mm.h> | ||
22 | #include <linux/socket.h> | ||
23 | #include <linux/sockios.h> | ||
24 | #include <linux/in.h> | ||
25 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/if_ether.h> | ||
28 | #include <linux/inet.h> | ||
29 | #include <linux/netdevice.h> | ||
30 | #include <linux/etherdevice.h> | ||
31 | #include <linux/notifier.h> | ||
32 | #include <net/ip.h> | ||
33 | #include <net/route.h> | ||
34 | #include <linux/skbuff.h> | 19 | #include <linux/skbuff.h> |
35 | #include <net/netlink.h> | 20 | #include <net/netlink.h> |
36 | #include <net/sock.h> | ||
37 | #include <net/pkt_sched.h> | 21 | #include <net/pkt_sched.h> |
38 | 22 | ||
39 | 23 | ||
40 | struct prio_sched_data | 24 | struct prio_sched_data |
41 | { | 25 | { |
42 | int bands; | 26 | int bands; |
27 | int curband; /* for round-robin */ | ||
43 | struct tcf_proto *filter_list; | 28 | struct tcf_proto *filter_list; |
44 | u8 prio2band[TC_PRIO_MAX+1]; | 29 | u8 prio2band[TC_PRIO_MAX+1]; |
45 | struct Qdisc *queues[TCQ_PRIO_BANDS]; | 30 | struct Qdisc *queues[TCQ_PRIO_BANDS]; |
31 | int mq; | ||
46 | }; | 32 | }; |
47 | 33 | ||
48 | 34 | ||
@@ -70,14 +56,17 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) | |||
70 | #endif | 56 | #endif |
71 | if (TC_H_MAJ(band)) | 57 | if (TC_H_MAJ(band)) |
72 | band = 0; | 58 | band = 0; |
73 | return q->queues[q->prio2band[band&TC_PRIO_MAX]]; | 59 | band = q->prio2band[band&TC_PRIO_MAX]; |
60 | goto out; | ||
74 | } | 61 | } |
75 | band = res.classid; | 62 | band = res.classid; |
76 | } | 63 | } |
77 | band = TC_H_MIN(band) - 1; | 64 | band = TC_H_MIN(band) - 1; |
78 | if (band >= q->bands) | 65 | if (band >= q->bands) |
79 | return q->queues[q->prio2band[0]]; | 66 | band = q->prio2band[0]; |
80 | 67 | out: | |
68 | if (q->mq) | ||
69 | skb_set_queue_mapping(skb, band); | ||
81 | return q->queues[band]; | 70 | return q->queues[band]; |
82 | } | 71 | } |
83 | 72 | ||
@@ -144,17 +133,58 @@ prio_dequeue(struct Qdisc* sch) | |||
144 | struct Qdisc *qdisc; | 133 | struct Qdisc *qdisc; |
145 | 134 | ||
146 | for (prio = 0; prio < q->bands; prio++) { | 135 | for (prio = 0; prio < q->bands; prio++) { |
147 | qdisc = q->queues[prio]; | 136 | /* Check if the target subqueue is available before |
148 | skb = qdisc->dequeue(qdisc); | 137 | * pulling an skb. This way we avoid excessive requeues |
149 | if (skb) { | 138 | * for slower queues. |
150 | sch->q.qlen--; | 139 | */ |
151 | return skb; | 140 | if (!netif_subqueue_stopped(sch->dev, (q->mq ? prio : 0))) { |
141 | qdisc = q->queues[prio]; | ||
142 | skb = qdisc->dequeue(qdisc); | ||
143 | if (skb) { | ||
144 | sch->q.qlen--; | ||
145 | return skb; | ||
146 | } | ||
152 | } | 147 | } |
153 | } | 148 | } |
154 | return NULL; | 149 | return NULL; |
155 | 150 | ||
156 | } | 151 | } |
157 | 152 | ||
153 | static struct sk_buff *rr_dequeue(struct Qdisc* sch) | ||
154 | { | ||
155 | struct sk_buff *skb; | ||
156 | struct prio_sched_data *q = qdisc_priv(sch); | ||
157 | struct Qdisc *qdisc; | ||
158 | int bandcount; | ||
159 | |||
160 | /* Only take one pass through the queues. If nothing is available, | ||
161 | * return nothing. | ||
162 | */ | ||
163 | for (bandcount = 0; bandcount < q->bands; bandcount++) { | ||
164 | /* Check if the target subqueue is available before | ||
165 | * pulling an skb. This way we avoid excessive requeues | ||
166 | * for slower queues. If the queue is stopped, try the | ||
167 | * next queue. | ||
168 | */ | ||
169 | if (!netif_subqueue_stopped(sch->dev, | ||
170 | (q->mq ? q->curband : 0))) { | ||
171 | qdisc = q->queues[q->curband]; | ||
172 | skb = qdisc->dequeue(qdisc); | ||
173 | if (skb) { | ||
174 | sch->q.qlen--; | ||
175 | q->curband++; | ||
176 | if (q->curband >= q->bands) | ||
177 | q->curband = 0; | ||
178 | return skb; | ||
179 | } | ||
180 | } | ||
181 | q->curband++; | ||
182 | if (q->curband >= q->bands) | ||
183 | q->curband = 0; | ||
184 | } | ||
185 | return NULL; | ||
186 | } | ||
187 | |||
158 | static unsigned int prio_drop(struct Qdisc* sch) | 188 | static unsigned int prio_drop(struct Qdisc* sch) |
159 | { | 189 | { |
160 | struct prio_sched_data *q = qdisc_priv(sch); | 190 | struct prio_sched_data *q = qdisc_priv(sch); |
@@ -198,21 +228,41 @@ prio_destroy(struct Qdisc* sch) | |||
198 | static int prio_tune(struct Qdisc *sch, struct rtattr *opt) | 228 | static int prio_tune(struct Qdisc *sch, struct rtattr *opt) |
199 | { | 229 | { |
200 | struct prio_sched_data *q = qdisc_priv(sch); | 230 | struct prio_sched_data *q = qdisc_priv(sch); |
201 | struct tc_prio_qopt *qopt = RTA_DATA(opt); | 231 | struct tc_prio_qopt *qopt; |
232 | struct rtattr *tb[TCA_PRIO_MAX]; | ||
202 | int i; | 233 | int i; |
203 | 234 | ||
204 | if (opt->rta_len < RTA_LENGTH(sizeof(*qopt))) | 235 | if (rtattr_parse_nested_compat(tb, TCA_PRIO_MAX, opt, qopt, |
236 | sizeof(*qopt))) | ||
205 | return -EINVAL; | 237 | return -EINVAL; |
206 | if (qopt->bands > TCQ_PRIO_BANDS || qopt->bands < 2) | 238 | q->bands = qopt->bands; |
239 | /* If we're multiqueue, make sure the number of incoming bands | ||
240 | * matches the number of queues on the device we're associating with. | ||
241 | * If the number of bands requested is zero, then set q->bands to | ||
242 | * dev->egress_subqueue_count. | ||
243 | */ | ||
244 | q->mq = RTA_GET_FLAG(tb[TCA_PRIO_MQ - 1]); | ||
245 | if (q->mq) { | ||
246 | if (sch->handle != TC_H_ROOT) | ||
247 | return -EINVAL; | ||
248 | if (netif_is_multiqueue(sch->dev)) { | ||
249 | if (q->bands == 0) | ||
250 | q->bands = sch->dev->egress_subqueue_count; | ||
251 | else if (q->bands != sch->dev->egress_subqueue_count) | ||
252 | return -EINVAL; | ||
253 | } else | ||
254 | return -EOPNOTSUPP; | ||
255 | } | ||
256 | |||
257 | if (q->bands > TCQ_PRIO_BANDS || q->bands < 2) | ||
207 | return -EINVAL; | 258 | return -EINVAL; |
208 | 259 | ||
209 | for (i=0; i<=TC_PRIO_MAX; i++) { | 260 | for (i=0; i<=TC_PRIO_MAX; i++) { |
210 | if (qopt->priomap[i] >= qopt->bands) | 261 | if (qopt->priomap[i] >= q->bands) |
211 | return -EINVAL; | 262 | return -EINVAL; |
212 | } | 263 | } |
213 | 264 | ||
214 | sch_tree_lock(sch); | 265 | sch_tree_lock(sch); |
215 | q->bands = qopt->bands; | ||
216 | memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1); | 266 | memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1); |
217 | 267 | ||
218 | for (i=q->bands; i<TCQ_PRIO_BANDS; i++) { | 268 | for (i=q->bands; i<TCQ_PRIO_BANDS; i++) { |
@@ -268,11 +318,17 @@ static int prio_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
268 | { | 318 | { |
269 | struct prio_sched_data *q = qdisc_priv(sch); | 319 | struct prio_sched_data *q = qdisc_priv(sch); |
270 | unsigned char *b = skb_tail_pointer(skb); | 320 | unsigned char *b = skb_tail_pointer(skb); |
321 | struct rtattr *nest; | ||
271 | struct tc_prio_qopt opt; | 322 | struct tc_prio_qopt opt; |
272 | 323 | ||
273 | opt.bands = q->bands; | 324 | opt.bands = q->bands; |
274 | memcpy(&opt.priomap, q->prio2band, TC_PRIO_MAX+1); | 325 | memcpy(&opt.priomap, q->prio2band, TC_PRIO_MAX+1); |
275 | RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); | 326 | |
327 | nest = RTA_NEST_COMPAT(skb, TCA_OPTIONS, sizeof(opt), &opt); | ||
328 | if (q->mq) | ||
329 | RTA_PUT_FLAG(skb, TCA_PRIO_MQ); | ||
330 | RTA_NEST_COMPAT_END(skb, nest); | ||
331 | |||
276 | return skb->len; | 332 | return skb->len; |
277 | 333 | ||
278 | rtattr_failure: | 334 | rtattr_failure: |
@@ -443,17 +499,44 @@ static struct Qdisc_ops prio_qdisc_ops = { | |||
443 | .owner = THIS_MODULE, | 499 | .owner = THIS_MODULE, |
444 | }; | 500 | }; |
445 | 501 | ||
502 | static struct Qdisc_ops rr_qdisc_ops = { | ||
503 | .next = NULL, | ||
504 | .cl_ops = &prio_class_ops, | ||
505 | .id = "rr", | ||
506 | .priv_size = sizeof(struct prio_sched_data), | ||
507 | .enqueue = prio_enqueue, | ||
508 | .dequeue = rr_dequeue, | ||
509 | .requeue = prio_requeue, | ||
510 | .drop = prio_drop, | ||
511 | .init = prio_init, | ||
512 | .reset = prio_reset, | ||
513 | .destroy = prio_destroy, | ||
514 | .change = prio_tune, | ||
515 | .dump = prio_dump, | ||
516 | .owner = THIS_MODULE, | ||
517 | }; | ||
518 | |||
446 | static int __init prio_module_init(void) | 519 | static int __init prio_module_init(void) |
447 | { | 520 | { |
448 | return register_qdisc(&prio_qdisc_ops); | 521 | int err; |
522 | |||
523 | err = register_qdisc(&prio_qdisc_ops); | ||
524 | if (err < 0) | ||
525 | return err; | ||
526 | err = register_qdisc(&rr_qdisc_ops); | ||
527 | if (err < 0) | ||
528 | unregister_qdisc(&prio_qdisc_ops); | ||
529 | return err; | ||
449 | } | 530 | } |
450 | 531 | ||
451 | static void __exit prio_module_exit(void) | 532 | static void __exit prio_module_exit(void) |
452 | { | 533 | { |
453 | unregister_qdisc(&prio_qdisc_ops); | 534 | unregister_qdisc(&prio_qdisc_ops); |
535 | unregister_qdisc(&rr_qdisc_ops); | ||
454 | } | 536 | } |
455 | 537 | ||
456 | module_init(prio_module_init) | 538 | module_init(prio_module_init) |
457 | module_exit(prio_module_exit) | 539 | module_exit(prio_module_exit) |
458 | 540 | ||
459 | MODULE_LICENSE("GPL"); | 541 | MODULE_LICENSE("GPL"); |
542 | MODULE_ALIAS("sch_rr"); | ||
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index 00db53eb8159..9b95fefb70f4 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | #include <linux/netdevice.h> | ||
21 | #include <linux/skbuff.h> | 20 | #include <linux/skbuff.h> |
22 | #include <net/pkt_sched.h> | 21 | #include <net/pkt_sched.h> |
23 | #include <net/inet_ecn.h> | 22 | #include <net/inet_ecn.h> |
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 96dfdf78d32c..957957309859 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c | |||
@@ -10,31 +10,17 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <asm/uaccess.h> | ||
14 | #include <asm/system.h> | ||
15 | #include <linux/bitops.h> | ||
16 | #include <linux/types.h> | 13 | #include <linux/types.h> |
17 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
18 | #include <linux/jiffies.h> | 15 | #include <linux/jiffies.h> |
19 | #include <linux/string.h> | 16 | #include <linux/string.h> |
20 | #include <linux/mm.h> | ||
21 | #include <linux/socket.h> | ||
22 | #include <linux/sockios.h> | ||
23 | #include <linux/in.h> | 17 | #include <linux/in.h> |
24 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/if_ether.h> | ||
27 | #include <linux/inet.h> | ||
28 | #include <linux/netdevice.h> | ||
29 | #include <linux/etherdevice.h> | ||
30 | #include <linux/notifier.h> | ||
31 | #include <linux/init.h> | 19 | #include <linux/init.h> |
32 | #include <net/ip.h> | ||
33 | #include <net/netlink.h> | ||
34 | #include <linux/ipv6.h> | 20 | #include <linux/ipv6.h> |
35 | #include <net/route.h> | ||
36 | #include <linux/skbuff.h> | 21 | #include <linux/skbuff.h> |
37 | #include <net/sock.h> | 22 | #include <net/ip.h> |
23 | #include <net/netlink.h> | ||
38 | #include <net/pkt_sched.h> | 24 | #include <net/pkt_sched.h> |
39 | 25 | ||
40 | 26 | ||
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index 53862953baaf..8c2639af4c6a 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c | |||
@@ -13,29 +13,12 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <asm/uaccess.h> | ||
17 | #include <asm/system.h> | ||
18 | #include <linux/bitops.h> | ||
19 | #include <linux/types.h> | 16 | #include <linux/types.h> |
20 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
21 | #include <linux/jiffies.h> | ||
22 | #include <linux/string.h> | 18 | #include <linux/string.h> |
23 | #include <linux/mm.h> | ||
24 | #include <linux/socket.h> | ||
25 | #include <linux/sockios.h> | ||
26 | #include <linux/in.h> | ||
27 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/if_ether.h> | ||
30 | #include <linux/inet.h> | ||
31 | #include <linux/netdevice.h> | ||
32 | #include <linux/etherdevice.h> | ||
33 | #include <linux/notifier.h> | ||
34 | #include <net/ip.h> | ||
35 | #include <net/netlink.h> | ||
36 | #include <net/route.h> | ||
37 | #include <linux/skbuff.h> | 20 | #include <linux/skbuff.h> |
38 | #include <net/sock.h> | 21 | #include <net/netlink.h> |
39 | #include <net/pkt_sched.h> | 22 | #include <net/pkt_sched.h> |
40 | 23 | ||
41 | 24 | ||
@@ -142,7 +125,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch) | |||
142 | 125 | ||
143 | if (skb->len > q->max_size) { | 126 | if (skb->len > q->max_size) { |
144 | sch->qstats.drops++; | 127 | sch->qstats.drops++; |
145 | #ifdef CONFIG_NET_CLS_POLICE | 128 | #ifdef CONFIG_NET_CLS_ACT |
146 | if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch)) | 129 | if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch)) |
147 | #endif | 130 | #endif |
148 | kfree_skb(skb); | 131 | kfree_skb(skb); |
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index f05ad9a30b4c..0968184ea6be 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c | |||
@@ -9,30 +9,17 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <asm/uaccess.h> | ||
13 | #include <asm/system.h> | ||
14 | #include <linux/bitops.h> | ||
15 | #include <linux/types.h> | 12 | #include <linux/types.h> |
16 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
17 | #include <linux/string.h> | 14 | #include <linux/string.h> |
18 | #include <linux/mm.h> | ||
19 | #include <linux/socket.h> | ||
20 | #include <linux/sockios.h> | ||
21 | #include <linux/in.h> | ||
22 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/if_arp.h> | 16 | #include <linux/if_arp.h> |
25 | #include <linux/if_ether.h> | ||
26 | #include <linux/inet.h> | ||
27 | #include <linux/netdevice.h> | 17 | #include <linux/netdevice.h> |
28 | #include <linux/etherdevice.h> | ||
29 | #include <linux/notifier.h> | ||
30 | #include <linux/init.h> | 18 | #include <linux/init.h> |
31 | #include <net/ip.h> | ||
32 | #include <net/route.h> | ||
33 | #include <linux/skbuff.h> | 19 | #include <linux/skbuff.h> |
34 | #include <linux/moduleparam.h> | 20 | #include <linux/moduleparam.h> |
35 | #include <net/sock.h> | 21 | #include <net/dst.h> |
22 | #include <net/neighbour.h> | ||
36 | #include <net/pkt_sched.h> | 23 | #include <net/pkt_sched.h> |
37 | 24 | ||
38 | /* | 25 | /* |
@@ -225,7 +212,6 @@ static int teql_qdisc_init(struct Qdisc *sch, struct rtattr *opt) | |||
225 | return 0; | 212 | return 0; |
226 | } | 213 | } |
227 | 214 | ||
228 | /* "teql*" netdevice routines */ | ||
229 | 215 | ||
230 | static int | 216 | static int |
231 | __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *dev) | 217 | __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *dev) |
@@ -277,6 +263,7 @@ static int teql_master_xmit(struct sk_buff *skb, struct net_device *dev) | |||
277 | int busy; | 263 | int busy; |
278 | int nores; | 264 | int nores; |
279 | int len = skb->len; | 265 | int len = skb->len; |
266 | int subq = skb->queue_mapping; | ||
280 | struct sk_buff *skb_res = NULL; | 267 | struct sk_buff *skb_res = NULL; |
281 | 268 | ||
282 | start = master->slaves; | 269 | start = master->slaves; |
@@ -293,7 +280,9 @@ restart: | |||
293 | 280 | ||
294 | if (slave->qdisc_sleeping != q) | 281 | if (slave->qdisc_sleeping != q) |
295 | continue; | 282 | continue; |
296 | if (netif_queue_stopped(slave) || ! netif_running(slave)) { | 283 | if (netif_queue_stopped(slave) || |
284 | netif_subqueue_stopped(slave, subq) || | ||
285 | !netif_running(slave)) { | ||
297 | busy = 1; | 286 | busy = 1; |
298 | continue; | 287 | continue; |
299 | } | 288 | } |
@@ -302,6 +291,7 @@ restart: | |||
302 | case 0: | 291 | case 0: |
303 | if (netif_tx_trylock(slave)) { | 292 | if (netif_tx_trylock(slave)) { |
304 | if (!netif_queue_stopped(slave) && | 293 | if (!netif_queue_stopped(slave) && |
294 | !netif_subqueue_stopped(slave, subq) && | ||
305 | slave->hard_start_xmit(skb, slave) == 0) { | 295 | slave->hard_start_xmit(skb, slave) == 0) { |
306 | netif_tx_unlock(slave); | 296 | netif_tx_unlock(slave); |
307 | master->slaves = NEXT_SLAVE(q); | 297 | master->slaves = NEXT_SLAVE(q); |
diff --git a/net/sctp/proc.c b/net/sctp/proc.c index 2f12bf2d8d3c..e4cd841a22e4 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c | |||
@@ -250,7 +250,7 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v) | |||
250 | return 0; | 250 | return 0; |
251 | } | 251 | } |
252 | 252 | ||
253 | static struct seq_operations sctp_eps_ops = { | 253 | static const struct seq_operations sctp_eps_ops = { |
254 | .start = sctp_eps_seq_start, | 254 | .start = sctp_eps_seq_start, |
255 | .next = sctp_eps_seq_next, | 255 | .next = sctp_eps_seq_next, |
256 | .stop = sctp_eps_seq_stop, | 256 | .stop = sctp_eps_seq_stop, |
@@ -361,7 +361,7 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v) | |||
361 | return 0; | 361 | return 0; |
362 | } | 362 | } |
363 | 363 | ||
364 | static struct seq_operations sctp_assoc_ops = { | 364 | static const struct seq_operations sctp_assoc_ops = { |
365 | .start = sctp_assocs_seq_start, | 365 | .start = sctp_assocs_seq_start, |
366 | .next = sctp_assocs_seq_next, | 366 | .next = sctp_assocs_seq_next, |
367 | .stop = sctp_assocs_seq_stop, | 367 | .stop = sctp_assocs_seq_stop, |
diff --git a/net/socket.c b/net/socket.c index f4530196a70a..b71114250046 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -1939,9 +1939,7 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, | |||
1939 | total_len = err; | 1939 | total_len = err; |
1940 | 1940 | ||
1941 | cmsg_ptr = (unsigned long)msg_sys.msg_control; | 1941 | cmsg_ptr = (unsigned long)msg_sys.msg_control; |
1942 | msg_sys.msg_flags = 0; | 1942 | msg_sys.msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT); |
1943 | if (MSG_CMSG_COMPAT & flags) | ||
1944 | msg_sys.msg_flags = MSG_CMSG_COMPAT; | ||
1945 | 1943 | ||
1946 | if (sock->file->f_flags & O_NONBLOCK) | 1944 | if (sock->file->f_flags & O_NONBLOCK) |
1947 | flags |= MSG_DONTWAIT; | 1945 | flags |= MSG_DONTWAIT; |
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 9527f2bb1744..aa55d0a03e6f 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
@@ -13,17 +13,22 @@ | |||
13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
14 | #include <linux/sunrpc/clnt.h> | 14 | #include <linux/sunrpc/clnt.h> |
15 | #include <linux/spinlock.h> | 15 | #include <linux/spinlock.h> |
16 | #include <linux/smp_lock.h> | ||
16 | 17 | ||
17 | #ifdef RPC_DEBUG | 18 | #ifdef RPC_DEBUG |
18 | # define RPCDBG_FACILITY RPCDBG_AUTH | 19 | # define RPCDBG_FACILITY RPCDBG_AUTH |
19 | #endif | 20 | #endif |
20 | 21 | ||
21 | static struct rpc_authops * auth_flavors[RPC_AUTH_MAXFLAVOR] = { | 22 | static DEFINE_SPINLOCK(rpc_authflavor_lock); |
23 | static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = { | ||
22 | &authnull_ops, /* AUTH_NULL */ | 24 | &authnull_ops, /* AUTH_NULL */ |
23 | &authunix_ops, /* AUTH_UNIX */ | 25 | &authunix_ops, /* AUTH_UNIX */ |
24 | NULL, /* others can be loadable modules */ | 26 | NULL, /* others can be loadable modules */ |
25 | }; | 27 | }; |
26 | 28 | ||
29 | static LIST_HEAD(cred_unused); | ||
30 | static unsigned long number_cred_unused; | ||
31 | |||
27 | static u32 | 32 | static u32 |
28 | pseudoflavor_to_flavor(u32 flavor) { | 33 | pseudoflavor_to_flavor(u32 flavor) { |
29 | if (flavor >= RPC_AUTH_MAXFLAVOR) | 34 | if (flavor >= RPC_AUTH_MAXFLAVOR) |
@@ -32,55 +37,67 @@ pseudoflavor_to_flavor(u32 flavor) { | |||
32 | } | 37 | } |
33 | 38 | ||
34 | int | 39 | int |
35 | rpcauth_register(struct rpc_authops *ops) | 40 | rpcauth_register(const struct rpc_authops *ops) |
36 | { | 41 | { |
37 | rpc_authflavor_t flavor; | 42 | rpc_authflavor_t flavor; |
43 | int ret = -EPERM; | ||
38 | 44 | ||
39 | if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR) | 45 | if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR) |
40 | return -EINVAL; | 46 | return -EINVAL; |
41 | if (auth_flavors[flavor] != NULL) | 47 | spin_lock(&rpc_authflavor_lock); |
42 | return -EPERM; /* what else? */ | 48 | if (auth_flavors[flavor] == NULL) { |
43 | auth_flavors[flavor] = ops; | 49 | auth_flavors[flavor] = ops; |
44 | return 0; | 50 | ret = 0; |
51 | } | ||
52 | spin_unlock(&rpc_authflavor_lock); | ||
53 | return ret; | ||
45 | } | 54 | } |
46 | 55 | ||
47 | int | 56 | int |
48 | rpcauth_unregister(struct rpc_authops *ops) | 57 | rpcauth_unregister(const struct rpc_authops *ops) |
49 | { | 58 | { |
50 | rpc_authflavor_t flavor; | 59 | rpc_authflavor_t flavor; |
60 | int ret = -EPERM; | ||
51 | 61 | ||
52 | if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR) | 62 | if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR) |
53 | return -EINVAL; | 63 | return -EINVAL; |
54 | if (auth_flavors[flavor] != ops) | 64 | spin_lock(&rpc_authflavor_lock); |
55 | return -EPERM; /* what else? */ | 65 | if (auth_flavors[flavor] == ops) { |
56 | auth_flavors[flavor] = NULL; | 66 | auth_flavors[flavor] = NULL; |
57 | return 0; | 67 | ret = 0; |
68 | } | ||
69 | spin_unlock(&rpc_authflavor_lock); | ||
70 | return ret; | ||
58 | } | 71 | } |
59 | 72 | ||
60 | struct rpc_auth * | 73 | struct rpc_auth * |
61 | rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt) | 74 | rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt) |
62 | { | 75 | { |
63 | struct rpc_auth *auth; | 76 | struct rpc_auth *auth; |
64 | struct rpc_authops *ops; | 77 | const struct rpc_authops *ops; |
65 | u32 flavor = pseudoflavor_to_flavor(pseudoflavor); | 78 | u32 flavor = pseudoflavor_to_flavor(pseudoflavor); |
66 | 79 | ||
67 | auth = ERR_PTR(-EINVAL); | 80 | auth = ERR_PTR(-EINVAL); |
68 | if (flavor >= RPC_AUTH_MAXFLAVOR) | 81 | if (flavor >= RPC_AUTH_MAXFLAVOR) |
69 | goto out; | 82 | goto out; |
70 | 83 | ||
71 | /* FIXME - auth_flavors[] really needs an rw lock, | ||
72 | * and module refcounting. */ | ||
73 | #ifdef CONFIG_KMOD | 84 | #ifdef CONFIG_KMOD |
74 | if ((ops = auth_flavors[flavor]) == NULL) | 85 | if ((ops = auth_flavors[flavor]) == NULL) |
75 | request_module("rpc-auth-%u", flavor); | 86 | request_module("rpc-auth-%u", flavor); |
76 | #endif | 87 | #endif |
77 | if ((ops = auth_flavors[flavor]) == NULL) | 88 | spin_lock(&rpc_authflavor_lock); |
89 | ops = auth_flavors[flavor]; | ||
90 | if (ops == NULL || !try_module_get(ops->owner)) { | ||
91 | spin_unlock(&rpc_authflavor_lock); | ||
78 | goto out; | 92 | goto out; |
93 | } | ||
94 | spin_unlock(&rpc_authflavor_lock); | ||
79 | auth = ops->create(clnt, pseudoflavor); | 95 | auth = ops->create(clnt, pseudoflavor); |
96 | module_put(ops->owner); | ||
80 | if (IS_ERR(auth)) | 97 | if (IS_ERR(auth)) |
81 | return auth; | 98 | return auth; |
82 | if (clnt->cl_auth) | 99 | if (clnt->cl_auth) |
83 | rpcauth_destroy(clnt->cl_auth); | 100 | rpcauth_release(clnt->cl_auth); |
84 | clnt->cl_auth = auth; | 101 | clnt->cl_auth = auth; |
85 | 102 | ||
86 | out: | 103 | out: |
@@ -88,7 +105,7 @@ out: | |||
88 | } | 105 | } |
89 | 106 | ||
90 | void | 107 | void |
91 | rpcauth_destroy(struct rpc_auth *auth) | 108 | rpcauth_release(struct rpc_auth *auth) |
92 | { | 109 | { |
93 | if (!atomic_dec_and_test(&auth->au_count)) | 110 | if (!atomic_dec_and_test(&auth->au_count)) |
94 | return; | 111 | return; |
@@ -97,11 +114,31 @@ rpcauth_destroy(struct rpc_auth *auth) | |||
97 | 114 | ||
98 | static DEFINE_SPINLOCK(rpc_credcache_lock); | 115 | static DEFINE_SPINLOCK(rpc_credcache_lock); |
99 | 116 | ||
117 | static void | ||
118 | rpcauth_unhash_cred_locked(struct rpc_cred *cred) | ||
119 | { | ||
120 | hlist_del_rcu(&cred->cr_hash); | ||
121 | smp_mb__before_clear_bit(); | ||
122 | clear_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags); | ||
123 | } | ||
124 | |||
125 | static void | ||
126 | rpcauth_unhash_cred(struct rpc_cred *cred) | ||
127 | { | ||
128 | spinlock_t *cache_lock; | ||
129 | |||
130 | cache_lock = &cred->cr_auth->au_credcache->lock; | ||
131 | spin_lock(cache_lock); | ||
132 | if (atomic_read(&cred->cr_count) == 0) | ||
133 | rpcauth_unhash_cred_locked(cred); | ||
134 | spin_unlock(cache_lock); | ||
135 | } | ||
136 | |||
100 | /* | 137 | /* |
101 | * Initialize RPC credential cache | 138 | * Initialize RPC credential cache |
102 | */ | 139 | */ |
103 | int | 140 | int |
104 | rpcauth_init_credcache(struct rpc_auth *auth, unsigned long expire) | 141 | rpcauth_init_credcache(struct rpc_auth *auth) |
105 | { | 142 | { |
106 | struct rpc_cred_cache *new; | 143 | struct rpc_cred_cache *new; |
107 | int i; | 144 | int i; |
@@ -111,8 +148,7 @@ rpcauth_init_credcache(struct rpc_auth *auth, unsigned long expire) | |||
111 | return -ENOMEM; | 148 | return -ENOMEM; |
112 | for (i = 0; i < RPC_CREDCACHE_NR; i++) | 149 | for (i = 0; i < RPC_CREDCACHE_NR; i++) |
113 | INIT_HLIST_HEAD(&new->hashtable[i]); | 150 | INIT_HLIST_HEAD(&new->hashtable[i]); |
114 | new->expire = expire; | 151 | spin_lock_init(&new->lock); |
115 | new->nextgc = jiffies + (expire >> 1); | ||
116 | auth->au_credcache = new; | 152 | auth->au_credcache = new; |
117 | return 0; | 153 | return 0; |
118 | } | 154 | } |
@@ -121,13 +157,13 @@ rpcauth_init_credcache(struct rpc_auth *auth, unsigned long expire) | |||
121 | * Destroy a list of credentials | 157 | * Destroy a list of credentials |
122 | */ | 158 | */ |
123 | static inline | 159 | static inline |
124 | void rpcauth_destroy_credlist(struct hlist_head *head) | 160 | void rpcauth_destroy_credlist(struct list_head *head) |
125 | { | 161 | { |
126 | struct rpc_cred *cred; | 162 | struct rpc_cred *cred; |
127 | 163 | ||
128 | while (!hlist_empty(head)) { | 164 | while (!list_empty(head)) { |
129 | cred = hlist_entry(head->first, struct rpc_cred, cr_hash); | 165 | cred = list_entry(head->next, struct rpc_cred, cr_lru); |
130 | hlist_del_init(&cred->cr_hash); | 166 | list_del_init(&cred->cr_lru); |
131 | put_rpccred(cred); | 167 | put_rpccred(cred); |
132 | } | 168 | } |
133 | } | 169 | } |
@@ -137,58 +173,95 @@ void rpcauth_destroy_credlist(struct hlist_head *head) | |||
137 | * that are not referenced. | 173 | * that are not referenced. |
138 | */ | 174 | */ |
139 | void | 175 | void |
140 | rpcauth_free_credcache(struct rpc_auth *auth) | 176 | rpcauth_clear_credcache(struct rpc_cred_cache *cache) |
141 | { | 177 | { |
142 | struct rpc_cred_cache *cache = auth->au_credcache; | 178 | LIST_HEAD(free); |
143 | HLIST_HEAD(free); | 179 | struct hlist_head *head; |
144 | struct hlist_node *pos, *next; | ||
145 | struct rpc_cred *cred; | 180 | struct rpc_cred *cred; |
146 | int i; | 181 | int i; |
147 | 182 | ||
148 | spin_lock(&rpc_credcache_lock); | 183 | spin_lock(&rpc_credcache_lock); |
184 | spin_lock(&cache->lock); | ||
149 | for (i = 0; i < RPC_CREDCACHE_NR; i++) { | 185 | for (i = 0; i < RPC_CREDCACHE_NR; i++) { |
150 | hlist_for_each_safe(pos, next, &cache->hashtable[i]) { | 186 | head = &cache->hashtable[i]; |
151 | cred = hlist_entry(pos, struct rpc_cred, cr_hash); | 187 | while (!hlist_empty(head)) { |
152 | __hlist_del(&cred->cr_hash); | 188 | cred = hlist_entry(head->first, struct rpc_cred, cr_hash); |
153 | hlist_add_head(&cred->cr_hash, &free); | 189 | get_rpccred(cred); |
190 | if (!list_empty(&cred->cr_lru)) { | ||
191 | list_del(&cred->cr_lru); | ||
192 | number_cred_unused--; | ||
193 | } | ||
194 | list_add_tail(&cred->cr_lru, &free); | ||
195 | rpcauth_unhash_cred_locked(cred); | ||
154 | } | 196 | } |
155 | } | 197 | } |
198 | spin_unlock(&cache->lock); | ||
156 | spin_unlock(&rpc_credcache_lock); | 199 | spin_unlock(&rpc_credcache_lock); |
157 | rpcauth_destroy_credlist(&free); | 200 | rpcauth_destroy_credlist(&free); |
158 | } | 201 | } |
159 | 202 | ||
160 | static void | 203 | /* |
161 | rpcauth_prune_expired(struct rpc_auth *auth, struct rpc_cred *cred, struct hlist_head *free) | 204 | * Destroy the RPC credential cache |
205 | */ | ||
206 | void | ||
207 | rpcauth_destroy_credcache(struct rpc_auth *auth) | ||
162 | { | 208 | { |
163 | if (atomic_read(&cred->cr_count) != 1) | 209 | struct rpc_cred_cache *cache = auth->au_credcache; |
164 | return; | 210 | |
165 | if (time_after(jiffies, cred->cr_expire + auth->au_credcache->expire)) | 211 | if (cache) { |
166 | cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE; | 212 | auth->au_credcache = NULL; |
167 | if (!(cred->cr_flags & RPCAUTH_CRED_UPTODATE)) { | 213 | rpcauth_clear_credcache(cache); |
168 | __hlist_del(&cred->cr_hash); | 214 | kfree(cache); |
169 | hlist_add_head(&cred->cr_hash, free); | ||
170 | } | 215 | } |
171 | } | 216 | } |
172 | 217 | ||
173 | /* | 218 | /* |
174 | * Remove stale credentials. Avoid sleeping inside the loop. | 219 | * Remove stale credentials. Avoid sleeping inside the loop. |
175 | */ | 220 | */ |
176 | static void | 221 | static int |
177 | rpcauth_gc_credcache(struct rpc_auth *auth, struct hlist_head *free) | 222 | rpcauth_prune_expired(struct list_head *free, int nr_to_scan) |
178 | { | 223 | { |
179 | struct rpc_cred_cache *cache = auth->au_credcache; | 224 | spinlock_t *cache_lock; |
180 | struct hlist_node *pos, *next; | 225 | struct rpc_cred *cred; |
181 | struct rpc_cred *cred; | ||
182 | int i; | ||
183 | 226 | ||
184 | dprintk("RPC: gc'ing RPC credentials for auth %p\n", auth); | 227 | while (!list_empty(&cred_unused)) { |
185 | for (i = 0; i < RPC_CREDCACHE_NR; i++) { | 228 | cred = list_entry(cred_unused.next, struct rpc_cred, cr_lru); |
186 | hlist_for_each_safe(pos, next, &cache->hashtable[i]) { | 229 | list_del_init(&cred->cr_lru); |
187 | cred = hlist_entry(pos, struct rpc_cred, cr_hash); | 230 | number_cred_unused--; |
188 | rpcauth_prune_expired(auth, cred, free); | 231 | if (atomic_read(&cred->cr_count) != 0) |
232 | continue; | ||
233 | cache_lock = &cred->cr_auth->au_credcache->lock; | ||
234 | spin_lock(cache_lock); | ||
235 | if (atomic_read(&cred->cr_count) == 0) { | ||
236 | get_rpccred(cred); | ||
237 | list_add_tail(&cred->cr_lru, free); | ||
238 | rpcauth_unhash_cred_locked(cred); | ||
239 | nr_to_scan--; | ||
189 | } | 240 | } |
241 | spin_unlock(cache_lock); | ||
242 | if (nr_to_scan == 0) | ||
243 | break; | ||
190 | } | 244 | } |
191 | cache->nextgc = jiffies + cache->expire; | 245 | return nr_to_scan; |
246 | } | ||
247 | |||
248 | /* | ||
249 | * Run memory cache shrinker. | ||
250 | */ | ||
251 | static int | ||
252 | rpcauth_cache_shrinker(int nr_to_scan, gfp_t gfp_mask) | ||
253 | { | ||
254 | LIST_HEAD(free); | ||
255 | int res; | ||
256 | |||
257 | if (list_empty(&cred_unused)) | ||
258 | return 0; | ||
259 | spin_lock(&rpc_credcache_lock); | ||
260 | nr_to_scan = rpcauth_prune_expired(&free, nr_to_scan); | ||
261 | res = (number_cred_unused / 100) * sysctl_vfs_cache_pressure; | ||
262 | spin_unlock(&rpc_credcache_lock); | ||
263 | rpcauth_destroy_credlist(&free); | ||
264 | return res; | ||
192 | } | 265 | } |
193 | 266 | ||
194 | /* | 267 | /* |
@@ -198,53 +271,56 @@ struct rpc_cred * | |||
198 | rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, | 271 | rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, |
199 | int flags) | 272 | int flags) |
200 | { | 273 | { |
274 | LIST_HEAD(free); | ||
201 | struct rpc_cred_cache *cache = auth->au_credcache; | 275 | struct rpc_cred_cache *cache = auth->au_credcache; |
202 | HLIST_HEAD(free); | 276 | struct hlist_node *pos; |
203 | struct hlist_node *pos, *next; | 277 | struct rpc_cred *cred = NULL, |
204 | struct rpc_cred *new = NULL, | 278 | *entry, *new; |
205 | *cred = NULL; | ||
206 | int nr = 0; | 279 | int nr = 0; |
207 | 280 | ||
208 | if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS)) | 281 | if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS)) |
209 | nr = acred->uid & RPC_CREDCACHE_MASK; | 282 | nr = acred->uid & RPC_CREDCACHE_MASK; |
210 | retry: | 283 | |
211 | spin_lock(&rpc_credcache_lock); | 284 | rcu_read_lock(); |
212 | if (time_before(cache->nextgc, jiffies)) | 285 | hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) { |
213 | rpcauth_gc_credcache(auth, &free); | 286 | if (!entry->cr_ops->crmatch(acred, entry, flags)) |
214 | hlist_for_each_safe(pos, next, &cache->hashtable[nr]) { | 287 | continue; |
215 | struct rpc_cred *entry; | 288 | spin_lock(&cache->lock); |
216 | entry = hlist_entry(pos, struct rpc_cred, cr_hash); | 289 | if (test_bit(RPCAUTH_CRED_HASHED, &entry->cr_flags) == 0) { |
217 | if (entry->cr_ops->crmatch(acred, entry, flags)) { | 290 | spin_unlock(&cache->lock); |
218 | hlist_del(&entry->cr_hash); | 291 | continue; |
219 | cred = entry; | ||
220 | break; | ||
221 | } | 292 | } |
222 | rpcauth_prune_expired(auth, entry, &free); | 293 | cred = get_rpccred(entry); |
294 | spin_unlock(&cache->lock); | ||
295 | break; | ||
223 | } | 296 | } |
224 | if (new) { | 297 | rcu_read_unlock(); |
225 | if (cred) | ||
226 | hlist_add_head(&new->cr_hash, &free); | ||
227 | else | ||
228 | cred = new; | ||
229 | } | ||
230 | if (cred) { | ||
231 | hlist_add_head(&cred->cr_hash, &cache->hashtable[nr]); | ||
232 | get_rpccred(cred); | ||
233 | } | ||
234 | spin_unlock(&rpc_credcache_lock); | ||
235 | 298 | ||
236 | rpcauth_destroy_credlist(&free); | 299 | if (cred != NULL) |
300 | goto found; | ||
237 | 301 | ||
238 | if (!cred) { | 302 | new = auth->au_ops->crcreate(auth, acred, flags); |
239 | new = auth->au_ops->crcreate(auth, acred, flags); | 303 | if (IS_ERR(new)) { |
240 | if (!IS_ERR(new)) { | 304 | cred = new; |
241 | #ifdef RPC_DEBUG | 305 | goto out; |
242 | new->cr_magic = RPCAUTH_CRED_MAGIC; | 306 | } |
243 | #endif | 307 | |
244 | goto retry; | 308 | spin_lock(&cache->lock); |
245 | } else | 309 | hlist_for_each_entry(entry, pos, &cache->hashtable[nr], cr_hash) { |
246 | cred = new; | 310 | if (!entry->cr_ops->crmatch(acred, entry, flags)) |
247 | } else if ((cred->cr_flags & RPCAUTH_CRED_NEW) | 311 | continue; |
312 | cred = get_rpccred(entry); | ||
313 | break; | ||
314 | } | ||
315 | if (cred == NULL) { | ||
316 | cred = new; | ||
317 | set_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags); | ||
318 | hlist_add_head_rcu(&cred->cr_hash, &cache->hashtable[nr]); | ||
319 | } else | ||
320 | list_add_tail(&new->cr_lru, &free); | ||
321 | spin_unlock(&cache->lock); | ||
322 | found: | ||
323 | if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags) | ||
248 | && cred->cr_ops->cr_init != NULL | 324 | && cred->cr_ops->cr_init != NULL |
249 | && !(flags & RPCAUTH_LOOKUP_NEW)) { | 325 | && !(flags & RPCAUTH_LOOKUP_NEW)) { |
250 | int res = cred->cr_ops->cr_init(auth, cred); | 326 | int res = cred->cr_ops->cr_init(auth, cred); |
@@ -253,8 +329,9 @@ retry: | |||
253 | cred = ERR_PTR(res); | 329 | cred = ERR_PTR(res); |
254 | } | 330 | } |
255 | } | 331 | } |
256 | 332 | rpcauth_destroy_credlist(&free); | |
257 | return (struct rpc_cred *) cred; | 333 | out: |
334 | return cred; | ||
258 | } | 335 | } |
259 | 336 | ||
260 | struct rpc_cred * | 337 | struct rpc_cred * |
@@ -275,10 +352,27 @@ rpcauth_lookupcred(struct rpc_auth *auth, int flags) | |||
275 | return ret; | 352 | return ret; |
276 | } | 353 | } |
277 | 354 | ||
355 | void | ||
356 | rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred, | ||
357 | struct rpc_auth *auth, const struct rpc_credops *ops) | ||
358 | { | ||
359 | INIT_HLIST_NODE(&cred->cr_hash); | ||
360 | INIT_LIST_HEAD(&cred->cr_lru); | ||
361 | atomic_set(&cred->cr_count, 1); | ||
362 | cred->cr_auth = auth; | ||
363 | cred->cr_ops = ops; | ||
364 | cred->cr_expire = jiffies; | ||
365 | #ifdef RPC_DEBUG | ||
366 | cred->cr_magic = RPCAUTH_CRED_MAGIC; | ||
367 | #endif | ||
368 | cred->cr_uid = acred->uid; | ||
369 | } | ||
370 | EXPORT_SYMBOL(rpcauth_init_cred); | ||
371 | |||
278 | struct rpc_cred * | 372 | struct rpc_cred * |
279 | rpcauth_bindcred(struct rpc_task *task) | 373 | rpcauth_bindcred(struct rpc_task *task) |
280 | { | 374 | { |
281 | struct rpc_auth *auth = task->tk_auth; | 375 | struct rpc_auth *auth = task->tk_client->cl_auth; |
282 | struct auth_cred acred = { | 376 | struct auth_cred acred = { |
283 | .uid = current->fsuid, | 377 | .uid = current->fsuid, |
284 | .gid = current->fsgid, | 378 | .gid = current->fsgid, |
@@ -288,7 +382,7 @@ rpcauth_bindcred(struct rpc_task *task) | |||
288 | int flags = 0; | 382 | int flags = 0; |
289 | 383 | ||
290 | dprintk("RPC: %5u looking up %s cred\n", | 384 | dprintk("RPC: %5u looking up %s cred\n", |
291 | task->tk_pid, task->tk_auth->au_ops->au_name); | 385 | task->tk_pid, task->tk_client->cl_auth->au_ops->au_name); |
292 | get_group_info(acred.group_info); | 386 | get_group_info(acred.group_info); |
293 | if (task->tk_flags & RPC_TASK_ROOTCREDS) | 387 | if (task->tk_flags & RPC_TASK_ROOTCREDS) |
294 | flags |= RPCAUTH_LOOKUP_ROOTCREDS; | 388 | flags |= RPCAUTH_LOOKUP_ROOTCREDS; |
@@ -304,19 +398,42 @@ rpcauth_bindcred(struct rpc_task *task) | |||
304 | void | 398 | void |
305 | rpcauth_holdcred(struct rpc_task *task) | 399 | rpcauth_holdcred(struct rpc_task *task) |
306 | { | 400 | { |
307 | dprintk("RPC: %5u holding %s cred %p\n", | 401 | struct rpc_cred *cred = task->tk_msg.rpc_cred; |
308 | task->tk_pid, task->tk_auth->au_ops->au_name, | 402 | if (cred != NULL) { |
309 | task->tk_msg.rpc_cred); | 403 | get_rpccred(cred); |
310 | if (task->tk_msg.rpc_cred) | 404 | dprintk("RPC: %5u holding %s cred %p\n", task->tk_pid, |
311 | get_rpccred(task->tk_msg.rpc_cred); | 405 | cred->cr_auth->au_ops->au_name, cred); |
406 | } | ||
312 | } | 407 | } |
313 | 408 | ||
314 | void | 409 | void |
315 | put_rpccred(struct rpc_cred *cred) | 410 | put_rpccred(struct rpc_cred *cred) |
316 | { | 411 | { |
317 | cred->cr_expire = jiffies; | 412 | /* Fast path for unhashed credentials */ |
413 | if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) | ||
414 | goto need_lock; | ||
415 | |||
318 | if (!atomic_dec_and_test(&cred->cr_count)) | 416 | if (!atomic_dec_and_test(&cred->cr_count)) |
319 | return; | 417 | return; |
418 | goto out_destroy; | ||
419 | need_lock: | ||
420 | if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock)) | ||
421 | return; | ||
422 | if (!list_empty(&cred->cr_lru)) { | ||
423 | number_cred_unused--; | ||
424 | list_del_init(&cred->cr_lru); | ||
425 | } | ||
426 | if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0) | ||
427 | rpcauth_unhash_cred(cred); | ||
428 | else if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) { | ||
429 | cred->cr_expire = jiffies; | ||
430 | list_add_tail(&cred->cr_lru, &cred_unused); | ||
431 | number_cred_unused++; | ||
432 | spin_unlock(&rpc_credcache_lock); | ||
433 | return; | ||
434 | } | ||
435 | spin_unlock(&rpc_credcache_lock); | ||
436 | out_destroy: | ||
320 | cred->cr_ops->crdestroy(cred); | 437 | cred->cr_ops->crdestroy(cred); |
321 | } | 438 | } |
322 | 439 | ||
@@ -326,7 +443,7 @@ rpcauth_unbindcred(struct rpc_task *task) | |||
326 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 443 | struct rpc_cred *cred = task->tk_msg.rpc_cred; |
327 | 444 | ||
328 | dprintk("RPC: %5u releasing %s cred %p\n", | 445 | dprintk("RPC: %5u releasing %s cred %p\n", |
329 | task->tk_pid, task->tk_auth->au_ops->au_name, cred); | 446 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); |
330 | 447 | ||
331 | put_rpccred(cred); | 448 | put_rpccred(cred); |
332 | task->tk_msg.rpc_cred = NULL; | 449 | task->tk_msg.rpc_cred = NULL; |
@@ -338,7 +455,7 @@ rpcauth_marshcred(struct rpc_task *task, __be32 *p) | |||
338 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 455 | struct rpc_cred *cred = task->tk_msg.rpc_cred; |
339 | 456 | ||
340 | dprintk("RPC: %5u marshaling %s cred %p\n", | 457 | dprintk("RPC: %5u marshaling %s cred %p\n", |
341 | task->tk_pid, task->tk_auth->au_ops->au_name, cred); | 458 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); |
342 | 459 | ||
343 | return cred->cr_ops->crmarshal(task, p); | 460 | return cred->cr_ops->crmarshal(task, p); |
344 | } | 461 | } |
@@ -349,7 +466,7 @@ rpcauth_checkverf(struct rpc_task *task, __be32 *p) | |||
349 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 466 | struct rpc_cred *cred = task->tk_msg.rpc_cred; |
350 | 467 | ||
351 | dprintk("RPC: %5u validating %s cred %p\n", | 468 | dprintk("RPC: %5u validating %s cred %p\n", |
352 | task->tk_pid, task->tk_auth->au_ops->au_name, cred); | 469 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); |
353 | 470 | ||
354 | return cred->cr_ops->crvalidate(task, p); | 471 | return cred->cr_ops->crvalidate(task, p); |
355 | } | 472 | } |
@@ -359,13 +476,17 @@ rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp, | |||
359 | __be32 *data, void *obj) | 476 | __be32 *data, void *obj) |
360 | { | 477 | { |
361 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 478 | struct rpc_cred *cred = task->tk_msg.rpc_cred; |
479 | int ret; | ||
362 | 480 | ||
363 | dprintk("RPC: %5u using %s cred %p to wrap rpc data\n", | 481 | dprintk("RPC: %5u using %s cred %p to wrap rpc data\n", |
364 | task->tk_pid, cred->cr_ops->cr_name, cred); | 482 | task->tk_pid, cred->cr_ops->cr_name, cred); |
365 | if (cred->cr_ops->crwrap_req) | 483 | if (cred->cr_ops->crwrap_req) |
366 | return cred->cr_ops->crwrap_req(task, encode, rqstp, data, obj); | 484 | return cred->cr_ops->crwrap_req(task, encode, rqstp, data, obj); |
367 | /* By default, we encode the arguments normally. */ | 485 | /* By default, we encode the arguments normally. */ |
368 | return encode(rqstp, data, obj); | 486 | lock_kernel(); |
487 | ret = encode(rqstp, data, obj); | ||
488 | unlock_kernel(); | ||
489 | return ret; | ||
369 | } | 490 | } |
370 | 491 | ||
371 | int | 492 | int |
@@ -373,6 +494,7 @@ rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp, | |||
373 | __be32 *data, void *obj) | 494 | __be32 *data, void *obj) |
374 | { | 495 | { |
375 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 496 | struct rpc_cred *cred = task->tk_msg.rpc_cred; |
497 | int ret; | ||
376 | 498 | ||
377 | dprintk("RPC: %5u using %s cred %p to unwrap rpc data\n", | 499 | dprintk("RPC: %5u using %s cred %p to unwrap rpc data\n", |
378 | task->tk_pid, cred->cr_ops->cr_name, cred); | 500 | task->tk_pid, cred->cr_ops->cr_name, cred); |
@@ -380,7 +502,10 @@ rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp, | |||
380 | return cred->cr_ops->crunwrap_resp(task, decode, rqstp, | 502 | return cred->cr_ops->crunwrap_resp(task, decode, rqstp, |
381 | data, obj); | 503 | data, obj); |
382 | /* By default, we decode the arguments normally. */ | 504 | /* By default, we decode the arguments normally. */ |
383 | return decode(rqstp, data, obj); | 505 | lock_kernel(); |
506 | ret = decode(rqstp, data, obj); | ||
507 | unlock_kernel(); | ||
508 | return ret; | ||
384 | } | 509 | } |
385 | 510 | ||
386 | int | 511 | int |
@@ -390,7 +515,7 @@ rpcauth_refreshcred(struct rpc_task *task) | |||
390 | int err; | 515 | int err; |
391 | 516 | ||
392 | dprintk("RPC: %5u refreshing %s cred %p\n", | 517 | dprintk("RPC: %5u refreshing %s cred %p\n", |
393 | task->tk_pid, task->tk_auth->au_ops->au_name, cred); | 518 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); |
394 | 519 | ||
395 | err = cred->cr_ops->crrefresh(task); | 520 | err = cred->cr_ops->crrefresh(task); |
396 | if (err < 0) | 521 | if (err < 0) |
@@ -401,17 +526,34 @@ rpcauth_refreshcred(struct rpc_task *task) | |||
401 | void | 526 | void |
402 | rpcauth_invalcred(struct rpc_task *task) | 527 | rpcauth_invalcred(struct rpc_task *task) |
403 | { | 528 | { |
529 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | ||
530 | |||
404 | dprintk("RPC: %5u invalidating %s cred %p\n", | 531 | dprintk("RPC: %5u invalidating %s cred %p\n", |
405 | task->tk_pid, task->tk_auth->au_ops->au_name, task->tk_msg.rpc_cred); | 532 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); |
406 | spin_lock(&rpc_credcache_lock); | 533 | if (cred) |
407 | if (task->tk_msg.rpc_cred) | 534 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
408 | task->tk_msg.rpc_cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE; | ||
409 | spin_unlock(&rpc_credcache_lock); | ||
410 | } | 535 | } |
411 | 536 | ||
412 | int | 537 | int |
413 | rpcauth_uptodatecred(struct rpc_task *task) | 538 | rpcauth_uptodatecred(struct rpc_task *task) |
414 | { | 539 | { |
415 | return !(task->tk_msg.rpc_cred) || | 540 | struct rpc_cred *cred = task->tk_msg.rpc_cred; |
416 | (task->tk_msg.rpc_cred->cr_flags & RPCAUTH_CRED_UPTODATE); | 541 | |
542 | return cred == NULL || | ||
543 | test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0; | ||
544 | } | ||
545 | |||
546 | |||
547 | static struct shrinker *rpc_cred_shrinker; | ||
548 | |||
549 | void __init rpcauth_init_module(void) | ||
550 | { | ||
551 | rpc_init_authunix(); | ||
552 | rpc_cred_shrinker = set_shrinker(DEFAULT_SEEKS, rpcauth_cache_shrinker); | ||
553 | } | ||
554 | |||
555 | void __exit rpcauth_remove_module(void) | ||
556 | { | ||
557 | if (rpc_cred_shrinker != NULL) | ||
558 | remove_shrinker(rpc_cred_shrinker); | ||
417 | } | 559 | } |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 4e4ccc5b6fea..abfda33bac64 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/types.h> | 43 | #include <linux/types.h> |
44 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
45 | #include <linux/sched.h> | 45 | #include <linux/sched.h> |
46 | #include <linux/smp_lock.h> | ||
46 | #include <linux/pagemap.h> | 47 | #include <linux/pagemap.h> |
47 | #include <linux/sunrpc/clnt.h> | 48 | #include <linux/sunrpc/clnt.h> |
48 | #include <linux/sunrpc/auth.h> | 49 | #include <linux/sunrpc/auth.h> |
@@ -54,9 +55,10 @@ | |||
54 | #include <linux/sunrpc/gss_api.h> | 55 | #include <linux/sunrpc/gss_api.h> |
55 | #include <asm/uaccess.h> | 56 | #include <asm/uaccess.h> |
56 | 57 | ||
57 | static struct rpc_authops authgss_ops; | 58 | static const struct rpc_authops authgss_ops; |
58 | 59 | ||
59 | static struct rpc_credops gss_credops; | 60 | static const struct rpc_credops gss_credops; |
61 | static const struct rpc_credops gss_nullops; | ||
60 | 62 | ||
61 | #ifdef RPC_DEBUG | 63 | #ifdef RPC_DEBUG |
62 | # define RPCDBG_FACILITY RPCDBG_AUTH | 64 | # define RPCDBG_FACILITY RPCDBG_AUTH |
@@ -64,7 +66,6 @@ static struct rpc_credops gss_credops; | |||
64 | 66 | ||
65 | #define NFS_NGROUPS 16 | 67 | #define NFS_NGROUPS 16 |
66 | 68 | ||
67 | #define GSS_CRED_EXPIRE (60 * HZ) /* XXX: reasonable? */ | ||
68 | #define GSS_CRED_SLACK 1024 /* XXX: unused */ | 69 | #define GSS_CRED_SLACK 1024 /* XXX: unused */ |
69 | /* length of a krb5 verifier (48), plus data added before arguments when | 70 | /* length of a krb5 verifier (48), plus data added before arguments when |
70 | * using integrity (two 4-byte integers): */ | 71 | * using integrity (two 4-byte integers): */ |
@@ -79,19 +80,16 @@ static struct rpc_credops gss_credops; | |||
79 | /* dump the buffer in `emacs-hexl' style */ | 80 | /* dump the buffer in `emacs-hexl' style */ |
80 | #define isprint(c) ((c > 0x1f) && (c < 0x7f)) | 81 | #define isprint(c) ((c > 0x1f) && (c < 0x7f)) |
81 | 82 | ||
82 | static DEFINE_RWLOCK(gss_ctx_lock); | ||
83 | |||
84 | struct gss_auth { | 83 | struct gss_auth { |
84 | struct kref kref; | ||
85 | struct rpc_auth rpc_auth; | 85 | struct rpc_auth rpc_auth; |
86 | struct gss_api_mech *mech; | 86 | struct gss_api_mech *mech; |
87 | enum rpc_gss_svc service; | 87 | enum rpc_gss_svc service; |
88 | struct list_head upcalls; | ||
89 | struct rpc_clnt *client; | 88 | struct rpc_clnt *client; |
90 | struct dentry *dentry; | 89 | struct dentry *dentry; |
91 | spinlock_t lock; | ||
92 | }; | 90 | }; |
93 | 91 | ||
94 | static void gss_destroy_ctx(struct gss_cl_ctx *); | 92 | static void gss_free_ctx(struct gss_cl_ctx *); |
95 | static struct rpc_pipe_ops gss_upcall_ops; | 93 | static struct rpc_pipe_ops gss_upcall_ops; |
96 | 94 | ||
97 | static inline struct gss_cl_ctx * | 95 | static inline struct gss_cl_ctx * |
@@ -105,20 +103,24 @@ static inline void | |||
105 | gss_put_ctx(struct gss_cl_ctx *ctx) | 103 | gss_put_ctx(struct gss_cl_ctx *ctx) |
106 | { | 104 | { |
107 | if (atomic_dec_and_test(&ctx->count)) | 105 | if (atomic_dec_and_test(&ctx->count)) |
108 | gss_destroy_ctx(ctx); | 106 | gss_free_ctx(ctx); |
109 | } | 107 | } |
110 | 108 | ||
109 | /* gss_cred_set_ctx: | ||
110 | * called by gss_upcall_callback and gss_create_upcall in order | ||
111 | * to set the gss context. The actual exchange of an old context | ||
112 | * and a new one is protected by the inode->i_lock. | ||
113 | */ | ||
111 | static void | 114 | static void |
112 | gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx) | 115 | gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx) |
113 | { | 116 | { |
114 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); | 117 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); |
115 | struct gss_cl_ctx *old; | 118 | struct gss_cl_ctx *old; |
116 | write_lock(&gss_ctx_lock); | 119 | |
117 | old = gss_cred->gc_ctx; | 120 | old = gss_cred->gc_ctx; |
118 | gss_cred->gc_ctx = ctx; | 121 | rcu_assign_pointer(gss_cred->gc_ctx, ctx); |
119 | cred->cr_flags |= RPCAUTH_CRED_UPTODATE; | 122 | set_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
120 | cred->cr_flags &= ~RPCAUTH_CRED_NEW; | 123 | clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags); |
121 | write_unlock(&gss_ctx_lock); | ||
122 | if (old) | 124 | if (old) |
123 | gss_put_ctx(old); | 125 | gss_put_ctx(old); |
124 | } | 126 | } |
@@ -129,10 +131,10 @@ gss_cred_is_uptodate_ctx(struct rpc_cred *cred) | |||
129 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); | 131 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); |
130 | int res = 0; | 132 | int res = 0; |
131 | 133 | ||
132 | read_lock(&gss_ctx_lock); | 134 | rcu_read_lock(); |
133 | if ((cred->cr_flags & RPCAUTH_CRED_UPTODATE) && gss_cred->gc_ctx) | 135 | if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) && gss_cred->gc_ctx) |
134 | res = 1; | 136 | res = 1; |
135 | read_unlock(&gss_ctx_lock); | 137 | rcu_read_unlock(); |
136 | return res; | 138 | return res; |
137 | } | 139 | } |
138 | 140 | ||
@@ -171,10 +173,10 @@ gss_cred_get_ctx(struct rpc_cred *cred) | |||
171 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); | 173 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); |
172 | struct gss_cl_ctx *ctx = NULL; | 174 | struct gss_cl_ctx *ctx = NULL; |
173 | 175 | ||
174 | read_lock(&gss_ctx_lock); | 176 | rcu_read_lock(); |
175 | if (gss_cred->gc_ctx) | 177 | if (gss_cred->gc_ctx) |
176 | ctx = gss_get_ctx(gss_cred->gc_ctx); | 178 | ctx = gss_get_ctx(gss_cred->gc_ctx); |
177 | read_unlock(&gss_ctx_lock); | 179 | rcu_read_unlock(); |
178 | return ctx; | 180 | return ctx; |
179 | } | 181 | } |
180 | 182 | ||
@@ -269,10 +271,10 @@ gss_release_msg(struct gss_upcall_msg *gss_msg) | |||
269 | } | 271 | } |
270 | 272 | ||
271 | static struct gss_upcall_msg * | 273 | static struct gss_upcall_msg * |
272 | __gss_find_upcall(struct gss_auth *gss_auth, uid_t uid) | 274 | __gss_find_upcall(struct rpc_inode *rpci, uid_t uid) |
273 | { | 275 | { |
274 | struct gss_upcall_msg *pos; | 276 | struct gss_upcall_msg *pos; |
275 | list_for_each_entry(pos, &gss_auth->upcalls, list) { | 277 | list_for_each_entry(pos, &rpci->in_downcall, list) { |
276 | if (pos->uid != uid) | 278 | if (pos->uid != uid) |
277 | continue; | 279 | continue; |
278 | atomic_inc(&pos->count); | 280 | atomic_inc(&pos->count); |
@@ -290,24 +292,24 @@ __gss_find_upcall(struct gss_auth *gss_auth, uid_t uid) | |||
290 | static inline struct gss_upcall_msg * | 292 | static inline struct gss_upcall_msg * |
291 | gss_add_msg(struct gss_auth *gss_auth, struct gss_upcall_msg *gss_msg) | 293 | gss_add_msg(struct gss_auth *gss_auth, struct gss_upcall_msg *gss_msg) |
292 | { | 294 | { |
295 | struct inode *inode = gss_auth->dentry->d_inode; | ||
296 | struct rpc_inode *rpci = RPC_I(inode); | ||
293 | struct gss_upcall_msg *old; | 297 | struct gss_upcall_msg *old; |
294 | 298 | ||
295 | spin_lock(&gss_auth->lock); | 299 | spin_lock(&inode->i_lock); |
296 | old = __gss_find_upcall(gss_auth, gss_msg->uid); | 300 | old = __gss_find_upcall(rpci, gss_msg->uid); |
297 | if (old == NULL) { | 301 | if (old == NULL) { |
298 | atomic_inc(&gss_msg->count); | 302 | atomic_inc(&gss_msg->count); |
299 | list_add(&gss_msg->list, &gss_auth->upcalls); | 303 | list_add(&gss_msg->list, &rpci->in_downcall); |
300 | } else | 304 | } else |
301 | gss_msg = old; | 305 | gss_msg = old; |
302 | spin_unlock(&gss_auth->lock); | 306 | spin_unlock(&inode->i_lock); |
303 | return gss_msg; | 307 | return gss_msg; |
304 | } | 308 | } |
305 | 309 | ||
306 | static void | 310 | static void |
307 | __gss_unhash_msg(struct gss_upcall_msg *gss_msg) | 311 | __gss_unhash_msg(struct gss_upcall_msg *gss_msg) |
308 | { | 312 | { |
309 | if (list_empty(&gss_msg->list)) | ||
310 | return; | ||
311 | list_del_init(&gss_msg->list); | 313 | list_del_init(&gss_msg->list); |
312 | rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno); | 314 | rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno); |
313 | wake_up_all(&gss_msg->waitqueue); | 315 | wake_up_all(&gss_msg->waitqueue); |
@@ -318,10 +320,14 @@ static void | |||
318 | gss_unhash_msg(struct gss_upcall_msg *gss_msg) | 320 | gss_unhash_msg(struct gss_upcall_msg *gss_msg) |
319 | { | 321 | { |
320 | struct gss_auth *gss_auth = gss_msg->auth; | 322 | struct gss_auth *gss_auth = gss_msg->auth; |
323 | struct inode *inode = gss_auth->dentry->d_inode; | ||
321 | 324 | ||
322 | spin_lock(&gss_auth->lock); | 325 | if (list_empty(&gss_msg->list)) |
323 | __gss_unhash_msg(gss_msg); | 326 | return; |
324 | spin_unlock(&gss_auth->lock); | 327 | spin_lock(&inode->i_lock); |
328 | if (!list_empty(&gss_msg->list)) | ||
329 | __gss_unhash_msg(gss_msg); | ||
330 | spin_unlock(&inode->i_lock); | ||
325 | } | 331 | } |
326 | 332 | ||
327 | static void | 333 | static void |
@@ -330,16 +336,16 @@ gss_upcall_callback(struct rpc_task *task) | |||
330 | struct gss_cred *gss_cred = container_of(task->tk_msg.rpc_cred, | 336 | struct gss_cred *gss_cred = container_of(task->tk_msg.rpc_cred, |
331 | struct gss_cred, gc_base); | 337 | struct gss_cred, gc_base); |
332 | struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall; | 338 | struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall; |
339 | struct inode *inode = gss_msg->auth->dentry->d_inode; | ||
333 | 340 | ||
334 | BUG_ON(gss_msg == NULL); | 341 | spin_lock(&inode->i_lock); |
335 | if (gss_msg->ctx) | 342 | if (gss_msg->ctx) |
336 | gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_get_ctx(gss_msg->ctx)); | 343 | gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_get_ctx(gss_msg->ctx)); |
337 | else | 344 | else |
338 | task->tk_status = gss_msg->msg.errno; | 345 | task->tk_status = gss_msg->msg.errno; |
339 | spin_lock(&gss_msg->auth->lock); | ||
340 | gss_cred->gc_upcall = NULL; | 346 | gss_cred->gc_upcall = NULL; |
341 | rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno); | 347 | rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno); |
342 | spin_unlock(&gss_msg->auth->lock); | 348 | spin_unlock(&inode->i_lock); |
343 | gss_release_msg(gss_msg); | 349 | gss_release_msg(gss_msg); |
344 | } | 350 | } |
345 | 351 | ||
@@ -386,11 +392,12 @@ static inline int | |||
386 | gss_refresh_upcall(struct rpc_task *task) | 392 | gss_refresh_upcall(struct rpc_task *task) |
387 | { | 393 | { |
388 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 394 | struct rpc_cred *cred = task->tk_msg.rpc_cred; |
389 | struct gss_auth *gss_auth = container_of(task->tk_client->cl_auth, | 395 | struct gss_auth *gss_auth = container_of(cred->cr_auth, |
390 | struct gss_auth, rpc_auth); | 396 | struct gss_auth, rpc_auth); |
391 | struct gss_cred *gss_cred = container_of(cred, | 397 | struct gss_cred *gss_cred = container_of(cred, |
392 | struct gss_cred, gc_base); | 398 | struct gss_cred, gc_base); |
393 | struct gss_upcall_msg *gss_msg; | 399 | struct gss_upcall_msg *gss_msg; |
400 | struct inode *inode = gss_auth->dentry->d_inode; | ||
394 | int err = 0; | 401 | int err = 0; |
395 | 402 | ||
396 | dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid, | 403 | dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid, |
@@ -400,7 +407,7 @@ gss_refresh_upcall(struct rpc_task *task) | |||
400 | err = PTR_ERR(gss_msg); | 407 | err = PTR_ERR(gss_msg); |
401 | goto out; | 408 | goto out; |
402 | } | 409 | } |
403 | spin_lock(&gss_auth->lock); | 410 | spin_lock(&inode->i_lock); |
404 | if (gss_cred->gc_upcall != NULL) | 411 | if (gss_cred->gc_upcall != NULL) |
405 | rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL, NULL); | 412 | rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL, NULL); |
406 | else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) { | 413 | else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) { |
@@ -411,7 +418,7 @@ gss_refresh_upcall(struct rpc_task *task) | |||
411 | rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback, NULL); | 418 | rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback, NULL); |
412 | } else | 419 | } else |
413 | err = gss_msg->msg.errno; | 420 | err = gss_msg->msg.errno; |
414 | spin_unlock(&gss_auth->lock); | 421 | spin_unlock(&inode->i_lock); |
415 | gss_release_msg(gss_msg); | 422 | gss_release_msg(gss_msg); |
416 | out: | 423 | out: |
417 | dprintk("RPC: %5u gss_refresh_upcall for uid %u result %d\n", | 424 | dprintk("RPC: %5u gss_refresh_upcall for uid %u result %d\n", |
@@ -422,6 +429,7 @@ out: | |||
422 | static inline int | 429 | static inline int |
423 | gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) | 430 | gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) |
424 | { | 431 | { |
432 | struct inode *inode = gss_auth->dentry->d_inode; | ||
425 | struct rpc_cred *cred = &gss_cred->gc_base; | 433 | struct rpc_cred *cred = &gss_cred->gc_base; |
426 | struct gss_upcall_msg *gss_msg; | 434 | struct gss_upcall_msg *gss_msg; |
427 | DEFINE_WAIT(wait); | 435 | DEFINE_WAIT(wait); |
@@ -435,12 +443,11 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) | |||
435 | } | 443 | } |
436 | for (;;) { | 444 | for (;;) { |
437 | prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_INTERRUPTIBLE); | 445 | prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_INTERRUPTIBLE); |
438 | spin_lock(&gss_auth->lock); | 446 | spin_lock(&inode->i_lock); |
439 | if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) { | 447 | if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) { |
440 | spin_unlock(&gss_auth->lock); | ||
441 | break; | 448 | break; |
442 | } | 449 | } |
443 | spin_unlock(&gss_auth->lock); | 450 | spin_unlock(&inode->i_lock); |
444 | if (signalled()) { | 451 | if (signalled()) { |
445 | err = -ERESTARTSYS; | 452 | err = -ERESTARTSYS; |
446 | goto out_intr; | 453 | goto out_intr; |
@@ -451,6 +458,7 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) | |||
451 | gss_cred_set_ctx(cred, gss_get_ctx(gss_msg->ctx)); | 458 | gss_cred_set_ctx(cred, gss_get_ctx(gss_msg->ctx)); |
452 | else | 459 | else |
453 | err = gss_msg->msg.errno; | 460 | err = gss_msg->msg.errno; |
461 | spin_unlock(&inode->i_lock); | ||
454 | out_intr: | 462 | out_intr: |
455 | finish_wait(&gss_msg->waitqueue, &wait); | 463 | finish_wait(&gss_msg->waitqueue, &wait); |
456 | gss_release_msg(gss_msg); | 464 | gss_release_msg(gss_msg); |
@@ -489,12 +497,11 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | |||
489 | const void *p, *end; | 497 | const void *p, *end; |
490 | void *buf; | 498 | void *buf; |
491 | struct rpc_clnt *clnt; | 499 | struct rpc_clnt *clnt; |
492 | struct gss_auth *gss_auth; | ||
493 | struct rpc_cred *cred; | ||
494 | struct gss_upcall_msg *gss_msg; | 500 | struct gss_upcall_msg *gss_msg; |
501 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
495 | struct gss_cl_ctx *ctx; | 502 | struct gss_cl_ctx *ctx; |
496 | uid_t uid; | 503 | uid_t uid; |
497 | int err = -EFBIG; | 504 | ssize_t err = -EFBIG; |
498 | 505 | ||
499 | if (mlen > MSG_BUF_MAXSIZE) | 506 | if (mlen > MSG_BUF_MAXSIZE) |
500 | goto out; | 507 | goto out; |
@@ -503,7 +510,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | |||
503 | if (!buf) | 510 | if (!buf) |
504 | goto out; | 511 | goto out; |
505 | 512 | ||
506 | clnt = RPC_I(filp->f_path.dentry->d_inode)->private; | 513 | clnt = RPC_I(inode)->private; |
507 | err = -EFAULT; | 514 | err = -EFAULT; |
508 | if (copy_from_user(buf, src, mlen)) | 515 | if (copy_from_user(buf, src, mlen)) |
509 | goto err; | 516 | goto err; |
@@ -519,43 +526,38 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | |||
519 | ctx = gss_alloc_context(); | 526 | ctx = gss_alloc_context(); |
520 | if (ctx == NULL) | 527 | if (ctx == NULL) |
521 | goto err; | 528 | goto err; |
522 | err = 0; | 529 | |
523 | gss_auth = container_of(clnt->cl_auth, struct gss_auth, rpc_auth); | 530 | err = -ENOENT; |
524 | p = gss_fill_context(p, end, ctx, gss_auth->mech); | 531 | /* Find a matching upcall */ |
532 | spin_lock(&inode->i_lock); | ||
533 | gss_msg = __gss_find_upcall(RPC_I(inode), uid); | ||
534 | if (gss_msg == NULL) { | ||
535 | spin_unlock(&inode->i_lock); | ||
536 | goto err_put_ctx; | ||
537 | } | ||
538 | list_del_init(&gss_msg->list); | ||
539 | spin_unlock(&inode->i_lock); | ||
540 | |||
541 | p = gss_fill_context(p, end, ctx, gss_msg->auth->mech); | ||
525 | if (IS_ERR(p)) { | 542 | if (IS_ERR(p)) { |
526 | err = PTR_ERR(p); | 543 | err = PTR_ERR(p); |
527 | if (err != -EACCES) | 544 | gss_msg->msg.errno = (err == -EACCES) ? -EACCES : -EAGAIN; |
528 | goto err_put_ctx; | 545 | goto err_release_msg; |
529 | } | ||
530 | spin_lock(&gss_auth->lock); | ||
531 | gss_msg = __gss_find_upcall(gss_auth, uid); | ||
532 | if (gss_msg) { | ||
533 | if (err == 0 && gss_msg->ctx == NULL) | ||
534 | gss_msg->ctx = gss_get_ctx(ctx); | ||
535 | gss_msg->msg.errno = err; | ||
536 | __gss_unhash_msg(gss_msg); | ||
537 | spin_unlock(&gss_auth->lock); | ||
538 | gss_release_msg(gss_msg); | ||
539 | } else { | ||
540 | struct auth_cred acred = { .uid = uid }; | ||
541 | spin_unlock(&gss_auth->lock); | ||
542 | cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, RPCAUTH_LOOKUP_NEW); | ||
543 | if (IS_ERR(cred)) { | ||
544 | err = PTR_ERR(cred); | ||
545 | goto err_put_ctx; | ||
546 | } | ||
547 | gss_cred_set_ctx(cred, gss_get_ctx(ctx)); | ||
548 | } | 546 | } |
549 | gss_put_ctx(ctx); | 547 | gss_msg->ctx = gss_get_ctx(ctx); |
550 | kfree(buf); | 548 | err = mlen; |
551 | dprintk("RPC: gss_pipe_downcall returning length %Zu\n", mlen); | 549 | |
552 | return mlen; | 550 | err_release_msg: |
551 | spin_lock(&inode->i_lock); | ||
552 | __gss_unhash_msg(gss_msg); | ||
553 | spin_unlock(&inode->i_lock); | ||
554 | gss_release_msg(gss_msg); | ||
553 | err_put_ctx: | 555 | err_put_ctx: |
554 | gss_put_ctx(ctx); | 556 | gss_put_ctx(ctx); |
555 | err: | 557 | err: |
556 | kfree(buf); | 558 | kfree(buf); |
557 | out: | 559 | out: |
558 | dprintk("RPC: gss_pipe_downcall returning %d\n", err); | 560 | dprintk("RPC: gss_pipe_downcall returning %Zd\n", err); |
559 | return err; | 561 | return err; |
560 | } | 562 | } |
561 | 563 | ||
@@ -563,27 +565,21 @@ static void | |||
563 | gss_pipe_release(struct inode *inode) | 565 | gss_pipe_release(struct inode *inode) |
564 | { | 566 | { |
565 | struct rpc_inode *rpci = RPC_I(inode); | 567 | struct rpc_inode *rpci = RPC_I(inode); |
566 | struct rpc_clnt *clnt; | 568 | struct gss_upcall_msg *gss_msg; |
567 | struct rpc_auth *auth; | ||
568 | struct gss_auth *gss_auth; | ||
569 | 569 | ||
570 | clnt = rpci->private; | 570 | spin_lock(&inode->i_lock); |
571 | auth = clnt->cl_auth; | 571 | while (!list_empty(&rpci->in_downcall)) { |
572 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); | ||
573 | spin_lock(&gss_auth->lock); | ||
574 | while (!list_empty(&gss_auth->upcalls)) { | ||
575 | struct gss_upcall_msg *gss_msg; | ||
576 | 572 | ||
577 | gss_msg = list_entry(gss_auth->upcalls.next, | 573 | gss_msg = list_entry(rpci->in_downcall.next, |
578 | struct gss_upcall_msg, list); | 574 | struct gss_upcall_msg, list); |
579 | gss_msg->msg.errno = -EPIPE; | 575 | gss_msg->msg.errno = -EPIPE; |
580 | atomic_inc(&gss_msg->count); | 576 | atomic_inc(&gss_msg->count); |
581 | __gss_unhash_msg(gss_msg); | 577 | __gss_unhash_msg(gss_msg); |
582 | spin_unlock(&gss_auth->lock); | 578 | spin_unlock(&inode->i_lock); |
583 | gss_release_msg(gss_msg); | 579 | gss_release_msg(gss_msg); |
584 | spin_lock(&gss_auth->lock); | 580 | spin_lock(&inode->i_lock); |
585 | } | 581 | } |
586 | spin_unlock(&gss_auth->lock); | 582 | spin_unlock(&inode->i_lock); |
587 | } | 583 | } |
588 | 584 | ||
589 | static void | 585 | static void |
@@ -637,18 +633,13 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) | |||
637 | gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor); | 633 | gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor); |
638 | if (gss_auth->service == 0) | 634 | if (gss_auth->service == 0) |
639 | goto err_put_mech; | 635 | goto err_put_mech; |
640 | INIT_LIST_HEAD(&gss_auth->upcalls); | ||
641 | spin_lock_init(&gss_auth->lock); | ||
642 | auth = &gss_auth->rpc_auth; | 636 | auth = &gss_auth->rpc_auth; |
643 | auth->au_cslack = GSS_CRED_SLACK >> 2; | 637 | auth->au_cslack = GSS_CRED_SLACK >> 2; |
644 | auth->au_rslack = GSS_VERF_SLACK >> 2; | 638 | auth->au_rslack = GSS_VERF_SLACK >> 2; |
645 | auth->au_ops = &authgss_ops; | 639 | auth->au_ops = &authgss_ops; |
646 | auth->au_flavor = flavor; | 640 | auth->au_flavor = flavor; |
647 | atomic_set(&auth->au_count, 1); | 641 | atomic_set(&auth->au_count, 1); |
648 | 642 | kref_init(&gss_auth->kref); | |
649 | err = rpcauth_init_credcache(auth, GSS_CRED_EXPIRE); | ||
650 | if (err) | ||
651 | goto err_put_mech; | ||
652 | 643 | ||
653 | gss_auth->dentry = rpc_mkpipe(clnt->cl_dentry, gss_auth->mech->gm_name, | 644 | gss_auth->dentry = rpc_mkpipe(clnt->cl_dentry, gss_auth->mech->gm_name, |
654 | clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); | 645 | clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); |
@@ -657,7 +648,13 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) | |||
657 | goto err_put_mech; | 648 | goto err_put_mech; |
658 | } | 649 | } |
659 | 650 | ||
651 | err = rpcauth_init_credcache(auth); | ||
652 | if (err) | ||
653 | goto err_unlink_pipe; | ||
654 | |||
660 | return auth; | 655 | return auth; |
656 | err_unlink_pipe: | ||
657 | rpc_unlink(gss_auth->dentry); | ||
661 | err_put_mech: | 658 | err_put_mech: |
662 | gss_mech_put(gss_auth->mech); | 659 | gss_mech_put(gss_auth->mech); |
663 | err_free: | 660 | err_free: |
@@ -668,6 +665,25 @@ out_dec: | |||
668 | } | 665 | } |
669 | 666 | ||
670 | static void | 667 | static void |
668 | gss_free(struct gss_auth *gss_auth) | ||
669 | { | ||
670 | rpc_unlink(gss_auth->dentry); | ||
671 | gss_auth->dentry = NULL; | ||
672 | gss_mech_put(gss_auth->mech); | ||
673 | |||
674 | kfree(gss_auth); | ||
675 | module_put(THIS_MODULE); | ||
676 | } | ||
677 | |||
678 | static void | ||
679 | gss_free_callback(struct kref *kref) | ||
680 | { | ||
681 | struct gss_auth *gss_auth = container_of(kref, struct gss_auth, kref); | ||
682 | |||
683 | gss_free(gss_auth); | ||
684 | } | ||
685 | |||
686 | static void | ||
671 | gss_destroy(struct rpc_auth *auth) | 687 | gss_destroy(struct rpc_auth *auth) |
672 | { | 688 | { |
673 | struct gss_auth *gss_auth; | 689 | struct gss_auth *gss_auth; |
@@ -675,23 +691,51 @@ gss_destroy(struct rpc_auth *auth) | |||
675 | dprintk("RPC: destroying GSS authenticator %p flavor %d\n", | 691 | dprintk("RPC: destroying GSS authenticator %p flavor %d\n", |
676 | auth, auth->au_flavor); | 692 | auth, auth->au_flavor); |
677 | 693 | ||
694 | rpcauth_destroy_credcache(auth); | ||
695 | |||
678 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); | 696 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); |
679 | rpc_unlink(gss_auth->dentry); | 697 | kref_put(&gss_auth->kref, gss_free_callback); |
680 | gss_auth->dentry = NULL; | 698 | } |
681 | gss_mech_put(gss_auth->mech); | ||
682 | 699 | ||
683 | rpcauth_free_credcache(auth); | 700 | /* |
684 | kfree(gss_auth); | 701 | * gss_destroying_context will cause the RPCSEC_GSS to send a NULL RPC call |
685 | module_put(THIS_MODULE); | 702 | * to the server with the GSS control procedure field set to |
703 | * RPC_GSS_PROC_DESTROY. This should normally cause the server to release | ||
704 | * all RPCSEC_GSS state associated with that context. | ||
705 | */ | ||
706 | static int | ||
707 | gss_destroying_context(struct rpc_cred *cred) | ||
708 | { | ||
709 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); | ||
710 | struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth); | ||
711 | struct rpc_task *task; | ||
712 | |||
713 | if (gss_cred->gc_ctx == NULL || | ||
714 | gss_cred->gc_ctx->gc_proc == RPC_GSS_PROC_DESTROY) | ||
715 | return 0; | ||
716 | |||
717 | gss_cred->gc_ctx->gc_proc = RPC_GSS_PROC_DESTROY; | ||
718 | cred->cr_ops = &gss_nullops; | ||
719 | |||
720 | /* Take a reference to ensure the cred will be destroyed either | ||
721 | * by the RPC call or by the put_rpccred() below */ | ||
722 | get_rpccred(cred); | ||
723 | |||
724 | task = rpc_call_null(gss_auth->client, cred, RPC_TASK_ASYNC); | ||
725 | if (!IS_ERR(task)) | ||
726 | rpc_put_task(task); | ||
727 | |||
728 | put_rpccred(cred); | ||
729 | return 1; | ||
686 | } | 730 | } |
687 | 731 | ||
688 | /* gss_destroy_cred (and gss_destroy_ctx) are used to clean up after failure | 732 | /* gss_destroy_cred (and gss_free_ctx) are used to clean up after failure |
689 | * to create a new cred or context, so they check that things have been | 733 | * to create a new cred or context, so they check that things have been |
690 | * allocated before freeing them. */ | 734 | * allocated before freeing them. */ |
691 | static void | 735 | static void |
692 | gss_destroy_ctx(struct gss_cl_ctx *ctx) | 736 | gss_do_free_ctx(struct gss_cl_ctx *ctx) |
693 | { | 737 | { |
694 | dprintk("RPC: gss_destroy_ctx\n"); | 738 | dprintk("RPC: gss_free_ctx\n"); |
695 | 739 | ||
696 | if (ctx->gc_gss_ctx) | 740 | if (ctx->gc_gss_ctx) |
697 | gss_delete_sec_context(&ctx->gc_gss_ctx); | 741 | gss_delete_sec_context(&ctx->gc_gss_ctx); |
@@ -701,15 +745,46 @@ gss_destroy_ctx(struct gss_cl_ctx *ctx) | |||
701 | } | 745 | } |
702 | 746 | ||
703 | static void | 747 | static void |
704 | gss_destroy_cred(struct rpc_cred *rc) | 748 | gss_free_ctx_callback(struct rcu_head *head) |
705 | { | 749 | { |
706 | struct gss_cred *cred = container_of(rc, struct gss_cred, gc_base); | 750 | struct gss_cl_ctx *ctx = container_of(head, struct gss_cl_ctx, gc_rcu); |
751 | gss_do_free_ctx(ctx); | ||
752 | } | ||
707 | 753 | ||
708 | dprintk("RPC: gss_destroy_cred \n"); | 754 | static void |
755 | gss_free_ctx(struct gss_cl_ctx *ctx) | ||
756 | { | ||
757 | call_rcu(&ctx->gc_rcu, gss_free_ctx_callback); | ||
758 | } | ||
709 | 759 | ||
710 | if (cred->gc_ctx) | 760 | static void |
711 | gss_put_ctx(cred->gc_ctx); | 761 | gss_free_cred(struct gss_cred *gss_cred) |
712 | kfree(cred); | 762 | { |
763 | dprintk("RPC: gss_free_cred %p\n", gss_cred); | ||
764 | kfree(gss_cred); | ||
765 | } | ||
766 | |||
767 | static void | ||
768 | gss_free_cred_callback(struct rcu_head *head) | ||
769 | { | ||
770 | struct gss_cred *gss_cred = container_of(head, struct gss_cred, gc_base.cr_rcu); | ||
771 | gss_free_cred(gss_cred); | ||
772 | } | ||
773 | |||
774 | static void | ||
775 | gss_destroy_cred(struct rpc_cred *cred) | ||
776 | { | ||
777 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); | ||
778 | struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth); | ||
779 | struct gss_cl_ctx *ctx = gss_cred->gc_ctx; | ||
780 | |||
781 | if (gss_destroying_context(cred)) | ||
782 | return; | ||
783 | rcu_assign_pointer(gss_cred->gc_ctx, NULL); | ||
784 | call_rcu(&cred->cr_rcu, gss_free_cred_callback); | ||
785 | if (ctx) | ||
786 | gss_put_ctx(ctx); | ||
787 | kref_put(&gss_auth->kref, gss_free_callback); | ||
713 | } | 788 | } |
714 | 789 | ||
715 | /* | 790 | /* |
@@ -734,16 +809,14 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) | |||
734 | if (!(cred = kzalloc(sizeof(*cred), GFP_KERNEL))) | 809 | if (!(cred = kzalloc(sizeof(*cred), GFP_KERNEL))) |
735 | goto out_err; | 810 | goto out_err; |
736 | 811 | ||
737 | atomic_set(&cred->gc_count, 1); | 812 | rpcauth_init_cred(&cred->gc_base, acred, auth, &gss_credops); |
738 | cred->gc_uid = acred->uid; | ||
739 | /* | 813 | /* |
740 | * Note: in order to force a call to call_refresh(), we deliberately | 814 | * Note: in order to force a call to call_refresh(), we deliberately |
741 | * fail to flag the credential as RPCAUTH_CRED_UPTODATE. | 815 | * fail to flag the credential as RPCAUTH_CRED_UPTODATE. |
742 | */ | 816 | */ |
743 | cred->gc_flags = 0; | 817 | cred->gc_base.cr_flags = 1UL << RPCAUTH_CRED_NEW; |
744 | cred->gc_base.cr_ops = &gss_credops; | ||
745 | cred->gc_base.cr_flags = RPCAUTH_CRED_NEW; | ||
746 | cred->gc_service = gss_auth->service; | 818 | cred->gc_service = gss_auth->service; |
819 | kref_get(&gss_auth->kref); | ||
747 | return &cred->gc_base; | 820 | return &cred->gc_base; |
748 | 821 | ||
749 | out_err: | 822 | out_err: |
@@ -774,7 +847,7 @@ gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags) | |||
774 | * we don't really care if the credential has expired or not, | 847 | * we don't really care if the credential has expired or not, |
775 | * since the caller should be prepared to reinitialise it. | 848 | * since the caller should be prepared to reinitialise it. |
776 | */ | 849 | */ |
777 | if ((flags & RPCAUTH_LOOKUP_NEW) && (rc->cr_flags & RPCAUTH_CRED_NEW)) | 850 | if ((flags & RPCAUTH_LOOKUP_NEW) && test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags)) |
778 | goto out; | 851 | goto out; |
779 | /* Don't match with creds that have expired. */ | 852 | /* Don't match with creds that have expired. */ |
780 | if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry)) | 853 | if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry)) |
@@ -830,7 +903,7 @@ gss_marshal(struct rpc_task *task, __be32 *p) | |||
830 | mic.data = (u8 *)(p + 1); | 903 | mic.data = (u8 *)(p + 1); |
831 | maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic); | 904 | maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic); |
832 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) { | 905 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) { |
833 | cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE; | 906 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
834 | } else if (maj_stat != 0) { | 907 | } else if (maj_stat != 0) { |
835 | printk("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat); | 908 | printk("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat); |
836 | goto out_put_ctx; | 909 | goto out_put_ctx; |
@@ -855,6 +928,13 @@ gss_refresh(struct rpc_task *task) | |||
855 | return 0; | 928 | return 0; |
856 | } | 929 | } |
857 | 930 | ||
931 | /* Dummy refresh routine: used only when destroying the context */ | ||
932 | static int | ||
933 | gss_refresh_null(struct rpc_task *task) | ||
934 | { | ||
935 | return -EACCES; | ||
936 | } | ||
937 | |||
858 | static __be32 * | 938 | static __be32 * |
859 | gss_validate(struct rpc_task *task, __be32 *p) | 939 | gss_validate(struct rpc_task *task, __be32 *p) |
860 | { | 940 | { |
@@ -883,12 +963,15 @@ gss_validate(struct rpc_task *task, __be32 *p) | |||
883 | 963 | ||
884 | maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic); | 964 | maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic); |
885 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) | 965 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) |
886 | cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE; | 966 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
887 | if (maj_stat) | 967 | if (maj_stat) { |
968 | dprintk("RPC: %5u gss_validate: gss_verify_mic returned" | ||
969 | "error 0x%08x\n", task->tk_pid, maj_stat); | ||
888 | goto out_bad; | 970 | goto out_bad; |
971 | } | ||
889 | /* We leave it to unwrap to calculate au_rslack. For now we just | 972 | /* We leave it to unwrap to calculate au_rslack. For now we just |
890 | * calculate the length of the verifier: */ | 973 | * calculate the length of the verifier: */ |
891 | task->tk_auth->au_verfsize = XDR_QUADLEN(len) + 2; | 974 | cred->cr_auth->au_verfsize = XDR_QUADLEN(len) + 2; |
892 | gss_put_ctx(ctx); | 975 | gss_put_ctx(ctx); |
893 | dprintk("RPC: %5u gss_validate: gss_verify_mic succeeded.\n", | 976 | dprintk("RPC: %5u gss_validate: gss_verify_mic succeeded.\n", |
894 | task->tk_pid); | 977 | task->tk_pid); |
@@ -917,7 +1000,9 @@ gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx, | |||
917 | offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base; | 1000 | offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base; |
918 | *p++ = htonl(rqstp->rq_seqno); | 1001 | *p++ = htonl(rqstp->rq_seqno); |
919 | 1002 | ||
1003 | lock_kernel(); | ||
920 | status = encode(rqstp, p, obj); | 1004 | status = encode(rqstp, p, obj); |
1005 | unlock_kernel(); | ||
921 | if (status) | 1006 | if (status) |
922 | return status; | 1007 | return status; |
923 | 1008 | ||
@@ -937,7 +1022,7 @@ gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx, | |||
937 | maj_stat = gss_get_mic(ctx->gc_gss_ctx, &integ_buf, &mic); | 1022 | maj_stat = gss_get_mic(ctx->gc_gss_ctx, &integ_buf, &mic); |
938 | status = -EIO; /* XXX? */ | 1023 | status = -EIO; /* XXX? */ |
939 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) | 1024 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) |
940 | cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE; | 1025 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
941 | else if (maj_stat) | 1026 | else if (maj_stat) |
942 | return status; | 1027 | return status; |
943 | q = xdr_encode_opaque(p, NULL, mic.len); | 1028 | q = xdr_encode_opaque(p, NULL, mic.len); |
@@ -1011,7 +1096,9 @@ gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx, | |||
1011 | offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base; | 1096 | offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base; |
1012 | *p++ = htonl(rqstp->rq_seqno); | 1097 | *p++ = htonl(rqstp->rq_seqno); |
1013 | 1098 | ||
1099 | lock_kernel(); | ||
1014 | status = encode(rqstp, p, obj); | 1100 | status = encode(rqstp, p, obj); |
1101 | unlock_kernel(); | ||
1015 | if (status) | 1102 | if (status) |
1016 | return status; | 1103 | return status; |
1017 | 1104 | ||
@@ -1036,7 +1123,7 @@ gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx, | |||
1036 | /* We're assuming that when GSS_S_CONTEXT_EXPIRED, the encryption was | 1123 | /* We're assuming that when GSS_S_CONTEXT_EXPIRED, the encryption was |
1037 | * done anyway, so it's safe to put the request on the wire: */ | 1124 | * done anyway, so it's safe to put the request on the wire: */ |
1038 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) | 1125 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) |
1039 | cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE; | 1126 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
1040 | else if (maj_stat) | 1127 | else if (maj_stat) |
1041 | return status; | 1128 | return status; |
1042 | 1129 | ||
@@ -1070,12 +1157,16 @@ gss_wrap_req(struct rpc_task *task, | |||
1070 | /* The spec seems a little ambiguous here, but I think that not | 1157 | /* The spec seems a little ambiguous here, but I think that not |
1071 | * wrapping context destruction requests makes the most sense. | 1158 | * wrapping context destruction requests makes the most sense. |
1072 | */ | 1159 | */ |
1160 | lock_kernel(); | ||
1073 | status = encode(rqstp, p, obj); | 1161 | status = encode(rqstp, p, obj); |
1162 | unlock_kernel(); | ||
1074 | goto out; | 1163 | goto out; |
1075 | } | 1164 | } |
1076 | switch (gss_cred->gc_service) { | 1165 | switch (gss_cred->gc_service) { |
1077 | case RPC_GSS_SVC_NONE: | 1166 | case RPC_GSS_SVC_NONE: |
1167 | lock_kernel(); | ||
1078 | status = encode(rqstp, p, obj); | 1168 | status = encode(rqstp, p, obj); |
1169 | unlock_kernel(); | ||
1079 | break; | 1170 | break; |
1080 | case RPC_GSS_SVC_INTEGRITY: | 1171 | case RPC_GSS_SVC_INTEGRITY: |
1081 | status = gss_wrap_req_integ(cred, ctx, encode, | 1172 | status = gss_wrap_req_integ(cred, ctx, encode, |
@@ -1123,7 +1214,7 @@ gss_unwrap_resp_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx, | |||
1123 | 1214 | ||
1124 | maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf, &mic); | 1215 | maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf, &mic); |
1125 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) | 1216 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) |
1126 | cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE; | 1217 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
1127 | if (maj_stat != GSS_S_COMPLETE) | 1218 | if (maj_stat != GSS_S_COMPLETE) |
1128 | return status; | 1219 | return status; |
1129 | return 0; | 1220 | return 0; |
@@ -1148,7 +1239,7 @@ gss_unwrap_resp_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx, | |||
1148 | 1239 | ||
1149 | maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset, rcv_buf); | 1240 | maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset, rcv_buf); |
1150 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) | 1241 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) |
1151 | cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE; | 1242 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
1152 | if (maj_stat != GSS_S_COMPLETE) | 1243 | if (maj_stat != GSS_S_COMPLETE) |
1153 | return status; | 1244 | return status; |
1154 | if (ntohl(*(*p)++) != rqstp->rq_seqno) | 1245 | if (ntohl(*(*p)++) != rqstp->rq_seqno) |
@@ -1188,10 +1279,12 @@ gss_unwrap_resp(struct rpc_task *task, | |||
1188 | break; | 1279 | break; |
1189 | } | 1280 | } |
1190 | /* take into account extra slack for integrity and privacy cases: */ | 1281 | /* take into account extra slack for integrity and privacy cases: */ |
1191 | task->tk_auth->au_rslack = task->tk_auth->au_verfsize + (p - savedp) | 1282 | cred->cr_auth->au_rslack = cred->cr_auth->au_verfsize + (p - savedp) |
1192 | + (savedlen - head->iov_len); | 1283 | + (savedlen - head->iov_len); |
1193 | out_decode: | 1284 | out_decode: |
1285 | lock_kernel(); | ||
1194 | status = decode(rqstp, p, obj); | 1286 | status = decode(rqstp, p, obj); |
1287 | unlock_kernel(); | ||
1195 | out: | 1288 | out: |
1196 | gss_put_ctx(ctx); | 1289 | gss_put_ctx(ctx); |
1197 | dprintk("RPC: %5u gss_unwrap_resp returning %d\n", task->tk_pid, | 1290 | dprintk("RPC: %5u gss_unwrap_resp returning %d\n", task->tk_pid, |
@@ -1199,7 +1292,7 @@ out: | |||
1199 | return status; | 1292 | return status; |
1200 | } | 1293 | } |
1201 | 1294 | ||
1202 | static struct rpc_authops authgss_ops = { | 1295 | static const struct rpc_authops authgss_ops = { |
1203 | .owner = THIS_MODULE, | 1296 | .owner = THIS_MODULE, |
1204 | .au_flavor = RPC_AUTH_GSS, | 1297 | .au_flavor = RPC_AUTH_GSS, |
1205 | #ifdef RPC_DEBUG | 1298 | #ifdef RPC_DEBUG |
@@ -1211,7 +1304,7 @@ static struct rpc_authops authgss_ops = { | |||
1211 | .crcreate = gss_create_cred | 1304 | .crcreate = gss_create_cred |
1212 | }; | 1305 | }; |
1213 | 1306 | ||
1214 | static struct rpc_credops gss_credops = { | 1307 | static const struct rpc_credops gss_credops = { |
1215 | .cr_name = "AUTH_GSS", | 1308 | .cr_name = "AUTH_GSS", |
1216 | .crdestroy = gss_destroy_cred, | 1309 | .crdestroy = gss_destroy_cred, |
1217 | .cr_init = gss_cred_init, | 1310 | .cr_init = gss_cred_init, |
@@ -1223,6 +1316,17 @@ static struct rpc_credops gss_credops = { | |||
1223 | .crunwrap_resp = gss_unwrap_resp, | 1316 | .crunwrap_resp = gss_unwrap_resp, |
1224 | }; | 1317 | }; |
1225 | 1318 | ||
1319 | static const struct rpc_credops gss_nullops = { | ||
1320 | .cr_name = "AUTH_GSS", | ||
1321 | .crdestroy = gss_destroy_cred, | ||
1322 | .crmatch = gss_match, | ||
1323 | .crmarshal = gss_marshal, | ||
1324 | .crrefresh = gss_refresh_null, | ||
1325 | .crvalidate = gss_validate, | ||
1326 | .crwrap_req = gss_wrap_req, | ||
1327 | .crunwrap_resp = gss_unwrap_resp, | ||
1328 | }; | ||
1329 | |||
1226 | static struct rpc_pipe_ops gss_upcall_ops = { | 1330 | static struct rpc_pipe_ops gss_upcall_ops = { |
1227 | .upcall = gss_pipe_upcall, | 1331 | .upcall = gss_pipe_upcall, |
1228 | .downcall = gss_pipe_downcall, | 1332 | .downcall = gss_pipe_downcall, |
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 7b1943217053..71b9daefdff3 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c | |||
@@ -201,7 +201,7 @@ gss_delete_sec_context_kerberos(void *internal_ctx) { | |||
201 | kfree(kctx); | 201 | kfree(kctx); |
202 | } | 202 | } |
203 | 203 | ||
204 | static struct gss_api_ops gss_kerberos_ops = { | 204 | static const struct gss_api_ops gss_kerberos_ops = { |
205 | .gss_import_sec_context = gss_import_sec_context_kerberos, | 205 | .gss_import_sec_context = gss_import_sec_context_kerberos, |
206 | .gss_get_mic = gss_get_mic_kerberos, | 206 | .gss_get_mic = gss_get_mic_kerberos, |
207 | .gss_verify_mic = gss_verify_mic_kerberos, | 207 | .gss_verify_mic = gss_verify_mic_kerberos, |
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c index 7e15aa68ae64..577d590e755f 100644 --- a/net/sunrpc/auth_gss/gss_spkm3_mech.c +++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c | |||
@@ -202,7 +202,7 @@ gss_get_mic_spkm3(struct gss_ctx *ctx, | |||
202 | return err; | 202 | return err; |
203 | } | 203 | } |
204 | 204 | ||
205 | static struct gss_api_ops gss_spkm3_ops = { | 205 | static const struct gss_api_ops gss_spkm3_ops = { |
206 | .gss_import_sec_context = gss_import_sec_context_spkm3, | 206 | .gss_import_sec_context = gss_import_sec_context_spkm3, |
207 | .gss_get_mic = gss_get_mic_spkm3, | 207 | .gss_get_mic = gss_get_mic_spkm3, |
208 | .gss_verify_mic = gss_verify_mic_spkm3, | 208 | .gss_verify_mic = gss_verify_mic_spkm3, |
diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c index 3df9fccab2f8..537d0e8589dd 100644 --- a/net/sunrpc/auth_null.c +++ b/net/sunrpc/auth_null.c | |||
@@ -76,7 +76,7 @@ nul_marshal(struct rpc_task *task, __be32 *p) | |||
76 | static int | 76 | static int |
77 | nul_refresh(struct rpc_task *task) | 77 | nul_refresh(struct rpc_task *task) |
78 | { | 78 | { |
79 | task->tk_msg.rpc_cred->cr_flags |= RPCAUTH_CRED_UPTODATE; | 79 | set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_msg.rpc_cred->cr_flags); |
80 | return 0; | 80 | return 0; |
81 | } | 81 | } |
82 | 82 | ||
@@ -101,7 +101,7 @@ nul_validate(struct rpc_task *task, __be32 *p) | |||
101 | return p; | 101 | return p; |
102 | } | 102 | } |
103 | 103 | ||
104 | struct rpc_authops authnull_ops = { | 104 | const struct rpc_authops authnull_ops = { |
105 | .owner = THIS_MODULE, | 105 | .owner = THIS_MODULE, |
106 | .au_flavor = RPC_AUTH_NULL, | 106 | .au_flavor = RPC_AUTH_NULL, |
107 | #ifdef RPC_DEBUG | 107 | #ifdef RPC_DEBUG |
@@ -122,7 +122,7 @@ struct rpc_auth null_auth = { | |||
122 | }; | 122 | }; |
123 | 123 | ||
124 | static | 124 | static |
125 | struct rpc_credops null_credops = { | 125 | const struct rpc_credops null_credops = { |
126 | .cr_name = "AUTH_NULL", | 126 | .cr_name = "AUTH_NULL", |
127 | .crdestroy = nul_destroy_cred, | 127 | .crdestroy = nul_destroy_cred, |
128 | .crmatch = nul_match, | 128 | .crmatch = nul_match, |
@@ -133,9 +133,11 @@ struct rpc_credops null_credops = { | |||
133 | 133 | ||
134 | static | 134 | static |
135 | struct rpc_cred null_cred = { | 135 | struct rpc_cred null_cred = { |
136 | .cr_lru = LIST_HEAD_INIT(null_cred.cr_lru), | ||
137 | .cr_auth = &null_auth, | ||
136 | .cr_ops = &null_credops, | 138 | .cr_ops = &null_credops, |
137 | .cr_count = ATOMIC_INIT(1), | 139 | .cr_count = ATOMIC_INIT(1), |
138 | .cr_flags = RPCAUTH_CRED_UPTODATE, | 140 | .cr_flags = 1UL << RPCAUTH_CRED_UPTODATE, |
139 | #ifdef RPC_DEBUG | 141 | #ifdef RPC_DEBUG |
140 | .cr_magic = RPCAUTH_CRED_MAGIC, | 142 | .cr_magic = RPCAUTH_CRED_MAGIC, |
141 | #endif | 143 | #endif |
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index 4e7733aee36e..5ed91e5bcee4 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c | |||
@@ -20,11 +20,6 @@ struct unx_cred { | |||
20 | gid_t uc_gids[NFS_NGROUPS]; | 20 | gid_t uc_gids[NFS_NGROUPS]; |
21 | }; | 21 | }; |
22 | #define uc_uid uc_base.cr_uid | 22 | #define uc_uid uc_base.cr_uid |
23 | #define uc_count uc_base.cr_count | ||
24 | #define uc_flags uc_base.cr_flags | ||
25 | #define uc_expire uc_base.cr_expire | ||
26 | |||
27 | #define UNX_CRED_EXPIRE (60 * HZ) | ||
28 | 23 | ||
29 | #define UNX_WRITESLACK (21 + (UNX_MAXNODENAME >> 2)) | 24 | #define UNX_WRITESLACK (21 + (UNX_MAXNODENAME >> 2)) |
30 | 25 | ||
@@ -34,15 +29,14 @@ struct unx_cred { | |||
34 | 29 | ||
35 | static struct rpc_auth unix_auth; | 30 | static struct rpc_auth unix_auth; |
36 | static struct rpc_cred_cache unix_cred_cache; | 31 | static struct rpc_cred_cache unix_cred_cache; |
37 | static struct rpc_credops unix_credops; | 32 | static const struct rpc_credops unix_credops; |
38 | 33 | ||
39 | static struct rpc_auth * | 34 | static struct rpc_auth * |
40 | unx_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) | 35 | unx_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) |
41 | { | 36 | { |
42 | dprintk("RPC: creating UNIX authenticator for client %p\n", | 37 | dprintk("RPC: creating UNIX authenticator for client %p\n", |
43 | clnt); | 38 | clnt); |
44 | if (atomic_inc_return(&unix_auth.au_count) == 0) | 39 | atomic_inc(&unix_auth.au_count); |
45 | unix_cred_cache.nextgc = jiffies + (unix_cred_cache.expire >> 1); | ||
46 | return &unix_auth; | 40 | return &unix_auth; |
47 | } | 41 | } |
48 | 42 | ||
@@ -50,7 +44,7 @@ static void | |||
50 | unx_destroy(struct rpc_auth *auth) | 44 | unx_destroy(struct rpc_auth *auth) |
51 | { | 45 | { |
52 | dprintk("RPC: destroying UNIX authenticator %p\n", auth); | 46 | dprintk("RPC: destroying UNIX authenticator %p\n", auth); |
53 | rpcauth_free_credcache(auth); | 47 | rpcauth_clear_credcache(auth->au_credcache); |
54 | } | 48 | } |
55 | 49 | ||
56 | /* | 50 | /* |
@@ -74,8 +68,8 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) | |||
74 | if (!(cred = kmalloc(sizeof(*cred), GFP_KERNEL))) | 68 | if (!(cred = kmalloc(sizeof(*cred), GFP_KERNEL))) |
75 | return ERR_PTR(-ENOMEM); | 69 | return ERR_PTR(-ENOMEM); |
76 | 70 | ||
77 | atomic_set(&cred->uc_count, 1); | 71 | rpcauth_init_cred(&cred->uc_base, acred, auth, &unix_credops); |
78 | cred->uc_flags = RPCAUTH_CRED_UPTODATE; | 72 | cred->uc_base.cr_flags = 1UL << RPCAUTH_CRED_UPTODATE; |
79 | if (flags & RPCAUTH_LOOKUP_ROOTCREDS) { | 73 | if (flags & RPCAUTH_LOOKUP_ROOTCREDS) { |
80 | cred->uc_uid = 0; | 74 | cred->uc_uid = 0; |
81 | cred->uc_gid = 0; | 75 | cred->uc_gid = 0; |
@@ -85,22 +79,34 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) | |||
85 | if (groups > NFS_NGROUPS) | 79 | if (groups > NFS_NGROUPS) |
86 | groups = NFS_NGROUPS; | 80 | groups = NFS_NGROUPS; |
87 | 81 | ||
88 | cred->uc_uid = acred->uid; | ||
89 | cred->uc_gid = acred->gid; | 82 | cred->uc_gid = acred->gid; |
90 | for (i = 0; i < groups; i++) | 83 | for (i = 0; i < groups; i++) |
91 | cred->uc_gids[i] = GROUP_AT(acred->group_info, i); | 84 | cred->uc_gids[i] = GROUP_AT(acred->group_info, i); |
92 | if (i < NFS_NGROUPS) | 85 | if (i < NFS_NGROUPS) |
93 | cred->uc_gids[i] = NOGROUP; | 86 | cred->uc_gids[i] = NOGROUP; |
94 | } | 87 | } |
95 | cred->uc_base.cr_ops = &unix_credops; | ||
96 | 88 | ||
97 | return (struct rpc_cred *) cred; | 89 | return &cred->uc_base; |
90 | } | ||
91 | |||
92 | static void | ||
93 | unx_free_cred(struct unx_cred *unx_cred) | ||
94 | { | ||
95 | dprintk("RPC: unx_free_cred %p\n", unx_cred); | ||
96 | kfree(unx_cred); | ||
97 | } | ||
98 | |||
99 | static void | ||
100 | unx_free_cred_callback(struct rcu_head *head) | ||
101 | { | ||
102 | struct unx_cred *unx_cred = container_of(head, struct unx_cred, uc_base.cr_rcu); | ||
103 | unx_free_cred(unx_cred); | ||
98 | } | 104 | } |
99 | 105 | ||
100 | static void | 106 | static void |
101 | unx_destroy_cred(struct rpc_cred *cred) | 107 | unx_destroy_cred(struct rpc_cred *cred) |
102 | { | 108 | { |
103 | kfree(cred); | 109 | call_rcu(&cred->cr_rcu, unx_free_cred_callback); |
104 | } | 110 | } |
105 | 111 | ||
106 | /* | 112 | /* |
@@ -111,7 +117,7 @@ unx_destroy_cred(struct rpc_cred *cred) | |||
111 | static int | 117 | static int |
112 | unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags) | 118 | unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags) |
113 | { | 119 | { |
114 | struct unx_cred *cred = (struct unx_cred *) rcred; | 120 | struct unx_cred *cred = container_of(rcred, struct unx_cred, uc_base); |
115 | int i; | 121 | int i; |
116 | 122 | ||
117 | if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS)) { | 123 | if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS)) { |
@@ -142,7 +148,7 @@ static __be32 * | |||
142 | unx_marshal(struct rpc_task *task, __be32 *p) | 148 | unx_marshal(struct rpc_task *task, __be32 *p) |
143 | { | 149 | { |
144 | struct rpc_clnt *clnt = task->tk_client; | 150 | struct rpc_clnt *clnt = task->tk_client; |
145 | struct unx_cred *cred = (struct unx_cred *) task->tk_msg.rpc_cred; | 151 | struct unx_cred *cred = container_of(task->tk_msg.rpc_cred, struct unx_cred, uc_base); |
146 | __be32 *base, *hold; | 152 | __be32 *base, *hold; |
147 | int i; | 153 | int i; |
148 | 154 | ||
@@ -175,7 +181,7 @@ unx_marshal(struct rpc_task *task, __be32 *p) | |||
175 | static int | 181 | static int |
176 | unx_refresh(struct rpc_task *task) | 182 | unx_refresh(struct rpc_task *task) |
177 | { | 183 | { |
178 | task->tk_msg.rpc_cred->cr_flags |= RPCAUTH_CRED_UPTODATE; | 184 | set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_msg.rpc_cred->cr_flags); |
179 | return 0; | 185 | return 0; |
180 | } | 186 | } |
181 | 187 | ||
@@ -198,13 +204,18 @@ unx_validate(struct rpc_task *task, __be32 *p) | |||
198 | printk("RPC: giant verf size: %u\n", size); | 204 | printk("RPC: giant verf size: %u\n", size); |
199 | return NULL; | 205 | return NULL; |
200 | } | 206 | } |
201 | task->tk_auth->au_rslack = (size >> 2) + 2; | 207 | task->tk_msg.rpc_cred->cr_auth->au_rslack = (size >> 2) + 2; |
202 | p += (size >> 2); | 208 | p += (size >> 2); |
203 | 209 | ||
204 | return p; | 210 | return p; |
205 | } | 211 | } |
206 | 212 | ||
207 | struct rpc_authops authunix_ops = { | 213 | void __init rpc_init_authunix(void) |
214 | { | ||
215 | spin_lock_init(&unix_cred_cache.lock); | ||
216 | } | ||
217 | |||
218 | const struct rpc_authops authunix_ops = { | ||
208 | .owner = THIS_MODULE, | 219 | .owner = THIS_MODULE, |
209 | .au_flavor = RPC_AUTH_UNIX, | 220 | .au_flavor = RPC_AUTH_UNIX, |
210 | #ifdef RPC_DEBUG | 221 | #ifdef RPC_DEBUG |
@@ -218,7 +229,6 @@ struct rpc_authops authunix_ops = { | |||
218 | 229 | ||
219 | static | 230 | static |
220 | struct rpc_cred_cache unix_cred_cache = { | 231 | struct rpc_cred_cache unix_cred_cache = { |
221 | .expire = UNX_CRED_EXPIRE, | ||
222 | }; | 232 | }; |
223 | 233 | ||
224 | static | 234 | static |
@@ -232,7 +242,7 @@ struct rpc_auth unix_auth = { | |||
232 | }; | 242 | }; |
233 | 243 | ||
234 | static | 244 | static |
235 | struct rpc_credops unix_credops = { | 245 | const struct rpc_credops unix_credops = { |
236 | .cr_name = "AUTH_UNIX", | 246 | .cr_name = "AUTH_UNIX", |
237 | .crdestroy = unx_destroy_cred, | 247 | .crdestroy = unx_destroy_cred, |
238 | .crmatch = unx_match, | 248 | .crmatch = unx_match, |
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 543b085ae2c1..01c3c4105204 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
@@ -1210,7 +1210,7 @@ static int c_show(struct seq_file *m, void *p) | |||
1210 | return cd->cache_show(m, cd, cp); | 1210 | return cd->cache_show(m, cd, cp); |
1211 | } | 1211 | } |
1212 | 1212 | ||
1213 | static struct seq_operations cache_content_op = { | 1213 | static const struct seq_operations cache_content_op = { |
1214 | .start = c_start, | 1214 | .start = c_start, |
1215 | .next = c_next, | 1215 | .next = c_next, |
1216 | .stop = c_stop, | 1216 | .stop = c_stop, |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index d8fbee40a19c..52429b1ffcc1 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -44,6 +44,12 @@ | |||
44 | dprintk("RPC: %5u %s (status %d)\n", t->tk_pid, \ | 44 | dprintk("RPC: %5u %s (status %d)\n", t->tk_pid, \ |
45 | __FUNCTION__, t->tk_status) | 45 | __FUNCTION__, t->tk_status) |
46 | 46 | ||
47 | /* | ||
48 | * All RPC clients are linked into this list | ||
49 | */ | ||
50 | static LIST_HEAD(all_clients); | ||
51 | static DEFINE_SPINLOCK(rpc_client_lock); | ||
52 | |||
47 | static DECLARE_WAIT_QUEUE_HEAD(destroy_wait); | 53 | static DECLARE_WAIT_QUEUE_HEAD(destroy_wait); |
48 | 54 | ||
49 | 55 | ||
@@ -66,6 +72,21 @@ static void call_connect_status(struct rpc_task *task); | |||
66 | static __be32 * call_header(struct rpc_task *task); | 72 | static __be32 * call_header(struct rpc_task *task); |
67 | static __be32 * call_verify(struct rpc_task *task); | 73 | static __be32 * call_verify(struct rpc_task *task); |
68 | 74 | ||
75 | static int rpc_ping(struct rpc_clnt *clnt, int flags); | ||
76 | |||
77 | static void rpc_register_client(struct rpc_clnt *clnt) | ||
78 | { | ||
79 | spin_lock(&rpc_client_lock); | ||
80 | list_add(&clnt->cl_clients, &all_clients); | ||
81 | spin_unlock(&rpc_client_lock); | ||
82 | } | ||
83 | |||
84 | static void rpc_unregister_client(struct rpc_clnt *clnt) | ||
85 | { | ||
86 | spin_lock(&rpc_client_lock); | ||
87 | list_del(&clnt->cl_clients); | ||
88 | spin_unlock(&rpc_client_lock); | ||
89 | } | ||
69 | 90 | ||
70 | static int | 91 | static int |
71 | rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name) | 92 | rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name) |
@@ -111,6 +132,9 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s | |||
111 | dprintk("RPC: creating %s client for %s (xprt %p)\n", | 132 | dprintk("RPC: creating %s client for %s (xprt %p)\n", |
112 | program->name, servname, xprt); | 133 | program->name, servname, xprt); |
113 | 134 | ||
135 | err = rpciod_up(); | ||
136 | if (err) | ||
137 | goto out_no_rpciod; | ||
114 | err = -EINVAL; | 138 | err = -EINVAL; |
115 | if (!xprt) | 139 | if (!xprt) |
116 | goto out_no_xprt; | 140 | goto out_no_xprt; |
@@ -121,8 +145,6 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s | |||
121 | clnt = kzalloc(sizeof(*clnt), GFP_KERNEL); | 145 | clnt = kzalloc(sizeof(*clnt), GFP_KERNEL); |
122 | if (!clnt) | 146 | if (!clnt) |
123 | goto out_err; | 147 | goto out_err; |
124 | atomic_set(&clnt->cl_users, 0); | ||
125 | atomic_set(&clnt->cl_count, 1); | ||
126 | clnt->cl_parent = clnt; | 148 | clnt->cl_parent = clnt; |
127 | 149 | ||
128 | clnt->cl_server = clnt->cl_inline_name; | 150 | clnt->cl_server = clnt->cl_inline_name; |
@@ -148,6 +170,8 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s | |||
148 | if (clnt->cl_metrics == NULL) | 170 | if (clnt->cl_metrics == NULL) |
149 | goto out_no_stats; | 171 | goto out_no_stats; |
150 | clnt->cl_program = program; | 172 | clnt->cl_program = program; |
173 | INIT_LIST_HEAD(&clnt->cl_tasks); | ||
174 | spin_lock_init(&clnt->cl_lock); | ||
151 | 175 | ||
152 | if (!xprt_bound(clnt->cl_xprt)) | 176 | if (!xprt_bound(clnt->cl_xprt)) |
153 | clnt->cl_autobind = 1; | 177 | clnt->cl_autobind = 1; |
@@ -155,6 +179,8 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s | |||
155 | clnt->cl_rtt = &clnt->cl_rtt_default; | 179 | clnt->cl_rtt = &clnt->cl_rtt_default; |
156 | rpc_init_rtt(&clnt->cl_rtt_default, xprt->timeout.to_initval); | 180 | rpc_init_rtt(&clnt->cl_rtt_default, xprt->timeout.to_initval); |
157 | 181 | ||
182 | kref_init(&clnt->cl_kref); | ||
183 | |||
158 | err = rpc_setup_pipedir(clnt, program->pipe_dir_name); | 184 | err = rpc_setup_pipedir(clnt, program->pipe_dir_name); |
159 | if (err < 0) | 185 | if (err < 0) |
160 | goto out_no_path; | 186 | goto out_no_path; |
@@ -172,6 +198,7 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s | |||
172 | if (clnt->cl_nodelen > UNX_MAXNODENAME) | 198 | if (clnt->cl_nodelen > UNX_MAXNODENAME) |
173 | clnt->cl_nodelen = UNX_MAXNODENAME; | 199 | clnt->cl_nodelen = UNX_MAXNODENAME; |
174 | memcpy(clnt->cl_nodename, utsname()->nodename, clnt->cl_nodelen); | 200 | memcpy(clnt->cl_nodename, utsname()->nodename, clnt->cl_nodelen); |
201 | rpc_register_client(clnt); | ||
175 | return clnt; | 202 | return clnt; |
176 | 203 | ||
177 | out_no_auth: | 204 | out_no_auth: |
@@ -188,6 +215,8 @@ out_no_stats: | |||
188 | out_err: | 215 | out_err: |
189 | xprt_put(xprt); | 216 | xprt_put(xprt); |
190 | out_no_xprt: | 217 | out_no_xprt: |
218 | rpciod_down(); | ||
219 | out_no_rpciod: | ||
191 | return ERR_PTR(err); | 220 | return ERR_PTR(err); |
192 | } | 221 | } |
193 | 222 | ||
@@ -205,13 +234,32 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
205 | { | 234 | { |
206 | struct rpc_xprt *xprt; | 235 | struct rpc_xprt *xprt; |
207 | struct rpc_clnt *clnt; | 236 | struct rpc_clnt *clnt; |
237 | struct rpc_xprtsock_create xprtargs = { | ||
238 | .proto = args->protocol, | ||
239 | .srcaddr = args->saddress, | ||
240 | .dstaddr = args->address, | ||
241 | .addrlen = args->addrsize, | ||
242 | .timeout = args->timeout | ||
243 | }; | ||
244 | char servername[20]; | ||
208 | 245 | ||
209 | xprt = xprt_create_transport(args->protocol, args->address, | 246 | xprt = xprt_create_transport(&xprtargs); |
210 | args->addrsize, args->timeout); | ||
211 | if (IS_ERR(xprt)) | 247 | if (IS_ERR(xprt)) |
212 | return (struct rpc_clnt *)xprt; | 248 | return (struct rpc_clnt *)xprt; |
213 | 249 | ||
214 | /* | 250 | /* |
251 | * If the caller chooses not to specify a hostname, whip | ||
252 | * up a string representation of the passed-in address. | ||
253 | */ | ||
254 | if (args->servername == NULL) { | ||
255 | struct sockaddr_in *addr = | ||
256 | (struct sockaddr_in *) &args->address; | ||
257 | snprintf(servername, sizeof(servername), NIPQUAD_FMT, | ||
258 | NIPQUAD(addr->sin_addr.s_addr)); | ||
259 | args->servername = servername; | ||
260 | } | ||
261 | |||
262 | /* | ||
215 | * By default, kernel RPC client connects from a reserved port. | 263 | * By default, kernel RPC client connects from a reserved port. |
216 | * CAP_NET_BIND_SERVICE will not be set for unprivileged requesters, | 264 | * CAP_NET_BIND_SERVICE will not be set for unprivileged requesters, |
217 | * but it is always enabled for rpciod, which handles the connect | 265 | * but it is always enabled for rpciod, which handles the connect |
@@ -245,8 +293,6 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
245 | clnt->cl_intr = 1; | 293 | clnt->cl_intr = 1; |
246 | if (args->flags & RPC_CLNT_CREATE_AUTOBIND) | 294 | if (args->flags & RPC_CLNT_CREATE_AUTOBIND) |
247 | clnt->cl_autobind = 1; | 295 | clnt->cl_autobind = 1; |
248 | if (args->flags & RPC_CLNT_CREATE_ONESHOT) | ||
249 | clnt->cl_oneshot = 1; | ||
250 | if (args->flags & RPC_CLNT_CREATE_DISCRTRY) | 296 | if (args->flags & RPC_CLNT_CREATE_DISCRTRY) |
251 | clnt->cl_discrtry = 1; | 297 | clnt->cl_discrtry = 1; |
252 | 298 | ||
@@ -268,24 +314,25 @@ rpc_clone_client(struct rpc_clnt *clnt) | |||
268 | new = kmemdup(clnt, sizeof(*new), GFP_KERNEL); | 314 | new = kmemdup(clnt, sizeof(*new), GFP_KERNEL); |
269 | if (!new) | 315 | if (!new) |
270 | goto out_no_clnt; | 316 | goto out_no_clnt; |
271 | atomic_set(&new->cl_count, 1); | 317 | new->cl_parent = clnt; |
272 | atomic_set(&new->cl_users, 0); | 318 | /* Turn off autobind on clones */ |
319 | new->cl_autobind = 0; | ||
320 | INIT_LIST_HEAD(&new->cl_tasks); | ||
321 | spin_lock_init(&new->cl_lock); | ||
322 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); | ||
273 | new->cl_metrics = rpc_alloc_iostats(clnt); | 323 | new->cl_metrics = rpc_alloc_iostats(clnt); |
274 | if (new->cl_metrics == NULL) | 324 | if (new->cl_metrics == NULL) |
275 | goto out_no_stats; | 325 | goto out_no_stats; |
326 | kref_init(&new->cl_kref); | ||
276 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); | 327 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); |
277 | if (err != 0) | 328 | if (err != 0) |
278 | goto out_no_path; | 329 | goto out_no_path; |
279 | new->cl_parent = clnt; | ||
280 | atomic_inc(&clnt->cl_count); | ||
281 | new->cl_xprt = xprt_get(clnt->cl_xprt); | ||
282 | /* Turn off autobind on clones */ | ||
283 | new->cl_autobind = 0; | ||
284 | new->cl_oneshot = 0; | ||
285 | new->cl_dead = 0; | ||
286 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); | ||
287 | if (new->cl_auth) | 330 | if (new->cl_auth) |
288 | atomic_inc(&new->cl_auth->au_count); | 331 | atomic_inc(&new->cl_auth->au_count); |
332 | xprt_get(clnt->cl_xprt); | ||
333 | kref_get(&clnt->cl_kref); | ||
334 | rpc_register_client(new); | ||
335 | rpciod_up(); | ||
289 | return new; | 336 | return new; |
290 | out_no_path: | 337 | out_no_path: |
291 | rpc_free_iostats(new->cl_metrics); | 338 | rpc_free_iostats(new->cl_metrics); |
@@ -298,86 +345,86 @@ out_no_clnt: | |||
298 | 345 | ||
299 | /* | 346 | /* |
300 | * Properly shut down an RPC client, terminating all outstanding | 347 | * Properly shut down an RPC client, terminating all outstanding |
301 | * requests. Note that we must be certain that cl_oneshot and | 348 | * requests. |
302 | * cl_dead are cleared, or else the client would be destroyed | ||
303 | * when the last task releases it. | ||
304 | */ | 349 | */ |
305 | int | 350 | void rpc_shutdown_client(struct rpc_clnt *clnt) |
306 | rpc_shutdown_client(struct rpc_clnt *clnt) | ||
307 | { | 351 | { |
308 | dprintk("RPC: shutting down %s client for %s, tasks=%d\n", | 352 | dprintk("RPC: shutting down %s client for %s\n", |
309 | clnt->cl_protname, clnt->cl_server, | 353 | clnt->cl_protname, clnt->cl_server); |
310 | atomic_read(&clnt->cl_users)); | 354 | |
311 | 355 | while (!list_empty(&clnt->cl_tasks)) { | |
312 | while (atomic_read(&clnt->cl_users) > 0) { | ||
313 | /* Don't let rpc_release_client destroy us */ | ||
314 | clnt->cl_oneshot = 0; | ||
315 | clnt->cl_dead = 0; | ||
316 | rpc_killall_tasks(clnt); | 356 | rpc_killall_tasks(clnt); |
317 | wait_event_timeout(destroy_wait, | 357 | wait_event_timeout(destroy_wait, |
318 | !atomic_read(&clnt->cl_users), 1*HZ); | 358 | list_empty(&clnt->cl_tasks), 1*HZ); |
319 | } | ||
320 | |||
321 | if (atomic_read(&clnt->cl_users) < 0) { | ||
322 | printk(KERN_ERR "RPC: rpc_shutdown_client clnt %p tasks=%d\n", | ||
323 | clnt, atomic_read(&clnt->cl_users)); | ||
324 | #ifdef RPC_DEBUG | ||
325 | rpc_show_tasks(); | ||
326 | #endif | ||
327 | BUG(); | ||
328 | } | 359 | } |
329 | 360 | ||
330 | return rpc_destroy_client(clnt); | 361 | rpc_release_client(clnt); |
331 | } | 362 | } |
332 | 363 | ||
333 | /* | 364 | /* |
334 | * Delete an RPC client | 365 | * Free an RPC client |
335 | */ | 366 | */ |
336 | int | 367 | static void |
337 | rpc_destroy_client(struct rpc_clnt *clnt) | 368 | rpc_free_client(struct kref *kref) |
338 | { | 369 | { |
339 | if (!atomic_dec_and_test(&clnt->cl_count)) | 370 | struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref); |
340 | return 1; | ||
341 | BUG_ON(atomic_read(&clnt->cl_users) != 0); | ||
342 | 371 | ||
343 | dprintk("RPC: destroying %s client for %s\n", | 372 | dprintk("RPC: destroying %s client for %s\n", |
344 | clnt->cl_protname, clnt->cl_server); | 373 | clnt->cl_protname, clnt->cl_server); |
345 | if (clnt->cl_auth) { | ||
346 | rpcauth_destroy(clnt->cl_auth); | ||
347 | clnt->cl_auth = NULL; | ||
348 | } | ||
349 | if (!IS_ERR(clnt->cl_dentry)) { | 374 | if (!IS_ERR(clnt->cl_dentry)) { |
350 | rpc_rmdir(clnt->cl_dentry); | 375 | rpc_rmdir(clnt->cl_dentry); |
351 | rpc_put_mount(); | 376 | rpc_put_mount(); |
352 | } | 377 | } |
353 | if (clnt->cl_parent != clnt) { | 378 | if (clnt->cl_parent != clnt) { |
354 | rpc_destroy_client(clnt->cl_parent); | 379 | rpc_release_client(clnt->cl_parent); |
355 | goto out_free; | 380 | goto out_free; |
356 | } | 381 | } |
357 | if (clnt->cl_server != clnt->cl_inline_name) | 382 | if (clnt->cl_server != clnt->cl_inline_name) |
358 | kfree(clnt->cl_server); | 383 | kfree(clnt->cl_server); |
359 | out_free: | 384 | out_free: |
385 | rpc_unregister_client(clnt); | ||
360 | rpc_free_iostats(clnt->cl_metrics); | 386 | rpc_free_iostats(clnt->cl_metrics); |
361 | clnt->cl_metrics = NULL; | 387 | clnt->cl_metrics = NULL; |
362 | xprt_put(clnt->cl_xprt); | 388 | xprt_put(clnt->cl_xprt); |
389 | rpciod_down(); | ||
363 | kfree(clnt); | 390 | kfree(clnt); |
364 | return 0; | ||
365 | } | 391 | } |
366 | 392 | ||
367 | /* | 393 | /* |
368 | * Release an RPC client | 394 | * Free an RPC client |
395 | */ | ||
396 | static void | ||
397 | rpc_free_auth(struct kref *kref) | ||
398 | { | ||
399 | struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref); | ||
400 | |||
401 | if (clnt->cl_auth == NULL) { | ||
402 | rpc_free_client(kref); | ||
403 | return; | ||
404 | } | ||
405 | |||
406 | /* | ||
407 | * Note: RPCSEC_GSS may need to send NULL RPC calls in order to | ||
408 | * release remaining GSS contexts. This mechanism ensures | ||
409 | * that it can do so safely. | ||
410 | */ | ||
411 | kref_init(kref); | ||
412 | rpcauth_release(clnt->cl_auth); | ||
413 | clnt->cl_auth = NULL; | ||
414 | kref_put(kref, rpc_free_client); | ||
415 | } | ||
416 | |||
417 | /* | ||
418 | * Release reference to the RPC client | ||
369 | */ | 419 | */ |
370 | void | 420 | void |
371 | rpc_release_client(struct rpc_clnt *clnt) | 421 | rpc_release_client(struct rpc_clnt *clnt) |
372 | { | 422 | { |
373 | dprintk("RPC: rpc_release_client(%p, %d)\n", | 423 | dprintk("RPC: rpc_release_client(%p)\n", clnt); |
374 | clnt, atomic_read(&clnt->cl_users)); | ||
375 | 424 | ||
376 | if (!atomic_dec_and_test(&clnt->cl_users)) | 425 | if (list_empty(&clnt->cl_tasks)) |
377 | return; | 426 | wake_up(&destroy_wait); |
378 | wake_up(&destroy_wait); | 427 | kref_put(&clnt->cl_kref, rpc_free_auth); |
379 | if (clnt->cl_oneshot || clnt->cl_dead) | ||
380 | rpc_destroy_client(clnt); | ||
381 | } | 428 | } |
382 | 429 | ||
383 | /** | 430 | /** |
@@ -468,82 +515,96 @@ void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset) | |||
468 | rpc_restore_sigmask(oldset); | 515 | rpc_restore_sigmask(oldset); |
469 | } | 516 | } |
470 | 517 | ||
471 | /* | 518 | static |
472 | * New rpc_call implementation | 519 | struct rpc_task *rpc_do_run_task(struct rpc_clnt *clnt, |
520 | struct rpc_message *msg, | ||
521 | int flags, | ||
522 | const struct rpc_call_ops *ops, | ||
523 | void *data) | ||
524 | { | ||
525 | struct rpc_task *task, *ret; | ||
526 | sigset_t oldset; | ||
527 | |||
528 | task = rpc_new_task(clnt, flags, ops, data); | ||
529 | if (task == NULL) { | ||
530 | rpc_release_calldata(ops, data); | ||
531 | return ERR_PTR(-ENOMEM); | ||
532 | } | ||
533 | |||
534 | /* Mask signals on synchronous RPC calls and RPCSEC_GSS upcalls */ | ||
535 | rpc_task_sigmask(task, &oldset); | ||
536 | if (msg != NULL) { | ||
537 | rpc_call_setup(task, msg, 0); | ||
538 | if (task->tk_status != 0) { | ||
539 | ret = ERR_PTR(task->tk_status); | ||
540 | rpc_put_task(task); | ||
541 | goto out; | ||
542 | } | ||
543 | } | ||
544 | atomic_inc(&task->tk_count); | ||
545 | rpc_execute(task); | ||
546 | ret = task; | ||
547 | out: | ||
548 | rpc_restore_sigmask(&oldset); | ||
549 | return ret; | ||
550 | } | ||
551 | |||
552 | /** | ||
553 | * rpc_call_sync - Perform a synchronous RPC call | ||
554 | * @clnt: pointer to RPC client | ||
555 | * @msg: RPC call parameters | ||
556 | * @flags: RPC call flags | ||
473 | */ | 557 | */ |
474 | int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) | 558 | int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) |
475 | { | 559 | { |
476 | struct rpc_task *task; | 560 | struct rpc_task *task; |
477 | sigset_t oldset; | 561 | int status; |
478 | int status; | ||
479 | |||
480 | /* If this client is slain all further I/O fails */ | ||
481 | if (clnt->cl_dead) | ||
482 | return -EIO; | ||
483 | 562 | ||
484 | BUG_ON(flags & RPC_TASK_ASYNC); | 563 | BUG_ON(flags & RPC_TASK_ASYNC); |
485 | 564 | ||
486 | task = rpc_new_task(clnt, flags, &rpc_default_ops, NULL); | 565 | task = rpc_do_run_task(clnt, msg, flags, &rpc_default_ops, NULL); |
487 | if (task == NULL) | 566 | if (IS_ERR(task)) |
488 | return -ENOMEM; | 567 | return PTR_ERR(task); |
489 | |||
490 | /* Mask signals on RPC calls _and_ GSS_AUTH upcalls */ | ||
491 | rpc_task_sigmask(task, &oldset); | ||
492 | |||
493 | /* Set up the call info struct and execute the task */ | ||
494 | rpc_call_setup(task, msg, 0); | ||
495 | if (task->tk_status == 0) { | ||
496 | atomic_inc(&task->tk_count); | ||
497 | rpc_execute(task); | ||
498 | } | ||
499 | status = task->tk_status; | 568 | status = task->tk_status; |
500 | rpc_put_task(task); | 569 | rpc_put_task(task); |
501 | rpc_restore_sigmask(&oldset); | ||
502 | return status; | 570 | return status; |
503 | } | 571 | } |
504 | 572 | ||
505 | /* | 573 | /** |
506 | * New rpc_call implementation | 574 | * rpc_call_async - Perform an asynchronous RPC call |
575 | * @clnt: pointer to RPC client | ||
576 | * @msg: RPC call parameters | ||
577 | * @flags: RPC call flags | ||
578 | * @ops: RPC call ops | ||
579 | * @data: user call data | ||
507 | */ | 580 | */ |
508 | int | 581 | int |
509 | rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, | 582 | rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, |
510 | const struct rpc_call_ops *tk_ops, void *data) | 583 | const struct rpc_call_ops *tk_ops, void *data) |
511 | { | 584 | { |
512 | struct rpc_task *task; | 585 | struct rpc_task *task; |
513 | sigset_t oldset; | ||
514 | int status; | ||
515 | |||
516 | /* If this client is slain all further I/O fails */ | ||
517 | status = -EIO; | ||
518 | if (clnt->cl_dead) | ||
519 | goto out_release; | ||
520 | |||
521 | flags |= RPC_TASK_ASYNC; | ||
522 | |||
523 | /* Create/initialize a new RPC task */ | ||
524 | status = -ENOMEM; | ||
525 | if (!(task = rpc_new_task(clnt, flags, tk_ops, data))) | ||
526 | goto out_release; | ||
527 | |||
528 | /* Mask signals on GSS_AUTH upcalls */ | ||
529 | rpc_task_sigmask(task, &oldset); | ||
530 | 586 | ||
531 | rpc_call_setup(task, msg, 0); | 587 | task = rpc_do_run_task(clnt, msg, flags|RPC_TASK_ASYNC, tk_ops, data); |
532 | 588 | if (IS_ERR(task)) | |
533 | /* Set up the call info struct and execute the task */ | 589 | return PTR_ERR(task); |
534 | status = task->tk_status; | 590 | rpc_put_task(task); |
535 | if (status == 0) | 591 | return 0; |
536 | rpc_execute(task); | ||
537 | else | ||
538 | rpc_put_task(task); | ||
539 | |||
540 | rpc_restore_sigmask(&oldset); | ||
541 | return status; | ||
542 | out_release: | ||
543 | rpc_release_calldata(tk_ops, data); | ||
544 | return status; | ||
545 | } | 592 | } |
546 | 593 | ||
594 | /** | ||
595 | * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it | ||
596 | * @clnt: pointer to RPC client | ||
597 | * @flags: RPC flags | ||
598 | * @ops: RPC call ops | ||
599 | * @data: user call data | ||
600 | */ | ||
601 | struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags, | ||
602 | const struct rpc_call_ops *tk_ops, | ||
603 | void *data) | ||
604 | { | ||
605 | return rpc_do_run_task(clnt, NULL, flags, tk_ops, data); | ||
606 | } | ||
607 | EXPORT_SYMBOL(rpc_run_task); | ||
547 | 608 | ||
548 | void | 609 | void |
549 | rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags) | 610 | rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags) |
@@ -745,7 +806,7 @@ call_reserveresult(struct rpc_task *task) | |||
745 | static void | 806 | static void |
746 | call_allocate(struct rpc_task *task) | 807 | call_allocate(struct rpc_task *task) |
747 | { | 808 | { |
748 | unsigned int slack = task->tk_auth->au_cslack; | 809 | unsigned int slack = task->tk_msg.rpc_cred->cr_auth->au_cslack; |
749 | struct rpc_rqst *req = task->tk_rqstp; | 810 | struct rpc_rqst *req = task->tk_rqstp; |
750 | struct rpc_xprt *xprt = task->tk_xprt; | 811 | struct rpc_xprt *xprt = task->tk_xprt; |
751 | struct rpc_procinfo *proc = task->tk_msg.rpc_proc; | 812 | struct rpc_procinfo *proc = task->tk_msg.rpc_proc; |
@@ -843,10 +904,8 @@ call_encode(struct rpc_task *task) | |||
843 | if (encode == NULL) | 904 | if (encode == NULL) |
844 | return; | 905 | return; |
845 | 906 | ||
846 | lock_kernel(); | ||
847 | task->tk_status = rpcauth_wrap_req(task, encode, req, p, | 907 | task->tk_status = rpcauth_wrap_req(task, encode, req, p, |
848 | task->tk_msg.rpc_argp); | 908 | task->tk_msg.rpc_argp); |
849 | unlock_kernel(); | ||
850 | if (task->tk_status == -ENOMEM) { | 909 | if (task->tk_status == -ENOMEM) { |
851 | /* XXX: Is this sane? */ | 910 | /* XXX: Is this sane? */ |
852 | rpc_delay(task, 3*HZ); | 911 | rpc_delay(task, 3*HZ); |
@@ -1177,10 +1236,8 @@ call_decode(struct rpc_task *task) | |||
1177 | task->tk_action = rpc_exit_task; | 1236 | task->tk_action = rpc_exit_task; |
1178 | 1237 | ||
1179 | if (decode) { | 1238 | if (decode) { |
1180 | lock_kernel(); | ||
1181 | task->tk_status = rpcauth_unwrap_resp(task, decode, req, p, | 1239 | task->tk_status = rpcauth_unwrap_resp(task, decode, req, p, |
1182 | task->tk_msg.rpc_resp); | 1240 | task->tk_msg.rpc_resp); |
1183 | unlock_kernel(); | ||
1184 | } | 1241 | } |
1185 | dprintk("RPC: %5u call_decode result %d\n", task->tk_pid, | 1242 | dprintk("RPC: %5u call_decode result %d\n", task->tk_pid, |
1186 | task->tk_status); | 1243 | task->tk_status); |
@@ -1273,9 +1330,9 @@ call_verify(struct rpc_task *task) | |||
1273 | * - if it isn't pointer subtraction in the NFS client may give | 1330 | * - if it isn't pointer subtraction in the NFS client may give |
1274 | * undefined results | 1331 | * undefined results |
1275 | */ | 1332 | */ |
1276 | printk(KERN_WARNING | 1333 | dprintk("RPC: %5u %s: XDR representation not a multiple of" |
1277 | "call_verify: XDR representation not a multiple of" | 1334 | " 4 bytes: 0x%x\n", task->tk_pid, __FUNCTION__, |
1278 | " 4 bytes: 0x%x\n", task->tk_rqstp->rq_rcv_buf.len); | 1335 | task->tk_rqstp->rq_rcv_buf.len); |
1279 | goto out_eio; | 1336 | goto out_eio; |
1280 | } | 1337 | } |
1281 | if ((len -= 3) < 0) | 1338 | if ((len -= 3) < 0) |
@@ -1283,7 +1340,8 @@ call_verify(struct rpc_task *task) | |||
1283 | p += 1; /* skip XID */ | 1340 | p += 1; /* skip XID */ |
1284 | 1341 | ||
1285 | if ((n = ntohl(*p++)) != RPC_REPLY) { | 1342 | if ((n = ntohl(*p++)) != RPC_REPLY) { |
1286 | printk(KERN_WARNING "call_verify: not an RPC reply: %x\n", n); | 1343 | dprintk("RPC: %5u %s: not an RPC reply: %x\n", |
1344 | task->tk_pid, __FUNCTION__, n); | ||
1287 | goto out_garbage; | 1345 | goto out_garbage; |
1288 | } | 1346 | } |
1289 | if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) { | 1347 | if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) { |
@@ -1334,7 +1392,8 @@ call_verify(struct rpc_task *task) | |||
1334 | "authentication.\n", task->tk_client->cl_server); | 1392 | "authentication.\n", task->tk_client->cl_server); |
1335 | break; | 1393 | break; |
1336 | default: | 1394 | default: |
1337 | printk(KERN_WARNING "call_verify: unknown auth error: %x\n", n); | 1395 | dprintk("RPC: %5u %s: unknown auth error: %x\n", |
1396 | task->tk_pid, __FUNCTION__, n); | ||
1338 | error = -EIO; | 1397 | error = -EIO; |
1339 | } | 1398 | } |
1340 | dprintk("RPC: %5u %s: call rejected %d\n", | 1399 | dprintk("RPC: %5u %s: call rejected %d\n", |
@@ -1342,7 +1401,8 @@ call_verify(struct rpc_task *task) | |||
1342 | goto out_err; | 1401 | goto out_err; |
1343 | } | 1402 | } |
1344 | if (!(p = rpcauth_checkverf(task, p))) { | 1403 | if (!(p = rpcauth_checkverf(task, p))) { |
1345 | printk(KERN_WARNING "call_verify: auth check failed\n"); | 1404 | dprintk("RPC: %5u %s: auth check failed\n", |
1405 | task->tk_pid, __FUNCTION__); | ||
1346 | goto out_garbage; /* bad verifier, retry */ | 1406 | goto out_garbage; /* bad verifier, retry */ |
1347 | } | 1407 | } |
1348 | len = p - (__be32 *)iov->iov_base - 1; | 1408 | len = p - (__be32 *)iov->iov_base - 1; |
@@ -1381,7 +1441,8 @@ call_verify(struct rpc_task *task) | |||
1381 | task->tk_pid, __FUNCTION__); | 1441 | task->tk_pid, __FUNCTION__); |
1382 | break; /* retry */ | 1442 | break; /* retry */ |
1383 | default: | 1443 | default: |
1384 | printk(KERN_WARNING "call_verify: server accept status: %x\n", n); | 1444 | dprintk("RPC: %5u %s: server accept status: %x\n", |
1445 | task->tk_pid, __FUNCTION__, n); | ||
1385 | /* Also retry */ | 1446 | /* Also retry */ |
1386 | } | 1447 | } |
1387 | 1448 | ||
@@ -1395,14 +1456,16 @@ out_garbage: | |||
1395 | out_retry: | 1456 | out_retry: |
1396 | return ERR_PTR(-EAGAIN); | 1457 | return ERR_PTR(-EAGAIN); |
1397 | } | 1458 | } |
1398 | printk(KERN_WARNING "RPC %s: retry failed, exit EIO\n", __FUNCTION__); | ||
1399 | out_eio: | 1459 | out_eio: |
1400 | error = -EIO; | 1460 | error = -EIO; |
1401 | out_err: | 1461 | out_err: |
1402 | rpc_exit(task, error); | 1462 | rpc_exit(task, error); |
1463 | dprintk("RPC: %5u %s: call failed with error %d\n", task->tk_pid, | ||
1464 | __FUNCTION__, error); | ||
1403 | return ERR_PTR(error); | 1465 | return ERR_PTR(error); |
1404 | out_overflow: | 1466 | out_overflow: |
1405 | printk(KERN_WARNING "RPC %s: server reply was truncated.\n", __FUNCTION__); | 1467 | dprintk("RPC: %5u %s: server reply was truncated.\n", task->tk_pid, |
1468 | __FUNCTION__); | ||
1406 | goto out_garbage; | 1469 | goto out_garbage; |
1407 | } | 1470 | } |
1408 | 1471 | ||
@@ -1421,7 +1484,7 @@ static struct rpc_procinfo rpcproc_null = { | |||
1421 | .p_decode = rpcproc_decode_null, | 1484 | .p_decode = rpcproc_decode_null, |
1422 | }; | 1485 | }; |
1423 | 1486 | ||
1424 | int rpc_ping(struct rpc_clnt *clnt, int flags) | 1487 | static int rpc_ping(struct rpc_clnt *clnt, int flags) |
1425 | { | 1488 | { |
1426 | struct rpc_message msg = { | 1489 | struct rpc_message msg = { |
1427 | .rpc_proc = &rpcproc_null, | 1490 | .rpc_proc = &rpcproc_null, |
@@ -1432,3 +1495,51 @@ int rpc_ping(struct rpc_clnt *clnt, int flags) | |||
1432 | put_rpccred(msg.rpc_cred); | 1495 | put_rpccred(msg.rpc_cred); |
1433 | return err; | 1496 | return err; |
1434 | } | 1497 | } |
1498 | |||
1499 | struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred, int flags) | ||
1500 | { | ||
1501 | struct rpc_message msg = { | ||
1502 | .rpc_proc = &rpcproc_null, | ||
1503 | .rpc_cred = cred, | ||
1504 | }; | ||
1505 | return rpc_do_run_task(clnt, &msg, flags, &rpc_default_ops, NULL); | ||
1506 | } | ||
1507 | EXPORT_SYMBOL(rpc_call_null); | ||
1508 | |||
1509 | #ifdef RPC_DEBUG | ||
1510 | void rpc_show_tasks(void) | ||
1511 | { | ||
1512 | struct rpc_clnt *clnt; | ||
1513 | struct rpc_task *t; | ||
1514 | |||
1515 | spin_lock(&rpc_client_lock); | ||
1516 | if (list_empty(&all_clients)) | ||
1517 | goto out; | ||
1518 | printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout " | ||
1519 | "-rpcwait -action- ---ops--\n"); | ||
1520 | list_for_each_entry(clnt, &all_clients, cl_clients) { | ||
1521 | if (list_empty(&clnt->cl_tasks)) | ||
1522 | continue; | ||
1523 | spin_lock(&clnt->cl_lock); | ||
1524 | list_for_each_entry(t, &clnt->cl_tasks, tk_task) { | ||
1525 | const char *rpc_waitq = "none"; | ||
1526 | |||
1527 | if (RPC_IS_QUEUED(t)) | ||
1528 | rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq); | ||
1529 | |||
1530 | printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n", | ||
1531 | t->tk_pid, | ||
1532 | (t->tk_msg.rpc_proc ? t->tk_msg.rpc_proc->p_proc : -1), | ||
1533 | t->tk_flags, t->tk_status, | ||
1534 | t->tk_client, | ||
1535 | (t->tk_client ? t->tk_client->cl_prog : 0), | ||
1536 | t->tk_rqstp, t->tk_timeout, | ||
1537 | rpc_waitq, | ||
1538 | t->tk_action, t->tk_ops); | ||
1539 | } | ||
1540 | spin_unlock(&clnt->cl_lock); | ||
1541 | } | ||
1542 | out: | ||
1543 | spin_unlock(&rpc_client_lock); | ||
1544 | } | ||
1545 | #endif | ||
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 5887457dc936..e787b6a43eee 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -344,7 +344,7 @@ rpc_info_open(struct inode *inode, struct file *file) | |||
344 | mutex_lock(&inode->i_mutex); | 344 | mutex_lock(&inode->i_mutex); |
345 | clnt = RPC_I(inode)->private; | 345 | clnt = RPC_I(inode)->private; |
346 | if (clnt) { | 346 | if (clnt) { |
347 | atomic_inc(&clnt->cl_users); | 347 | kref_get(&clnt->cl_kref); |
348 | m->private = clnt; | 348 | m->private = clnt; |
349 | } else { | 349 | } else { |
350 | single_release(inode, file); | 350 | single_release(inode, file); |
@@ -448,6 +448,15 @@ void rpc_put_mount(void) | |||
448 | simple_release_fs(&rpc_mount, &rpc_mount_count); | 448 | simple_release_fs(&rpc_mount, &rpc_mount_count); |
449 | } | 449 | } |
450 | 450 | ||
451 | static int rpc_delete_dentry(struct dentry *dentry) | ||
452 | { | ||
453 | return 1; | ||
454 | } | ||
455 | |||
456 | static struct dentry_operations rpc_dentry_operations = { | ||
457 | .d_delete = rpc_delete_dentry, | ||
458 | }; | ||
459 | |||
451 | static int | 460 | static int |
452 | rpc_lookup_parent(char *path, struct nameidata *nd) | 461 | rpc_lookup_parent(char *path, struct nameidata *nd) |
453 | { | 462 | { |
@@ -506,7 +515,7 @@ rpc_get_inode(struct super_block *sb, int mode) | |||
506 | * FIXME: This probably has races. | 515 | * FIXME: This probably has races. |
507 | */ | 516 | */ |
508 | static void | 517 | static void |
509 | rpc_depopulate(struct dentry *parent) | 518 | rpc_depopulate(struct dentry *parent, int start, int eof) |
510 | { | 519 | { |
511 | struct inode *dir = parent->d_inode; | 520 | struct inode *dir = parent->d_inode; |
512 | struct list_head *pos, *next; | 521 | struct list_head *pos, *next; |
@@ -518,6 +527,10 @@ repeat: | |||
518 | spin_lock(&dcache_lock); | 527 | spin_lock(&dcache_lock); |
519 | list_for_each_safe(pos, next, &parent->d_subdirs) { | 528 | list_for_each_safe(pos, next, &parent->d_subdirs) { |
520 | dentry = list_entry(pos, struct dentry, d_u.d_child); | 529 | dentry = list_entry(pos, struct dentry, d_u.d_child); |
530 | if (!dentry->d_inode || | ||
531 | dentry->d_inode->i_ino < start || | ||
532 | dentry->d_inode->i_ino >= eof) | ||
533 | continue; | ||
521 | spin_lock(&dentry->d_lock); | 534 | spin_lock(&dentry->d_lock); |
522 | if (!d_unhashed(dentry)) { | 535 | if (!d_unhashed(dentry)) { |
523 | dget_locked(dentry); | 536 | dget_locked(dentry); |
@@ -533,11 +546,11 @@ repeat: | |||
533 | if (n) { | 546 | if (n) { |
534 | do { | 547 | do { |
535 | dentry = dvec[--n]; | 548 | dentry = dvec[--n]; |
536 | if (dentry->d_inode) { | 549 | if (S_ISREG(dentry->d_inode->i_mode)) |
537 | rpc_close_pipes(dentry->d_inode); | ||
538 | simple_unlink(dir, dentry); | 550 | simple_unlink(dir, dentry); |
539 | } | 551 | else if (S_ISDIR(dentry->d_inode->i_mode)) |
540 | inode_dir_notify(dir, DN_DELETE); | 552 | simple_rmdir(dir, dentry); |
553 | d_delete(dentry); | ||
541 | dput(dentry); | 554 | dput(dentry); |
542 | } while (n); | 555 | } while (n); |
543 | goto repeat; | 556 | goto repeat; |
@@ -560,6 +573,7 @@ rpc_populate(struct dentry *parent, | |||
560 | dentry = d_alloc_name(parent, files[i].name); | 573 | dentry = d_alloc_name(parent, files[i].name); |
561 | if (!dentry) | 574 | if (!dentry) |
562 | goto out_bad; | 575 | goto out_bad; |
576 | dentry->d_op = &rpc_dentry_operations; | ||
563 | mode = files[i].mode; | 577 | mode = files[i].mode; |
564 | inode = rpc_get_inode(dir->i_sb, mode); | 578 | inode = rpc_get_inode(dir->i_sb, mode); |
565 | if (!inode) { | 579 | if (!inode) { |
@@ -607,21 +621,14 @@ static int | |||
607 | __rpc_rmdir(struct inode *dir, struct dentry *dentry) | 621 | __rpc_rmdir(struct inode *dir, struct dentry *dentry) |
608 | { | 622 | { |
609 | int error; | 623 | int error; |
610 | 624 | error = simple_rmdir(dir, dentry); | |
611 | shrink_dcache_parent(dentry); | 625 | if (!error) |
612 | if (d_unhashed(dentry)) | 626 | d_delete(dentry); |
613 | return 0; | 627 | return error; |
614 | if ((error = simple_rmdir(dir, dentry)) != 0) | ||
615 | return error; | ||
616 | if (!error) { | ||
617 | inode_dir_notify(dir, DN_DELETE); | ||
618 | d_drop(dentry); | ||
619 | } | ||
620 | return 0; | ||
621 | } | 628 | } |
622 | 629 | ||
623 | static struct dentry * | 630 | static struct dentry * |
624 | rpc_lookup_create(struct dentry *parent, const char *name, int len) | 631 | rpc_lookup_create(struct dentry *parent, const char *name, int len, int exclusive) |
625 | { | 632 | { |
626 | struct inode *dir = parent->d_inode; | 633 | struct inode *dir = parent->d_inode; |
627 | struct dentry *dentry; | 634 | struct dentry *dentry; |
@@ -630,7 +637,9 @@ rpc_lookup_create(struct dentry *parent, const char *name, int len) | |||
630 | dentry = lookup_one_len(name, parent, len); | 637 | dentry = lookup_one_len(name, parent, len); |
631 | if (IS_ERR(dentry)) | 638 | if (IS_ERR(dentry)) |
632 | goto out_err; | 639 | goto out_err; |
633 | if (dentry->d_inode) { | 640 | if (!dentry->d_inode) |
641 | dentry->d_op = &rpc_dentry_operations; | ||
642 | else if (exclusive) { | ||
634 | dput(dentry); | 643 | dput(dentry); |
635 | dentry = ERR_PTR(-EEXIST); | 644 | dentry = ERR_PTR(-EEXIST); |
636 | goto out_err; | 645 | goto out_err; |
@@ -649,7 +658,7 @@ rpc_lookup_negative(char *path, struct nameidata *nd) | |||
649 | 658 | ||
650 | if ((error = rpc_lookup_parent(path, nd)) != 0) | 659 | if ((error = rpc_lookup_parent(path, nd)) != 0) |
651 | return ERR_PTR(error); | 660 | return ERR_PTR(error); |
652 | dentry = rpc_lookup_create(nd->dentry, nd->last.name, nd->last.len); | 661 | dentry = rpc_lookup_create(nd->dentry, nd->last.name, nd->last.len, 1); |
653 | if (IS_ERR(dentry)) | 662 | if (IS_ERR(dentry)) |
654 | rpc_release_path(nd); | 663 | rpc_release_path(nd); |
655 | return dentry; | 664 | return dentry; |
@@ -681,7 +690,7 @@ out: | |||
681 | rpc_release_path(&nd); | 690 | rpc_release_path(&nd); |
682 | return dentry; | 691 | return dentry; |
683 | err_depopulate: | 692 | err_depopulate: |
684 | rpc_depopulate(dentry); | 693 | rpc_depopulate(dentry, RPCAUTH_info, RPCAUTH_EOF); |
685 | __rpc_rmdir(dir, dentry); | 694 | __rpc_rmdir(dir, dentry); |
686 | err_dput: | 695 | err_dput: |
687 | dput(dentry); | 696 | dput(dentry); |
@@ -701,7 +710,7 @@ rpc_rmdir(struct dentry *dentry) | |||
701 | parent = dget_parent(dentry); | 710 | parent = dget_parent(dentry); |
702 | dir = parent->d_inode; | 711 | dir = parent->d_inode; |
703 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | 712 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); |
704 | rpc_depopulate(dentry); | 713 | rpc_depopulate(dentry, RPCAUTH_info, RPCAUTH_EOF); |
705 | error = __rpc_rmdir(dir, dentry); | 714 | error = __rpc_rmdir(dir, dentry); |
706 | dput(dentry); | 715 | dput(dentry); |
707 | mutex_unlock(&dir->i_mutex); | 716 | mutex_unlock(&dir->i_mutex); |
@@ -716,10 +725,21 @@ rpc_mkpipe(struct dentry *parent, const char *name, void *private, struct rpc_pi | |||
716 | struct inode *dir, *inode; | 725 | struct inode *dir, *inode; |
717 | struct rpc_inode *rpci; | 726 | struct rpc_inode *rpci; |
718 | 727 | ||
719 | dentry = rpc_lookup_create(parent, name, strlen(name)); | 728 | dentry = rpc_lookup_create(parent, name, strlen(name), 0); |
720 | if (IS_ERR(dentry)) | 729 | if (IS_ERR(dentry)) |
721 | return dentry; | 730 | return dentry; |
722 | dir = parent->d_inode; | 731 | dir = parent->d_inode; |
732 | if (dentry->d_inode) { | ||
733 | rpci = RPC_I(dentry->d_inode); | ||
734 | if (rpci->private != private || | ||
735 | rpci->ops != ops || | ||
736 | rpci->flags != flags) { | ||
737 | dput (dentry); | ||
738 | dentry = ERR_PTR(-EBUSY); | ||
739 | } | ||
740 | rpci->nkern_readwriters++; | ||
741 | goto out; | ||
742 | } | ||
723 | inode = rpc_get_inode(dir->i_sb, S_IFIFO | S_IRUSR | S_IWUSR); | 743 | inode = rpc_get_inode(dir->i_sb, S_IFIFO | S_IRUSR | S_IWUSR); |
724 | if (!inode) | 744 | if (!inode) |
725 | goto err_dput; | 745 | goto err_dput; |
@@ -730,6 +750,7 @@ rpc_mkpipe(struct dentry *parent, const char *name, void *private, struct rpc_pi | |||
730 | rpci->private = private; | 750 | rpci->private = private; |
731 | rpci->flags = flags; | 751 | rpci->flags = flags; |
732 | rpci->ops = ops; | 752 | rpci->ops = ops; |
753 | rpci->nkern_readwriters = 1; | ||
733 | inode_dir_notify(dir, DN_CREATE); | 754 | inode_dir_notify(dir, DN_CREATE); |
734 | dget(dentry); | 755 | dget(dentry); |
735 | out: | 756 | out: |
@@ -754,13 +775,11 @@ rpc_unlink(struct dentry *dentry) | |||
754 | parent = dget_parent(dentry); | 775 | parent = dget_parent(dentry); |
755 | dir = parent->d_inode; | 776 | dir = parent->d_inode; |
756 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | 777 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); |
757 | if (!d_unhashed(dentry)) { | 778 | if (--RPC_I(dentry->d_inode)->nkern_readwriters == 0) { |
758 | d_drop(dentry); | 779 | rpc_close_pipes(dentry->d_inode); |
759 | if (dentry->d_inode) { | 780 | error = simple_unlink(dir, dentry); |
760 | rpc_close_pipes(dentry->d_inode); | 781 | if (!error) |
761 | error = simple_unlink(dir, dentry); | 782 | d_delete(dentry); |
762 | } | ||
763 | inode_dir_notify(dir, DN_DELETE); | ||
764 | } | 783 | } |
765 | dput(dentry); | 784 | dput(dentry); |
766 | mutex_unlock(&dir->i_mutex); | 785 | mutex_unlock(&dir->i_mutex); |
@@ -833,6 +852,7 @@ init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) | |||
833 | rpci->nreaders = 0; | 852 | rpci->nreaders = 0; |
834 | rpci->nwriters = 0; | 853 | rpci->nwriters = 0; |
835 | INIT_LIST_HEAD(&rpci->in_upcall); | 854 | INIT_LIST_HEAD(&rpci->in_upcall); |
855 | INIT_LIST_HEAD(&rpci->in_downcall); | ||
836 | INIT_LIST_HEAD(&rpci->pipe); | 856 | INIT_LIST_HEAD(&rpci->pipe); |
837 | rpci->pipelen = 0; | 857 | rpci->pipelen = 0; |
838 | init_waitqueue_head(&rpci->waitq); | 858 | init_waitqueue_head(&rpci->waitq); |
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index 6c7aa8a1f0c6..d1740dbab991 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c | |||
@@ -12,6 +12,8 @@ | |||
12 | * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> | 12 | * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/module.h> | ||
16 | |||
15 | #include <linux/types.h> | 17 | #include <linux/types.h> |
16 | #include <linux/socket.h> | 18 | #include <linux/socket.h> |
17 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
@@ -184,8 +186,8 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, | |||
184 | .program = &rpcb_program, | 186 | .program = &rpcb_program, |
185 | .version = version, | 187 | .version = version, |
186 | .authflavor = RPC_AUTH_UNIX, | 188 | .authflavor = RPC_AUTH_UNIX, |
187 | .flags = (RPC_CLNT_CREATE_ONESHOT | | 189 | .flags = (RPC_CLNT_CREATE_NOPING | |
188 | RPC_CLNT_CREATE_NOPING), | 190 | RPC_CLNT_CREATE_INTR), |
189 | }; | 191 | }; |
190 | 192 | ||
191 | ((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT); | 193 | ((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT); |
@@ -238,6 +240,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay) | |||
238 | 240 | ||
239 | error = rpc_call_sync(rpcb_clnt, &msg, 0); | 241 | error = rpc_call_sync(rpcb_clnt, &msg, 0); |
240 | 242 | ||
243 | rpc_shutdown_client(rpcb_clnt); | ||
241 | if (error < 0) | 244 | if (error < 0) |
242 | printk(KERN_WARNING "RPC: failed to contact local rpcbind " | 245 | printk(KERN_WARNING "RPC: failed to contact local rpcbind " |
243 | "server (errno %d).\n", -error); | 246 | "server (errno %d).\n", -error); |
@@ -246,21 +249,20 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay) | |||
246 | return error; | 249 | return error; |
247 | } | 250 | } |
248 | 251 | ||
249 | #ifdef CONFIG_ROOT_NFS | ||
250 | /** | 252 | /** |
251 | * rpcb_getport_external - obtain the port for an RPC service on a given host | 253 | * rpcb_getport_sync - obtain the port for an RPC service on a given host |
252 | * @sin: address of remote peer | 254 | * @sin: address of remote peer |
253 | * @prog: RPC program number to bind | 255 | * @prog: RPC program number to bind |
254 | * @vers: RPC version number to bind | 256 | * @vers: RPC version number to bind |
255 | * @prot: transport protocol to use to make this request | 257 | * @prot: transport protocol to use to make this request |
256 | * | 258 | * |
257 | * Called from outside the RPC client in a synchronous task context. | 259 | * Called from outside the RPC client in a synchronous task context. |
260 | * Uses default timeout parameters specified by underlying transport. | ||
258 | * | 261 | * |
259 | * For now, this supports only version 2 queries, but is used only by | 262 | * XXX: Needs to support IPv6, and rpcbind versions 3 and 4 |
260 | * mount_clnt for NFS_ROOT. | ||
261 | */ | 263 | */ |
262 | int rpcb_getport_external(struct sockaddr_in *sin, __u32 prog, | 264 | int rpcb_getport_sync(struct sockaddr_in *sin, __u32 prog, |
263 | __u32 vers, int prot) | 265 | __u32 vers, int prot) |
264 | { | 266 | { |
265 | struct rpcbind_args map = { | 267 | struct rpcbind_args map = { |
266 | .r_prog = prog, | 268 | .r_prog = prog, |
@@ -277,15 +279,16 @@ int rpcb_getport_external(struct sockaddr_in *sin, __u32 prog, | |||
277 | char hostname[40]; | 279 | char hostname[40]; |
278 | int status; | 280 | int status; |
279 | 281 | ||
280 | dprintk("RPC: rpcb_getport_external(%u.%u.%u.%u, %u, %u, %d)\n", | 282 | dprintk("RPC: %s(" NIPQUAD_FMT ", %u, %u, %d)\n", |
281 | NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot); | 283 | __FUNCTION__, NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot); |
282 | 284 | ||
283 | sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr)); | 285 | sprintf(hostname, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr)); |
284 | rpcb_clnt = rpcb_create(hostname, (struct sockaddr *)sin, prot, 2, 0); | 286 | rpcb_clnt = rpcb_create(hostname, (struct sockaddr *)sin, prot, 2, 0); |
285 | if (IS_ERR(rpcb_clnt)) | 287 | if (IS_ERR(rpcb_clnt)) |
286 | return PTR_ERR(rpcb_clnt); | 288 | return PTR_ERR(rpcb_clnt); |
287 | 289 | ||
288 | status = rpc_call_sync(rpcb_clnt, &msg, 0); | 290 | status = rpc_call_sync(rpcb_clnt, &msg, 0); |
291 | rpc_shutdown_client(rpcb_clnt); | ||
289 | 292 | ||
290 | if (status >= 0) { | 293 | if (status >= 0) { |
291 | if (map.r_port != 0) | 294 | if (map.r_port != 0) |
@@ -294,16 +297,16 @@ int rpcb_getport_external(struct sockaddr_in *sin, __u32 prog, | |||
294 | } | 297 | } |
295 | return status; | 298 | return status; |
296 | } | 299 | } |
297 | #endif | 300 | EXPORT_SYMBOL_GPL(rpcb_getport_sync); |
298 | 301 | ||
299 | /** | 302 | /** |
300 | * rpcb_getport - obtain the port for a given RPC service on a given host | 303 | * rpcb_getport_async - obtain the port for a given RPC service on a given host |
301 | * @task: task that is waiting for portmapper request | 304 | * @task: task that is waiting for portmapper request |
302 | * | 305 | * |
303 | * This one can be called for an ongoing RPC request, and can be used in | 306 | * This one can be called for an ongoing RPC request, and can be used in |
304 | * an async (rpciod) context. | 307 | * an async (rpciod) context. |
305 | */ | 308 | */ |
306 | void rpcb_getport(struct rpc_task *task) | 309 | void rpcb_getport_async(struct rpc_task *task) |
307 | { | 310 | { |
308 | struct rpc_clnt *clnt = task->tk_client; | 311 | struct rpc_clnt *clnt = task->tk_client; |
309 | int bind_version; | 312 | int bind_version; |
@@ -314,17 +317,17 @@ void rpcb_getport(struct rpc_task *task) | |||
314 | struct sockaddr addr; | 317 | struct sockaddr addr; |
315 | int status; | 318 | int status; |
316 | 319 | ||
317 | dprintk("RPC: %5u rpcb_getport(%s, %u, %u, %d)\n", | 320 | dprintk("RPC: %5u %s(%s, %u, %u, %d)\n", |
318 | task->tk_pid, clnt->cl_server, | 321 | task->tk_pid, __FUNCTION__, |
319 | clnt->cl_prog, clnt->cl_vers, xprt->prot); | 322 | clnt->cl_server, clnt->cl_prog, clnt->cl_vers, xprt->prot); |
320 | 323 | ||
321 | /* Autobind on cloned rpc clients is discouraged */ | 324 | /* Autobind on cloned rpc clients is discouraged */ |
322 | BUG_ON(clnt->cl_parent != clnt); | 325 | BUG_ON(clnt->cl_parent != clnt); |
323 | 326 | ||
324 | if (xprt_test_and_set_binding(xprt)) { | 327 | if (xprt_test_and_set_binding(xprt)) { |
325 | status = -EACCES; /* tell caller to check again */ | 328 | status = -EACCES; /* tell caller to check again */ |
326 | dprintk("RPC: %5u rpcb_getport waiting for another binder\n", | 329 | dprintk("RPC: %5u %s: waiting for another binder\n", |
327 | task->tk_pid); | 330 | task->tk_pid, __FUNCTION__); |
328 | goto bailout_nowake; | 331 | goto bailout_nowake; |
329 | } | 332 | } |
330 | 333 | ||
@@ -335,27 +338,28 @@ void rpcb_getport(struct rpc_task *task) | |||
335 | /* Someone else may have bound if we slept */ | 338 | /* Someone else may have bound if we slept */ |
336 | if (xprt_bound(xprt)) { | 339 | if (xprt_bound(xprt)) { |
337 | status = 0; | 340 | status = 0; |
338 | dprintk("RPC: %5u rpcb_getport already bound\n", task->tk_pid); | 341 | dprintk("RPC: %5u %s: already bound\n", |
342 | task->tk_pid, __FUNCTION__); | ||
339 | goto bailout_nofree; | 343 | goto bailout_nofree; |
340 | } | 344 | } |
341 | 345 | ||
342 | if (rpcb_next_version[xprt->bind_index].rpc_proc == NULL) { | 346 | if (rpcb_next_version[xprt->bind_index].rpc_proc == NULL) { |
343 | xprt->bind_index = 0; | 347 | xprt->bind_index = 0; |
344 | status = -EACCES; /* tell caller to try again later */ | 348 | status = -EACCES; /* tell caller to try again later */ |
345 | dprintk("RPC: %5u rpcb_getport no more getport versions " | 349 | dprintk("RPC: %5u %s: no more getport versions available\n", |
346 | "available\n", task->tk_pid); | 350 | task->tk_pid, __FUNCTION__); |
347 | goto bailout_nofree; | 351 | goto bailout_nofree; |
348 | } | 352 | } |
349 | bind_version = rpcb_next_version[xprt->bind_index].rpc_vers; | 353 | bind_version = rpcb_next_version[xprt->bind_index].rpc_vers; |
350 | 354 | ||
351 | dprintk("RPC: %5u rpcb_getport trying rpcbind version %u\n", | 355 | dprintk("RPC: %5u %s: trying rpcbind version %u\n", |
352 | task->tk_pid, bind_version); | 356 | task->tk_pid, __FUNCTION__, bind_version); |
353 | 357 | ||
354 | map = kzalloc(sizeof(struct rpcbind_args), GFP_ATOMIC); | 358 | map = kzalloc(sizeof(struct rpcbind_args), GFP_ATOMIC); |
355 | if (!map) { | 359 | if (!map) { |
356 | status = -ENOMEM; | 360 | status = -ENOMEM; |
357 | dprintk("RPC: %5u rpcb_getport no memory available\n", | 361 | dprintk("RPC: %5u %s: no memory available\n", |
358 | task->tk_pid); | 362 | task->tk_pid, __FUNCTION__); |
359 | goto bailout_nofree; | 363 | goto bailout_nofree; |
360 | } | 364 | } |
361 | map->r_prog = clnt->cl_prog; | 365 | map->r_prog = clnt->cl_prog; |
@@ -373,16 +377,17 @@ void rpcb_getport(struct rpc_task *task) | |||
373 | rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot, bind_version, 0); | 377 | rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot, bind_version, 0); |
374 | if (IS_ERR(rpcb_clnt)) { | 378 | if (IS_ERR(rpcb_clnt)) { |
375 | status = PTR_ERR(rpcb_clnt); | 379 | status = PTR_ERR(rpcb_clnt); |
376 | dprintk("RPC: %5u rpcb_getport rpcb_create failed, error %ld\n", | 380 | dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n", |
377 | task->tk_pid, PTR_ERR(rpcb_clnt)); | 381 | task->tk_pid, __FUNCTION__, PTR_ERR(rpcb_clnt)); |
378 | goto bailout; | 382 | goto bailout; |
379 | } | 383 | } |
380 | 384 | ||
381 | child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map); | 385 | child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map); |
386 | rpc_release_client(rpcb_clnt); | ||
382 | if (IS_ERR(child)) { | 387 | if (IS_ERR(child)) { |
383 | status = -EIO; | 388 | status = -EIO; |
384 | dprintk("RPC: %5u rpcb_getport rpc_run_task failed\n", | 389 | dprintk("RPC: %5u %s: rpc_run_task failed\n", |
385 | task->tk_pid); | 390 | task->tk_pid, __FUNCTION__); |
386 | goto bailout_nofree; | 391 | goto bailout_nofree; |
387 | } | 392 | } |
388 | rpc_put_task(child); | 393 | rpc_put_task(child); |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 944d75396fb3..2ac43c41c3a9 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #ifdef RPC_DEBUG | 25 | #ifdef RPC_DEBUG |
26 | #define RPCDBG_FACILITY RPCDBG_SCHED | 26 | #define RPCDBG_FACILITY RPCDBG_SCHED |
27 | #define RPC_TASK_MAGIC_ID 0xf00baa | 27 | #define RPC_TASK_MAGIC_ID 0xf00baa |
28 | static int rpc_task_id; | ||
29 | #endif | 28 | #endif |
30 | 29 | ||
31 | /* | 30 | /* |
@@ -40,7 +39,6 @@ static mempool_t *rpc_task_mempool __read_mostly; | |||
40 | static mempool_t *rpc_buffer_mempool __read_mostly; | 39 | static mempool_t *rpc_buffer_mempool __read_mostly; |
41 | 40 | ||
42 | static void __rpc_default_timer(struct rpc_task *task); | 41 | static void __rpc_default_timer(struct rpc_task *task); |
43 | static void rpciod_killall(void); | ||
44 | static void rpc_async_schedule(struct work_struct *); | 42 | static void rpc_async_schedule(struct work_struct *); |
45 | static void rpc_release_task(struct rpc_task *task); | 43 | static void rpc_release_task(struct rpc_task *task); |
46 | 44 | ||
@@ -50,23 +48,13 @@ static void rpc_release_task(struct rpc_task *task); | |||
50 | static RPC_WAITQ(delay_queue, "delayq"); | 48 | static RPC_WAITQ(delay_queue, "delayq"); |
51 | 49 | ||
52 | /* | 50 | /* |
53 | * All RPC tasks are linked into this list | ||
54 | */ | ||
55 | static LIST_HEAD(all_tasks); | ||
56 | |||
57 | /* | ||
58 | * rpciod-related stuff | 51 | * rpciod-related stuff |
59 | */ | 52 | */ |
60 | static DEFINE_MUTEX(rpciod_mutex); | 53 | static DEFINE_MUTEX(rpciod_mutex); |
61 | static unsigned int rpciod_users; | 54 | static atomic_t rpciod_users = ATOMIC_INIT(0); |
62 | struct workqueue_struct *rpciod_workqueue; | 55 | struct workqueue_struct *rpciod_workqueue; |
63 | 56 | ||
64 | /* | 57 | /* |
65 | * Spinlock for other critical sections of code. | ||
66 | */ | ||
67 | static DEFINE_SPINLOCK(rpc_sched_lock); | ||
68 | |||
69 | /* | ||
70 | * Disable the timer for a given RPC task. Should be called with | 58 | * Disable the timer for a given RPC task. Should be called with |
71 | * queue->lock and bh_disabled in order to avoid races within | 59 | * queue->lock and bh_disabled in order to avoid races within |
72 | * rpc_run_timer(). | 60 | * rpc_run_timer(). |
@@ -267,18 +255,33 @@ static int rpc_wait_bit_interruptible(void *word) | |||
267 | return 0; | 255 | return 0; |
268 | } | 256 | } |
269 | 257 | ||
258 | #ifdef RPC_DEBUG | ||
259 | static void rpc_task_set_debuginfo(struct rpc_task *task) | ||
260 | { | ||
261 | static atomic_t rpc_pid; | ||
262 | |||
263 | task->tk_magic = RPC_TASK_MAGIC_ID; | ||
264 | task->tk_pid = atomic_inc_return(&rpc_pid); | ||
265 | } | ||
266 | #else | ||
267 | static inline void rpc_task_set_debuginfo(struct rpc_task *task) | ||
268 | { | ||
269 | } | ||
270 | #endif | ||
271 | |||
270 | static void rpc_set_active(struct rpc_task *task) | 272 | static void rpc_set_active(struct rpc_task *task) |
271 | { | 273 | { |
274 | struct rpc_clnt *clnt; | ||
272 | if (test_and_set_bit(RPC_TASK_ACTIVE, &task->tk_runstate) != 0) | 275 | if (test_and_set_bit(RPC_TASK_ACTIVE, &task->tk_runstate) != 0) |
273 | return; | 276 | return; |
274 | spin_lock(&rpc_sched_lock); | 277 | rpc_task_set_debuginfo(task); |
275 | #ifdef RPC_DEBUG | ||
276 | task->tk_magic = RPC_TASK_MAGIC_ID; | ||
277 | task->tk_pid = rpc_task_id++; | ||
278 | #endif | ||
279 | /* Add to global list of all tasks */ | 278 | /* Add to global list of all tasks */ |
280 | list_add_tail(&task->tk_task, &all_tasks); | 279 | clnt = task->tk_client; |
281 | spin_unlock(&rpc_sched_lock); | 280 | if (clnt != NULL) { |
281 | spin_lock(&clnt->cl_lock); | ||
282 | list_add_tail(&task->tk_task, &clnt->cl_tasks); | ||
283 | spin_unlock(&clnt->cl_lock); | ||
284 | } | ||
282 | } | 285 | } |
283 | 286 | ||
284 | /* | 287 | /* |
@@ -818,6 +821,7 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, cons | |||
818 | if (tk_ops->rpc_call_prepare != NULL) | 821 | if (tk_ops->rpc_call_prepare != NULL) |
819 | task->tk_action = rpc_prepare_task; | 822 | task->tk_action = rpc_prepare_task; |
820 | task->tk_calldata = calldata; | 823 | task->tk_calldata = calldata; |
824 | INIT_LIST_HEAD(&task->tk_task); | ||
821 | 825 | ||
822 | /* Initialize retry counters */ | 826 | /* Initialize retry counters */ |
823 | task->tk_garb_retry = 2; | 827 | task->tk_garb_retry = 2; |
@@ -830,7 +834,7 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, cons | |||
830 | task->tk_workqueue = rpciod_workqueue; | 834 | task->tk_workqueue = rpciod_workqueue; |
831 | 835 | ||
832 | if (clnt) { | 836 | if (clnt) { |
833 | atomic_inc(&clnt->cl_users); | 837 | kref_get(&clnt->cl_kref); |
834 | if (clnt->cl_softrtry) | 838 | if (clnt->cl_softrtry) |
835 | task->tk_flags |= RPC_TASK_SOFT; | 839 | task->tk_flags |= RPC_TASK_SOFT; |
836 | if (!clnt->cl_intr) | 840 | if (!clnt->cl_intr) |
@@ -860,9 +864,7 @@ static void rpc_free_task(struct rcu_head *rcu) | |||
860 | } | 864 | } |
861 | 865 | ||
862 | /* | 866 | /* |
863 | * Create a new task for the specified client. We have to | 867 | * Create a new task for the specified client. |
864 | * clean up after an allocation failure, as the client may | ||
865 | * have specified "oneshot". | ||
866 | */ | 868 | */ |
867 | struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *calldata) | 869 | struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *calldata) |
868 | { | 870 | { |
@@ -870,7 +872,7 @@ struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc | |||
870 | 872 | ||
871 | task = rpc_alloc_task(); | 873 | task = rpc_alloc_task(); |
872 | if (!task) | 874 | if (!task) |
873 | goto cleanup; | 875 | goto out; |
874 | 876 | ||
875 | rpc_init_task(task, clnt, flags, tk_ops, calldata); | 877 | rpc_init_task(task, clnt, flags, tk_ops, calldata); |
876 | 878 | ||
@@ -878,16 +880,6 @@ struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc | |||
878 | task->tk_flags |= RPC_TASK_DYNAMIC; | 880 | task->tk_flags |= RPC_TASK_DYNAMIC; |
879 | out: | 881 | out: |
880 | return task; | 882 | return task; |
881 | |||
882 | cleanup: | ||
883 | /* Check whether to release the client */ | ||
884 | if (clnt) { | ||
885 | printk("rpc_new_task: failed, users=%d, oneshot=%d\n", | ||
886 | atomic_read(&clnt->cl_users), clnt->cl_oneshot); | ||
887 | atomic_inc(&clnt->cl_users); /* pretend we were used ... */ | ||
888 | rpc_release_client(clnt); | ||
889 | } | ||
890 | goto out; | ||
891 | } | 883 | } |
892 | 884 | ||
893 | 885 | ||
@@ -920,11 +912,13 @@ static void rpc_release_task(struct rpc_task *task) | |||
920 | #endif | 912 | #endif |
921 | dprintk("RPC: %5u release task\n", task->tk_pid); | 913 | dprintk("RPC: %5u release task\n", task->tk_pid); |
922 | 914 | ||
923 | /* Remove from global task list */ | 915 | if (!list_empty(&task->tk_task)) { |
924 | spin_lock(&rpc_sched_lock); | 916 | struct rpc_clnt *clnt = task->tk_client; |
925 | list_del(&task->tk_task); | 917 | /* Remove from client task list */ |
926 | spin_unlock(&rpc_sched_lock); | 918 | spin_lock(&clnt->cl_lock); |
927 | 919 | list_del(&task->tk_task); | |
920 | spin_unlock(&clnt->cl_lock); | ||
921 | } | ||
928 | BUG_ON (RPC_IS_QUEUED(task)); | 922 | BUG_ON (RPC_IS_QUEUED(task)); |
929 | 923 | ||
930 | /* Synchronously delete any running timer */ | 924 | /* Synchronously delete any running timer */ |
@@ -939,29 +933,6 @@ static void rpc_release_task(struct rpc_task *task) | |||
939 | rpc_put_task(task); | 933 | rpc_put_task(task); |
940 | } | 934 | } |
941 | 935 | ||
942 | /** | ||
943 | * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it | ||
944 | * @clnt: pointer to RPC client | ||
945 | * @flags: RPC flags | ||
946 | * @ops: RPC call ops | ||
947 | * @data: user call data | ||
948 | */ | ||
949 | struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags, | ||
950 | const struct rpc_call_ops *ops, | ||
951 | void *data) | ||
952 | { | ||
953 | struct rpc_task *task; | ||
954 | task = rpc_new_task(clnt, flags, ops, data); | ||
955 | if (task == NULL) { | ||
956 | rpc_release_calldata(ops, data); | ||
957 | return ERR_PTR(-ENOMEM); | ||
958 | } | ||
959 | atomic_inc(&task->tk_count); | ||
960 | rpc_execute(task); | ||
961 | return task; | ||
962 | } | ||
963 | EXPORT_SYMBOL(rpc_run_task); | ||
964 | |||
965 | /* | 936 | /* |
966 | * Kill all tasks for the given client. | 937 | * Kill all tasks for the given client. |
967 | * XXX: kill their descendants as well? | 938 | * XXX: kill their descendants as well? |
@@ -969,44 +940,25 @@ EXPORT_SYMBOL(rpc_run_task); | |||
969 | void rpc_killall_tasks(struct rpc_clnt *clnt) | 940 | void rpc_killall_tasks(struct rpc_clnt *clnt) |
970 | { | 941 | { |
971 | struct rpc_task *rovr; | 942 | struct rpc_task *rovr; |
972 | struct list_head *le; | ||
973 | 943 | ||
974 | dprintk("RPC: killing all tasks for client %p\n", clnt); | ||
975 | 944 | ||
945 | if (list_empty(&clnt->cl_tasks)) | ||
946 | return; | ||
947 | dprintk("RPC: killing all tasks for client %p\n", clnt); | ||
976 | /* | 948 | /* |
977 | * Spin lock all_tasks to prevent changes... | 949 | * Spin lock all_tasks to prevent changes... |
978 | */ | 950 | */ |
979 | spin_lock(&rpc_sched_lock); | 951 | spin_lock(&clnt->cl_lock); |
980 | alltask_for_each(rovr, le, &all_tasks) { | 952 | list_for_each_entry(rovr, &clnt->cl_tasks, tk_task) { |
981 | if (! RPC_IS_ACTIVATED(rovr)) | 953 | if (! RPC_IS_ACTIVATED(rovr)) |
982 | continue; | 954 | continue; |
983 | if (!clnt || rovr->tk_client == clnt) { | 955 | if (!(rovr->tk_flags & RPC_TASK_KILLED)) { |
984 | rovr->tk_flags |= RPC_TASK_KILLED; | 956 | rovr->tk_flags |= RPC_TASK_KILLED; |
985 | rpc_exit(rovr, -EIO); | 957 | rpc_exit(rovr, -EIO); |
986 | rpc_wake_up_task(rovr); | 958 | rpc_wake_up_task(rovr); |
987 | } | 959 | } |
988 | } | 960 | } |
989 | spin_unlock(&rpc_sched_lock); | 961 | spin_unlock(&clnt->cl_lock); |
990 | } | ||
991 | |||
992 | static void rpciod_killall(void) | ||
993 | { | ||
994 | unsigned long flags; | ||
995 | |||
996 | while (!list_empty(&all_tasks)) { | ||
997 | clear_thread_flag(TIF_SIGPENDING); | ||
998 | rpc_killall_tasks(NULL); | ||
999 | flush_workqueue(rpciod_workqueue); | ||
1000 | if (!list_empty(&all_tasks)) { | ||
1001 | dprintk("RPC: rpciod_killall: waiting for tasks " | ||
1002 | "to exit\n"); | ||
1003 | yield(); | ||
1004 | } | ||
1005 | } | ||
1006 | |||
1007 | spin_lock_irqsave(¤t->sighand->siglock, flags); | ||
1008 | recalc_sigpending(); | ||
1009 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); | ||
1010 | } | 962 | } |
1011 | 963 | ||
1012 | /* | 964 | /* |
@@ -1018,28 +970,27 @@ rpciod_up(void) | |||
1018 | struct workqueue_struct *wq; | 970 | struct workqueue_struct *wq; |
1019 | int error = 0; | 971 | int error = 0; |
1020 | 972 | ||
973 | if (atomic_inc_not_zero(&rpciod_users)) | ||
974 | return 0; | ||
975 | |||
1021 | mutex_lock(&rpciod_mutex); | 976 | mutex_lock(&rpciod_mutex); |
1022 | dprintk("RPC: rpciod_up: users %u\n", rpciod_users); | 977 | |
1023 | rpciod_users++; | 978 | /* Guard against races with rpciod_down() */ |
1024 | if (rpciod_workqueue) | 979 | if (rpciod_workqueue != NULL) |
1025 | goto out; | 980 | goto out_ok; |
1026 | /* | ||
1027 | * If there's no pid, we should be the first user. | ||
1028 | */ | ||
1029 | if (rpciod_users > 1) | ||
1030 | printk(KERN_WARNING "rpciod_up: no workqueue, %u users??\n", rpciod_users); | ||
1031 | /* | 981 | /* |
1032 | * Create the rpciod thread and wait for it to start. | 982 | * Create the rpciod thread and wait for it to start. |
1033 | */ | 983 | */ |
984 | dprintk("RPC: creating workqueue rpciod\n"); | ||
1034 | error = -ENOMEM; | 985 | error = -ENOMEM; |
1035 | wq = create_workqueue("rpciod"); | 986 | wq = create_workqueue("rpciod"); |
1036 | if (wq == NULL) { | 987 | if (wq == NULL) |
1037 | printk(KERN_WARNING "rpciod_up: create workqueue failed, error=%d\n", error); | ||
1038 | rpciod_users--; | ||
1039 | goto out; | 988 | goto out; |
1040 | } | 989 | |
1041 | rpciod_workqueue = wq; | 990 | rpciod_workqueue = wq; |
1042 | error = 0; | 991 | error = 0; |
992 | out_ok: | ||
993 | atomic_inc(&rpciod_users); | ||
1043 | out: | 994 | out: |
1044 | mutex_unlock(&rpciod_mutex); | 995 | mutex_unlock(&rpciod_mutex); |
1045 | return error; | 996 | return error; |
@@ -1048,59 +999,19 @@ out: | |||
1048 | void | 999 | void |
1049 | rpciod_down(void) | 1000 | rpciod_down(void) |
1050 | { | 1001 | { |
1002 | if (!atomic_dec_and_test(&rpciod_users)) | ||
1003 | return; | ||
1004 | |||
1051 | mutex_lock(&rpciod_mutex); | 1005 | mutex_lock(&rpciod_mutex); |
1052 | dprintk("RPC: rpciod_down sema %u\n", rpciod_users); | 1006 | dprintk("RPC: destroying workqueue rpciod\n"); |
1053 | if (rpciod_users) { | ||
1054 | if (--rpciod_users) | ||
1055 | goto out; | ||
1056 | } else | ||
1057 | printk(KERN_WARNING "rpciod_down: no users??\n"); | ||
1058 | 1007 | ||
1059 | if (!rpciod_workqueue) { | 1008 | if (atomic_read(&rpciod_users) == 0 && rpciod_workqueue != NULL) { |
1060 | dprintk("RPC: rpciod_down: Nothing to do!\n"); | 1009 | destroy_workqueue(rpciod_workqueue); |
1061 | goto out; | 1010 | rpciod_workqueue = NULL; |
1062 | } | 1011 | } |
1063 | rpciod_killall(); | ||
1064 | |||
1065 | destroy_workqueue(rpciod_workqueue); | ||
1066 | rpciod_workqueue = NULL; | ||
1067 | out: | ||
1068 | mutex_unlock(&rpciod_mutex); | 1012 | mutex_unlock(&rpciod_mutex); |
1069 | } | 1013 | } |
1070 | 1014 | ||
1071 | #ifdef RPC_DEBUG | ||
1072 | void rpc_show_tasks(void) | ||
1073 | { | ||
1074 | struct list_head *le; | ||
1075 | struct rpc_task *t; | ||
1076 | |||
1077 | spin_lock(&rpc_sched_lock); | ||
1078 | if (list_empty(&all_tasks)) { | ||
1079 | spin_unlock(&rpc_sched_lock); | ||
1080 | return; | ||
1081 | } | ||
1082 | printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout " | ||
1083 | "-rpcwait -action- ---ops--\n"); | ||
1084 | alltask_for_each(t, le, &all_tasks) { | ||
1085 | const char *rpc_waitq = "none"; | ||
1086 | |||
1087 | if (RPC_IS_QUEUED(t)) | ||
1088 | rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq); | ||
1089 | |||
1090 | printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n", | ||
1091 | t->tk_pid, | ||
1092 | (t->tk_msg.rpc_proc ? t->tk_msg.rpc_proc->p_proc : -1), | ||
1093 | t->tk_flags, t->tk_status, | ||
1094 | t->tk_client, | ||
1095 | (t->tk_client ? t->tk_client->cl_prog : 0), | ||
1096 | t->tk_rqstp, t->tk_timeout, | ||
1097 | rpc_waitq, | ||
1098 | t->tk_action, t->tk_ops); | ||
1099 | } | ||
1100 | spin_unlock(&rpc_sched_lock); | ||
1101 | } | ||
1102 | #endif | ||
1103 | |||
1104 | void | 1015 | void |
1105 | rpc_destroy_mempool(void) | 1016 | rpc_destroy_mempool(void) |
1106 | { | 1017 | { |
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 73075dec83c0..384c4ad5ab86 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c | |||
@@ -28,15 +28,11 @@ EXPORT_SYMBOL(rpc_init_task); | |||
28 | EXPORT_SYMBOL(rpc_sleep_on); | 28 | EXPORT_SYMBOL(rpc_sleep_on); |
29 | EXPORT_SYMBOL(rpc_wake_up_next); | 29 | EXPORT_SYMBOL(rpc_wake_up_next); |
30 | EXPORT_SYMBOL(rpc_wake_up_task); | 30 | EXPORT_SYMBOL(rpc_wake_up_task); |
31 | EXPORT_SYMBOL(rpciod_down); | ||
32 | EXPORT_SYMBOL(rpciod_up); | ||
33 | EXPORT_SYMBOL(rpc_new_task); | ||
34 | EXPORT_SYMBOL(rpc_wake_up_status); | 31 | EXPORT_SYMBOL(rpc_wake_up_status); |
35 | 32 | ||
36 | /* RPC client functions */ | 33 | /* RPC client functions */ |
37 | EXPORT_SYMBOL(rpc_clone_client); | 34 | EXPORT_SYMBOL(rpc_clone_client); |
38 | EXPORT_SYMBOL(rpc_bind_new_program); | 35 | EXPORT_SYMBOL(rpc_bind_new_program); |
39 | EXPORT_SYMBOL(rpc_destroy_client); | ||
40 | EXPORT_SYMBOL(rpc_shutdown_client); | 36 | EXPORT_SYMBOL(rpc_shutdown_client); |
41 | EXPORT_SYMBOL(rpc_killall_tasks); | 37 | EXPORT_SYMBOL(rpc_killall_tasks); |
42 | EXPORT_SYMBOL(rpc_call_sync); | 38 | EXPORT_SYMBOL(rpc_call_sync); |
@@ -61,7 +57,7 @@ EXPORT_SYMBOL(rpcauth_unregister); | |||
61 | EXPORT_SYMBOL(rpcauth_create); | 57 | EXPORT_SYMBOL(rpcauth_create); |
62 | EXPORT_SYMBOL(rpcauth_lookupcred); | 58 | EXPORT_SYMBOL(rpcauth_lookupcred); |
63 | EXPORT_SYMBOL(rpcauth_lookup_credcache); | 59 | EXPORT_SYMBOL(rpcauth_lookup_credcache); |
64 | EXPORT_SYMBOL(rpcauth_free_credcache); | 60 | EXPORT_SYMBOL(rpcauth_destroy_credcache); |
65 | EXPORT_SYMBOL(rpcauth_init_credcache); | 61 | EXPORT_SYMBOL(rpcauth_init_credcache); |
66 | EXPORT_SYMBOL(put_rpccred); | 62 | EXPORT_SYMBOL(put_rpccred); |
67 | 63 | ||
@@ -156,6 +152,7 @@ init_sunrpc(void) | |||
156 | cache_register(&ip_map_cache); | 152 | cache_register(&ip_map_cache); |
157 | cache_register(&unix_gid_cache); | 153 | cache_register(&unix_gid_cache); |
158 | init_socket_xprt(); | 154 | init_socket_xprt(); |
155 | rpcauth_init_module(); | ||
159 | out: | 156 | out: |
160 | return err; | 157 | return err; |
161 | } | 158 | } |
@@ -163,6 +160,7 @@ out: | |||
163 | static void __exit | 160 | static void __exit |
164 | cleanup_sunrpc(void) | 161 | cleanup_sunrpc(void) |
165 | { | 162 | { |
163 | rpcauth_remove_module(); | ||
166 | cleanup_socket_xprt(); | 164 | cleanup_socket_xprt(); |
167 | unregister_rpc_pipefs(); | 165 | unregister_rpc_pipefs(); |
168 | rpc_destroy_mempool(); | 166 | rpc_destroy_mempool(); |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 5baf48de2558..64b9b8c743c4 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -644,6 +644,7 @@ svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr, int buflen) | |||
644 | struct msghdr msg = { | 644 | struct msghdr msg = { |
645 | .msg_flags = MSG_DONTWAIT, | 645 | .msg_flags = MSG_DONTWAIT, |
646 | }; | 646 | }; |
647 | struct sockaddr *sin; | ||
647 | int len; | 648 | int len; |
648 | 649 | ||
649 | len = kernel_recvmsg(svsk->sk_sock, &msg, iov, nr, buflen, | 650 | len = kernel_recvmsg(svsk->sk_sock, &msg, iov, nr, buflen, |
@@ -654,6 +655,19 @@ svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr, int buflen) | |||
654 | memcpy(&rqstp->rq_addr, &svsk->sk_remote, svsk->sk_remotelen); | 655 | memcpy(&rqstp->rq_addr, &svsk->sk_remote, svsk->sk_remotelen); |
655 | rqstp->rq_addrlen = svsk->sk_remotelen; | 656 | rqstp->rq_addrlen = svsk->sk_remotelen; |
656 | 657 | ||
658 | /* Destination address in request is needed for binding the | ||
659 | * source address in RPC callbacks later. | ||
660 | */ | ||
661 | sin = (struct sockaddr *)&svsk->sk_local; | ||
662 | switch (sin->sa_family) { | ||
663 | case AF_INET: | ||
664 | rqstp->rq_daddr.addr = ((struct sockaddr_in *)sin)->sin_addr; | ||
665 | break; | ||
666 | case AF_INET6: | ||
667 | rqstp->rq_daddr.addr6 = ((struct sockaddr_in6 *)sin)->sin6_addr; | ||
668 | break; | ||
669 | } | ||
670 | |||
657 | dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n", | 671 | dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n", |
658 | svsk, iov[0].iov_base, iov[0].iov_len, len); | 672 | svsk, iov[0].iov_base, iov[0].iov_len, len); |
659 | 673 | ||
@@ -1064,6 +1078,12 @@ svc_tcp_accept(struct svc_sock *svsk) | |||
1064 | goto failed; | 1078 | goto failed; |
1065 | memcpy(&newsvsk->sk_remote, sin, slen); | 1079 | memcpy(&newsvsk->sk_remote, sin, slen); |
1066 | newsvsk->sk_remotelen = slen; | 1080 | newsvsk->sk_remotelen = slen; |
1081 | err = kernel_getsockname(newsock, sin, &slen); | ||
1082 | if (unlikely(err < 0)) { | ||
1083 | dprintk("svc_tcp_accept: kernel_getsockname error %d\n", -err); | ||
1084 | slen = offsetof(struct sockaddr, sa_data); | ||
1085 | } | ||
1086 | memcpy(&newsvsk->sk_local, sin, slen); | ||
1067 | 1087 | ||
1068 | svc_sock_received(newsvsk); | 1088 | svc_sock_received(newsvsk); |
1069 | 1089 | ||
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 5b05b73e4c1d..c8c2edccad7e 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -127,7 +127,7 @@ static void xprt_clear_locked(struct rpc_xprt *xprt) | |||
127 | clear_bit(XPRT_LOCKED, &xprt->state); | 127 | clear_bit(XPRT_LOCKED, &xprt->state); |
128 | smp_mb__after_clear_bit(); | 128 | smp_mb__after_clear_bit(); |
129 | } else | 129 | } else |
130 | schedule_work(&xprt->task_cleanup); | 130 | queue_work(rpciod_workqueue, &xprt->task_cleanup); |
131 | } | 131 | } |
132 | 132 | ||
133 | /* | 133 | /* |
@@ -515,7 +515,7 @@ xprt_init_autodisconnect(unsigned long data) | |||
515 | if (xprt_connecting(xprt)) | 515 | if (xprt_connecting(xprt)) |
516 | xprt_release_write(xprt, NULL); | 516 | xprt_release_write(xprt, NULL); |
517 | else | 517 | else |
518 | schedule_work(&xprt->task_cleanup); | 518 | queue_work(rpciod_workqueue, &xprt->task_cleanup); |
519 | return; | 519 | return; |
520 | out_abort: | 520 | out_abort: |
521 | spin_unlock(&xprt->transport_lock); | 521 | spin_unlock(&xprt->transport_lock); |
@@ -886,27 +886,24 @@ void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long i | |||
886 | 886 | ||
887 | /** | 887 | /** |
888 | * xprt_create_transport - create an RPC transport | 888 | * xprt_create_transport - create an RPC transport |
889 | * @proto: requested transport protocol | 889 | * @args: rpc transport creation arguments |
890 | * @ap: remote peer address | ||
891 | * @size: length of address | ||
892 | * @to: timeout parameters | ||
893 | * | 890 | * |
894 | */ | 891 | */ |
895 | struct rpc_xprt *xprt_create_transport(int proto, struct sockaddr *ap, size_t size, struct rpc_timeout *to) | 892 | struct rpc_xprt *xprt_create_transport(struct rpc_xprtsock_create *args) |
896 | { | 893 | { |
897 | struct rpc_xprt *xprt; | 894 | struct rpc_xprt *xprt; |
898 | struct rpc_rqst *req; | 895 | struct rpc_rqst *req; |
899 | 896 | ||
900 | switch (proto) { | 897 | switch (args->proto) { |
901 | case IPPROTO_UDP: | 898 | case IPPROTO_UDP: |
902 | xprt = xs_setup_udp(ap, size, to); | 899 | xprt = xs_setup_udp(args); |
903 | break; | 900 | break; |
904 | case IPPROTO_TCP: | 901 | case IPPROTO_TCP: |
905 | xprt = xs_setup_tcp(ap, size, to); | 902 | xprt = xs_setup_tcp(args); |
906 | break; | 903 | break; |
907 | default: | 904 | default: |
908 | printk(KERN_ERR "RPC: unrecognized transport protocol: %d\n", | 905 | printk(KERN_ERR "RPC: unrecognized transport protocol: %d\n", |
909 | proto); | 906 | args->proto); |
910 | return ERR_PTR(-EIO); | 907 | return ERR_PTR(-EIO); |
911 | } | 908 | } |
912 | if (IS_ERR(xprt)) { | 909 | if (IS_ERR(xprt)) { |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index cc33c5880abb..4ae7eed7f617 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -235,6 +235,7 @@ struct sock_xprt { | |||
235 | * Connection of transports | 235 | * Connection of transports |
236 | */ | 236 | */ |
237 | struct delayed_work connect_worker; | 237 | struct delayed_work connect_worker; |
238 | struct sockaddr_storage addr; | ||
238 | unsigned short port; | 239 | unsigned short port; |
239 | 240 | ||
240 | /* | 241 | /* |
@@ -653,8 +654,7 @@ static void xs_destroy(struct rpc_xprt *xprt) | |||
653 | 654 | ||
654 | dprintk("RPC: xs_destroy xprt %p\n", xprt); | 655 | dprintk("RPC: xs_destroy xprt %p\n", xprt); |
655 | 656 | ||
656 | cancel_delayed_work(&transport->connect_worker); | 657 | cancel_rearming_delayed_work(&transport->connect_worker); |
657 | flush_scheduled_work(); | ||
658 | 658 | ||
659 | xprt_disconnect(xprt); | 659 | xprt_disconnect(xprt); |
660 | xs_close(xprt); | 660 | xs_close(xprt); |
@@ -1001,7 +1001,7 @@ static void xs_tcp_state_change(struct sock *sk) | |||
1001 | /* Try to schedule an autoclose RPC calls */ | 1001 | /* Try to schedule an autoclose RPC calls */ |
1002 | set_bit(XPRT_CLOSE_WAIT, &xprt->state); | 1002 | set_bit(XPRT_CLOSE_WAIT, &xprt->state); |
1003 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0) | 1003 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0) |
1004 | schedule_work(&xprt->task_cleanup); | 1004 | queue_work(rpciod_workqueue, &xprt->task_cleanup); |
1005 | default: | 1005 | default: |
1006 | xprt_disconnect(xprt); | 1006 | xprt_disconnect(xprt); |
1007 | } | 1007 | } |
@@ -1146,31 +1146,36 @@ static void xs_set_port(struct rpc_xprt *xprt, unsigned short port) | |||
1146 | sap->sin_port = htons(port); | 1146 | sap->sin_port = htons(port); |
1147 | } | 1147 | } |
1148 | 1148 | ||
1149 | static int xs_bindresvport(struct sock_xprt *transport, struct socket *sock) | 1149 | static int xs_bind(struct sock_xprt *transport, struct socket *sock) |
1150 | { | 1150 | { |
1151 | struct sockaddr_in myaddr = { | 1151 | struct sockaddr_in myaddr = { |
1152 | .sin_family = AF_INET, | 1152 | .sin_family = AF_INET, |
1153 | }; | 1153 | }; |
1154 | struct sockaddr_in *sa; | ||
1154 | int err; | 1155 | int err; |
1155 | unsigned short port = transport->port; | 1156 | unsigned short port = transport->port; |
1156 | 1157 | ||
1158 | if (!transport->xprt.resvport) | ||
1159 | port = 0; | ||
1160 | sa = (struct sockaddr_in *)&transport->addr; | ||
1161 | myaddr.sin_addr = sa->sin_addr; | ||
1157 | do { | 1162 | do { |
1158 | myaddr.sin_port = htons(port); | 1163 | myaddr.sin_port = htons(port); |
1159 | err = kernel_bind(sock, (struct sockaddr *) &myaddr, | 1164 | err = kernel_bind(sock, (struct sockaddr *) &myaddr, |
1160 | sizeof(myaddr)); | 1165 | sizeof(myaddr)); |
1166 | if (!transport->xprt.resvport) | ||
1167 | break; | ||
1161 | if (err == 0) { | 1168 | if (err == 0) { |
1162 | transport->port = port; | 1169 | transport->port = port; |
1163 | dprintk("RPC: xs_bindresvport bound to port %u\n", | 1170 | break; |
1164 | port); | ||
1165 | return 0; | ||
1166 | } | 1171 | } |
1167 | if (port <= xprt_min_resvport) | 1172 | if (port <= xprt_min_resvport) |
1168 | port = xprt_max_resvport; | 1173 | port = xprt_max_resvport; |
1169 | else | 1174 | else |
1170 | port--; | 1175 | port--; |
1171 | } while (err == -EADDRINUSE && port != transport->port); | 1176 | } while (err == -EADDRINUSE && port != transport->port); |
1172 | 1177 | dprintk("RPC: xs_bind "NIPQUAD_FMT":%u: %s (%d)\n", | |
1173 | dprintk("RPC: can't bind to reserved port (%d).\n", -err); | 1178 | NIPQUAD(myaddr.sin_addr), port, err ? "failed" : "ok", err); |
1174 | return err; | 1179 | return err; |
1175 | } | 1180 | } |
1176 | 1181 | ||
@@ -1229,7 +1234,7 @@ static void xs_udp_connect_worker(struct work_struct *work) | |||
1229 | } | 1234 | } |
1230 | xs_reclassify_socket(sock); | 1235 | xs_reclassify_socket(sock); |
1231 | 1236 | ||
1232 | if (xprt->resvport && xs_bindresvport(transport, sock) < 0) { | 1237 | if (xs_bind(transport, sock)) { |
1233 | sock_release(sock); | 1238 | sock_release(sock); |
1234 | goto out; | 1239 | goto out; |
1235 | } | 1240 | } |
@@ -1316,7 +1321,7 @@ static void xs_tcp_connect_worker(struct work_struct *work) | |||
1316 | } | 1321 | } |
1317 | xs_reclassify_socket(sock); | 1322 | xs_reclassify_socket(sock); |
1318 | 1323 | ||
1319 | if (xprt->resvport && xs_bindresvport(transport, sock) < 0) { | 1324 | if (xs_bind(transport, sock)) { |
1320 | sock_release(sock); | 1325 | sock_release(sock); |
1321 | goto out; | 1326 | goto out; |
1322 | } | 1327 | } |
@@ -1410,18 +1415,16 @@ static void xs_connect(struct rpc_task *task) | |||
1410 | dprintk("RPC: xs_connect delayed xprt %p for %lu " | 1415 | dprintk("RPC: xs_connect delayed xprt %p for %lu " |
1411 | "seconds\n", | 1416 | "seconds\n", |
1412 | xprt, xprt->reestablish_timeout / HZ); | 1417 | xprt, xprt->reestablish_timeout / HZ); |
1413 | schedule_delayed_work(&transport->connect_worker, | 1418 | queue_delayed_work(rpciod_workqueue, |
1414 | xprt->reestablish_timeout); | 1419 | &transport->connect_worker, |
1420 | xprt->reestablish_timeout); | ||
1415 | xprt->reestablish_timeout <<= 1; | 1421 | xprt->reestablish_timeout <<= 1; |
1416 | if (xprt->reestablish_timeout > XS_TCP_MAX_REEST_TO) | 1422 | if (xprt->reestablish_timeout > XS_TCP_MAX_REEST_TO) |
1417 | xprt->reestablish_timeout = XS_TCP_MAX_REEST_TO; | 1423 | xprt->reestablish_timeout = XS_TCP_MAX_REEST_TO; |
1418 | } else { | 1424 | } else { |
1419 | dprintk("RPC: xs_connect scheduled xprt %p\n", xprt); | 1425 | dprintk("RPC: xs_connect scheduled xprt %p\n", xprt); |
1420 | schedule_delayed_work(&transport->connect_worker, 0); | 1426 | queue_delayed_work(rpciod_workqueue, |
1421 | 1427 | &transport->connect_worker, 0); | |
1422 | /* flush_scheduled_work can sleep... */ | ||
1423 | if (!RPC_IS_ASYNC(task)) | ||
1424 | flush_scheduled_work(); | ||
1425 | } | 1428 | } |
1426 | } | 1429 | } |
1427 | 1430 | ||
@@ -1476,7 +1479,7 @@ static struct rpc_xprt_ops xs_udp_ops = { | |||
1476 | .set_buffer_size = xs_udp_set_buffer_size, | 1479 | .set_buffer_size = xs_udp_set_buffer_size, |
1477 | .reserve_xprt = xprt_reserve_xprt_cong, | 1480 | .reserve_xprt = xprt_reserve_xprt_cong, |
1478 | .release_xprt = xprt_release_xprt_cong, | 1481 | .release_xprt = xprt_release_xprt_cong, |
1479 | .rpcbind = rpcb_getport, | 1482 | .rpcbind = rpcb_getport_async, |
1480 | .set_port = xs_set_port, | 1483 | .set_port = xs_set_port, |
1481 | .connect = xs_connect, | 1484 | .connect = xs_connect, |
1482 | .buf_alloc = rpc_malloc, | 1485 | .buf_alloc = rpc_malloc, |
@@ -1493,7 +1496,7 @@ static struct rpc_xprt_ops xs_udp_ops = { | |||
1493 | static struct rpc_xprt_ops xs_tcp_ops = { | 1496 | static struct rpc_xprt_ops xs_tcp_ops = { |
1494 | .reserve_xprt = xprt_reserve_xprt, | 1497 | .reserve_xprt = xprt_reserve_xprt, |
1495 | .release_xprt = xs_tcp_release_xprt, | 1498 | .release_xprt = xs_tcp_release_xprt, |
1496 | .rpcbind = rpcb_getport, | 1499 | .rpcbind = rpcb_getport_async, |
1497 | .set_port = xs_set_port, | 1500 | .set_port = xs_set_port, |
1498 | .connect = xs_connect, | 1501 | .connect = xs_connect, |
1499 | .buf_alloc = rpc_malloc, | 1502 | .buf_alloc = rpc_malloc, |
@@ -1505,12 +1508,12 @@ static struct rpc_xprt_ops xs_tcp_ops = { | |||
1505 | .print_stats = xs_tcp_print_stats, | 1508 | .print_stats = xs_tcp_print_stats, |
1506 | }; | 1509 | }; |
1507 | 1510 | ||
1508 | static struct rpc_xprt *xs_setup_xprt(struct sockaddr *addr, size_t addrlen, unsigned int slot_table_size) | 1511 | static struct rpc_xprt *xs_setup_xprt(struct rpc_xprtsock_create *args, unsigned int slot_table_size) |
1509 | { | 1512 | { |
1510 | struct rpc_xprt *xprt; | 1513 | struct rpc_xprt *xprt; |
1511 | struct sock_xprt *new; | 1514 | struct sock_xprt *new; |
1512 | 1515 | ||
1513 | if (addrlen > sizeof(xprt->addr)) { | 1516 | if (args->addrlen > sizeof(xprt->addr)) { |
1514 | dprintk("RPC: xs_setup_xprt: address too large\n"); | 1517 | dprintk("RPC: xs_setup_xprt: address too large\n"); |
1515 | return ERR_PTR(-EBADF); | 1518 | return ERR_PTR(-EBADF); |
1516 | } | 1519 | } |
@@ -1532,8 +1535,10 @@ static struct rpc_xprt *xs_setup_xprt(struct sockaddr *addr, size_t addrlen, uns | |||
1532 | return ERR_PTR(-ENOMEM); | 1535 | return ERR_PTR(-ENOMEM); |
1533 | } | 1536 | } |
1534 | 1537 | ||
1535 | memcpy(&xprt->addr, addr, addrlen); | 1538 | memcpy(&xprt->addr, args->dstaddr, args->addrlen); |
1536 | xprt->addrlen = addrlen; | 1539 | xprt->addrlen = args->addrlen; |
1540 | if (args->srcaddr) | ||
1541 | memcpy(&new->addr, args->srcaddr, args->addrlen); | ||
1537 | new->port = xs_get_random_port(); | 1542 | new->port = xs_get_random_port(); |
1538 | 1543 | ||
1539 | return xprt; | 1544 | return xprt; |
@@ -1541,22 +1546,20 @@ static struct rpc_xprt *xs_setup_xprt(struct sockaddr *addr, size_t addrlen, uns | |||
1541 | 1546 | ||
1542 | /** | 1547 | /** |
1543 | * xs_setup_udp - Set up transport to use a UDP socket | 1548 | * xs_setup_udp - Set up transport to use a UDP socket |
1544 | * @addr: address of remote server | 1549 | * @args: rpc transport creation arguments |
1545 | * @addrlen: length of address in bytes | ||
1546 | * @to: timeout parameters | ||
1547 | * | 1550 | * |
1548 | */ | 1551 | */ |
1549 | struct rpc_xprt *xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to) | 1552 | struct rpc_xprt *xs_setup_udp(struct rpc_xprtsock_create *args) |
1550 | { | 1553 | { |
1551 | struct rpc_xprt *xprt; | 1554 | struct rpc_xprt *xprt; |
1552 | struct sock_xprt *transport; | 1555 | struct sock_xprt *transport; |
1553 | 1556 | ||
1554 | xprt = xs_setup_xprt(addr, addrlen, xprt_udp_slot_table_entries); | 1557 | xprt = xs_setup_xprt(args, xprt_udp_slot_table_entries); |
1555 | if (IS_ERR(xprt)) | 1558 | if (IS_ERR(xprt)) |
1556 | return xprt; | 1559 | return xprt; |
1557 | transport = container_of(xprt, struct sock_xprt, xprt); | 1560 | transport = container_of(xprt, struct sock_xprt, xprt); |
1558 | 1561 | ||
1559 | if (ntohs(((struct sockaddr_in *)addr)->sin_port) != 0) | 1562 | if (ntohs(((struct sockaddr_in *)args->dstaddr)->sin_port) != 0) |
1560 | xprt_set_bound(xprt); | 1563 | xprt_set_bound(xprt); |
1561 | 1564 | ||
1562 | xprt->prot = IPPROTO_UDP; | 1565 | xprt->prot = IPPROTO_UDP; |
@@ -1572,8 +1575,8 @@ struct rpc_xprt *xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_ | |||
1572 | 1575 | ||
1573 | xprt->ops = &xs_udp_ops; | 1576 | xprt->ops = &xs_udp_ops; |
1574 | 1577 | ||
1575 | if (to) | 1578 | if (args->timeout) |
1576 | xprt->timeout = *to; | 1579 | xprt->timeout = *args->timeout; |
1577 | else | 1580 | else |
1578 | xprt_set_timeout(&xprt->timeout, 5, 5 * HZ); | 1581 | xprt_set_timeout(&xprt->timeout, 5, 5 * HZ); |
1579 | 1582 | ||
@@ -1586,22 +1589,20 @@ struct rpc_xprt *xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_ | |||
1586 | 1589 | ||
1587 | /** | 1590 | /** |
1588 | * xs_setup_tcp - Set up transport to use a TCP socket | 1591 | * xs_setup_tcp - Set up transport to use a TCP socket |
1589 | * @addr: address of remote server | 1592 | * @args: rpc transport creation arguments |
1590 | * @addrlen: length of address in bytes | ||
1591 | * @to: timeout parameters | ||
1592 | * | 1593 | * |
1593 | */ | 1594 | */ |
1594 | struct rpc_xprt *xs_setup_tcp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to) | 1595 | struct rpc_xprt *xs_setup_tcp(struct rpc_xprtsock_create *args) |
1595 | { | 1596 | { |
1596 | struct rpc_xprt *xprt; | 1597 | struct rpc_xprt *xprt; |
1597 | struct sock_xprt *transport; | 1598 | struct sock_xprt *transport; |
1598 | 1599 | ||
1599 | xprt = xs_setup_xprt(addr, addrlen, xprt_tcp_slot_table_entries); | 1600 | xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries); |
1600 | if (IS_ERR(xprt)) | 1601 | if (IS_ERR(xprt)) |
1601 | return xprt; | 1602 | return xprt; |
1602 | transport = container_of(xprt, struct sock_xprt, xprt); | 1603 | transport = container_of(xprt, struct sock_xprt, xprt); |
1603 | 1604 | ||
1604 | if (ntohs(((struct sockaddr_in *)addr)->sin_port) != 0) | 1605 | if (ntohs(((struct sockaddr_in *)args->dstaddr)->sin_port) != 0) |
1605 | xprt_set_bound(xprt); | 1606 | xprt_set_bound(xprt); |
1606 | 1607 | ||
1607 | xprt->prot = IPPROTO_TCP; | 1608 | xprt->prot = IPPROTO_TCP; |
@@ -1616,8 +1617,8 @@ struct rpc_xprt *xs_setup_tcp(struct sockaddr *addr, size_t addrlen, struct rpc_ | |||
1616 | 1617 | ||
1617 | xprt->ops = &xs_tcp_ops; | 1618 | xprt->ops = &xs_tcp_ops; |
1618 | 1619 | ||
1619 | if (to) | 1620 | if (args->timeout) |
1620 | xprt->timeout = *to; | 1621 | xprt->timeout = *args->timeout; |
1621 | else | 1622 | else |
1622 | xprt_set_timeout(&xprt->timeout, 2, 60 * HZ); | 1623 | xprt_set_timeout(&xprt->timeout, 2, 60 * HZ); |
1623 | 1624 | ||
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c index 77d2d9ce8962..711ca4b1f051 100644 --- a/net/tipc/eth_media.c +++ b/net/tipc/eth_media.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * net/tipc/eth_media.c: Ethernet bearer support for TIPC | 2 | * net/tipc/eth_media.c: Ethernet bearer support for TIPC |
3 | * | 3 | * |
4 | * Copyright (c) 2001-2006, Ericsson AB | 4 | * Copyright (c) 2001-2007, Ericsson AB |
5 | * Copyright (c) 2005-2006, Wind River Systems | 5 | * Copyright (c) 2005-2007, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
@@ -87,6 +87,9 @@ static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr, | |||
87 | /** | 87 | /** |
88 | * recv_msg - handle incoming TIPC message from an Ethernet interface | 88 | * recv_msg - handle incoming TIPC message from an Ethernet interface |
89 | * | 89 | * |
90 | * Accept only packets explicitly sent to this node, or broadcast packets; | ||
91 | * ignores packets sent using Ethernet multicast, and traffic sent to other | ||
92 | * nodes (which can happen if interface is running in promiscuous mode). | ||
90 | * Routine truncates any Ethernet padding/CRC appended to the message, | 93 | * Routine truncates any Ethernet padding/CRC appended to the message, |
91 | * and ensures message size matches actual length | 94 | * and ensures message size matches actual length |
92 | */ | 95 | */ |
@@ -98,9 +101,7 @@ static int recv_msg(struct sk_buff *buf, struct net_device *dev, | |||
98 | u32 size; | 101 | u32 size; |
99 | 102 | ||
100 | if (likely(eb_ptr->bearer)) { | 103 | if (likely(eb_ptr->bearer)) { |
101 | if (likely(!dev->promiscuity) || | 104 | if (likely(buf->pkt_type <= PACKET_BROADCAST)) { |
102 | !memcmp(skb_mac_header(buf), dev->dev_addr, ETH_ALEN) || | ||
103 | !memcmp(skb_mac_header(buf), dev->broadcast, ETH_ALEN)) { | ||
104 | size = msg_size((struct tipc_msg *)buf->data); | 105 | size = msg_size((struct tipc_msg *)buf->data); |
105 | skb_trim(buf, size); | 106 | skb_trim(buf, size); |
106 | if (likely(buf->len == size)) { | 107 | if (likely(buf->len == size)) { |
diff --git a/net/tipc/link.c b/net/tipc/link.c index 2124f32ef29f..5adfdfd49d61 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * net/tipc/link.c: TIPC link code | 2 | * net/tipc/link.c: TIPC link code |
3 | * | 3 | * |
4 | * Copyright (c) 1996-2006, Ericsson AB | 4 | * Copyright (c) 1996-2007, Ericsson AB |
5 | * Copyright (c) 2004-2006, Wind River Systems | 5 | * Copyright (c) 2004-2007, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
@@ -1260,7 +1260,7 @@ again: | |||
1260 | * (Must not hold any locks while building message.) | 1260 | * (Must not hold any locks while building message.) |
1261 | */ | 1261 | */ |
1262 | 1262 | ||
1263 | res = msg_build(hdr, msg_sect, num_sect, sender->max_pkt, | 1263 | res = msg_build(hdr, msg_sect, num_sect, sender->publ.max_pkt, |
1264 | !sender->user_port, &buf); | 1264 | !sender->user_port, &buf); |
1265 | 1265 | ||
1266 | read_lock_bh(&tipc_net_lock); | 1266 | read_lock_bh(&tipc_net_lock); |
@@ -1271,7 +1271,7 @@ again: | |||
1271 | if (likely(l_ptr)) { | 1271 | if (likely(l_ptr)) { |
1272 | if (likely(buf)) { | 1272 | if (likely(buf)) { |
1273 | res = link_send_buf_fast(l_ptr, buf, | 1273 | res = link_send_buf_fast(l_ptr, buf, |
1274 | &sender->max_pkt); | 1274 | &sender->publ.max_pkt); |
1275 | if (unlikely(res < 0)) | 1275 | if (unlikely(res < 0)) |
1276 | buf_discard(buf); | 1276 | buf_discard(buf); |
1277 | exit: | 1277 | exit: |
@@ -1299,12 +1299,12 @@ exit: | |||
1299 | * then re-try fast path or fragment the message | 1299 | * then re-try fast path or fragment the message |
1300 | */ | 1300 | */ |
1301 | 1301 | ||
1302 | sender->max_pkt = link_max_pkt(l_ptr); | 1302 | sender->publ.max_pkt = link_max_pkt(l_ptr); |
1303 | tipc_node_unlock(node); | 1303 | tipc_node_unlock(node); |
1304 | read_unlock_bh(&tipc_net_lock); | 1304 | read_unlock_bh(&tipc_net_lock); |
1305 | 1305 | ||
1306 | 1306 | ||
1307 | if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt) | 1307 | if ((msg_hdr_sz(hdr) + res) <= sender->publ.max_pkt) |
1308 | goto again; | 1308 | goto again; |
1309 | 1309 | ||
1310 | return link_send_sections_long(sender, msg_sect, | 1310 | return link_send_sections_long(sender, msg_sect, |
@@ -1357,7 +1357,7 @@ static int link_send_sections_long(struct port *sender, | |||
1357 | 1357 | ||
1358 | again: | 1358 | again: |
1359 | fragm_no = 1; | 1359 | fragm_no = 1; |
1360 | max_pkt = sender->max_pkt - INT_H_SIZE; | 1360 | max_pkt = sender->publ.max_pkt - INT_H_SIZE; |
1361 | /* leave room for tunnel header in case of link changeover */ | 1361 | /* leave room for tunnel header in case of link changeover */ |
1362 | fragm_sz = max_pkt - INT_H_SIZE; | 1362 | fragm_sz = max_pkt - INT_H_SIZE; |
1363 | /* leave room for fragmentation header in each fragment */ | 1363 | /* leave room for fragmentation header in each fragment */ |
@@ -1463,7 +1463,7 @@ error: | |||
1463 | goto reject; | 1463 | goto reject; |
1464 | } | 1464 | } |
1465 | if (link_max_pkt(l_ptr) < max_pkt) { | 1465 | if (link_max_pkt(l_ptr) < max_pkt) { |
1466 | sender->max_pkt = link_max_pkt(l_ptr); | 1466 | sender->publ.max_pkt = link_max_pkt(l_ptr); |
1467 | tipc_node_unlock(node); | 1467 | tipc_node_unlock(node); |
1468 | for (; buf_chain; buf_chain = buf) { | 1468 | for (; buf_chain; buf_chain = buf) { |
1469 | buf = buf_chain->next; | 1469 | buf = buf_chain->next; |
diff --git a/net/tipc/port.c b/net/tipc/port.c index bcd5da00737b..5d2b9ce84d0a 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * net/tipc/port.c: TIPC port code | 2 | * net/tipc/port.c: TIPC port code |
3 | * | 3 | * |
4 | * Copyright (c) 1992-2006, Ericsson AB | 4 | * Copyright (c) 1992-2007, Ericsson AB |
5 | * Copyright (c) 2004-2005, Wind River Systems | 5 | * Copyright (c) 2004-2007, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
@@ -239,6 +239,8 @@ u32 tipc_createport_raw(void *usr_handle, | |||
239 | } | 239 | } |
240 | 240 | ||
241 | tipc_port_lock(ref); | 241 | tipc_port_lock(ref); |
242 | p_ptr->publ.usr_handle = usr_handle; | ||
243 | p_ptr->publ.max_pkt = MAX_PKT_DEFAULT; | ||
242 | p_ptr->publ.ref = ref; | 244 | p_ptr->publ.ref = ref; |
243 | msg = &p_ptr->publ.phdr; | 245 | msg = &p_ptr->publ.phdr; |
244 | msg_init(msg, DATA_LOW, TIPC_NAMED_MSG, TIPC_OK, LONG_H_SIZE, 0); | 246 | msg_init(msg, DATA_LOW, TIPC_NAMED_MSG, TIPC_OK, LONG_H_SIZE, 0); |
@@ -248,11 +250,9 @@ u32 tipc_createport_raw(void *usr_handle, | |||
248 | msg_set_importance(msg,importance); | 250 | msg_set_importance(msg,importance); |
249 | p_ptr->last_in_seqno = 41; | 251 | p_ptr->last_in_seqno = 41; |
250 | p_ptr->sent = 1; | 252 | p_ptr->sent = 1; |
251 | p_ptr->publ.usr_handle = usr_handle; | ||
252 | INIT_LIST_HEAD(&p_ptr->wait_list); | 253 | INIT_LIST_HEAD(&p_ptr->wait_list); |
253 | INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list); | 254 | INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list); |
254 | p_ptr->congested_link = NULL; | 255 | p_ptr->congested_link = NULL; |
255 | p_ptr->max_pkt = MAX_PKT_DEFAULT; | ||
256 | p_ptr->dispatcher = dispatcher; | 256 | p_ptr->dispatcher = dispatcher; |
257 | p_ptr->wakeup = wakeup; | 257 | p_ptr->wakeup = wakeup; |
258 | p_ptr->user_port = NULL; | 258 | p_ptr->user_port = NULL; |
@@ -1243,7 +1243,7 @@ int tipc_connect2port(u32 ref, struct tipc_portid const *peer) | |||
1243 | res = TIPC_OK; | 1243 | res = TIPC_OK; |
1244 | exit: | 1244 | exit: |
1245 | tipc_port_unlock(p_ptr); | 1245 | tipc_port_unlock(p_ptr); |
1246 | p_ptr->max_pkt = tipc_link_get_max_pkt(peer->node, ref); | 1246 | p_ptr->publ.max_pkt = tipc_link_get_max_pkt(peer->node, ref); |
1247 | return res; | 1247 | return res; |
1248 | } | 1248 | } |
1249 | 1249 | ||
diff --git a/net/tipc/port.h b/net/tipc/port.h index 7ef4d64b32f7..e5f8c16429bd 100644 --- a/net/tipc/port.h +++ b/net/tipc/port.h | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * net/tipc/port.h: Include file for TIPC port code | 2 | * net/tipc/port.h: Include file for TIPC port code |
3 | * | 3 | * |
4 | * Copyright (c) 1994-2006, Ericsson AB | 4 | * Copyright (c) 1994-2007, Ericsson AB |
5 | * Copyright (c) 2004-2005, Wind River Systems | 5 | * Copyright (c) 2004-2007, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
@@ -81,7 +81,6 @@ struct user_port { | |||
81 | * @acked: | 81 | * @acked: |
82 | * @publications: list of publications for port | 82 | * @publications: list of publications for port |
83 | * @pub_count: total # of publications port has made during its lifetime | 83 | * @pub_count: total # of publications port has made during its lifetime |
84 | * @max_pkt: maximum packet size "hint" used when building messages sent by port | ||
85 | * @probing_state: | 84 | * @probing_state: |
86 | * @probing_interval: | 85 | * @probing_interval: |
87 | * @last_in_seqno: | 86 | * @last_in_seqno: |
@@ -102,7 +101,6 @@ struct port { | |||
102 | u32 acked; | 101 | u32 acked; |
103 | struct list_head publications; | 102 | struct list_head publications; |
104 | u32 pub_count; | 103 | u32 pub_count; |
105 | u32 max_pkt; | ||
106 | u32 probing_state; | 104 | u32 probing_state; |
107 | u32 probing_interval; | 105 | u32 probing_interval; |
108 | u32 last_in_seqno; | 106 | u32 last_in_seqno; |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 45832fb75ea4..4a8f37f48764 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * net/tipc/socket.c: TIPC socket API | 2 | * net/tipc/socket.c: TIPC socket API |
3 | * | 3 | * |
4 | * Copyright (c) 2001-2006, Ericsson AB | 4 | * Copyright (c) 2001-2007, Ericsson AB |
5 | * Copyright (c) 2004-2006, Wind River Systems | 5 | * Copyright (c) 2004-2007, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
@@ -607,23 +607,24 @@ exit: | |||
607 | static int send_stream(struct kiocb *iocb, struct socket *sock, | 607 | static int send_stream(struct kiocb *iocb, struct socket *sock, |
608 | struct msghdr *m, size_t total_len) | 608 | struct msghdr *m, size_t total_len) |
609 | { | 609 | { |
610 | struct tipc_port *tport; | ||
610 | struct msghdr my_msg; | 611 | struct msghdr my_msg; |
611 | struct iovec my_iov; | 612 | struct iovec my_iov; |
612 | struct iovec *curr_iov; | 613 | struct iovec *curr_iov; |
613 | int curr_iovlen; | 614 | int curr_iovlen; |
614 | char __user *curr_start; | 615 | char __user *curr_start; |
616 | u32 hdr_size; | ||
615 | int curr_left; | 617 | int curr_left; |
616 | int bytes_to_send; | 618 | int bytes_to_send; |
617 | int bytes_sent; | 619 | int bytes_sent; |
618 | int res; | 620 | int res; |
619 | 621 | ||
620 | if (likely(total_len <= TIPC_MAX_USER_MSG_SIZE)) | 622 | /* Handle special cases where there is no connection */ |
621 | return send_packet(iocb, sock, m, total_len); | ||
622 | |||
623 | /* Can only send large data streams if already connected */ | ||
624 | 623 | ||
625 | if (unlikely(sock->state != SS_CONNECTED)) { | 624 | if (unlikely(sock->state != SS_CONNECTED)) { |
626 | if (sock->state == SS_DISCONNECTING) | 625 | if (sock->state == SS_UNCONNECTED) |
626 | return send_packet(iocb, sock, m, total_len); | ||
627 | else if (sock->state == SS_DISCONNECTING) | ||
627 | return -EPIPE; | 628 | return -EPIPE; |
628 | else | 629 | else |
629 | return -ENOTCONN; | 630 | return -ENOTCONN; |
@@ -648,17 +649,25 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, | |||
648 | my_msg.msg_name = NULL; | 649 | my_msg.msg_name = NULL; |
649 | bytes_sent = 0; | 650 | bytes_sent = 0; |
650 | 651 | ||
652 | tport = tipc_sk(sock->sk)->p; | ||
653 | hdr_size = msg_hdr_sz(&tport->phdr); | ||
654 | |||
651 | while (curr_iovlen--) { | 655 | while (curr_iovlen--) { |
652 | curr_start = curr_iov->iov_base; | 656 | curr_start = curr_iov->iov_base; |
653 | curr_left = curr_iov->iov_len; | 657 | curr_left = curr_iov->iov_len; |
654 | 658 | ||
655 | while (curr_left) { | 659 | while (curr_left) { |
656 | bytes_to_send = (curr_left < TIPC_MAX_USER_MSG_SIZE) | 660 | bytes_to_send = tport->max_pkt - hdr_size; |
657 | ? curr_left : TIPC_MAX_USER_MSG_SIZE; | 661 | if (bytes_to_send > TIPC_MAX_USER_MSG_SIZE) |
662 | bytes_to_send = TIPC_MAX_USER_MSG_SIZE; | ||
663 | if (curr_left < bytes_to_send) | ||
664 | bytes_to_send = curr_left; | ||
658 | my_iov.iov_base = curr_start; | 665 | my_iov.iov_base = curr_start; |
659 | my_iov.iov_len = bytes_to_send; | 666 | my_iov.iov_len = bytes_to_send; |
660 | if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0) { | 667 | if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0) { |
661 | return bytes_sent ? bytes_sent : res; | 668 | if (bytes_sent != 0) |
669 | res = bytes_sent; | ||
670 | return res; | ||
662 | } | 671 | } |
663 | curr_left -= bytes_to_send; | 672 | curr_left -= bytes_to_send; |
664 | curr_start += bytes_to_send; | 673 | curr_start += bytes_to_send; |
@@ -1600,33 +1609,6 @@ static int getsockopt(struct socket *sock, | |||
1600 | } | 1609 | } |
1601 | 1610 | ||
1602 | /** | 1611 | /** |
1603 | * Placeholders for non-implemented functionality | ||
1604 | * | ||
1605 | * Returns error code (POSIX-compliant where defined) | ||
1606 | */ | ||
1607 | |||
1608 | static int ioctl(struct socket *s, u32 cmd, unsigned long arg) | ||
1609 | { | ||
1610 | return -EINVAL; | ||
1611 | } | ||
1612 | |||
1613 | static int no_mmap(struct file *file, struct socket *sock, | ||
1614 | struct vm_area_struct *vma) | ||
1615 | { | ||
1616 | return -EINVAL; | ||
1617 | } | ||
1618 | static ssize_t no_sendpage(struct socket *sock, struct page *page, | ||
1619 | int offset, size_t size, int flags) | ||
1620 | { | ||
1621 | return -EINVAL; | ||
1622 | } | ||
1623 | |||
1624 | static int no_skpair(struct socket *s1, struct socket *s2) | ||
1625 | { | ||
1626 | return -EOPNOTSUPP; | ||
1627 | } | ||
1628 | |||
1629 | /** | ||
1630 | * Protocol switches for the various types of TIPC sockets | 1612 | * Protocol switches for the various types of TIPC sockets |
1631 | */ | 1613 | */ |
1632 | 1614 | ||
@@ -1636,19 +1618,19 @@ static struct proto_ops msg_ops = { | |||
1636 | .release = release, | 1618 | .release = release, |
1637 | .bind = bind, | 1619 | .bind = bind, |
1638 | .connect = connect, | 1620 | .connect = connect, |
1639 | .socketpair = no_skpair, | 1621 | .socketpair = sock_no_socketpair, |
1640 | .accept = accept, | 1622 | .accept = accept, |
1641 | .getname = get_name, | 1623 | .getname = get_name, |
1642 | .poll = poll, | 1624 | .poll = poll, |
1643 | .ioctl = ioctl, | 1625 | .ioctl = sock_no_ioctl, |
1644 | .listen = listen, | 1626 | .listen = listen, |
1645 | .shutdown = shutdown, | 1627 | .shutdown = shutdown, |
1646 | .setsockopt = setsockopt, | 1628 | .setsockopt = setsockopt, |
1647 | .getsockopt = getsockopt, | 1629 | .getsockopt = getsockopt, |
1648 | .sendmsg = send_msg, | 1630 | .sendmsg = send_msg, |
1649 | .recvmsg = recv_msg, | 1631 | .recvmsg = recv_msg, |
1650 | .mmap = no_mmap, | 1632 | .mmap = sock_no_mmap, |
1651 | .sendpage = no_sendpage | 1633 | .sendpage = sock_no_sendpage |
1652 | }; | 1634 | }; |
1653 | 1635 | ||
1654 | static struct proto_ops packet_ops = { | 1636 | static struct proto_ops packet_ops = { |
@@ -1657,19 +1639,19 @@ static struct proto_ops packet_ops = { | |||
1657 | .release = release, | 1639 | .release = release, |
1658 | .bind = bind, | 1640 | .bind = bind, |
1659 | .connect = connect, | 1641 | .connect = connect, |
1660 | .socketpair = no_skpair, | 1642 | .socketpair = sock_no_socketpair, |
1661 | .accept = accept, | 1643 | .accept = accept, |
1662 | .getname = get_name, | 1644 | .getname = get_name, |
1663 | .poll = poll, | 1645 | .poll = poll, |
1664 | .ioctl = ioctl, | 1646 | .ioctl = sock_no_ioctl, |
1665 | .listen = listen, | 1647 | .listen = listen, |
1666 | .shutdown = shutdown, | 1648 | .shutdown = shutdown, |
1667 | .setsockopt = setsockopt, | 1649 | .setsockopt = setsockopt, |
1668 | .getsockopt = getsockopt, | 1650 | .getsockopt = getsockopt, |
1669 | .sendmsg = send_packet, | 1651 | .sendmsg = send_packet, |
1670 | .recvmsg = recv_msg, | 1652 | .recvmsg = recv_msg, |
1671 | .mmap = no_mmap, | 1653 | .mmap = sock_no_mmap, |
1672 | .sendpage = no_sendpage | 1654 | .sendpage = sock_no_sendpage |
1673 | }; | 1655 | }; |
1674 | 1656 | ||
1675 | static struct proto_ops stream_ops = { | 1657 | static struct proto_ops stream_ops = { |
@@ -1678,19 +1660,19 @@ static struct proto_ops stream_ops = { | |||
1678 | .release = release, | 1660 | .release = release, |
1679 | .bind = bind, | 1661 | .bind = bind, |
1680 | .connect = connect, | 1662 | .connect = connect, |
1681 | .socketpair = no_skpair, | 1663 | .socketpair = sock_no_socketpair, |
1682 | .accept = accept, | 1664 | .accept = accept, |
1683 | .getname = get_name, | 1665 | .getname = get_name, |
1684 | .poll = poll, | 1666 | .poll = poll, |
1685 | .ioctl = ioctl, | 1667 | .ioctl = sock_no_ioctl, |
1686 | .listen = listen, | 1668 | .listen = listen, |
1687 | .shutdown = shutdown, | 1669 | .shutdown = shutdown, |
1688 | .setsockopt = setsockopt, | 1670 | .setsockopt = setsockopt, |
1689 | .getsockopt = getsockopt, | 1671 | .getsockopt = getsockopt, |
1690 | .sendmsg = send_stream, | 1672 | .sendmsg = send_stream, |
1691 | .recvmsg = recv_stream, | 1673 | .recvmsg = recv_stream, |
1692 | .mmap = no_mmap, | 1674 | .mmap = sock_no_mmap, |
1693 | .sendpage = no_sendpage | 1675 | .sendpage = sock_no_sendpage |
1694 | }; | 1676 | }; |
1695 | 1677 | ||
1696 | static struct net_proto_family tipc_family_ops = { | 1678 | static struct net_proto_family tipc_family_ops = { |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index d70fa30d4294..65ebccc0a698 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -592,7 +592,8 @@ static struct sock * unix_create1(struct socket *sock) | |||
592 | u->dentry = NULL; | 592 | u->dentry = NULL; |
593 | u->mnt = NULL; | 593 | u->mnt = NULL; |
594 | spin_lock_init(&u->lock); | 594 | spin_lock_init(&u->lock); |
595 | atomic_set(&u->inflight, sock ? 0 : -1); | 595 | atomic_set(&u->inflight, 0); |
596 | INIT_LIST_HEAD(&u->link); | ||
596 | mutex_init(&u->readlock); /* single task reading lock */ | 597 | mutex_init(&u->readlock); /* single task reading lock */ |
597 | init_waitqueue_head(&u->peer_wait); | 598 | init_waitqueue_head(&u->peer_wait); |
598 | unix_insert_socket(unix_sockets_unbound, sk); | 599 | unix_insert_socket(unix_sockets_unbound, sk); |
@@ -1134,9 +1135,6 @@ restart: | |||
1134 | /* take ten and and send info to listening sock */ | 1135 | /* take ten and and send info to listening sock */ |
1135 | spin_lock(&other->sk_receive_queue.lock); | 1136 | spin_lock(&other->sk_receive_queue.lock); |
1136 | __skb_queue_tail(&other->sk_receive_queue, skb); | 1137 | __skb_queue_tail(&other->sk_receive_queue, skb); |
1137 | /* Undo artificially decreased inflight after embrion | ||
1138 | * is installed to listening socket. */ | ||
1139 | atomic_inc(&newu->inflight); | ||
1140 | spin_unlock(&other->sk_receive_queue.lock); | 1138 | spin_unlock(&other->sk_receive_queue.lock); |
1141 | unix_state_unlock(other); | 1139 | unix_state_unlock(other); |
1142 | other->sk_data_ready(other, 0); | 1140 | other->sk_data_ready(other, 0); |
@@ -2048,7 +2046,7 @@ static int unix_seq_show(struct seq_file *seq, void *v) | |||
2048 | return 0; | 2046 | return 0; |
2049 | } | 2047 | } |
2050 | 2048 | ||
2051 | static struct seq_operations unix_seq_ops = { | 2049 | static const struct seq_operations unix_seq_ops = { |
2052 | .start = unix_seq_start, | 2050 | .start = unix_seq_start, |
2053 | .next = unix_seq_next, | 2051 | .next = unix_seq_next, |
2054 | .stop = unix_seq_stop, | 2052 | .stop = unix_seq_stop, |
diff --git a/net/unix/garbage.c b/net/unix/garbage.c index f20b7ea7c555..406b6433e467 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c | |||
@@ -62,6 +62,10 @@ | |||
62 | * AV 1 Mar 1999 | 62 | * AV 1 Mar 1999 |
63 | * Damn. Added missing check for ->dead in listen queues scanning. | 63 | * Damn. Added missing check for ->dead in listen queues scanning. |
64 | * | 64 | * |
65 | * Miklos Szeredi 25 Jun 2007 | ||
66 | * Reimplement with a cycle collecting algorithm. This should | ||
67 | * solve several problems with the previous code, like being racy | ||
68 | * wrt receive and holding up unrelated socket operations. | ||
65 | */ | 69 | */ |
66 | 70 | ||
67 | #include <linux/kernel.h> | 71 | #include <linux/kernel.h> |
@@ -84,10 +88,9 @@ | |||
84 | 88 | ||
85 | /* Internal data structures and random procedures: */ | 89 | /* Internal data structures and random procedures: */ |
86 | 90 | ||
87 | #define GC_HEAD ((struct sock *)(-1)) | 91 | static LIST_HEAD(gc_inflight_list); |
88 | #define GC_ORPHAN ((struct sock *)(-3)) | 92 | static LIST_HEAD(gc_candidates); |
89 | 93 | static DEFINE_SPINLOCK(unix_gc_lock); | |
90 | static struct sock *gc_current = GC_HEAD; /* stack of objects to mark */ | ||
91 | 94 | ||
92 | atomic_t unix_tot_inflight = ATOMIC_INIT(0); | 95 | atomic_t unix_tot_inflight = ATOMIC_INIT(0); |
93 | 96 | ||
@@ -122,8 +125,16 @@ void unix_inflight(struct file *fp) | |||
122 | { | 125 | { |
123 | struct sock *s = unix_get_socket(fp); | 126 | struct sock *s = unix_get_socket(fp); |
124 | if(s) { | 127 | if(s) { |
125 | atomic_inc(&unix_sk(s)->inflight); | 128 | struct unix_sock *u = unix_sk(s); |
129 | spin_lock(&unix_gc_lock); | ||
130 | if (atomic_inc_return(&u->inflight) == 1) { | ||
131 | BUG_ON(!list_empty(&u->link)); | ||
132 | list_add_tail(&u->link, &gc_inflight_list); | ||
133 | } else { | ||
134 | BUG_ON(list_empty(&u->link)); | ||
135 | } | ||
126 | atomic_inc(&unix_tot_inflight); | 136 | atomic_inc(&unix_tot_inflight); |
137 | spin_unlock(&unix_gc_lock); | ||
127 | } | 138 | } |
128 | } | 139 | } |
129 | 140 | ||
@@ -131,182 +142,218 @@ void unix_notinflight(struct file *fp) | |||
131 | { | 142 | { |
132 | struct sock *s = unix_get_socket(fp); | 143 | struct sock *s = unix_get_socket(fp); |
133 | if(s) { | 144 | if(s) { |
134 | atomic_dec(&unix_sk(s)->inflight); | 145 | struct unix_sock *u = unix_sk(s); |
146 | spin_lock(&unix_gc_lock); | ||
147 | BUG_ON(list_empty(&u->link)); | ||
148 | if (atomic_dec_and_test(&u->inflight)) | ||
149 | list_del_init(&u->link); | ||
135 | atomic_dec(&unix_tot_inflight); | 150 | atomic_dec(&unix_tot_inflight); |
151 | spin_unlock(&unix_gc_lock); | ||
136 | } | 152 | } |
137 | } | 153 | } |
138 | 154 | ||
155 | static inline struct sk_buff *sock_queue_head(struct sock *sk) | ||
156 | { | ||
157 | return (struct sk_buff *) &sk->sk_receive_queue; | ||
158 | } | ||
139 | 159 | ||
140 | /* | 160 | #define receive_queue_for_each_skb(sk, next, skb) \ |
141 | * Garbage Collector Support Functions | 161 | for (skb = sock_queue_head(sk)->next, next = skb->next; \ |
142 | */ | 162 | skb != sock_queue_head(sk); skb = next, next = skb->next) |
143 | 163 | ||
144 | static inline struct sock *pop_stack(void) | 164 | static void scan_inflight(struct sock *x, void (*func)(struct sock *), |
165 | struct sk_buff_head *hitlist) | ||
145 | { | 166 | { |
146 | struct sock *p = gc_current; | 167 | struct sk_buff *skb; |
147 | gc_current = unix_sk(p)->gc_tree; | 168 | struct sk_buff *next; |
148 | return p; | 169 | |
170 | spin_lock(&x->sk_receive_queue.lock); | ||
171 | receive_queue_for_each_skb(x, next, skb) { | ||
172 | /* | ||
173 | * Do we have file descriptors ? | ||
174 | */ | ||
175 | if (UNIXCB(skb).fp) { | ||
176 | bool hit = false; | ||
177 | /* | ||
178 | * Process the descriptors of this socket | ||
179 | */ | ||
180 | int nfd = UNIXCB(skb).fp->count; | ||
181 | struct file **fp = UNIXCB(skb).fp->fp; | ||
182 | while (nfd--) { | ||
183 | /* | ||
184 | * Get the socket the fd matches | ||
185 | * if it indeed does so | ||
186 | */ | ||
187 | struct sock *sk = unix_get_socket(*fp++); | ||
188 | if(sk) { | ||
189 | hit = true; | ||
190 | func(sk); | ||
191 | } | ||
192 | } | ||
193 | if (hit && hitlist != NULL) { | ||
194 | __skb_unlink(skb, &x->sk_receive_queue); | ||
195 | __skb_queue_tail(hitlist, skb); | ||
196 | } | ||
197 | } | ||
198 | } | ||
199 | spin_unlock(&x->sk_receive_queue.lock); | ||
149 | } | 200 | } |
150 | 201 | ||
151 | static inline int empty_stack(void) | 202 | static void scan_children(struct sock *x, void (*func)(struct sock *), |
203 | struct sk_buff_head *hitlist) | ||
152 | { | 204 | { |
153 | return gc_current == GC_HEAD; | 205 | if (x->sk_state != TCP_LISTEN) |
206 | scan_inflight(x, func, hitlist); | ||
207 | else { | ||
208 | struct sk_buff *skb; | ||
209 | struct sk_buff *next; | ||
210 | struct unix_sock *u; | ||
211 | LIST_HEAD(embryos); | ||
212 | |||
213 | /* | ||
214 | * For a listening socket collect the queued embryos | ||
215 | * and perform a scan on them as well. | ||
216 | */ | ||
217 | spin_lock(&x->sk_receive_queue.lock); | ||
218 | receive_queue_for_each_skb(x, next, skb) { | ||
219 | u = unix_sk(skb->sk); | ||
220 | |||
221 | /* | ||
222 | * An embryo cannot be in-flight, so it's safe | ||
223 | * to use the list link. | ||
224 | */ | ||
225 | BUG_ON(!list_empty(&u->link)); | ||
226 | list_add_tail(&u->link, &embryos); | ||
227 | } | ||
228 | spin_unlock(&x->sk_receive_queue.lock); | ||
229 | |||
230 | while (!list_empty(&embryos)) { | ||
231 | u = list_entry(embryos.next, struct unix_sock, link); | ||
232 | scan_inflight(&u->sk, func, hitlist); | ||
233 | list_del_init(&u->link); | ||
234 | } | ||
235 | } | ||
154 | } | 236 | } |
155 | 237 | ||
156 | static void maybe_unmark_and_push(struct sock *x) | 238 | static void dec_inflight(struct sock *sk) |
157 | { | 239 | { |
158 | struct unix_sock *u = unix_sk(x); | 240 | atomic_dec(&unix_sk(sk)->inflight); |
241 | } | ||
159 | 242 | ||
160 | if (u->gc_tree != GC_ORPHAN) | 243 | static void inc_inflight(struct sock *sk) |
161 | return; | 244 | { |
162 | sock_hold(x); | 245 | atomic_inc(&unix_sk(sk)->inflight); |
163 | u->gc_tree = gc_current; | ||
164 | gc_current = x; | ||
165 | } | 246 | } |
166 | 247 | ||
248 | static void inc_inflight_move_tail(struct sock *sk) | ||
249 | { | ||
250 | struct unix_sock *u = unix_sk(sk); | ||
251 | |||
252 | atomic_inc(&u->inflight); | ||
253 | /* | ||
254 | * If this is still a candidate, move it to the end of the | ||
255 | * list, so that it's checked even if it was already passed | ||
256 | * over | ||
257 | */ | ||
258 | if (u->gc_candidate) | ||
259 | list_move_tail(&u->link, &gc_candidates); | ||
260 | } | ||
167 | 261 | ||
168 | /* The external entry point: unix_gc() */ | 262 | /* The external entry point: unix_gc() */ |
169 | 263 | ||
170 | void unix_gc(void) | 264 | void unix_gc(void) |
171 | { | 265 | { |
172 | static DEFINE_MUTEX(unix_gc_sem); | 266 | static bool gc_in_progress = false; |
173 | int i; | ||
174 | struct sock *s; | ||
175 | struct sk_buff_head hitlist; | ||
176 | struct sk_buff *skb; | ||
177 | 267 | ||
178 | /* | 268 | struct unix_sock *u; |
179 | * Avoid a recursive GC. | 269 | struct unix_sock *next; |
180 | */ | 270 | struct sk_buff_head hitlist; |
271 | struct list_head cursor; | ||
181 | 272 | ||
182 | if (!mutex_trylock(&unix_gc_sem)) | 273 | spin_lock(&unix_gc_lock); |
183 | return; | ||
184 | 274 | ||
185 | spin_lock(&unix_table_lock); | 275 | /* Avoid a recursive GC. */ |
276 | if (gc_in_progress) | ||
277 | goto out; | ||
186 | 278 | ||
187 | forall_unix_sockets(i, s) | 279 | gc_in_progress = true; |
188 | { | ||
189 | unix_sk(s)->gc_tree = GC_ORPHAN; | ||
190 | } | ||
191 | /* | 280 | /* |
192 | * Everything is now marked | 281 | * First, select candidates for garbage collection. Only |
193 | */ | 282 | * in-flight sockets are considered, and from those only ones |
194 | 283 | * which don't have any external reference. | |
195 | /* Invariant to be maintained: | 284 | * |
196 | - everything unmarked is either: | 285 | * Holding unix_gc_lock will protect these candidates from |
197 | -- (a) on the stack, or | 286 | * being detached, and hence from gaining an external |
198 | -- (b) has all of its children unmarked | 287 | * reference. This also means, that since there are no |
199 | - everything on the stack is always unmarked | 288 | * possible receivers, the receive queues of these sockets are |
200 | - nothing is ever pushed onto the stack twice, because: | 289 | * static during the GC, even though the dequeue is done |
201 | -- nothing previously unmarked is ever pushed on the stack | 290 | * before the detach without atomicity guarantees. |
202 | */ | 291 | */ |
292 | list_for_each_entry_safe(u, next, &gc_inflight_list, link) { | ||
293 | int total_refs; | ||
294 | int inflight_refs; | ||
295 | |||
296 | total_refs = file_count(u->sk.sk_socket->file); | ||
297 | inflight_refs = atomic_read(&u->inflight); | ||
298 | |||
299 | BUG_ON(inflight_refs < 1); | ||
300 | BUG_ON(total_refs < inflight_refs); | ||
301 | if (total_refs == inflight_refs) { | ||
302 | list_move_tail(&u->link, &gc_candidates); | ||
303 | u->gc_candidate = 1; | ||
304 | } | ||
305 | } | ||
203 | 306 | ||
204 | /* | 307 | /* |
205 | * Push root set | 308 | * Now remove all internal in-flight reference to children of |
309 | * the candidates. | ||
206 | */ | 310 | */ |
207 | 311 | list_for_each_entry(u, &gc_candidates, link) | |
208 | forall_unix_sockets(i, s) | 312 | scan_children(&u->sk, dec_inflight, NULL); |
209 | { | ||
210 | int open_count = 0; | ||
211 | |||
212 | /* | ||
213 | * If all instances of the descriptor are not | ||
214 | * in flight we are in use. | ||
215 | * | ||
216 | * Special case: when socket s is embrion, it may be | ||
217 | * hashed but still not in queue of listening socket. | ||
218 | * In this case (see unix_create1()) we set artificial | ||
219 | * negative inflight counter to close race window. | ||
220 | * It is trick of course and dirty one. | ||
221 | */ | ||
222 | if (s->sk_socket && s->sk_socket->file) | ||
223 | open_count = file_count(s->sk_socket->file); | ||
224 | if (open_count > atomic_read(&unix_sk(s)->inflight)) | ||
225 | maybe_unmark_and_push(s); | ||
226 | } | ||
227 | 313 | ||
228 | /* | 314 | /* |
229 | * Mark phase | 315 | * Restore the references for children of all candidates, |
316 | * which have remaining references. Do this recursively, so | ||
317 | * only those remain, which form cyclic references. | ||
318 | * | ||
319 | * Use a "cursor" link, to make the list traversal safe, even | ||
320 | * though elements might be moved about. | ||
230 | */ | 321 | */ |
322 | list_add(&cursor, &gc_candidates); | ||
323 | while (cursor.next != &gc_candidates) { | ||
324 | u = list_entry(cursor.next, struct unix_sock, link); | ||
231 | 325 | ||
232 | while (!empty_stack()) | 326 | /* Move cursor to after the current position. */ |
233 | { | 327 | list_move(&cursor, &u->link); |
234 | struct sock *x = pop_stack(); | ||
235 | struct sock *sk; | ||
236 | |||
237 | spin_lock(&x->sk_receive_queue.lock); | ||
238 | skb = skb_peek(&x->sk_receive_queue); | ||
239 | |||
240 | /* | ||
241 | * Loop through all but first born | ||
242 | */ | ||
243 | 328 | ||
244 | while (skb && skb != (struct sk_buff *)&x->sk_receive_queue) { | 329 | if (atomic_read(&u->inflight) > 0) { |
245 | /* | 330 | list_move_tail(&u->link, &gc_inflight_list); |
246 | * Do we have file descriptors ? | 331 | u->gc_candidate = 0; |
247 | */ | 332 | scan_children(&u->sk, inc_inflight_move_tail, NULL); |
248 | if(UNIXCB(skb).fp) | ||
249 | { | ||
250 | /* | ||
251 | * Process the descriptors of this socket | ||
252 | */ | ||
253 | int nfd=UNIXCB(skb).fp->count; | ||
254 | struct file **fp = UNIXCB(skb).fp->fp; | ||
255 | while(nfd--) | ||
256 | { | ||
257 | /* | ||
258 | * Get the socket the fd matches if | ||
259 | * it indeed does so | ||
260 | */ | ||
261 | if((sk=unix_get_socket(*fp++))!=NULL) | ||
262 | { | ||
263 | maybe_unmark_and_push(sk); | ||
264 | } | ||
265 | } | ||
266 | } | ||
267 | /* We have to scan not-yet-accepted ones too */ | ||
268 | if (x->sk_state == TCP_LISTEN) | ||
269 | maybe_unmark_and_push(skb->sk); | ||
270 | skb=skb->next; | ||
271 | } | 333 | } |
272 | spin_unlock(&x->sk_receive_queue.lock); | ||
273 | sock_put(x); | ||
274 | } | 334 | } |
335 | list_del(&cursor); | ||
275 | 336 | ||
337 | /* | ||
338 | * Now gc_candidates contains only garbage. Restore original | ||
339 | * inflight counters for these as well, and remove the skbuffs | ||
340 | * which are creating the cycle(s). | ||
341 | */ | ||
276 | skb_queue_head_init(&hitlist); | 342 | skb_queue_head_init(&hitlist); |
343 | list_for_each_entry(u, &gc_candidates, link) | ||
344 | scan_children(&u->sk, inc_inflight, &hitlist); | ||
277 | 345 | ||
278 | forall_unix_sockets(i, s) | 346 | spin_unlock(&unix_gc_lock); |
279 | { | ||
280 | struct unix_sock *u = unix_sk(s); | ||
281 | 347 | ||
282 | if (u->gc_tree == GC_ORPHAN) { | 348 | /* Here we are. Hitlist is filled. Die. */ |
283 | struct sk_buff *nextsk; | 349 | __skb_queue_purge(&hitlist); |
284 | 350 | ||
285 | spin_lock(&s->sk_receive_queue.lock); | 351 | spin_lock(&unix_gc_lock); |
286 | skb = skb_peek(&s->sk_receive_queue); | ||
287 | while (skb && | ||
288 | skb != (struct sk_buff *)&s->sk_receive_queue) { | ||
289 | nextsk = skb->next; | ||
290 | /* | ||
291 | * Do we have file descriptors ? | ||
292 | */ | ||
293 | if (UNIXCB(skb).fp) { | ||
294 | __skb_unlink(skb, | ||
295 | &s->sk_receive_queue); | ||
296 | __skb_queue_tail(&hitlist, skb); | ||
297 | } | ||
298 | skb = nextsk; | ||
299 | } | ||
300 | spin_unlock(&s->sk_receive_queue.lock); | ||
301 | } | ||
302 | u->gc_tree = GC_ORPHAN; | ||
303 | } | ||
304 | spin_unlock(&unix_table_lock); | ||
305 | 352 | ||
306 | /* | 353 | /* All candidates should have been detached by now. */ |
307 | * Here we are. Hitlist is filled. Die. | 354 | BUG_ON(!list_empty(&gc_candidates)); |
308 | */ | 355 | gc_in_progress = false; |
309 | 356 | ||
310 | __skb_queue_purge(&hitlist); | 357 | out: |
311 | mutex_unlock(&unix_gc_sem); | 358 | spin_unlock(&unix_gc_lock); |
312 | } | 359 | } |
diff --git a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c index 205106521ecb..236e7eaf1b7f 100644 --- a/net/wanrouter/wanproc.c +++ b/net/wanrouter/wanproc.c | |||
@@ -164,14 +164,14 @@ static int status_show(struct seq_file *m, void *v) | |||
164 | return 0; | 164 | return 0; |
165 | } | 165 | } |
166 | 166 | ||
167 | static struct seq_operations config_op = { | 167 | static const struct seq_operations config_op = { |
168 | .start = r_start, | 168 | .start = r_start, |
169 | .next = r_next, | 169 | .next = r_next, |
170 | .stop = r_stop, | 170 | .stop = r_stop, |
171 | .show = config_show, | 171 | .show = config_show, |
172 | }; | 172 | }; |
173 | 173 | ||
174 | static struct seq_operations status_op = { | 174 | static const struct seq_operations status_op = { |
175 | .start = r_start, | 175 | .start = r_start, |
176 | .next = r_next, | 176 | .next = r_next, |
177 | .stop = r_stop, | 177 | .stop = r_stop, |
diff --git a/net/wireless/Makefile b/net/wireless/Makefile index 3a96ae60271c..092116e390b6 100644 --- a/net/wireless/Makefile +++ b/net/wireless/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | obj-$(CONFIG_WIRELESS_EXT) += wext.o | 1 | obj-$(CONFIG_WIRELESS_EXT) += wext.o |
2 | obj-$(CONFIG_CFG80211) += cfg80211.o | 2 | obj-$(CONFIG_CFG80211) += cfg80211.o |
3 | 3 | ||
4 | cfg80211-y += core.o sysfs.o | 4 | cfg80211-y += core.o sysfs.o radiotap.o |
diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c new file mode 100644 index 000000000000..68c11d099917 --- /dev/null +++ b/net/wireless/radiotap.c | |||
@@ -0,0 +1,257 @@ | |||
1 | /* | ||
2 | * Radiotap parser | ||
3 | * | ||
4 | * Copyright 2007 Andy Green <andy@warmcat.com> | ||
5 | */ | ||
6 | |||
7 | #include <net/cfg80211.h> | ||
8 | #include <net/ieee80211_radiotap.h> | ||
9 | #include <asm/unaligned.h> | ||
10 | |||
11 | /* function prototypes and related defs are in include/net/cfg80211.h */ | ||
12 | |||
13 | /** | ||
14 | * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization | ||
15 | * @iterator: radiotap_iterator to initialize | ||
16 | * @radiotap_header: radiotap header to parse | ||
17 | * @max_length: total length we can parse into (eg, whole packet length) | ||
18 | * | ||
19 | * Returns: 0 or a negative error code if there is a problem. | ||
20 | * | ||
21 | * This function initializes an opaque iterator struct which can then | ||
22 | * be passed to ieee80211_radiotap_iterator_next() to visit every radiotap | ||
23 | * argument which is present in the header. It knows about extended | ||
24 | * present headers and handles them. | ||
25 | * | ||
26 | * How to use: | ||
27 | * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator | ||
28 | * struct ieee80211_radiotap_iterator (no need to init the struct beforehand) | ||
29 | * checking for a good 0 return code. Then loop calling | ||
30 | * __ieee80211_radiotap_iterator_next()... it returns either 0, | ||
31 | * -ENOENT if there are no more args to parse, or -EINVAL if there is a problem. | ||
32 | * The iterator's @this_arg member points to the start of the argument | ||
33 | * associated with the current argument index that is present, which can be | ||
34 | * found in the iterator's @this_arg_index member. This arg index corresponds | ||
35 | * to the IEEE80211_RADIOTAP_... defines. | ||
36 | * | ||
37 | * Radiotap header length: | ||
38 | * You can find the CPU-endian total radiotap header length in | ||
39 | * iterator->max_length after executing ieee80211_radiotap_iterator_init() | ||
40 | * successfully. | ||
41 | * | ||
42 | * Alignment Gotcha: | ||
43 | * You must take care when dereferencing iterator.this_arg | ||
44 | * for multibyte types... the pointer is not aligned. Use | ||
45 | * get_unaligned((type *)iterator.this_arg) to dereference | ||
46 | * iterator.this_arg for type "type" safely on all arches. | ||
47 | * | ||
48 | * Example code: | ||
49 | * See Documentation/networking/radiotap-headers.txt | ||
50 | */ | ||
51 | |||
52 | int ieee80211_radiotap_iterator_init( | ||
53 | struct ieee80211_radiotap_iterator *iterator, | ||
54 | struct ieee80211_radiotap_header *radiotap_header, | ||
55 | int max_length) | ||
56 | { | ||
57 | /* Linux only supports version 0 radiotap format */ | ||
58 | if (radiotap_header->it_version) | ||
59 | return -EINVAL; | ||
60 | |||
61 | /* sanity check for allowed length and radiotap length field */ | ||
62 | if (max_length < le16_to_cpu(get_unaligned(&radiotap_header->it_len))) | ||
63 | return -EINVAL; | ||
64 | |||
65 | iterator->rtheader = radiotap_header; | ||
66 | iterator->max_length = le16_to_cpu(get_unaligned( | ||
67 | &radiotap_header->it_len)); | ||
68 | iterator->arg_index = 0; | ||
69 | iterator->bitmap_shifter = le32_to_cpu(get_unaligned( | ||
70 | &radiotap_header->it_present)); | ||
71 | iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header); | ||
72 | iterator->this_arg = NULL; | ||
73 | |||
74 | /* find payload start allowing for extended bitmap(s) */ | ||
75 | |||
76 | if (unlikely(iterator->bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT))) { | ||
77 | while (le32_to_cpu(get_unaligned((__le32 *)iterator->arg)) & | ||
78 | (1<<IEEE80211_RADIOTAP_EXT)) { | ||
79 | iterator->arg += sizeof(u32); | ||
80 | |||
81 | /* | ||
82 | * check for insanity where the present bitmaps | ||
83 | * keep claiming to extend up to or even beyond the | ||
84 | * stated radiotap header length | ||
85 | */ | ||
86 | |||
87 | if (((ulong)iterator->arg - | ||
88 | (ulong)iterator->rtheader) > iterator->max_length) | ||
89 | return -EINVAL; | ||
90 | } | ||
91 | |||
92 | iterator->arg += sizeof(u32); | ||
93 | |||
94 | /* | ||
95 | * no need to check again for blowing past stated radiotap | ||
96 | * header length, because ieee80211_radiotap_iterator_next | ||
97 | * checks it before it is dereferenced | ||
98 | */ | ||
99 | } | ||
100 | |||
101 | /* we are all initialized happily */ | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | EXPORT_SYMBOL(ieee80211_radiotap_iterator_init); | ||
106 | |||
107 | |||
108 | /** | ||
109 | * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg | ||
110 | * @iterator: radiotap_iterator to move to next arg (if any) | ||
111 | * | ||
112 | * Returns: 0 if there is an argument to handle, | ||
113 | * -ENOENT if there are no more args or -EINVAL | ||
114 | * if there is something else wrong. | ||
115 | * | ||
116 | * This function provides the next radiotap arg index (IEEE80211_RADIOTAP_*) | ||
117 | * in @this_arg_index and sets @this_arg to point to the | ||
118 | * payload for the field. It takes care of alignment handling and extended | ||
119 | * present fields. @this_arg can be changed by the caller (eg, | ||
120 | * incremented to move inside a compound argument like | ||
121 | * IEEE80211_RADIOTAP_CHANNEL). The args pointed to are in | ||
122 | * little-endian format whatever the endianess of your CPU. | ||
123 | * | ||
124 | * Alignment Gotcha: | ||
125 | * You must take care when dereferencing iterator.this_arg | ||
126 | * for multibyte types... the pointer is not aligned. Use | ||
127 | * get_unaligned((type *)iterator.this_arg) to dereference | ||
128 | * iterator.this_arg for type "type" safely on all arches. | ||
129 | */ | ||
130 | |||
131 | int ieee80211_radiotap_iterator_next( | ||
132 | struct ieee80211_radiotap_iterator *iterator) | ||
133 | { | ||
134 | |||
135 | /* | ||
136 | * small length lookup table for all radiotap types we heard of | ||
137 | * starting from b0 in the bitmap, so we can walk the payload | ||
138 | * area of the radiotap header | ||
139 | * | ||
140 | * There is a requirement to pad args, so that args | ||
141 | * of a given length must begin at a boundary of that length | ||
142 | * -- but note that compound args are allowed (eg, 2 x u16 | ||
143 | * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not | ||
144 | * a reliable indicator of alignment requirement. | ||
145 | * | ||
146 | * upper nybble: content alignment for arg | ||
147 | * lower nybble: content length for arg | ||
148 | */ | ||
149 | |||
150 | static const u8 rt_sizes[] = { | ||
151 | [IEEE80211_RADIOTAP_TSFT] = 0x88, | ||
152 | [IEEE80211_RADIOTAP_FLAGS] = 0x11, | ||
153 | [IEEE80211_RADIOTAP_RATE] = 0x11, | ||
154 | [IEEE80211_RADIOTAP_CHANNEL] = 0x24, | ||
155 | [IEEE80211_RADIOTAP_FHSS] = 0x22, | ||
156 | [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 0x11, | ||
157 | [IEEE80211_RADIOTAP_DBM_ANTNOISE] = 0x11, | ||
158 | [IEEE80211_RADIOTAP_LOCK_QUALITY] = 0x22, | ||
159 | [IEEE80211_RADIOTAP_TX_ATTENUATION] = 0x22, | ||
160 | [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 0x22, | ||
161 | [IEEE80211_RADIOTAP_DBM_TX_POWER] = 0x11, | ||
162 | [IEEE80211_RADIOTAP_ANTENNA] = 0x11, | ||
163 | [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 0x11, | ||
164 | [IEEE80211_RADIOTAP_DB_ANTNOISE] = 0x11 | ||
165 | /* | ||
166 | * add more here as they are defined in | ||
167 | * include/net/ieee80211_radiotap.h | ||
168 | */ | ||
169 | }; | ||
170 | |||
171 | /* | ||
172 | * for every radiotap entry we can at | ||
173 | * least skip (by knowing the length)... | ||
174 | */ | ||
175 | |||
176 | while (iterator->arg_index < sizeof(rt_sizes)) { | ||
177 | int hit = 0; | ||
178 | int pad; | ||
179 | |||
180 | if (!(iterator->bitmap_shifter & 1)) | ||
181 | goto next_entry; /* arg not present */ | ||
182 | |||
183 | /* | ||
184 | * arg is present, account for alignment padding | ||
185 | * 8-bit args can be at any alignment | ||
186 | * 16-bit args must start on 16-bit boundary | ||
187 | * 32-bit args must start on 32-bit boundary | ||
188 | * 64-bit args must start on 64-bit boundary | ||
189 | * | ||
190 | * note that total arg size can differ from alignment of | ||
191 | * elements inside arg, so we use upper nybble of length | ||
192 | * table to base alignment on | ||
193 | * | ||
194 | * also note: these alignments are ** relative to the | ||
195 | * start of the radiotap header **. There is no guarantee | ||
196 | * that the radiotap header itself is aligned on any | ||
197 | * kind of boundary. | ||
198 | * | ||
199 | * the above is why get_unaligned() is used to dereference | ||
200 | * multibyte elements from the radiotap area | ||
201 | */ | ||
202 | |||
203 | pad = (((ulong)iterator->arg) - | ||
204 | ((ulong)iterator->rtheader)) & | ||
205 | ((rt_sizes[iterator->arg_index] >> 4) - 1); | ||
206 | |||
207 | if (pad) | ||
208 | iterator->arg += | ||
209 | (rt_sizes[iterator->arg_index] >> 4) - pad; | ||
210 | |||
211 | /* | ||
212 | * this is what we will return to user, but we need to | ||
213 | * move on first so next call has something fresh to test | ||
214 | */ | ||
215 | iterator->this_arg_index = iterator->arg_index; | ||
216 | iterator->this_arg = iterator->arg; | ||
217 | hit = 1; | ||
218 | |||
219 | /* internally move on the size of this arg */ | ||
220 | iterator->arg += rt_sizes[iterator->arg_index] & 0x0f; | ||
221 | |||
222 | /* | ||
223 | * check for insanity where we are given a bitmap that | ||
224 | * claims to have more arg content than the length of the | ||
225 | * radiotap section. We will normally end up equalling this | ||
226 | * max_length on the last arg, never exceeding it. | ||
227 | */ | ||
228 | |||
229 | if (((ulong)iterator->arg - (ulong)iterator->rtheader) > | ||
230 | iterator->max_length) | ||
231 | return -EINVAL; | ||
232 | |||
233 | next_entry: | ||
234 | iterator->arg_index++; | ||
235 | if (unlikely((iterator->arg_index & 31) == 0)) { | ||
236 | /* completed current u32 bitmap */ | ||
237 | if (iterator->bitmap_shifter & 1) { | ||
238 | /* b31 was set, there is more */ | ||
239 | /* move to next u32 bitmap */ | ||
240 | iterator->bitmap_shifter = le32_to_cpu( | ||
241 | get_unaligned(iterator->next_bitmap)); | ||
242 | iterator->next_bitmap++; | ||
243 | } else | ||
244 | /* no more bitmaps: end */ | ||
245 | iterator->arg_index = sizeof(rt_sizes); | ||
246 | } else /* just try the next bit */ | ||
247 | iterator->bitmap_shifter >>= 1; | ||
248 | |||
249 | /* if we found a valid arg earlier, return it now */ | ||
250 | if (hit) | ||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | /* we don't know how to handle any more args, we're done */ | ||
255 | return -ENOENT; | ||
256 | } | ||
257 | EXPORT_SYMBOL(ieee80211_radiotap_iterator_next); | ||
diff --git a/net/x25/x25_proc.c b/net/x25/x25_proc.c index 96001f0c64fc..7405b9c5b7f2 100644 --- a/net/x25/x25_proc.c +++ b/net/x25/x25_proc.c | |||
@@ -234,21 +234,21 @@ out: | |||
234 | return 0; | 234 | return 0; |
235 | } | 235 | } |
236 | 236 | ||
237 | static struct seq_operations x25_seq_route_ops = { | 237 | static const struct seq_operations x25_seq_route_ops = { |
238 | .start = x25_seq_route_start, | 238 | .start = x25_seq_route_start, |
239 | .next = x25_seq_route_next, | 239 | .next = x25_seq_route_next, |
240 | .stop = x25_seq_route_stop, | 240 | .stop = x25_seq_route_stop, |
241 | .show = x25_seq_route_show, | 241 | .show = x25_seq_route_show, |
242 | }; | 242 | }; |
243 | 243 | ||
244 | static struct seq_operations x25_seq_socket_ops = { | 244 | static const struct seq_operations x25_seq_socket_ops = { |
245 | .start = x25_seq_socket_start, | 245 | .start = x25_seq_socket_start, |
246 | .next = x25_seq_socket_next, | 246 | .next = x25_seq_socket_next, |
247 | .stop = x25_seq_socket_stop, | 247 | .stop = x25_seq_socket_stop, |
248 | .show = x25_seq_socket_show, | 248 | .show = x25_seq_socket_show, |
249 | }; | 249 | }; |
250 | 250 | ||
251 | static struct seq_operations x25_seq_forward_ops = { | 251 | static const struct seq_operations x25_seq_forward_ops = { |
252 | .start = x25_seq_forward_start, | 252 | .start = x25_seq_forward_start, |
253 | .next = x25_seq_forward_next, | 253 | .next = x25_seq_forward_next, |
254 | .stop = x25_seq_forward_stop, | 254 | .stop = x25_seq_forward_stop, |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index dfacb9c2a6e3..e070c3f938fb 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -686,6 +686,37 @@ out: | |||
686 | return x; | 686 | return x; |
687 | } | 687 | } |
688 | 688 | ||
689 | struct xfrm_state * | ||
690 | xfrm_stateonly_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | ||
691 | unsigned short family, u8 mode, u8 proto, u32 reqid) | ||
692 | { | ||
693 | unsigned int h = xfrm_dst_hash(daddr, saddr, reqid, family); | ||
694 | struct xfrm_state *rx = NULL, *x = NULL; | ||
695 | struct hlist_node *entry; | ||
696 | |||
697 | spin_lock(&xfrm_state_lock); | ||
698 | hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) { | ||
699 | if (x->props.family == family && | ||
700 | x->props.reqid == reqid && | ||
701 | !(x->props.flags & XFRM_STATE_WILDRECV) && | ||
702 | xfrm_state_addr_check(x, daddr, saddr, family) && | ||
703 | mode == x->props.mode && | ||
704 | proto == x->id.proto && | ||
705 | x->km.state == XFRM_STATE_VALID) { | ||
706 | rx = x; | ||
707 | break; | ||
708 | } | ||
709 | } | ||
710 | |||
711 | if (rx) | ||
712 | xfrm_state_hold(rx); | ||
713 | spin_unlock(&xfrm_state_lock); | ||
714 | |||
715 | |||
716 | return rx; | ||
717 | } | ||
718 | EXPORT_SYMBOL(xfrm_stateonly_find); | ||
719 | |||
689 | static void __xfrm_state_insert(struct xfrm_state *x) | 720 | static void __xfrm_state_insert(struct xfrm_state *x) |
690 | { | 721 | { |
691 | unsigned int h; | 722 | unsigned int h; |