root/drivers/net/slip.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sl_alloc
  2. sl_free
  3. sl_changedmtu
  4. sl_lock
  5. sl_unlock
  6. sl_bump
  7. sl_encaps
  8. slip_write_wakeup
  9. sl_xmit
  10. sl_header
  11. sl_rebuild_header
  12. sl_open
  13. sl_close
  14. slip_receive_room
  15. slip_receive_buf
  16. slip_open
  17. slip_close
  18. sl_get_stats
  19. slip_esc
  20. slip_unesc
  21. slip_esc6
  22. slip_unesc6
  23. sl_set_mac_address
  24. sl_set_dev_mac_address
  25. sl_get_ax25_mode
  26. slip_ioctl
  27. sl_open_dev
  28. slip_init
  29. init_module
  30. cleanup_module

   1 /*
   2  * slip.c       This module implements the SLIP protocol for kernel-based
   3  *              devices like TTY.  It interfaces between a raw TTY, and the
   4  *              kernel's INET protocol layers.
   5  *
   6  * Version:     @(#)slip.c      0.8.3   12/24/94
   7  *
   8  * Authors:     Laurence Culhane, <loz@holmes.demon.co.uk>
   9  *              Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
  10  *
  11  * Fixes:
  12  *              Alan Cox        :       Sanity checks and avoid tx overruns.
  13  *                                      Has a new sl->mtu field.
  14  *              Alan Cox        :       Found cause of overrun. ifconfig sl0 mtu upwards.
  15  *                                      Driver now spots this and grows/shrinks its buffers(hack!).
  16  *                                      Memory leak if you run out of memory setting up a slip driver fixed.
  17  *              Matt Dillon     :       Printable slip (borrowed from NET2E)
  18  *      Pauline Middelink       :       Slip driver fixes.
  19  *              Alan Cox        :       Honours the old SL_COMPRESSED flag
  20  *              Alan Cox        :       KISS AX.25 and AXUI IP support
  21  *              Michael Riepe   :       Automatic CSLIP recognition added
  22  *              Charles Hedrick :       CSLIP header length problem fix.
  23  *              Alan Cox        :       Corrected non-IP cases of the above.
  24  *              Alan Cox        :       Now uses hardware type as per FvK.
  25  *              Alan Cox        :       Default to 192.168.0.0 (RFC 1597)
  26  *              A.N.Kuznetsov   :       dev_tint() recursion fix.
  27  *      Dmitry Gorodchanin      :       SLIP memory leaks
  28  *      Dmitry Gorodchanin      :       Code cleanup. Reduce tty driver
  29  *                                      buffering from 4096 to 256 bytes.
  30  *                                      Improving SLIP response time.
  31  *                                      CONFIG_SLIP_MODE_SLIP6.
  32  *                                      ifconfig sl? up & down now works correctly.
  33  *                                      Modularization.
  34  *              Alan Cox        :       Oops - fix AX.25 buffer lengths
  35  *      Dmitry Gorodchanin      :       Even more cleanups. Preserve CSLIP
  36  *                                      statistics. Include CSLIP code only
  37  *                                      if it really needed.
  38  *              Alan Cox        :       Free slhc buffers in the right place.
  39  *              Alan Cox        :       Allow for digipeated IP over AX.25
  40  *
  41  *
  42  *
  43  *      FIXME:  This driver still makes some IP'ish assumptions. It should build cleanly KISS TNC only without
  44  *      CONFIG_INET defined.
  45  *      I hope now it is fixed ;)
  46  */
  47 
  48 #define SL_CHECK_TRANSMIT
  49 #include <linux/config.h>
  50 #ifdef MODULE
  51 #include <linux/module.h>
  52 #include <linux/version.h>
  53 #endif
  54 
  55 /* Undef this, if you don't need 6bit encapsulation code in the driver */
  56 #define CONFIG_SLIP_MODE_SLIP6
  57 
  58 #include <asm/system.h>
  59 #include <asm/segment.h>
  60 #include <asm/bitops.h>
  61 #include <linux/string.h>
  62 #include <linux/mm.h>
  63 #include <linux/interrupt.h>
  64 #include <linux/in.h>
  65 #include <linux/tty.h>
  66 #include <linux/errno.h>
  67 #include <linux/netdevice.h>
  68 #ifdef CONFIG_AX25
  69 #include <linux/timer.h>
  70 #include <net/ax25.h>
  71 #endif
  72 #include <linux/etherdevice.h>
  73 #include <linux/skbuff.h>
  74 #include <linux/if_arp.h>
  75 #include "slip.h"
  76 #ifdef CONFIG_INET
  77 #include <linux/ip.h>
  78 #include <linux/tcp.h>
  79 #include "slhc.h"
  80 #endif
  81 
  82 #ifdef MODULE
  83 #define SLIP_VERSION    "0.8.3-NET3.019-NEWTTY-MODULAR"
  84 #else
  85 #define SLIP_VERSION    "0.8.3-NET3.019-NEWTTY"
  86 #endif
  87 
  88 
  89 static struct slip      sl_ctrl[SL_NRUNIT];
  90 static struct tty_ldisc sl_ldisc;
  91 static int              already = 0;
  92 
  93 static int slip_esc(unsigned char *p, unsigned char *d, int len);
  94 static void slip_unesc(struct slip *sl, unsigned char c);
  95 #ifdef CONFIG_SLIP_MODE_SLIP6
  96 static int slip_esc6(unsigned char *p, unsigned char *d, int len);
  97 static void slip_unesc6(struct slip *sl, unsigned char c);
  98 #endif
  99 
 100 
 101 /* Find a free SLIP channel, and link in this `tty' line. */
 102 static inline struct slip *
 103 sl_alloc(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 104 {
 105         struct slip *sl;
 106         int i;
 107 
 108         for (i = 0; i < SL_NRUNIT; i++) {
 109                 sl = &sl_ctrl[i];
 110                 if (!set_bit(SLF_INUSE, &sl->flags)) {
 111                         return sl;
 112                 }
 113         }
 114         return NULL;
 115 }
 116 
 117 
 118 /* Free a SLIP channel. */
 119 static inline void
 120 sl_free(struct slip *sl)
     /* [previous][next][first][last][top][bottom][index][help] */
 121 {
 122         /* Free all SLIP frame buffers. */
 123         if (sl->rbuff)  {
 124                 kfree(sl->rbuff);
 125         }
 126         sl->rbuff = NULL;
 127         if (sl->xbuff)  {
 128                 kfree(sl->xbuff);
 129         }
 130         sl->xbuff = NULL;
 131 #ifdef SL_INCLUDE_CSLIP
 132         /* Save CSLIP statistics */
 133         if (sl->slcomp)  {
 134                 sl->rx_compressed += sl->slcomp->sls_i_compressed;
 135                 sl->rx_dropped    += sl->slcomp->sls_i_tossed;
 136                 sl->tx_compressed += sl->slcomp->sls_o_compressed;
 137                 sl->tx_misses     += sl->slcomp->sls_o_misses;
 138         }
 139         if (sl->cbuff)  {
 140                 kfree(sl->cbuff);
 141         }
 142         sl->cbuff = NULL;
 143         if(sl->slcomp)
 144                 slhc_free(sl->slcomp);
 145         sl->slcomp = NULL;
 146 #endif
 147 
 148         if (!clear_bit(SLF_INUSE, &sl->flags)) {
 149                 printk("%s: sl_free for already free unit.\n", sl->dev->name);
 150         }
 151 }
 152 
 153 /* MTU has been changed by the IP layer. Unfortunately we are not told about this, but
 154    we spot it ourselves and fix things up. We could be in an upcall from the tty
 155    driver, or in an ip packet queue. */
 156 
 157 static void sl_changedmtu(struct slip *sl)
     /* [previous][next][first][last][top][bottom][index][help] */
 158 {
 159         struct device *dev = sl->dev;
 160         unsigned char *xbuff, *rbuff, *oxbuff, *orbuff;
 161 #ifdef SL_INCLUDE_CSLIP
 162         unsigned char *cbuff, *ocbuff;
 163 #endif
 164         int len;
 165         unsigned long flags;
 166 
 167         len = dev->mtu * 2;
 168 /*
 169  * allow for arrival of larger UDP packets, even if we say not to
 170  * also fixes a bug in which SunOS sends 512-byte packets even with
 171  * an MSS of 128
 172  */
 173         if (len < 576 * 2)  {
 174                 len = 576 * 2;
 175         }
 176 
 177         xbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
 178         rbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
 179 #ifdef SL_INCLUDE_CSLIP
 180         cbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
 181 #endif
 182 
 183 #ifdef SL_INCLUDE_CSLIP
 184         if (xbuff == NULL || rbuff == NULL || cbuff == NULL)  {
 185 #else
 186         if (xbuff == NULL || rbuff == NULL)  {
 187 #endif
 188                 printk("%s: unable to grow slip buffers, MTU change cancelled.\n",
 189                        sl->dev->name);
 190                 dev->mtu = sl->mtu;
 191                 if (xbuff != NULL)  {
 192                         kfree(xbuff);
 193                 }
 194                 if (rbuff != NULL)  {
 195                         kfree(rbuff);
 196                 }
 197 #ifdef SL_INCLUDE_CSLIP
 198                 if (cbuff != NULL)  {
 199                         kfree(cbuff);
 200                 }
 201 #endif
 202                 return;
 203         }
 204 
 205         save_flags(flags); cli();
 206 
 207         oxbuff    = sl->xbuff;
 208         sl->xbuff = xbuff;
 209         orbuff    = sl->rbuff;
 210         sl->rbuff = rbuff;
 211 #ifdef SL_INCLUDE_CSLIP
 212         ocbuff    = sl->cbuff;
 213         sl->cbuff = cbuff;
 214 #endif
 215         if (sl->xleft)  {
 216                 if (sl->xleft <= len)  {
 217                         memcpy(sl->xbuff, sl->xhead, sl->xleft);
 218                 } else  {
 219                         sl->xleft = 0;
 220                         sl->tx_dropped++;
 221                 }
 222         }
 223         sl->xhead = sl->xbuff;
 224 
 225         if (sl->rcount)  {
 226                 if (sl->rcount <= len) {
 227                         memcpy(sl->rbuff, orbuff, sl->rcount);
 228                 } else  {
 229                         sl->rcount = 0;
 230                         sl->rx_over_errors++;
 231                         set_bit(SLF_ERROR, &sl->flags);
 232                 }
 233         }
 234 #ifdef CONFIG_AX25
 235         sl->mtu      = dev->mtu + 73;
 236 #else
 237         sl->mtu      = dev->mtu;
 238 #endif
 239         sl->buffsize = len;
 240 
 241         restore_flags(flags);
 242 
 243         if (oxbuff != NULL)   {
 244                 kfree(oxbuff);
 245         }
 246         if (orbuff != NULL)    {
 247                 kfree(orbuff);
 248         }
 249 #ifdef SL_INCLUDE_CSLIP
 250         if (ocbuff != NULL)  {
 251                 kfree(ocbuff);
 252         }
 253 #endif
 254 }
 255 
 256 
 257 /* Set the "sending" flag.  This must be atomic, hence the ASM. */
 258 static inline void
 259 sl_lock(struct slip *sl)
     /* [previous][next][first][last][top][bottom][index][help] */
 260 {
 261         if (set_bit(0, (void *) &sl->dev->tbusy))  {
 262                 printk("%s: trying to lock already locked device!\n", sl->dev->name);
 263         }
 264 }
 265 
 266 
 267 /* Clear the "sending" flag.  This must be atomic, hence the ASM. */
 268 static inline void
 269 sl_unlock(struct slip *sl)
     /* [previous][next][first][last][top][bottom][index][help] */
 270 {
 271         if (!clear_bit(0, (void *)&sl->dev->tbusy))  {
 272                 printk("%s: trying to unlock already unlocked device!\n", sl->dev->name);
 273         }
 274 }
 275 
 276 /* Send one completely decapsulated IP datagram to the IP layer. */
 277 static void
 278 sl_bump(struct slip *sl)
     /* [previous][next][first][last][top][bottom][index][help] */
 279 {
 280         struct sk_buff *skb;
 281         int count;
 282 
 283         count = sl->rcount;
 284 #ifdef SL_INCLUDE_CSLIP
 285         if (sl->mode & (SL_MODE_ADAPTIVE | SL_MODE_CSLIP)) {
 286                 unsigned char c;
 287                 if ((c = sl->rbuff[0]) & SL_TYPE_COMPRESSED_TCP) {
 288                         /* ignore compressed packets when CSLIP is off */
 289                         if (!(sl->mode & SL_MODE_CSLIP)) {
 290                                 printk("%s: compressed packet ignored\n", sl->dev->name);
 291                                 return;
 292                         }
 293                         /* make sure we've reserved enough space for uncompress to use */
 294                         if (count + 80 > sl->buffsize) {
 295                                 sl->rx_over_errors++;
 296                                 return;
 297                         }
 298                         count = slhc_uncompress(sl->slcomp, sl->rbuff, count);
 299                         if (count <= 0) {
 300                                 return;
 301                         }
 302                 } else if (c >= SL_TYPE_UNCOMPRESSED_TCP) {
 303                         if (!(sl->mode & SL_MODE_CSLIP)) {
 304                                 /* turn on header compression */
 305                                 sl->mode |= SL_MODE_CSLIP;
 306                                 sl->mode &= ~SL_MODE_ADAPTIVE;
 307                                 printk("%s: header compression turned on\n", sl->dev->name);
 308                         }
 309                         sl->rbuff[0] &= 0x4f;
 310                         if (slhc_remember(sl->slcomp, sl->rbuff, count) <= 0) {
 311                                 return;
 312                         }
 313                 }
 314         }
 315 #endif  /* SL_INCLUDE_CSLIP */
 316 
 317         skb = dev_alloc_skb(count);
 318         if (skb == NULL)  {
 319                 printk("%s: memory squeeze, dropping packet.\n", sl->dev->name);
 320                 sl->rx_dropped++;
 321                 return;
 322         }
 323         skb->dev = sl->dev;
 324         memcpy(skb_put(skb,count), sl->rbuff, count);
 325         skb->mac.raw=skb->data;
 326         if(sl->mode&(SL_MODE_AX25|SL_MODE_AX25VC))
 327                 skb->protocol=htons(ETH_P_AX25);
 328         else
 329                 skb->protocol=htons(ETH_P_IP);
 330         netif_rx(skb);
 331         sl->rx_packets++;
 332 }
 333 
 334 /* Encapsulate one IP datagram and stuff into a TTY queue. */
 335 static void
 336 sl_encaps(struct slip *sl, unsigned char *icp, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 337 {
 338         unsigned char *p;
 339         int actual, count;
 340 
 341 
 342 #ifdef CONFIG_AX25
 343         if (sl->mtu != sl->dev->mtu + 73) {     /* Someone has been ifconfigging */
 344 #else
 345         if (sl->mtu != sl->dev->mtu) {  /* Someone has been ifconfigging */
 346 #endif
 347                 sl_changedmtu(sl);
 348         }
 349 
 350         if (len > sl->mtu) {            /* Sigh, shouldn't occur BUT ... */
 351                 len = sl->mtu;
 352                 printk ("%s: truncating oversized transmit packet!\n", sl->dev->name);
 353                 sl->tx_dropped++;
 354                 sl_unlock(sl);
 355                 return;
 356         }
 357 
 358         p = icp;
 359 #ifdef SL_INCLUDE_CSLIP
 360         if (sl->mode & SL_MODE_CSLIP)  {
 361                 len = slhc_compress(sl->slcomp, p, len, sl->cbuff, &p, 1);
 362         }
 363 #endif
 364 #ifdef CONFIG_SLIP_MODE_SLIP6
 365         if(sl->mode & SL_MODE_SLIP6)
 366                 count = slip_esc6(p, (unsigned char *) sl->xbuff, len);
 367         else
 368 #endif
 369                 count = slip_esc(p, (unsigned char *) sl->xbuff, len);
 370 
 371         /* Order of next two lines is *very* important.
 372          * When we are sending a little amount of data,
 373          * the transfer may be completed inside driver.write()
 374          * routine, because it's running with interrupts enabled.
 375          * In this case we *never* got WRITE_WAKEUP event,
 376          * if we did not request it before write operation.
 377          *       14 Oct 1994  Dmitry Gorodchanin.
 378          */
 379         sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
 380         actual = sl->tty->driver.write(sl->tty, 0, sl->xbuff, count);
 381 #ifdef SL_CHECK_TRANSMIT
 382         sl->dev->trans_start = jiffies;
 383 #endif
 384         sl->xleft = count - actual;
 385         sl->xhead = sl->xbuff + actual;
 386 }
 387 
 388 /*
 389  * Called by the driver when there's room for more data.  If we have
 390  * more packets to send, we send them here.
 391  */
 392 static void slip_write_wakeup(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 393 {
 394         int actual;
 395         struct slip *sl = (struct slip *) tty->disc_data;
 396 
 397         /* First make sure we're connected. */
 398         if (!sl || sl->magic != SLIP_MAGIC || !sl->dev->start) {
 399                 return;
 400         }
 401 
 402         if (sl->xleft <= 0)  {
 403                 /* Now serial buffer is almost free & we can start
 404                  * transmission of another packet */
 405                 sl->tx_packets++;
 406                 tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 407                 sl_unlock(sl);
 408                 mark_bh(NET_BH);
 409                 return;
 410         }
 411 
 412         actual = tty->driver.write(tty, 0, sl->xhead, sl->xleft);
 413         sl->xleft -= actual;
 414         sl->xhead += actual;
 415 }
 416 
 417 /* Encapsulate an IP datagram and kick it into a TTY queue. */
 418 static int
 419 sl_xmit(struct sk_buff *skb, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 420 {
 421         struct slip *sl = &sl_ctrl[dev->base_addr];
 422 
 423         if (!dev->start)  {
 424                 printk("%s: xmit call when iface is down\n", dev->name);
 425                 return 1;
 426         }
 427         /*
 428          * If we are busy already- too bad.  We ought to be able
 429          * to queue things at this point, to allow for a little
 430          * frame buffer.  Oh well...
 431          * -----------------------------------------------------
 432          * I hate queues in SLIP driver. May be it's efficient,
 433          * but for me latency is more important. ;)
 434          * So, no queues !
 435          *        14 Oct 1994  Dmitry Gorodchanin.
 436          */
 437         if (dev->tbusy) {
 438                 /* May be we must check transmitter timeout here ?
 439                  *      14 Oct 1994 Dmitry Gorodchanin.
 440                  */
 441 #ifdef SL_CHECK_TRANSMIT
 442                 if (jiffies - dev->trans_start  < 20 * HZ)  {
 443                         /* 20 sec timeout not reached */
 444                         return 1;
 445                 }
 446                 printk("%s: transmit timed out, %s?\n", dev->name,
 447                        (sl->tty->driver.chars_in_buffer(sl->tty) || sl->xleft) ?
 448                        "bad line quality" : "driver error");
 449                 sl->xleft = 0;
 450                 sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 451                 sl_unlock(sl);
 452 #else
 453                 return 1;
 454 #endif
 455         }
 456 
 457         /* We were not busy, so we are now... :-) */
 458         if (skb != NULL) {
 459                 sl_lock(sl);
 460                 sl_encaps(sl, skb->data, skb->len);
 461                 dev_kfree_skb(skb, FREE_WRITE);
 462         }
 463         return 0;
 464 }
 465 
 466 
 467 /* Return the frame type ID.  This is normally IP but maybe be AX.25. */
 468 
 469 /* Fill in the MAC-level header. Not used by SLIP. */
 470 static int
 471 sl_header(struct sk_buff *skb, struct device *dev, unsigned short type,
     /* [previous][next][first][last][top][bottom][index][help] */
 472           void *daddr, void *saddr, unsigned len)
 473 {
 474 #ifdef CONFIG_AX25
 475 #ifdef CONFIG_INET
 476         struct slip *sl = &sl_ctrl[dev->base_addr];
 477 
 478         if (((sl->mode & SL_MODE_AX25) || (sl->mode & SL_MODE_AX25VC)) && type != htons(ETH_P_AX25))  {
 479                 return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
 480         }
 481 #endif
 482 #endif
 483         return 0;
 484 }
 485 
 486 
 487 /* Rebuild the MAC-level header.  Not used by SLIP. */
 488 static int
 489 sl_rebuild_header(void *buff, struct device *dev, unsigned long raddr,
     /* [previous][next][first][last][top][bottom][index][help] */
 490                   struct sk_buff *skb)
 491 {
 492 #ifdef CONFIG_AX25
 493 #ifdef CONFIG_INET
 494         struct slip *sl = &sl_ctrl[dev->base_addr];
 495 
 496         if ((sl->mode & SL_MODE_AX25) || (sl->mode & SL_MODE_AX25VC)) {
 497                 return ax25_rebuild_header(buff, dev, raddr, skb);
 498         }
 499 #endif
 500 #endif
 501         return 0;
 502 }
 503 
 504 
 505 /* Open the low-level part of the SLIP channel. Easy! */
 506 static int
 507 sl_open(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 508 {
 509         struct slip *sl = &sl_ctrl[dev->base_addr];
 510         unsigned long len;
 511 
 512         if (sl->tty == NULL) {
 513                 return -ENODEV;
 514         }
 515 
 516         /*
 517          * Allocate the SLIP frame buffers:
 518          *
 519          * rbuff        Receive buffer.
 520          * xbuff        Transmit buffer.
 521          * cbuff        Temporary compression buffer.
 522          */
 523         len = dev->mtu * 2;
 524         /*
 525          * allow for arrival of larger UDP packets, even if we say not to
 526          * also fixes a bug in which SunOS sends 512-byte packets even with
 527          * an MSS of 128
 528          */
 529         if (len < 576 * 2)  {
 530                 len = 576 * 2;
 531         }
 532         sl->rbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
 533         if (sl->rbuff == NULL)   {
 534                 goto norbuff;
 535         }
 536         sl->xbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
 537         if (sl->xbuff == NULL)   {
 538                 goto noxbuff;
 539         }
 540 #ifdef SL_INCLUDE_CSLIP
 541         sl->cbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
 542         if (sl->cbuff == NULL)   {
 543                 goto nocbuff;
 544         }
 545         sl->slcomp = slhc_init(16, 16);
 546         if (sl->slcomp == NULL)  {
 547                 goto noslcomp;
 548         }
 549 #endif
 550 
 551 #ifdef CONFIG_AX25
 552         sl->mtu      = dev->mtu + 73;
 553 #else
 554         sl->mtu      = dev->mtu;
 555 #endif
 556         sl->buffsize = len;
 557         sl->rcount   = 0;
 558         sl->xleft    = 0;
 559 #ifdef CONFIG_SLIP_MODE_SLIP6
 560         sl->xdata    = 0;
 561         sl->xbits    = 0;
 562 #endif
 563         sl->flags   &= (1 << SLF_INUSE);      /* Clear ESCAPE & ERROR flags */
 564 
 565         /* Needed because address '0' is special */
 566         if (dev->pa_addr == 0)  {
 567                 dev->pa_addr=ntohl(0xC0A80001);
 568         }
 569         dev->tbusy  = 0;
 570 /*      dev->flags |= IFF_UP; */
 571         dev->start  = 1;
 572 
 573         return 0;
 574 
 575         /* Cleanup */
 576 #ifdef SL_INCLUDE_CSLIP
 577 noslcomp:
 578         kfree(sl->cbuff);
 579 nocbuff:
 580 #endif
 581         kfree(sl->xbuff);
 582 noxbuff:
 583         kfree(sl->rbuff);
 584 norbuff:
 585         return -ENOMEM;
 586 }
 587 
 588 
 589 /* Close the low-level part of the SLIP channel. Easy! */
 590 static int
 591 sl_close(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 592 {
 593         struct slip *sl = &sl_ctrl[dev->base_addr];
 594 
 595         if (sl->tty == NULL) {
 596                 return -EBUSY;
 597         }
 598         sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 599         dev->tbusy = 1;
 600         dev->start = 0;
 601         
 602 /*      dev->flags &= ~IFF_UP; */
 603 
 604         return 0;
 605 }
 606 
 607 static int
 608 slip_receive_room(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 609 {
 610         return 65536;  /* We can handle an infinite amount of data. :-) */
 611 }
 612 
 613 /*
 614  * Handle the 'receiver data ready' interrupt.
 615  * This function is called by the 'tty_io' module in the kernel when
 616  * a block of SLIP data has been received, which can now be decapsulated
 617  * and sent on to some IP layer for further processing.
 618  */
 619 static void
 620 slip_receive_buf(struct tty_struct *tty, unsigned char *cp, char *fp, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 621 {
 622         struct slip *sl = (struct slip *) tty->disc_data;
 623 
 624         if (!sl || sl->magic != SLIP_MAGIC || !sl->dev->start)
 625                 return;
 626 
 627         /*
 628          * Argh! mtu change time! - costs us the packet part received
 629          * at the change
 630          */
 631 #ifdef CONFIG_AX25
 632         if (sl->mtu != sl->dev->mtu + 73)  {
 633 #else
 634         if (sl->mtu != sl->dev->mtu)  {
 635 #endif
 636                 sl_changedmtu(sl);
 637         }
 638 
 639         /* Read the characters out of the buffer */
 640         while (count--) {
 641                 if (fp && *fp++) {
 642                         if (!set_bit(SLF_ERROR, &sl->flags))  {
 643                                 sl->rx_errors++;
 644                         }
 645                         cp++;
 646                         continue;
 647                 }
 648 #ifdef CONFIG_SLIP_MODE_SLIP6
 649                 if (sl->mode & SL_MODE_SLIP6)
 650                         slip_unesc6(sl, *cp++);
 651                 else
 652 #endif
 653                         slip_unesc(sl, *cp++);
 654         }
 655 }
 656 
 657 /*
 658  * Open the high-level part of the SLIP channel.
 659  * This function is called by the TTY module when the
 660  * SLIP line discipline is called for.  Because we are
 661  * sure the tty line exists, we only have to link it to
 662  * a free SLIP channel...
 663  */
 664 static int
 665 slip_open(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 666 {
 667         struct slip *sl = (struct slip *) tty->disc_data;
 668         int err;
 669 
 670         /* First make sure we're not already connected. */
 671         if (sl && sl->magic == SLIP_MAGIC) {
 672                 return -EEXIST;
 673         }
 674 
 675         /* OK.  Find a free SLIP channel to use. */
 676         if ((sl = sl_alloc()) == NULL) {
 677                 return -ENFILE;
 678         }
 679 
 680         sl->tty = tty;
 681         tty->disc_data = sl;
 682         if (tty->driver.flush_buffer)  {
 683                 tty->driver.flush_buffer(tty);
 684         }
 685         if (tty->ldisc.flush_buffer)  {
 686                 tty->ldisc.flush_buffer(tty);
 687         }
 688 
 689         /* Restore default settings */
 690         sl->mode      = SL_MODE_DEFAULT;
 691         sl->dev->type = ARPHRD_SLIP + sl->mode;
 692 #ifdef CONFIG_AX25      
 693         if (sl->dev->type == 260 || sl->dev->type == 272) {     /* KISS */
 694                 sl->dev->type = ARPHRD_AX25;
 695         }
 696 #endif  
 697         /* Perform the low-level SLIP initialization. */
 698         if ((err = sl_open(sl->dev)))  {
 699                 return err;
 700         }
 701         
 702 #ifdef MODULE
 703         MOD_INC_USE_COUNT;
 704 #endif
 705 
 706         /* Done.  We have linked the TTY line to a channel. */
 707         return sl->dev->base_addr;
 708 }
 709 
 710 
 711 /*
 712  * Close down a SLIP channel.
 713  * This means flushing out any pending queues, and then restoring the
 714  * TTY line discipline to what it was before it got hooked to SLIP
 715  * (which usually is TTY again).
 716  */
 717 static void
 718 slip_close(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 719 {
 720         struct slip *sl = (struct slip *) tty->disc_data;
 721 
 722         /* First make sure we're connected. */
 723         if (!sl || sl->magic != SLIP_MAGIC) {
 724                 return;
 725         }
 726 
 727         (void) dev_close(sl->dev);
 728         
 729         tty->disc_data = 0;
 730         sl->tty = NULL;
 731         sl_free(sl);
 732 #ifdef MODULE
 733         MOD_DEC_USE_COUNT;
 734 #endif
 735 }
 736 
 737 
 738 static struct enet_statistics *
 739 sl_get_stats(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 740 {
 741         static struct enet_statistics stats;
 742         struct slip *sl = &sl_ctrl[dev->base_addr];
 743 #ifdef SL_INCLUDE_CSLIP
 744         struct slcompress *comp;
 745 #endif
 746 
 747         memset(&stats, 0, sizeof(struct enet_statistics));
 748 
 749         stats.rx_packets     = sl->rx_packets;
 750         stats.tx_packets     = sl->tx_packets;
 751         stats.rx_dropped     = sl->rx_dropped;
 752         stats.tx_dropped     = sl->tx_dropped;
 753         stats.tx_errors      = sl->tx_errors;
 754         stats.rx_errors      = sl->rx_errors;
 755         stats.rx_over_errors = sl->rx_over_errors;
 756 #ifdef SL_INCLUDE_CSLIP
 757         stats.rx_fifo_errors = sl->rx_compressed;
 758         stats.tx_fifo_errors = sl->tx_compressed;
 759         stats.collisions     = sl->tx_misses;
 760         comp = sl->slcomp;
 761         if (comp) {
 762                 stats.rx_fifo_errors += comp->sls_i_compressed;
 763                 stats.rx_dropped     += comp->sls_i_tossed;
 764                 stats.tx_fifo_errors += comp->sls_o_compressed;
 765                 stats.collisions     += comp->sls_o_misses;
 766         }
 767 #endif /* CONFIG_INET */
 768         return (&stats);
 769 }
 770 
 771 
 772  /************************************************************************
 773   *                     STANDARD SLIP ENCAPSULATION                      *
 774   ************************************************************************/
 775 
 776 int
 777 slip_esc(unsigned char *s, unsigned char *d, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 778 {
 779         unsigned char *ptr = d;
 780         unsigned char c;
 781 
 782         /*
 783          * Send an initial END character to flush out any
 784          * data that may have accumulated in the receiver
 785          * due to line noise.
 786          */
 787 
 788         *ptr++ = END;
 789 
 790         /*
 791          * For each byte in the packet, send the appropriate
 792          * character sequence, according to the SLIP protocol.
 793          */
 794 
 795         while (len-- > 0) {
 796                 switch(c = *s++) {
 797                  case END:
 798                         *ptr++ = ESC;
 799                         *ptr++ = ESC_END;
 800                         break;
 801                  case ESC:
 802                         *ptr++ = ESC;
 803                         *ptr++ = ESC_ESC;
 804                         break;
 805                  default:
 806                         *ptr++ = c;
 807                         break;
 808                 }
 809         }
 810         *ptr++ = END;
 811         return (ptr - d);
 812 }
 813 
 814 static void
 815 slip_unesc(struct slip *sl, unsigned char s)
     /* [previous][next][first][last][top][bottom][index][help] */
 816 {
 817 
 818         switch(s) {
 819          case END:
 820                 if (!clear_bit(SLF_ERROR, &sl->flags) && (sl->rcount > 2))  {
 821                         sl_bump(sl);
 822                 }
 823                 clear_bit(SLF_ESCAPE, &sl->flags);
 824                 sl->rcount = 0;
 825                 return;
 826 
 827          case ESC:
 828                 set_bit(SLF_ESCAPE, &sl->flags);
 829                 return;
 830          case ESC_ESC:
 831                 if (clear_bit(SLF_ESCAPE, &sl->flags))  {
 832                         s = ESC;
 833                 }
 834                 break;
 835          case ESC_END:
 836                 if (clear_bit(SLF_ESCAPE, &sl->flags))  {
 837                         s = END;
 838                 }
 839                 break;
 840         }
 841         if (!test_bit(SLF_ERROR, &sl->flags))  {
 842                 if (sl->rcount < sl->buffsize)  {
 843                         sl->rbuff[sl->rcount++] = s;
 844                         return;
 845                 }
 846                 sl->rx_over_errors++;
 847                 set_bit(SLF_ERROR, &sl->flags);
 848         }
 849 }
 850 
 851 
 852 #ifdef CONFIG_SLIP_MODE_SLIP6
 853 /************************************************************************
 854  *                       6 BIT SLIP ENCAPSULATION                       *
 855  ************************************************************************/
 856 
 857 int
 858 slip_esc6(unsigned char *s, unsigned char *d, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 859 {
 860         unsigned char *ptr = d;
 861         unsigned char c;
 862         int i;
 863         unsigned short v = 0;
 864         short bits = 0;
 865 
 866         /*
 867          * Send an initial END character to flush out any
 868          * data that may have accumulated in the receiver
 869          * due to line noise.
 870          */
 871 
 872         *ptr++ = 0x70;
 873 
 874         /*
 875          * Encode the packet into printable ascii characters
 876          */
 877 
 878         for (i = 0; i < len; ++i) {
 879                 v = (v << 8) | s[i];
 880                 bits += 8;
 881                 while (bits >= 6) {
 882                         bits -= 6;
 883                         c = 0x30 + ((v >> bits) & 0x3F);
 884                         *ptr++ = c;
 885                 }
 886         }
 887         if (bits) {
 888                 c = 0x30 + ((v << (6 - bits)) & 0x3F);
 889                 *ptr++ = c;
 890         }
 891         *ptr++ = 0x70;
 892         return ptr - d;
 893 }
 894 
 895 void
 896 slip_unesc6(struct slip *sl, unsigned char s)
     /* [previous][next][first][last][top][bottom][index][help] */
 897 {
 898         unsigned char c;
 899 
 900         if (s == 0x70) {
 901                 if (!clear_bit(SLF_ERROR, &sl->flags) && (sl->rcount > 2))  {
 902                         sl_bump(sl);
 903                 }
 904                 sl->rcount = 0;
 905                 sl->xbits = 0;
 906                 sl->xdata = 0;
 907         } else if (s >= 0x30 && s < 0x70) {
 908                 sl->xdata = (sl->xdata << 6) | ((s - 0x30) & 0x3F);
 909                 sl->xbits += 6;
 910                 if (sl->xbits >= 8) {
 911                         sl->xbits -= 8;
 912                         c = (unsigned char)(sl->xdata >> sl->xbits);
 913                         if (!test_bit(SLF_ERROR, &sl->flags))  {
 914                                 if (sl->rcount < sl->buffsize)  {
 915                                         sl->rbuff[sl->rcount++] = c;
 916                                         return;
 917                                 }
 918                                 sl->rx_over_errors++;
 919                                 set_bit(SLF_ERROR, &sl->flags);
 920                         }
 921                 }
 922         }
 923 }
 924 #endif /* CONFIG_SLIP_MODE_SLIP6 */
 925 
 926 #ifdef CONFIG_AX25
 927 int
 928 sl_set_mac_address(struct device *dev, void *addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 929 {
 930         int err;
 931 
 932         err = verify_area(VERIFY_READ, addr, AX25_ADDR_LEN);
 933         if (err)  {
 934                 return err;
 935         }
 936 
 937         memcpy_fromfs(dev->dev_addr, addr, AX25_ADDR_LEN);      /* addr is an AX.25 shifted ASCII mac address */
 938 
 939         return 0;
 940 }
 941 
 942 static int
 943 sl_set_dev_mac_address(struct device *dev, void *addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 944 {
 945         memcpy(dev->dev_addr, addr, AX25_ADDR_LEN);
 946         return 0;
 947 }
 948 
 949 int sl_get_ax25_mode(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 950 {
 951         struct slip *sl = &sl_ctrl[dev->base_addr];
 952 
 953         return sl->mode & SL_MODE_AX25VC;
 954 }
 955 
 956 #endif /* CONFIG_AX25 */
 957 
 958 
 959 /* Perform I/O control on an active SLIP channel. */
 960 static int
 961 slip_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 962 {
 963         struct slip *sl = (struct slip *) tty->disc_data;
 964         int err;
 965         unsigned int tmp;
 966 
 967         /* First make sure we're connected. */
 968         if (!sl || sl->magic != SLIP_MAGIC) {
 969                 return -EINVAL;
 970         }
 971 
 972         switch(cmd) {
 973          case SIOCGIFNAME:
 974                 err = verify_area(VERIFY_WRITE, arg, strlen(sl->dev->name) + 1);
 975                 if (err)  {
 976                         return -err;
 977                 }
 978                 memcpy_tofs(arg, sl->dev->name, strlen(sl->dev->name) + 1);
 979                 return 0;
 980 
 981         case SIOCGIFENCAP:
 982                 err = verify_area(VERIFY_WRITE, arg, sizeof(int));
 983                 if (err)  {
 984                         return -err;
 985                 }
 986                 put_user(sl->mode, (int *)arg);
 987                 return 0;
 988 
 989         case SIOCSIFENCAP:
 990                 err = verify_area(VERIFY_READ, arg, sizeof(int));
 991                 if (err)  {
 992                         return -err;
 993                 }
 994                 tmp = get_user((int *)arg);
 995 #ifndef SL_INCLUDE_CSLIP
 996                 if (tmp & (SL_MODE_CSLIP|SL_MODE_ADAPTIVE))  {
 997                         return -EINVAL;
 998                 }
 999 #else
1000                 if ((tmp & (SL_MODE_ADAPTIVE | SL_MODE_CSLIP)) ==
1001                     (SL_MODE_ADAPTIVE | SL_MODE_CSLIP))  {
1002                         /* return -EINVAL; */
1003                         tmp &= ~SL_MODE_ADAPTIVE;
1004                 }
1005 #endif
1006 #ifndef CONFIG_SLIP_MODE_SLIP6
1007                 if (tmp & SL_MODE_SLIP6)  {
1008                         return -EINVAL;
1009                 }
1010 #endif
1011 #ifndef CONFIG_AX25
1012                 if ((tmp & SL_MODE_AX25) || (tmp & SL_MODE_AX25VC)) {
1013                         return -EINVAL;
1014                 }
1015 #else
1016                 if ((tmp & SL_MODE_AX25) || (tmp & SL_MODE_AX25VC)) {
1017                         sl->dev->addr_len=AX25_ADDR_LEN;          /* sizeof an AX.25 addr */
1018                         sl->dev->hard_header_len=73; /* We don't do digipeaters */
1019                 } else  {
1020                         sl->dev->addr_len=0;    /* No mac addr in slip mode */
1021                         sl->dev->hard_header_len=0;
1022                 }
1023 #endif
1024                 sl->mode = tmp;
1025                 sl->dev->type = ARPHRD_SLIP+sl->mode;
1026 #ifdef CONFIG_AX25              
1027                 if (sl->dev->type == 260 || sl->dev->type == 272)  {
1028                         sl->dev->type = ARPHRD_AX25;
1029                 }
1030 #endif          
1031                 return 0;
1032 
1033          case SIOCSIFHWADDR:
1034 #ifdef CONFIG_AX25
1035                 return sl_set_mac_address(sl->dev, arg);
1036 #else
1037                 return -EINVAL;
1038 #endif
1039 
1040         /* Allow stty to read, but not set, the serial port */
1041         case TCGETS:
1042         case TCGETA:
1043                 return n_tty_ioctl(tty, (struct file *) file, cmd, (unsigned long) arg);
1044 
1045         default:
1046                 return -ENOIOCTLCMD;
1047         }
1048 }
1049 
1050 static int sl_open_dev(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
1051 {
1052         struct slip *sl = &sl_ctrl[dev->base_addr];
1053         if(sl->tty==NULL)
1054                 return -ENODEV;
1055         return 0;
1056 }
1057 
1058 /* Initialize the SLIP driver.  Called by DDI. */
1059 int
1060 slip_init(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
1061 {
1062         struct slip *sl = &sl_ctrl[dev->base_addr];
1063         int i;
1064 #ifdef CONFIG_AX25
1065         static char ax25_bcast[AX25_ADDR_LEN] =
1066                 {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
1067         static char ax25_test[AX25_ADDR_LEN] =
1068                 {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
1069 #endif
1070 
1071         if (already++ == 0) {
1072                 printk("SLIP: version %s (%d channels) %s\n",
1073                        SLIP_VERSION, SL_NRUNIT,
1074 #ifdef CONFIG_SLIP_MODE_SLIP6
1075                        "(6 bit encapsulation enabled)"
1076 #else
1077                        ""
1078 #endif
1079                        );
1080 #if defined(SL_INCLUDE_CSLIP) && !defined(MODULE)
1081                 printk("CSLIP: code copyright 1989 Regents of the University of California\n");
1082 #endif
1083 #ifdef CONFIG_AX25
1084                 printk("AX25: KISS encapsulation enabled\n");
1085 #endif
1086                 /* Fill in our LDISC request block. */
1087                 memset(&sl_ldisc, 0, sizeof(sl_ldisc));
1088                 sl_ldisc.magic  = TTY_LDISC_MAGIC;
1089                 sl_ldisc.flags  = 0;
1090                 sl_ldisc.open   = slip_open;
1091                 sl_ldisc.close  = slip_close;
1092                 sl_ldisc.read   = NULL;
1093                 sl_ldisc.write  = NULL;
1094                 sl_ldisc.ioctl  = (int (*)(struct tty_struct *, struct file *,
1095                                            unsigned int, unsigned long)) slip_ioctl;
1096                 sl_ldisc.select = NULL;
1097                 sl_ldisc.receive_buf = slip_receive_buf;
1098                 sl_ldisc.receive_room = slip_receive_room;
1099                 sl_ldisc.write_wakeup = slip_write_wakeup;
1100                 if ((i = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0)  {
1101                         printk("SLIP: can't register line discipline (err = %d)\n", i);
1102                 }
1103         }
1104 
1105         /* Set up the "SLIP Control Block". (And clear statistics) */
1106         
1107         memset(sl, 0, sizeof (struct slip));
1108         sl->magic  = SLIP_MAGIC;
1109         sl->dev    = dev;
1110         
1111         /* Finish setting up the DEVICE info. */
1112         dev->mtu                = SL_MTU;
1113         dev->hard_start_xmit    = sl_xmit;
1114         dev->open               = sl_open_dev;
1115         dev->stop               = sl_close;
1116         dev->hard_header        = sl_header;
1117         dev->get_stats          = sl_get_stats;
1118 #ifdef HAVE_SET_MAC_ADDR
1119 #ifdef CONFIG_AX25
1120         dev->set_mac_address    = sl_set_dev_mac_address;
1121 #endif
1122 #endif
1123         dev->hard_header_len    = 0;
1124         dev->addr_len           = 0;
1125         dev->type               = ARPHRD_SLIP + SL_MODE_DEFAULT;
1126 #ifdef CONFIG_AX25
1127         if (sl->dev->type == 260 || sl->dev->type == 272)  {
1128                 sl->dev->type = ARPHRD_AX25;
1129         }
1130         memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);      /* Only activated in AX.25 mode */
1131         memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);        /*    ""      ""       ""    "" */
1132 #endif
1133         dev->rebuild_header     = sl_rebuild_header;
1134 
1135         for (i = 0; i < DEV_NUMBUFFS; i++)  {
1136                 skb_queue_head_init(&dev->buffs[i]);
1137         }
1138 
1139         /* New-style flags. */
1140         dev->flags              = 0;
1141         dev->family             = AF_INET;
1142         dev->pa_addr            = 0;
1143         dev->pa_brdaddr         = 0;
1144         dev->pa_mask            = 0;
1145         dev->pa_alen            = 4;
1146 
1147         return 0;
1148 }
1149 #ifdef MODULE
1150 char kernel_version[] = UTS_RELEASE;
1151 
1152 static struct device dev_slip[SL_NRUNIT] =  {
1153         {
1154                 "sl0",          /* slip */
1155                 0, 0, 0, 0,     /* memory */
1156                 0, 0,           /* base, irq */
1157                 0, 0, 0, NULL, slip_init,
1158         },
1159         { "sl1" , 0, 0, 0, 0,  1, 0, 0, 0, 0, NULL, slip_init },
1160         { "sl2" , 0, 0, 0, 0,  2, 0, 0, 0, 0, NULL, slip_init },
1161         { "sl3" , 0, 0, 0, 0,  3, 0, 0, 0, 0, NULL, slip_init },
1162 #ifdef SL_SLIP_LOTS
1163         { "sl4" , 0, 0, 0, 0,  4, 0, 0, 0, 0, NULL, slip_init },
1164         { "sl5" , 0, 0, 0, 0,  5, 0, 0, 0, 0, NULL, slip_init },
1165         { "sl6" , 0, 0, 0, 0,  6, 0, 0, 0, 0, NULL, slip_init },
1166         { "sl7" , 0, 0, 0, 0,  7, 0, 0, 0, 0, NULL, slip_init },
1167         { "sl8" , 0, 0, 0, 0,  8, 0, 0, 0, 0, NULL, slip_init },
1168         { "sl9" , 0, 0, 0, 0,  9, 0, 0, 0, 0, NULL, slip_init },
1169         { "sl10", 0, 0, 0, 0, 10, 0, 0, 0, 0, NULL, slip_init },
1170         { "sl11", 0, 0, 0, 0, 11, 0, 0, 0, 0, NULL, slip_init },
1171         { "sl12", 0, 0, 0, 0, 12, 0, 0, 0, 0, NULL, slip_init },
1172         { "sl13", 0, 0, 0, 0, 13, 0, 0, 0, 0, NULL, slip_init },
1173         { "sl14", 0, 0, 0, 0, 14, 0, 0, 0, 0, NULL, slip_init },
1174         { "sl15", 0, 0, 0, 0, 15, 0, 0, 0, 0, NULL, slip_init },
1175 #endif /* SL_SLIP_LOTS */
1176 };
1177 
1178 int
1179 init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1180 {
1181         int err;
1182         int i;
1183 
1184         for (i = 0; i < SL_NRUNIT; i++)  {
1185                 if ((err = register_netdev(&dev_slip[i])))  {
1186                         if (err == -EEXIST)  {
1187                                 printk("SLIP: devices already present. Module not loaded.\n");
1188                         }
1189                         return err;
1190                 }
1191         }
1192         return 0;
1193 }
1194 
1195 void
1196 cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1197 {
1198         int i;
1199 
1200         if (MOD_IN_USE)  {
1201                 printk("SLIP: device busy, remove delayed\n");
1202                 return;
1203         }
1204         for (i = 0; i < SL_NRUNIT; i++)  {
1205                 unregister_netdev(&dev_slip[i]);
1206         }
1207         if ((i = tty_register_ldisc(N_SLIP, NULL)))  {
1208                 printk("SLIP: can't unregister line discipline (err = %d)\n", i);
1209         }
1210         already = 0;
1211 }
1212 #endif /* MODULE */

/* [previous][next][first][last][top][bottom][index][help] */