diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /net/atm/br2684.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'net/atm/br2684.c')
-rw-r--r-- | net/atm/br2684.c | 102 |
1 files changed, 49 insertions, 53 deletions
diff --git a/net/atm/br2684.c b/net/atm/br2684.c index 26a646d4eb32..d6c7ceaf13e9 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c | |||
@@ -6,6 +6,8 @@ | |||
6 | * Eric Kinzie, 2006-2007, US Naval Research Laboratory | 6 | * Eric Kinzie, 2006-2007, US Naval Research Laboratory |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ | ||
10 | |||
9 | #include <linux/module.h> | 11 | #include <linux/module.h> |
10 | #include <linux/init.h> | 12 | #include <linux/init.h> |
11 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
@@ -15,7 +17,8 @@ | |||
15 | #include <linux/etherdevice.h> | 17 | #include <linux/etherdevice.h> |
16 | #include <linux/rtnetlink.h> | 18 | #include <linux/rtnetlink.h> |
17 | #include <linux/ip.h> | 19 | #include <linux/ip.h> |
18 | #include <asm/uaccess.h> | 20 | #include <linux/uaccess.h> |
21 | #include <linux/slab.h> | ||
19 | #include <net/arp.h> | 22 | #include <net/arp.h> |
20 | #include <linux/atm.h> | 23 | #include <linux/atm.h> |
21 | #include <linux/atmdev.h> | 24 | #include <linux/atmdev.h> |
@@ -26,20 +29,14 @@ | |||
26 | 29 | ||
27 | #include "common.h" | 30 | #include "common.h" |
28 | 31 | ||
29 | #ifdef SKB_DEBUG | ||
30 | static void skb_debug(const struct sk_buff *skb) | 32 | static void skb_debug(const struct sk_buff *skb) |
31 | { | 33 | { |
34 | #ifdef SKB_DEBUG | ||
32 | #define NUM2PRINT 50 | 35 | #define NUM2PRINT 50 |
33 | char buf[NUM2PRINT * 3 + 1]; /* 3 chars per byte */ | 36 | print_hex_dump(KERN_DEBUG, "br2684: skb: ", DUMP_OFFSET, |
34 | int i = 0; | 37 | 16, 1, skb->data, min(NUM2PRINT, skb->len), true); |
35 | for (i = 0; i < skb->len && i < NUM2PRINT; i++) { | ||
36 | sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]); | ||
37 | } | ||
38 | printk(KERN_DEBUG "br2684: skb: %s\n", buf); | ||
39 | } | ||
40 | #else | ||
41 | #define skb_debug(skb) do {} while (0) | ||
42 | #endif | 38 | #endif |
39 | } | ||
43 | 40 | ||
44 | #define BR2684_ETHERTYPE_LEN 2 | 41 | #define BR2684_ETHERTYPE_LEN 2 |
45 | #define BR2684_PAD_LEN 2 | 42 | #define BR2684_PAD_LEN 2 |
@@ -68,7 +65,7 @@ struct br2684_vcc { | |||
68 | struct atm_vcc *atmvcc; | 65 | struct atm_vcc *atmvcc; |
69 | struct net_device *device; | 66 | struct net_device *device; |
70 | /* keep old push, pop functions for chaining */ | 67 | /* keep old push, pop functions for chaining */ |
71 | void (*old_push) (struct atm_vcc * vcc, struct sk_buff * skb); | 68 | void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb); |
72 | void (*old_pop)(struct atm_vcc *vcc, struct sk_buff *skb); | 69 | void (*old_pop)(struct atm_vcc *vcc, struct sk_buff *skb); |
73 | enum br2684_encaps encaps; | 70 | enum br2684_encaps encaps; |
74 | struct list_head brvccs; | 71 | struct list_head brvccs; |
@@ -148,7 +145,7 @@ static void br2684_pop(struct atm_vcc *vcc, struct sk_buff *skb) | |||
148 | struct br2684_vcc *brvcc = BR2684_VCC(vcc); | 145 | struct br2684_vcc *brvcc = BR2684_VCC(vcc); |
149 | struct net_device *net_dev = skb->dev; | 146 | struct net_device *net_dev = skb->dev; |
150 | 147 | ||
151 | pr_debug("br2684_pop(vcc %p ; net_dev %p )\n", vcc, net_dev); | 148 | pr_debug("(vcc %p ; net_dev %p )\n", vcc, net_dev); |
152 | brvcc->old_pop(vcc, skb); | 149 | brvcc->old_pop(vcc, skb); |
153 | 150 | ||
154 | if (!net_dev) | 151 | if (!net_dev) |
@@ -244,7 +241,7 @@ static netdev_tx_t br2684_start_xmit(struct sk_buff *skb, | |||
244 | struct br2684_dev *brdev = BRPRIV(dev); | 241 | struct br2684_dev *brdev = BRPRIV(dev); |
245 | struct br2684_vcc *brvcc; | 242 | struct br2684_vcc *brvcc; |
246 | 243 | ||
247 | pr_debug("br2684_start_xmit, skb_dst(skb)=%p\n", skb_dst(skb)); | 244 | pr_debug("skb_dst(skb)=%p\n", skb_dst(skb)); |
248 | read_lock(&devs_lock); | 245 | read_lock(&devs_lock); |
249 | brvcc = pick_outgoing_vcc(skb, brdev); | 246 | brvcc = pick_outgoing_vcc(skb, brdev); |
250 | if (brvcc == NULL) { | 247 | if (brvcc == NULL) { |
@@ -300,7 +297,8 @@ static int br2684_setfilt(struct atm_vcc *atmvcc, void __user * arg) | |||
300 | struct br2684_dev *brdev; | 297 | struct br2684_dev *brdev; |
301 | read_lock(&devs_lock); | 298 | read_lock(&devs_lock); |
302 | brdev = BRPRIV(br2684_find_dev(&fs.ifspec)); | 299 | brdev = BRPRIV(br2684_find_dev(&fs.ifspec)); |
303 | if (brdev == NULL || list_empty(&brdev->brvccs) || brdev->brvccs.next != brdev->brvccs.prev) /* >1 VCC */ | 300 | if (brdev == NULL || list_empty(&brdev->brvccs) || |
301 | brdev->brvccs.next != brdev->brvccs.prev) /* >1 VCC */ | ||
304 | brvcc = NULL; | 302 | brvcc = NULL; |
305 | else | 303 | else |
306 | brvcc = list_entry_brvcc(brdev->brvccs.next); | 304 | brvcc = list_entry_brvcc(brdev->brvccs.next); |
@@ -352,7 +350,7 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) | |||
352 | struct net_device *net_dev = brvcc->device; | 350 | struct net_device *net_dev = brvcc->device; |
353 | struct br2684_dev *brdev = BRPRIV(net_dev); | 351 | struct br2684_dev *brdev = BRPRIV(net_dev); |
354 | 352 | ||
355 | pr_debug("br2684_push\n"); | 353 | pr_debug("\n"); |
356 | 354 | ||
357 | if (unlikely(skb == NULL)) { | 355 | if (unlikely(skb == NULL)) { |
358 | /* skb==NULL means VCC is being destroyed */ | 356 | /* skb==NULL means VCC is being destroyed */ |
@@ -376,29 +374,25 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) | |||
376 | __skb_trim(skb, skb->len - 4); | 374 | __skb_trim(skb, skb->len - 4); |
377 | 375 | ||
378 | /* accept packets that have "ipv[46]" in the snap header */ | 376 | /* accept packets that have "ipv[46]" in the snap header */ |
379 | if ((skb->len >= (sizeof(llc_oui_ipv4))) | 377 | if ((skb->len >= (sizeof(llc_oui_ipv4))) && |
380 | && | 378 | (memcmp(skb->data, llc_oui_ipv4, |
381 | (memcmp | 379 | sizeof(llc_oui_ipv4) - BR2684_ETHERTYPE_LEN) == 0)) { |
382 | (skb->data, llc_oui_ipv4, | 380 | if (memcmp(skb->data + 6, ethertype_ipv6, |
383 | sizeof(llc_oui_ipv4) - BR2684_ETHERTYPE_LEN) == 0)) { | 381 | sizeof(ethertype_ipv6)) == 0) |
384 | if (memcmp | ||
385 | (skb->data + 6, ethertype_ipv6, | ||
386 | sizeof(ethertype_ipv6)) == 0) | ||
387 | skb->protocol = htons(ETH_P_IPV6); | 382 | skb->protocol = htons(ETH_P_IPV6); |
388 | else if (memcmp | 383 | else if (memcmp(skb->data + 6, ethertype_ipv4, |
389 | (skb->data + 6, ethertype_ipv4, | 384 | sizeof(ethertype_ipv4)) == 0) |
390 | sizeof(ethertype_ipv4)) == 0) | ||
391 | skb->protocol = htons(ETH_P_IP); | 385 | skb->protocol = htons(ETH_P_IP); |
392 | else | 386 | else |
393 | goto error; | 387 | goto error; |
394 | skb_pull(skb, sizeof(llc_oui_ipv4)); | 388 | skb_pull(skb, sizeof(llc_oui_ipv4)); |
395 | skb_reset_network_header(skb); | 389 | skb_reset_network_header(skb); |
396 | skb->pkt_type = PACKET_HOST; | 390 | skb->pkt_type = PACKET_HOST; |
397 | /* | 391 | /* |
398 | * Let us waste some time for checking the encapsulation. | 392 | * Let us waste some time for checking the encapsulation. |
399 | * Note, that only 7 char is checked so frames with a valid FCS | 393 | * Note, that only 7 char is checked so frames with a valid FCS |
400 | * are also accepted (but FCS is not checked of course). | 394 | * are also accepted (but FCS is not checked of course). |
401 | */ | 395 | */ |
402 | } else if ((skb->len >= sizeof(llc_oui_pid_pad)) && | 396 | } else if ((skb->len >= sizeof(llc_oui_pid_pad)) && |
403 | (memcmp(skb->data, llc_oui_pid_pad, 7) == 0)) { | 397 | (memcmp(skb->data, llc_oui_pid_pad, 7) == 0)) { |
404 | skb_pull(skb, sizeof(llc_oui_pid_pad)); | 398 | skb_pull(skb, sizeof(llc_oui_pid_pad)); |
@@ -479,8 +473,7 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg) | |||
479 | write_lock_irq(&devs_lock); | 473 | write_lock_irq(&devs_lock); |
480 | net_dev = br2684_find_dev(&be.ifspec); | 474 | net_dev = br2684_find_dev(&be.ifspec); |
481 | if (net_dev == NULL) { | 475 | if (net_dev == NULL) { |
482 | printk(KERN_ERR | 476 | pr_err("tried to attach to non-existant device\n"); |
483 | "br2684: tried to attach to non-existant device\n"); | ||
484 | err = -ENXIO; | 477 | err = -ENXIO; |
485 | goto error; | 478 | goto error; |
486 | } | 479 | } |
@@ -494,17 +487,16 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg) | |||
494 | err = -EEXIST; | 487 | err = -EEXIST; |
495 | goto error; | 488 | goto error; |
496 | } | 489 | } |
497 | if (be.fcs_in != BR2684_FCSIN_NO || be.fcs_out != BR2684_FCSOUT_NO || | 490 | if (be.fcs_in != BR2684_FCSIN_NO || |
498 | be.fcs_auto || be.has_vpiid || be.send_padding || (be.encaps != | 491 | be.fcs_out != BR2684_FCSOUT_NO || |
499 | BR2684_ENCAPS_VC | 492 | be.fcs_auto || be.has_vpiid || be.send_padding || |
500 | && be.encaps != | 493 | (be.encaps != BR2684_ENCAPS_VC && |
501 | BR2684_ENCAPS_LLC) | 494 | be.encaps != BR2684_ENCAPS_LLC) || |
502 | || be.min_size != 0) { | 495 | be.min_size != 0) { |
503 | err = -EINVAL; | 496 | err = -EINVAL; |
504 | goto error; | 497 | goto error; |
505 | } | 498 | } |
506 | pr_debug("br2684_regvcc vcc=%p, encaps=%d, brvcc=%p\n", atmvcc, | 499 | pr_debug("vcc=%p, encaps=%d, brvcc=%p\n", atmvcc, be.encaps, brvcc); |
507 | be.encaps, brvcc); | ||
508 | if (list_empty(&brdev->brvccs) && !brdev->mac_was_set) { | 500 | if (list_empty(&brdev->brvccs) && !brdev->mac_was_set) { |
509 | unsigned char *esi = atmvcc->dev->esi; | 501 | unsigned char *esi = atmvcc->dev->esi; |
510 | if (esi[0] | esi[1] | esi[2] | esi[3] | esi[4] | esi[5]) | 502 | if (esi[0] | esi[1] | esi[2] | esi[3] | esi[4] | esi[5]) |
@@ -541,7 +533,8 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg) | |||
541 | } | 533 | } |
542 | __module_get(THIS_MODULE); | 534 | __module_get(THIS_MODULE); |
543 | return 0; | 535 | return 0; |
544 | error: | 536 | |
537 | error: | ||
545 | write_unlock_irq(&devs_lock); | 538 | write_unlock_irq(&devs_lock); |
546 | kfree(brvcc); | 539 | kfree(brvcc); |
547 | return err; | 540 | return err; |
@@ -554,6 +547,12 @@ static const struct net_device_ops br2684_netdev_ops = { | |||
554 | .ndo_validate_addr = eth_validate_addr, | 547 | .ndo_validate_addr = eth_validate_addr, |
555 | }; | 548 | }; |
556 | 549 | ||
550 | static const struct net_device_ops br2684_netdev_ops_routed = { | ||
551 | .ndo_start_xmit = br2684_start_xmit, | ||
552 | .ndo_set_mac_address = br2684_mac_addr, | ||
553 | .ndo_change_mtu = eth_change_mtu | ||
554 | }; | ||
555 | |||
557 | static void br2684_setup(struct net_device *netdev) | 556 | static void br2684_setup(struct net_device *netdev) |
558 | { | 557 | { |
559 | struct br2684_dev *brdev = BRPRIV(netdev); | 558 | struct br2684_dev *brdev = BRPRIV(netdev); |
@@ -569,11 +568,10 @@ static void br2684_setup(struct net_device *netdev) | |||
569 | static void br2684_setup_routed(struct net_device *netdev) | 568 | static void br2684_setup_routed(struct net_device *netdev) |
570 | { | 569 | { |
571 | struct br2684_dev *brdev = BRPRIV(netdev); | 570 | struct br2684_dev *brdev = BRPRIV(netdev); |
572 | brdev->net_dev = netdev; | ||
573 | 571 | ||
572 | brdev->net_dev = netdev; | ||
574 | netdev->hard_header_len = 0; | 573 | netdev->hard_header_len = 0; |
575 | 574 | netdev->netdev_ops = &br2684_netdev_ops_routed; | |
576 | netdev->netdev_ops = &br2684_netdev_ops; | ||
577 | netdev->addr_len = 0; | 575 | netdev->addr_len = 0; |
578 | netdev->mtu = 1500; | 576 | netdev->mtu = 1500; |
579 | netdev->type = ARPHRD_PPP; | 577 | netdev->type = ARPHRD_PPP; |
@@ -582,7 +580,7 @@ static void br2684_setup_routed(struct net_device *netdev) | |||
582 | INIT_LIST_HEAD(&brdev->brvccs); | 580 | INIT_LIST_HEAD(&brdev->brvccs); |
583 | } | 581 | } |
584 | 582 | ||
585 | static int br2684_create(void __user * arg) | 583 | static int br2684_create(void __user *arg) |
586 | { | 584 | { |
587 | int err; | 585 | int err; |
588 | struct net_device *netdev; | 586 | struct net_device *netdev; |
@@ -590,11 +588,10 @@ static int br2684_create(void __user * arg) | |||
590 | struct atm_newif_br2684 ni; | 588 | struct atm_newif_br2684 ni; |
591 | enum br2684_payload payload; | 589 | enum br2684_payload payload; |
592 | 590 | ||
593 | pr_debug("br2684_create\n"); | 591 | pr_debug("\n"); |
594 | 592 | ||
595 | if (copy_from_user(&ni, arg, sizeof ni)) { | 593 | if (copy_from_user(&ni, arg, sizeof ni)) |
596 | return -EFAULT; | 594 | return -EFAULT; |
597 | } | ||
598 | 595 | ||
599 | if (ni.media & BR2684_FLAG_ROUTED) | 596 | if (ni.media & BR2684_FLAG_ROUTED) |
600 | payload = p_routed; | 597 | payload = p_routed; |
@@ -602,9 +599,8 @@ static int br2684_create(void __user * arg) | |||
602 | payload = p_bridged; | 599 | payload = p_bridged; |
603 | ni.media &= 0xffff; /* strip flags */ | 600 | ni.media &= 0xffff; /* strip flags */ |
604 | 601 | ||
605 | if (ni.media != BR2684_MEDIA_ETHERNET || ni.mtu != 1500) { | 602 | if (ni.media != BR2684_MEDIA_ETHERNET || ni.mtu != 1500) |
606 | return -EINVAL; | 603 | return -EINVAL; |
607 | } | ||
608 | 604 | ||
609 | netdev = alloc_netdev(sizeof(struct br2684_dev), | 605 | netdev = alloc_netdev(sizeof(struct br2684_dev), |
610 | ni.ifname[0] ? ni.ifname : "nas%d", | 606 | ni.ifname[0] ? ni.ifname : "nas%d", |
@@ -619,7 +615,7 @@ static int br2684_create(void __user * arg) | |||
619 | /* open, stop, do_ioctl ? */ | 615 | /* open, stop, do_ioctl ? */ |
620 | err = register_netdev(netdev); | 616 | err = register_netdev(netdev); |
621 | if (err < 0) { | 617 | if (err < 0) { |
622 | printk(KERN_ERR "br2684_create: register_netdev failed\n"); | 618 | pr_err("register_netdev failed\n"); |
623 | free_netdev(netdev); | 619 | free_netdev(netdev); |
624 | return err; | 620 | return err; |
625 | } | 621 | } |