1 /* 2 Experimental ethernet netdevice using ATM AAL5 as underlying carrier 3 (RFC1483 obsoleted by RFC2684) for Linux 2.4 4 Author: Marcell GAL, 2000, XDSL Ltd, Hungary 5 */ 6 7 #include <linux/module.h> 8 #include <linux/init.h> 9 #include <linux/kernel.h> 10 #include <linux/list.h> 11 #include <linux/netdevice.h> 12 #include <linux/skbuff.h> 13 #include <linux/etherdevice.h> 14 #include <linux/rtnetlink.h> 15 #include <linux/ip.h> 16 #include <asm/uaccess.h> 17 #include <net/arp.h> 18 #include <linux/atm.h> 19 #include <linux/atmdev.h> 20 #include <linux/capability.h> 21 #include <linux/seq_file.h> 22 23 #include <linux/atmbr2684.h> 24 25 #include "common.h" 26 27 #ifdef SKB_DEBUG 28 static void skb_debug(const struct sk_buff *skb) 29 { 30 #define NUM2PRINT 50 31 char buf[NUM2PRINT * 3 + 1]; /* 3 chars per byte */ 32 int i = 0; 33 for (i = 0; i < skb->len && i < NUM2PRINT; i++) { 34 sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]); 35 } 36 printk(KERN_DEBUG "br2684: skb: %s\n", buf); 37 } 38 #else 39 #define skb_debug(skb) do {} while (0) 40 #endif 41 42 static unsigned char llc_oui_pid_pad[] = 43 { 0xAA, 0xAA, 0x03, 0x00, 0x80, 0xC2, 0x00, 0x07, 0x00, 0x00 }; 44 #define PADLEN (2) 45 46 enum br2684_encaps { 47 e_vc = BR2684_ENCAPS_VC, 48 e_llc = BR2684_ENCAPS_LLC, 49 }; 50 51 struct br2684_vcc { 52 struct atm_vcc *atmvcc; 53 struct net_device *device; 54 /* keep old push,pop functions for chaining */ 55 void (*old_push)(struct atm_vcc *vcc,struct sk_buff *skb); 56 /* void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb); */ 57 enum br2684_encaps encaps; 58 struct list_head brvccs; 59 #ifdef CONFIG_ATM_BR2684_IPFILTER 60 struct br2684_filter filter; 61 #endif /* CONFIG_ATM_BR2684_IPFILTER */ 62 unsigned copies_needed, copies_failed; 63 }; 64 65 struct br2684_dev { 66 struct net_device *net_dev; 67 struct list_head br2684_devs; 68 int number; 69 struct list_head brvccs; /* one device <=> one vcc (before xmas) */ 70 struct net_device_stats stats; 71 int mac_was_set; 72 }; 73 74 /* 75 * This lock should be held for writing any time the list of devices or 76 * their attached vcc's could be altered. It should be held for reading 77 * any time these are being queried. Note that we sometimes need to 78 * do read-locking under interrupt context, so write locking must block 79 * the current CPU's interrupts 80 */ 81 static DEFINE_RWLOCK(devs_lock); 82 83 static LIST_HEAD(br2684_devs); 84 85 static inline struct br2684_dev *BRPRIV(const struct net_device *net_dev) 86 { 87 return (struct br2684_dev *) net_dev->priv; 88 } 89 90 static inline struct net_device *list_entry_brdev(const struct list_head *le) 91 { 92 return list_entry(le, struct br2684_dev, br2684_devs)->net_dev; 93 } 94 95 static inline struct br2684_vcc *BR2684_VCC(const struct atm_vcc *atmvcc) 96 { 97 return (struct br2684_vcc *) (atmvcc->user_back); 98 } 99 100 static inline struct br2684_vcc *list_entry_brvcc(const struct list_head *le) 101 { 102 return list_entry(le, struct br2684_vcc, brvccs); 103 } 104 105 /* Caller should hold read_lock(&devs_lock) */ 106 static struct net_device *br2684_find_dev(const struct br2684_if_spec *s) 107 { 108 struct list_head *lh; 109 struct net_device *net_dev; 110 switch (s->method) { 111 case BR2684_FIND_BYNUM: 112 list_for_each(lh, &br2684_devs) { 113 net_dev = list_entry_brdev(lh); 114 if (BRPRIV(net_dev)->number == s->spec.devnum) 115 return net_dev; 116 } 117 break; 118 case BR2684_FIND_BYIFNAME: 119 list_for_each(lh, &br2684_devs) { 120 net_dev = list_entry_brdev(lh); 121 if (!strncmp(net_dev->name, s->spec.ifname, IFNAMSIZ)) 122 return net_dev; 123 } 124 break; 125 } 126 return NULL; 127 } 128 129 /* 130 * Send a packet out a particular vcc. Not to useful right now, but paves 131 * the way for multiple vcc's per itf. Returns true if we can send, 132 * otherwise false 133 */ 134 static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev, 135 struct br2684_vcc *brvcc) 136 { 137 struct atm_vcc *atmvcc; 138 int minheadroom = (brvcc->encaps == e_llc) ? 10 : 2; 139 if (skb_headroom(skb) < minheadroom) { 140 struct sk_buff *skb2 = skb_realloc_headroom(skb, minheadroom); 141 brvcc->copies_needed++; 142 dev_kfree_skb(skb); 143 if (skb2 == NULL) { 144 brvcc->copies_failed++; 145 return 0; 146 } 147 skb = skb2; 148 } 149 skb_push(skb, minheadroom); 150 if (brvcc->encaps == e_llc) 151 skb_copy_to_linear_data(skb, llc_oui_pid_pad, 10); 152 else 153 memset(skb->data, 0, 2); 154 skb_debug(skb); 155 156 ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc; 157 pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, atmvcc->dev); 158 if (!atm_may_send(atmvcc, skb->truesize)) { 159 /* we free this here for now, because we cannot know in a higher 160 layer whether the skb point it supplied wasn't freed yet. 161 now, it always is. 162 */ 163 dev_kfree_skb(skb); 164 return 0; 165 } 166 atomic_add(skb->truesize, &sk_atm(atmvcc)->sk_wmem_alloc); 167 ATM_SKB(skb)->atm_options = atmvcc->atm_options; 168 brdev->stats.tx_packets++; 169 brdev->stats.tx_bytes += skb->len; 170 atmvcc->send(atmvcc, skb); 171 return 1; 172 } 173 174 static inline struct br2684_vcc *pick_outgoing_vcc(struct sk_buff *skb, 175 struct br2684_dev *brdev) 176 { 177 return list_empty(&brdev->brvccs) ? NULL : 178 list_entry_brvcc(brdev->brvccs.next); /* 1 vcc/dev right now */ 179 } 180 181 static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev) 182 { 183 struct br2684_dev *brdev = BRPRIV(dev); 184 struct br2684_vcc *brvcc; 185 186 pr_debug("br2684_start_xmit, skb->dst=%p\n", skb->dst); 187 read_lock(&devs_lock); 188 brvcc = pick_outgoing_vcc(skb, brdev); 189 if (brvcc == NULL) { 190 pr_debug("no vcc attached to dev %s\n", dev->name); 191 brdev->stats.tx_errors++; 192 brdev->stats.tx_carrier_errors++; 193 /* netif_stop_queue(dev); */ 194 dev_kfree_skb(skb); 195 read_unlock(&devs_lock); 196 return 0; 197 } 198 if (!br2684_xmit_vcc(skb, brdev, brvcc)) { 199 /* 200 * We should probably use netif_*_queue() here, but that 201 * involves added complication. We need to walk before 202 * we can run 203 */ 204 /* don't free here! this pointer might be no longer valid! 205 dev_kfree_skb(skb); 206 */ 207 brdev->stats.tx_errors++; 208 brdev->stats.tx_fifo_errors++; 209 } 210 read_unlock(&devs_lock); 211 return 0; 212 } 213 214 static struct net_device_stats *br2684_get_stats(struct net_device *dev) 215 { 216 pr_debug("br2684_get_stats\n"); 217 return &BRPRIV(dev)->stats; 218 } 219 220 221 /* 222 * We remember when the MAC gets set, so we don't override it later with 223 * the ESI of the ATM card of the first VC 224 */ 225 static int (*my_eth_mac_addr)(struct net_device *, void *); 226 static int br2684_mac_addr(struct net_device *dev, void *p) 227 { 228 int err = my_eth_mac_addr(dev, p); 229 if (!err) 230 BRPRIV(dev)->mac_was_set = 1; 231 return err; 232 } 233 234 #ifdef CONFIG_ATM_BR2684_IPFILTER 235 /* this IOCTL is experimental. */ 236 static int br2684_setfilt(struct atm_vcc *atmvcc, void __user *arg) 237 { 238 struct br2684_vcc *brvcc; 239 struct br2684_filter_set fs; 240 241 if (copy_from_user(&fs, arg, sizeof fs)) 242 return -EFAULT; 243 if (fs.ifspec.method != BR2684_FIND_BYNOTHING) { 244 /* 245 * This is really a per-vcc thing, but we can also search 246 * by device 247 */ 248 struct br2684_dev *brdev; 249 read_lock(&devs_lock); 250 brdev = BRPRIV(br2684_find_dev(&fs.ifspec)); 251 if (brdev == NULL || list_empty(&brdev->brvccs) || 252 brdev->brvccs.next != brdev->brvccs.prev) /* >1 VCC */ 253 brvcc = NULL; 254 else 255 brvcc = list_entry_brvcc(brdev->brvccs.next); 256 read_unlock(&devs_lock); 257 if (brvcc == NULL) 258 return -ESRCH; 259 } else 260 brvcc = BR2684_VCC(atmvcc); 261 memcpy(&brvcc->filter, &fs.filter, sizeof(brvcc->filter)); 262 return 0; 263 } 264 265 /* Returns 1 if packet should be dropped */ 266 static inline int 267 packet_fails_filter(__be16 type, struct br2684_vcc *brvcc, struct sk_buff *skb) 268 { 269 if (brvcc->filter.netmask == 0) 270 return 0; /* no filter in place */ 271 if (type == htons(ETH_P_IP) && 272 (((struct iphdr *) (skb->data))->daddr & brvcc->filter. 273 netmask) == brvcc->filter.prefix) 274 return 0; 275 if (type == htons(ETH_P_ARP)) 276 return 0; 277 /* TODO: we should probably filter ARPs too.. don't want to have 278 * them returning values that don't make sense, or is that ok? 279 */ 280 return 1; /* drop */ 281 } 282 #endif /* CONFIG_ATM_BR2684_IPFILTER */ 283 284 static void br2684_close_vcc(struct br2684_vcc *brvcc) 285 { 286 pr_debug("removing VCC %p from dev %p\n", brvcc, brvcc->device); 287 write_lock_irq(&devs_lock); 288 list_del(&brvcc->brvccs); 289 write_unlock_irq(&devs_lock); 290 brvcc->atmvcc->user_back = NULL; /* what about vcc->recvq ??? */ 291 brvcc->old_push(brvcc->atmvcc, NULL); /* pass on the bad news */ 292 kfree(brvcc); 293 module_put(THIS_MODULE); 294 } 295 296 /* when AAL5 PDU comes in: */ 297 static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) 298 { 299 struct br2684_vcc *brvcc = BR2684_VCC(atmvcc); 300 struct net_device *net_dev = brvcc->device; 301 struct br2684_dev *brdev = BRPRIV(net_dev); 302 int plen = sizeof(llc_oui_pid_pad) + ETH_HLEN; 303 304 pr_debug("br2684_push\n"); 305 306 if (unlikely(skb == NULL)) { 307 /* skb==NULL means VCC is being destroyed */ 308 br2684_close_vcc(brvcc); 309 if (list_empty(&brdev->brvccs)) { 310 read_lock(&devs_lock); 311 list_del(&brdev->br2684_devs); 312 read_unlock(&devs_lock); 313 unregister_netdev(net_dev); 314 free_netdev(net_dev); 315 } 316 return; 317 } 318 319 skb_debug(skb); 320 atm_return(atmvcc, skb->truesize); 321 pr_debug("skb from brdev %p\n", brdev); 322 if (brvcc->encaps == e_llc) { 323 /* let us waste some time for checking the encapsulation. 324 Note, that only 7 char is checked so frames with a valid FCS 325 are also accepted (but FCS is not checked of course) */ 326 if (memcmp(skb->data, llc_oui_pid_pad, 7)) { 327 brdev->stats.rx_errors++; 328 dev_kfree_skb(skb); 329 return; 330 } 331 332 /* Strip FCS if present */ 333 if (skb->len > 7 && skb->data[7] == 0x01) 334 __skb_trim(skb, skb->len - 4); 335 } else { 336 plen = PADLEN + ETH_HLEN; /* pad, dstmac,srcmac, ethtype */ 337 /* first 2 chars should be 0 */ 338 if (*((u16 *) (skb->data)) != 0) { 339 brdev->stats.rx_errors++; 340 dev_kfree_skb(skb); 341 return; 342 } 343 } 344 if (skb->len < plen) { 345 brdev->stats.rx_errors++; 346 dev_kfree_skb(skb); /* dev_ not needed? */ 347 return; 348 } 349 350 skb_pull(skb, plen - ETH_HLEN); 351 skb->protocol = eth_type_trans(skb, net_dev); 352 #ifdef CONFIG_ATM_BR2684_IPFILTER 353 if (unlikely(packet_fails_filter(skb->protocol, brvcc, skb))) { 354 brdev->stats.rx_dropped++; 355 dev_kfree_skb(skb); 356 return; 357 } 358 #endif /* CONFIG_ATM_BR2684_IPFILTER */ 359 skb->dev = net_dev; 360 ATM_SKB(skb)->vcc = atmvcc; /* needed ? */ 361 pr_debug("received packet's protocol: %x\n", ntohs(skb->protocol)); 362 skb_debug(skb); 363 if (unlikely(!(net_dev->flags & IFF_UP))) { 364 /* sigh, interface is down */ 365 brdev->stats.rx_dropped++; 366 dev_kfree_skb(skb); 367 return; 368 } 369 brdev->stats.rx_packets++; 370 brdev->stats.rx_bytes += skb->len; 371 memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data)); 372 netif_rx(skb); 373 } 374 375 static int br2684_regvcc(struct atm_vcc *atmvcc, void __user *arg) 376 { 377 /* assign a vcc to a dev 378 Note: we do not have explicit unassign, but look at _push() 379 */ 380 int err; 381 struct br2684_vcc *brvcc; 382 struct sk_buff *skb; 383 struct sk_buff_head *rq; 384 struct br2684_dev *brdev; 385 struct net_device *net_dev; 386 struct atm_backend_br2684 be; 387 unsigned long flags; 388 389 if (copy_from_user(&be, arg, sizeof be)) 390 return -EFAULT; 391 brvcc = kzalloc(sizeof(struct br2684_vcc), GFP_KERNEL); 392 if (!brvcc) 393 return -ENOMEM; 394 write_lock_irq(&devs_lock); 395 net_dev = br2684_find_dev(&be.ifspec); 396 if (net_dev == NULL) { 397 printk(KERN_ERR 398 "br2684: tried to attach to non-existant device\n"); 399 err = -ENXIO; 400 goto error; 401 } 402 brdev = BRPRIV(net_dev); 403 if (atmvcc->push == NULL) { 404 err = -EBADFD; 405 goto error; 406 } 407 if (!list_empty(&brdev->brvccs)) { 408 /* Only 1 VCC/dev right now */ 409 err = -EEXIST; 410 goto error; 411 } 412 if (be.fcs_in != BR2684_FCSIN_NO || be.fcs_out != BR2684_FCSOUT_NO || 413 be.fcs_auto || be.has_vpiid || be.send_padding || (be.encaps != 414 BR2684_ENCAPS_VC && be.encaps != BR2684_ENCAPS_LLC) || 415 be.min_size != 0) { 416 err = -EINVAL; 417 goto error; 418 } 419 pr_debug("br2684_regvcc vcc=%p, encaps=%d, brvcc=%p\n", atmvcc, be.encaps, 420 brvcc); 421 if (list_empty(&brdev->brvccs) && !brdev->mac_was_set) { 422 unsigned char *esi = atmvcc->dev->esi; 423 if (esi[0] | esi[1] | esi[2] | esi[3] | esi[4] | esi[5]) 424 memcpy(net_dev->dev_addr, esi, net_dev->addr_len); 425 else 426 net_dev->dev_addr[2] = 1; 427 } 428 list_add(&brvcc->brvccs, &brdev->brvccs); 429 write_unlock_irq(&devs_lock); 430 brvcc->device = net_dev; 431 brvcc->atmvcc = atmvcc; 432 atmvcc->user_back = brvcc; 433 brvcc->encaps = (enum br2684_encaps) be.encaps; 434 brvcc->old_push = atmvcc->push; 435 barrier(); 436 atmvcc->push = br2684_push; 437 438 rq = &sk_atm(atmvcc)->sk_receive_queue; 439 440 spin_lock_irqsave(&rq->lock, flags); 441 if (skb_queue_empty(rq)) { 442 skb = NULL; 443 } else { 444 /* NULL terminate the list. */ 445 rq->prev->next = NULL; 446 skb = rq->next; 447 } 448 rq->prev = rq->next = (struct sk_buff *)rq; 449 rq->qlen = 0; 450 spin_unlock_irqrestore(&rq->lock, flags); 451 452 while (skb) { 453 struct sk_buff *next = skb->next; 454 455 skb->next = skb->prev = NULL; 456 BRPRIV(skb->dev)->stats.rx_bytes -= skb->len; 457 BRPRIV(skb->dev)->stats.rx_packets--; 458 br2684_push(atmvcc, skb); 459 460 skb = next; 461 } 462 __module_get(THIS_MODULE); 463 return 0; 464 error: 465 write_unlock_irq(&devs_lock); 466 kfree(brvcc); 467 return err; 468 } 469 470 static void br2684_setup(struct net_device *netdev) 471 { 472 struct br2684_dev *brdev = BRPRIV(netdev); 473 474 ether_setup(netdev); 475 brdev->net_dev = netdev; 476 477 my_eth_mac_addr = netdev->set_mac_address; 478 netdev->set_mac_address = br2684_mac_addr; 479 netdev->hard_start_xmit = br2684_start_xmit; 480 netdev->get_stats = br2684_get_stats; 481 482 INIT_LIST_HEAD(&brdev->brvccs); 483 } 484 485 static int br2684_create(void __user *arg) 486 { 487 int err; 488 struct net_device *netdev; 489 struct br2684_dev *brdev; 490 struct atm_newif_br2684 ni; 491 492 pr_debug("br2684_create\n"); 493 494 if (copy_from_user(&ni, arg, sizeof ni)) { 495 return -EFAULT; 496 } 497 if (ni.media != BR2684_MEDIA_ETHERNET || ni.mtu != 1500) { 498 return -EINVAL; 499 } 500 501 netdev = alloc_netdev(sizeof(struct br2684_dev), 502 ni.ifname[0] ? ni.ifname : "nas%d", 503 br2684_setup); 504 if (!netdev) 505 return -ENOMEM; 506 507 brdev = BRPRIV(netdev); 508 509 pr_debug("registered netdev %s\n", netdev->name); 510 /* open, stop, do_ioctl ? */ 511 err = register_netdev(netdev); 512 if (err < 0) { 513 printk(KERN_ERR "br2684_create: register_netdev failed\n"); 514 free_netdev(netdev); 515 return err; 516 } 517 518 write_lock_irq(&devs_lock); 519 brdev->number = list_empty(&br2684_devs) ? 1 : 520 BRPRIV(list_entry_brdev(br2684_devs.prev))->number + 1; 521 list_add_tail(&brdev->br2684_devs, &br2684_devs); 522 write_unlock_irq(&devs_lock); 523 return 0; 524 } 525 526 /* 527 * This handles ioctls actually performed on our vcc - we must return 528 * -ENOIOCTLCMD for any unrecognized ioctl 529 */ 530 static int br2684_ioctl(struct socket *sock, unsigned int cmd, 531 unsigned long arg) 532 { 533 struct atm_vcc *atmvcc = ATM_SD(sock); 534 void __user *argp = (void __user *)arg; 535 536 int err; 537 switch(cmd) { 538 case ATM_SETBACKEND: 539 case ATM_NEWBACKENDIF: { 540 atm_backend_t b; 541 err = get_user(b, (atm_backend_t __user *) argp); 542 if (err) 543 return -EFAULT; 544 if (b != ATM_BACKEND_BR2684) 545 return -ENOIOCTLCMD; 546 if (!capable(CAP_NET_ADMIN)) 547 return -EPERM; 548 if (cmd == ATM_SETBACKEND) 549 return br2684_regvcc(atmvcc, argp); 550 else 551 return br2684_create(argp); 552 } 553 #ifdef CONFIG_ATM_BR2684_IPFILTER 554 case BR2684_SETFILT: 555 if (atmvcc->push != br2684_push) 556 return -ENOIOCTLCMD; 557 if (!capable(CAP_NET_ADMIN)) 558 return -EPERM; 559 err = br2684_setfilt(atmvcc, argp); 560 return err; 561 #endif /* CONFIG_ATM_BR2684_IPFILTER */ 562 } 563 return -ENOIOCTLCMD; 564 } 565 566 static struct atm_ioctl br2684_ioctl_ops = { 567 .owner = THIS_MODULE, 568 .ioctl = br2684_ioctl, 569 }; 570 571 572 #ifdef CONFIG_PROC_FS 573 static void *br2684_seq_start(struct seq_file *seq, loff_t *pos) 574 { 575 read_lock(&devs_lock); 576 return seq_list_start(&br2684_devs, *pos); 577 } 578 579 static void *br2684_seq_next(struct seq_file *seq, void *v, loff_t *pos) 580 { 581 return seq_list_next(v, &br2684_devs, pos); 582 } 583 584 static void br2684_seq_stop(struct seq_file *seq, void *v) 585 { 586 read_unlock(&devs_lock); 587 } 588 589 static int br2684_seq_show(struct seq_file *seq, void *v) 590 { 591 const struct br2684_dev *brdev = list_entry(v, struct br2684_dev, 592 br2684_devs); 593 const struct net_device *net_dev = brdev->net_dev; 594 const struct br2684_vcc *brvcc; 595 DECLARE_MAC_BUF(mac); 596 597 seq_printf(seq, "dev %.16s: num=%d, mac=%s (%s)\n", 598 net_dev->name, 599 brdev->number, 600 print_mac(mac, net_dev->dev_addr), 601 brdev->mac_was_set ? "set" : "auto"); 602 603 list_for_each_entry(brvcc, &brdev->brvccs, brvccs) { 604 seq_printf(seq, " vcc %d.%d.%d: encaps=%s" 605 ", failed copies %u/%u" 606 "\n", brvcc->atmvcc->dev->number, 607 brvcc->atmvcc->vpi, brvcc->atmvcc->vci, 608 (brvcc->encaps == e_llc) ? "LLC" : "VC" 609 , brvcc->copies_failed 610 , brvcc->copies_needed 611 ); 612 #ifdef CONFIG_ATM_BR2684_IPFILTER 613 #define b1(var, byte) ((u8 *) &brvcc->filter.var)[byte] 614 #define bs(var) b1(var, 0), b1(var, 1), b1(var, 2), b1(var, 3) 615 if (brvcc->filter.netmask != 0) 616 seq_printf(seq, " filter=%d.%d.%d.%d/" 617 "%d.%d.%d.%d\n", 618 bs(prefix), bs(netmask)); 619 #undef bs 620 #undef b1 621 #endif /* CONFIG_ATM_BR2684_IPFILTER */ 622 } 623 return 0; 624 } 625 626 static const struct seq_operations br2684_seq_ops = { 627 .start = br2684_seq_start, 628 .next = br2684_seq_next, 629 .stop = br2684_seq_stop, 630 .show = br2684_seq_show, 631 }; 632 633 static int br2684_proc_open(struct inode *inode, struct file *file) 634 { 635 return seq_open(file, &br2684_seq_ops); 636 } 637 638 static const struct file_operations br2684_proc_ops = { 639 .owner = THIS_MODULE, 640 .open = br2684_proc_open, 641 .read = seq_read, 642 .llseek = seq_lseek, 643 .release = seq_release, 644 }; 645 646 extern struct proc_dir_entry *atm_proc_root; /* from proc.c */ 647 #endif 648 649 static int __init br2684_init(void) 650 { 651 #ifdef CONFIG_PROC_FS 652 struct proc_dir_entry *p; 653 if ((p = create_proc_entry("br2684", 0, atm_proc_root)) == NULL) 654 return -ENOMEM; 655 p->proc_fops = &br2684_proc_ops; 656 #endif 657 register_atm_ioctl(&br2684_ioctl_ops); 658 return 0; 659 } 660 661 static void __exit br2684_exit(void) 662 { 663 struct net_device *net_dev; 664 struct br2684_dev *brdev; 665 struct br2684_vcc *brvcc; 666 deregister_atm_ioctl(&br2684_ioctl_ops); 667 668 #ifdef CONFIG_PROC_FS 669 remove_proc_entry("br2684", atm_proc_root); 670 #endif 671 672 while (!list_empty(&br2684_devs)) { 673 net_dev = list_entry_brdev(br2684_devs.next); 674 brdev = BRPRIV(net_dev); 675 while (!list_empty(&brdev->brvccs)) { 676 brvcc = list_entry_brvcc(brdev->brvccs.next); 677 br2684_close_vcc(brvcc); 678 } 679 680 list_del(&brdev->br2684_devs); 681 unregister_netdev(net_dev); 682 free_netdev(net_dev); 683 } 684 } 685 686 module_init(br2684_init); 687 module_exit(br2684_exit); 688 689 MODULE_AUTHOR("Marcell GAL"); 690 MODULE_DESCRIPTION("RFC2684 bridged protocols over ATM/AAL5"); 691 MODULE_LICENSE("GPL"); 692