root/drivers/net/slip.c

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

DEFINITIONS

This source file includes following definitions.
  1. ip_dump
  2. clh_dump
  3. sl_initialize
  4. sl_find
  5. sl_alloc
  6. sl_free
  7. sl_changedmtu
  8. sl_enqueue
  9. sl_dequeue
  10. sl_lock
  11. sl_unlock
  12. sl_bump
  13. sl_next
  14. sl_encaps
  15. sl_xmit
  16. sl_type_trans
  17. sl_header
  18. sl_add_arp
  19. sl_rebuild_header
  20. sl_open
  21. sl_close
  22. slip_recv
  23. slip_open
  24. slip_close
  25. slip_esc
  26. slip_unesc
  27. slip_esc6
  28. slip_unesc6
  29. slip_ioctl
  30. slip_init

   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 (via DDI).
   5  *
   6  * Version:     @(#)slip.c      0.7.6   05/25/93
   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  */
  21 #include <asm/segment.h>
  22 #include <asm/system.h>
  23 
  24 #include <linux/config.h>
  25 #include <linux/types.h>
  26 #include <linux/kernel.h>
  27 #include <linux/sched.h>
  28 #include <linux/string.h>
  29 #include <linux/mm.h>
  30 #include <linux/socket.h>
  31 #include <linux/termios.h>
  32 #include <linux/sockios.h>
  33 #include <linux/interrupt.h>
  34 #include <linux/tty.h>
  35 #include <linux/errno.h>
  36 #include <linux/stat.h>
  37 #include <linux/tty.h>
  38 #include <linux/in.h>
  39 #include "inet.h"
  40 #include "dev.h"
  41 #include "eth.h"
  42 #include "ip.h"
  43 #include "route.h"
  44 #include "protocol.h"
  45 #include "tcp.h"
  46 #include "skbuff.h"
  47 #include "sock.h"
  48 #include "arp.h"
  49 #include "slip.h"
  50 #include "slhc.h"
  51 
  52 #define SLIP_VERSION    "0.7.5"
  53 
  54 /* Define some IP layer stuff.  Not all systems have it. */
  55 #ifdef SL_DUMP
  56 #   define      IP_VERSION      4       /* version# of our IP software  */
  57 #   define      IPF_F_OFFSET    0x1fff  /* Offset field                 */
  58 #   define      IPF_DF          0x4000  /* Don't fragment flag          */
  59 #   define      IPF_MF          0x2000  /* More Fragments flag          */
  60 #   define      IP_OF_COPIED    0x80    /* Copied-on-fragmentation flag */
  61 #   define      IP_OF_CLASS     0x60    /* Option class                 */
  62 #   define      IP_OF_NUMBER    0x1f    /* Option number                */
  63 #endif
  64 
  65 
  66 static struct slip      sl_ctrl[SL_NRUNIT];
  67 static struct tty_ldisc sl_ldisc;
  68 static int              already = 0;
  69 
  70 
  71 /* Dump the contents of an IP datagram. */
  72 static void
  73 ip_dump(unsigned char *ptr, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
  74 {
  75 #ifdef SL_DUMP
  76   struct iphdr *ip;
  77   struct tcphdr *th;
  78   int dlen, doff;
  79 
  80   if (inet_debug != DBG_SLIP) return;
  81 
  82   ip = (struct iphdr *) ptr;
  83   th = (struct tcphdr *) (ptr + ip->ihl * 4);
  84   printk("\r%s -> %s seq %lx ack %lx len %d\n",
  85          in_ntoa(ip->saddr), in_ntoa(ip->daddr), 
  86          ntohl(th->seq), ntohl(th->ack_seq), ntohs(ip->tot_len));
  87   return;
  88 
  89   printk("\r*****\n");
  90   printk("%p %d\n", ptr, len);
  91   ip = (struct iphdr *) ptr;
  92   dlen = ntohs(ip->tot_len);
  93   doff = ((ntohs(ip->frag_off) & IPF_F_OFFSET) << 3);
  94 
  95 
  96   printk("SLIP: %s->", in_ntoa(ip->saddr));
  97   printk("%s\n", in_ntoa(ip->daddr));
  98   printk(" len %u ihl %u ver %u ttl %u prot %u",
  99         dlen, ip->ihl, ip->version, ip->ttl, ip->protocol);
 100 
 101   if (ip->tos != 0) printk(" tos %u", ip->tos);
 102   if (doff != 0 || (ntohs(ip->frag_off) & IPF_MF))
 103         printk(" id %u offs %u", ntohs(ip->id), doff);
 104 
 105   if (ntohs(ip->frag_off) & IPF_DF) printk(" DF");
 106   if (ntohs(ip->frag_off) & IPF_MF) printk(" MF");
 107   printk("\n*****\n");
 108 #endif
 109 }
 110 
 111 #if 0
 112 void clh_dump(unsigned char *cp, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 113 {
 114   if (len > 60)
 115     len = 60;
 116   printk("%d:", len);
 117   while (len > 0) {
 118     printk(" %x", *cp++);
 119     len--;
 120   }
 121   printk("\n\n");
 122 }
 123 #endif
 124 
 125 /* Initialize a SLIP control block for use. */
 126 static void
 127 sl_initialize(struct slip *sl, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 128 {
 129   sl->inuse             = 0;
 130   sl->sending           = 0;
 131   sl->escape            = 0;
 132   sl->flags             = 0;
 133 #ifdef SL_COMPRESSED
 134   sl->mode              = SL_MODE_CSLIP;        /* Default */
 135 #else
 136   sl->mode              = SL_MODE_SLIP;         /* Default for non compressors */
 137 #endif  
 138 
 139   sl->line              = dev->base_addr;
 140   sl->tty               = NULL;
 141   sl->dev               = dev;
 142   sl->slcomp            = NULL;
 143 
 144   /* Clear all pointers. */
 145   sl->rbuff             = NULL;
 146   sl->xbuff             = NULL;
 147   sl->cbuff             = NULL;
 148 
 149   sl->rhead             = NULL;
 150   sl->rend              = NULL;
 151   dev->rmem_end         = (unsigned long) NULL;
 152   dev->rmem_start       = (unsigned long) NULL;
 153   dev->mem_end          = (unsigned long) NULL;
 154   dev->mem_start        = (unsigned long) NULL;
 155 }
 156 
 157 
 158 /* Find a SLIP channel from its `tty' link. */
 159 static struct slip *
 160 sl_find(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 161 {
 162   struct slip *sl;
 163   int i;
 164 
 165   if (tty == NULL) return(NULL);
 166   for (i = 0; i < SL_NRUNIT; i++) {
 167         sl = &sl_ctrl[i];
 168         if (sl->tty == tty) return(sl);
 169   }
 170   return(NULL);
 171 }
 172 
 173 
 174 /* Find a free SLIP channel, and link in this `tty' line. */
 175 static inline struct slip *
 176 sl_alloc(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 177 {
 178   unsigned long flags;
 179   struct slip *sl;
 180   int i;
 181 
 182   save_flags (flags);
 183   cli();
 184   for (i = 0; i < SL_NRUNIT; i++) {
 185         sl = &sl_ctrl[i];
 186         if (sl->inuse == 0) {
 187                 sl->inuse = 1;
 188                 sl->tty = NULL;
 189                 restore_flags(flags);
 190                 return(sl);
 191         }
 192   }
 193   restore_flags(flags);
 194   return(NULL);
 195 }
 196 
 197 
 198 /* Free a SLIP channel. */
 199 static inline void
 200 sl_free(struct slip *sl)
     /* [previous][next][first][last][top][bottom][index][help] */
 201 {
 202   unsigned long flags;
 203 
 204   if (sl->inuse) {
 205         save_flags(flags);
 206         cli();
 207         sl->inuse = 0;
 208         sl->tty = NULL;
 209         restore_flags(flags);
 210   }
 211 }
 212 
 213 /* MTU has been changed by the IP layer. Unfortunately we are not told about this, but
 214    we spot it ourselves and fix things up. We could be in an upcall from the tty
 215    driver, or in an ip packet queue. */
 216    
 217 static void sl_changedmtu(struct slip *sl)
     /* [previous][next][first][last][top][bottom][index][help] */
 218 {
 219         struct device *dev=sl->dev;
 220         unsigned char *tb,*rb,*cb,*tf,*rf,*cf;
 221         int l;
 222         int omtu=sl->mtu;
 223         
 224         sl->mtu=dev->mtu;
 225         l=(dev->mtu *2);
 226         
 227         DPRINTF((DBG_SLIP,"SLIP: mtu changed!\n"));
 228         
 229         tb= (unsigned char *) kmalloc(l + 4, GFP_KERNEL);
 230         rb= (unsigned char *) kmalloc(l + 4, GFP_KERNEL);
 231         cb= (unsigned char *) kmalloc(l + 4, GFP_KERNEL);
 232         
 233         if(tb==NULL || rb==NULL || cb==NULL)
 234         {
 235                 printk("Unable to grow slip buffers. MTU change cancelled.\n");
 236                 sl->mtu=omtu;
 237                 dev->mtu=omtu;
 238                 if(tb!=NULL)
 239                         kfree(tb);
 240                 if(rb!=NULL)
 241                         kfree(rb);
 242                 if(cb!=NULL)
 243                         kfree(cb);
 244                 return;
 245         }
 246         
 247         cli();
 248         
 249         tf=(unsigned char *)sl->dev->mem_start;
 250         sl->dev->mem_start=(unsigned long)tb;
 251         sl->dev->mem_end=(unsigned long) (sl->dev->mem_start + l);
 252         rf=(unsigned char *)sl->dev->rmem_start;
 253         sl->dev->rmem_start=(unsigned long)rb;
 254         sl->dev->rmem_end=(unsigned long) (sl->dev->rmem_start + l);
 255         
 256         sl->xbuff = (unsigned char *) sl->dev->mem_start;
 257         sl->rbuff = (unsigned char *) sl->dev->rmem_start;
 258         sl->rend  = (unsigned char *) sl->dev->rmem_end;
 259         sl->rhead = sl->rbuff;
 260         
 261         cf=sl->cbuff;
 262         sl->cbuff=cb;
 263         
 264         sl->escape=0;
 265         sl->sending=0;
 266         sl->rcount=0;
 267 
 268         sti();  
 269         
 270         if(rf!=NULL)
 271                 kfree(rf);
 272         if(tf!=NULL)
 273                 kfree(tf);
 274         if(cf!=NULL)
 275                 kfree(cf);
 276 }
 277 
 278 
 279 /* Stuff one byte into a SLIP receiver buffer. */
 280 static inline void
 281 sl_enqueue(struct slip *sl, unsigned char c)
     /* [previous][next][first][last][top][bottom][index][help] */
 282 {
 283   unsigned long flags;
 284 
 285   save_flags(flags);
 286   cli();
 287   if (sl->rhead < sl->rend) {
 288         *sl->rhead = c;
 289         sl->rhead++;
 290         sl->rcount++;
 291   } else sl->roverrun++;
 292   restore_flags(flags);
 293 }
 294 
 295 /* Release 'i' bytes from a SLIP receiver buffer. */
 296 static inline void
 297 sl_dequeue(struct slip *sl, int i)
     /* [previous][next][first][last][top][bottom][index][help] */
 298 {
 299   unsigned long flags;
 300 
 301   save_flags(flags);
 302   cli();
 303   if (sl->rhead > sl->rbuff) {
 304         sl->rhead -= i;
 305         sl->rcount -= i;
 306   }
 307   restore_flags(flags);
 308 }
 309 
 310 
 311 /* Set the "sending" flag.  This must be atomic, hence the ASM. */
 312 static inline void
 313 sl_lock(struct slip *sl)
     /* [previous][next][first][last][top][bottom][index][help] */
 314 {
 315   unsigned long flags;
 316 
 317   save_flags(flags);
 318   cli();
 319   sl->sending = 1;
 320   sl->dev->tbusy = 1;
 321   restore_flags(flags);
 322 }
 323 
 324 
 325 /* Clear the "sending" flag.  This must be atomic, hence the ASM. */
 326 static inline void
 327 sl_unlock(struct slip *sl)
     /* [previous][next][first][last][top][bottom][index][help] */
 328 {
 329   unsigned long flags;
 330 
 331   save_flags(flags);
 332   cli();
 333   sl->sending = 0;
 334   sl->dev->tbusy = 0;
 335   restore_flags(flags);
 336 }
 337 
 338 
 339 /* Send one completely decapsulated IP datagram to the IP layer. */
 340 static void
 341 sl_bump(struct slip *sl)
     /* [previous][next][first][last][top][bottom][index][help] */
 342 {
 343   int done;
 344   unsigned char c;
 345   unsigned long flags;
 346   int count;
 347 
 348   count = sl->rcount;
 349   if (sl->mode & SL_MODE_CSLIP) {
 350     if ((c = sl->rbuff[0]) & SL_TYPE_COMPRESSED_TCP) {
 351       /* make sure we've reserved enough space for uncompress to use */
 352       save_flags(flags);
 353       cli();
 354       if ((sl->rhead + 80) < sl->rend) {
 355         sl->rhead += 80;
 356         sl->rcount += 80;
 357         done = 1;
 358       } else {
 359         sl->roverrun++;
 360         done = 0;
 361       }
 362       restore_flags(flags);
 363       if (! done)  /* not enough space available */
 364         return;
 365 
 366       count = slhc_uncompress(sl->slcomp, sl->rbuff, count);
 367       if (count <= 0) {
 368         sl->errors++;
 369         return;
 370       }
 371     } else if (c >= SL_TYPE_UNCOMPRESSED_TCP) {
 372       sl->rbuff[0] &= 0x4f;
 373       if (slhc_remember(sl->slcomp, sl->rbuff, count) <= 0) {
 374         sl->errors++;
 375         return;
 376       }
 377     }
 378   }
 379 
 380   DPRINTF((DBG_SLIP, "<< \"%s\" recv:\r\n", sl->dev->name));
 381   ip_dump(sl->rbuff, sl->rcount);
 382 
 383   /* Bump the datagram to the upper layers... */
 384   do {
 385         DPRINTF((DBG_SLIP, "SLIP: packet is %d at 0x%X\n",
 386                                         sl->rcount, sl->rbuff));
 387         /* clh_dump(sl->rbuff, count); */
 388         done = dev_rint(sl->rbuff, count, 0, sl->dev);
 389         if (done == 0 || done == 1) break;
 390   } while(1);
 391 
 392   sl->rpacket++;
 393 }
 394 
 395 
 396 /* TTY finished sending a datagram, so clean up. */
 397 static void
 398 sl_next(struct slip *sl)
     /* [previous][next][first][last][top][bottom][index][help] */
 399 {
 400   DPRINTF((DBG_SLIP, "SLIP: sl_next(0x%X) called!\n", sl));
 401   sl_unlock(sl);
 402   dev_tint(sl->dev);
 403 }
 404 
 405 
 406 /* Encapsulate one IP datagram and stuff into a TTY queue. */
 407 static void
 408 sl_encaps(struct slip *sl, unsigned char *icp, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 409 {
 410   unsigned char *bp, *p;
 411   int count;
 412 
 413   DPRINTF((DBG_SLIP, "SLIP: sl_encaps(0x%X, %d) called\n", icp, len));
 414   DPRINTF((DBG_SLIP, ">> \"%s\" sent:\r\n", sl->dev->name));
 415   
 416   ip_dump(icp, len);
 417   
 418   if(sl->mtu != sl->dev->mtu)   /* Someone has been ifconfigging */
 419         sl_changedmtu(sl);
 420   
 421   if(len>sl->mtu)               /* Sigh, shouldn't occur BUT ... */
 422   {
 423         len=sl->mtu;
 424         printk("slip: truncating oversized transmit packet!\n");
 425   }
 426 
 427   p = icp;
 428   if(sl->mode & SL_MODE_CSLIP)
 429           len = slhc_compress(sl->slcomp, p, len, sl->cbuff, &p, 1);
 430 
 431 #ifdef OLD  
 432   /*
 433    * Send an initial END character to flush out any
 434    * data that may have accumulated in the receiver
 435    * due to line noise.
 436    */
 437   bp = sl->xbuff;
 438   *bp++ = END;
 439   count = 1;
 440 
 441   /*
 442    * For each byte in the packet, send the appropriate
 443    * character sequence, according to the SLIP protocol.
 444    */
 445   while(len-- > 0) {
 446         c = *p++;
 447         switch(c) {
 448                 case END:
 449                         *bp++ = ESC;
 450                         *bp++ = ESC_END;
 451                         count += 2;
 452                         break;
 453                 case ESC:
 454                         *bp++ = ESC;
 455                         *bp++ = ESC_ESC;
 456                         count += 2;
 457                         break;
 458                 default:
 459                         *bp++ = c;
 460                         count++;
 461         }
 462   }
 463   *bp++ = END;  
 464   count++;
 465 #else
 466   if(sl->mode & SL_MODE_SLIP6)
 467         count=slip_esc6(p, (unsigned char *)sl->xbuff,len);
 468   else
 469         count=slip_esc(p, (unsigned char *)sl->xbuff,len);
 470 #endif            
 471   sl->spacket++;
 472   bp = sl->xbuff;
 473 
 474   /* Tell TTY to send it on its way. */
 475   DPRINTF((DBG_SLIP, "SLIP: kicking TTY for %d bytes at 0x%X\n", count, bp));
 476   if (tty_write_data(sl->tty, (char *) bp, count,
 477              (void (*)(void *))sl_next, (void *) sl) == 0) {
 478         DPRINTF((DBG_SLIP, "SLIP: TTY already done with %d bytes!\n", count));
 479         sl_next(sl);
 480   }
 481 }
 482 
 483 
 484 /* Encapsulate an IP datagram and kick it into a TTY queue. */
 485 static int
 486 sl_xmit(struct sk_buff *skb, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 487 {
 488   struct tty_struct *tty;
 489   struct slip *sl;
 490 
 491   /* Find the correct SLIP channel to use. */
 492   sl = &sl_ctrl[dev->base_addr];
 493   tty = sl->tty;
 494   DPRINTF((DBG_SLIP, "SLIP: sl_xmit(\"%s\") skb=0x%X busy=%d\n",
 495                                 dev->name, skb, sl->sending));
 496 
 497   /*
 498    * If we are busy already- too bad.  We ought to be able
 499    * to queue things at this point, to allow for a little
 500    * frame buffer.  Oh well...
 501    */
 502   if (sl->sending) {
 503         DPRINTF((DBG_SLIP, "SLIP: sl_xmit: BUSY\r\n"));
 504         sl->sbusy++;
 505         return(1);
 506   }
 507 
 508   /* We were not, so we are now... :-) */
 509   if (skb != NULL) {
 510         sl_lock(sl);
 511         sl_encaps(sl, (unsigned char *) (skb + 1), skb->len);
 512         if (skb->free) kfree_skb(skb, FREE_WRITE);
 513   }
 514   return(0);
 515 }
 516 
 517 
 518 /* Return the frame type ID.  This is always IP. */
 519 static unsigned short
 520 sl_type_trans (struct sk_buff *skb, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 521 {
 522   return(NET16(ETH_P_IP));
 523 }
 524 
 525 
 526 /* Fill in the MAC-level header. Not used by SLIP. */
 527 static int
 528 sl_header(unsigned char *buff, struct device *dev, unsigned short type,
     /* [previous][next][first][last][top][bottom][index][help] */
 529           unsigned long daddr, unsigned long saddr, unsigned len)
 530 {
 531   return(0);
 532 }
 533 
 534 
 535 /* Add an ARP-entry for this device's broadcast address. Not used. */
 536 static void
 537 sl_add_arp(unsigned long addr, struct sk_buff *skb, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 538 {
 539 }
 540 
 541 
 542 /* Rebuild the MAC-level header.  Not used by SLIP. */
 543 static int
 544 sl_rebuild_header(void *buff, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 545 {
 546   return(0);
 547 }
 548 
 549 
 550 /* Open the low-level part of the SLIP channel. Easy! */
 551 static int
 552 sl_open(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 553 {
 554   struct slip *sl;
 555   unsigned char *p;
 556   unsigned long l;
 557 
 558   sl = &sl_ctrl[dev->base_addr];
 559   if (sl->tty == NULL) {
 560         DPRINTF((DBG_SLIP, "SLIP: channel %d not connected!\n", sl->line));
 561         return(-ENXIO);
 562   }
 563   sl->dev = dev;
 564 
 565   /*
 566    * Allocate the SLIP frame buffers:
 567    *
 568    * mem_end    Top of frame buffers
 569    * mem_start  Start of frame buffers
 570    * rmem_end   Top of RECV frame buffer
 571    * rmem_start Start of RECV frame buffer
 572    */
 573   l = (dev->mtu * 2);
 574   p = (unsigned char *) kmalloc(l + 4, GFP_KERNEL);
 575   if (p == NULL) {
 576         DPRINTF((DBG_SLIP, "SLIP: no memory for SLIP XMIT buffer!\n"));
 577         return(-ENOMEM);
 578   }
 579   
 580   sl->mtu               = dev->mtu;
 581   sl->dev->mem_start    = (unsigned long) p;
 582   sl->dev->mem_end      = (unsigned long) (sl->dev->mem_start + l);
 583 
 584   p = (unsigned char *) kmalloc(l + 4, GFP_KERNEL);
 585   if (p == NULL) {
 586         DPRINTF((DBG_SLIP, "SLIP: no memory for SLIP RECV buffer!\n"));
 587         return(-ENOMEM);
 588   }
 589   sl->dev->rmem_start   = (unsigned long) p;
 590   sl->dev->rmem_end     = (unsigned long) (sl->dev->rmem_start + l);
 591 
 592   sl->xbuff             = (unsigned char *) sl->dev->mem_start;
 593   sl->rbuff             = (unsigned char *) sl->dev->rmem_start;
 594   sl->rend              = (unsigned char *) sl->dev->rmem_end;
 595   sl->rhead             = sl->rbuff;
 596 
 597   sl->escape            = 0;
 598   sl->sending           = 0;
 599   sl->rcount            = 0;
 600 
 601   p = (unsigned char *) kmalloc(l + 4, GFP_KERNEL);
 602   if (p == NULL) {
 603         kfree((unsigned char *)sl->dev->mem_start);
 604         DPRINTF((DBG_SLIP, "SLIP: no memory for SLIP COMPRESS buffer!\n"));
 605         return(-ENOMEM);
 606   }
 607   sl->cbuff             = p;
 608 
 609   sl->slcomp = slhc_init(16, 16);
 610   if (sl->slcomp == NULL) {
 611         kfree((unsigned char *)sl->dev->mem_start);
 612         kfree((unsigned char *)sl->dev->rmem_start);
 613         kfree(sl->cbuff);
 614         DPRINTF((DBG_SLIP, "SLIP: no memory for SLCOMP!\n"));
 615         return(-ENOMEM);
 616   }
 617 
 618   DPRINTF((DBG_SLIP, "SLIP: channel %d opened.\n", sl->line));
 619   return(0);
 620 }
 621 
 622 
 623 /* Close the low-level part of the SLIP channel. Easy! */
 624 static int
 625 sl_close(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 626 {
 627   struct slip *sl;
 628 
 629   sl = &sl_ctrl[dev->base_addr];
 630   if (sl->tty == NULL) {
 631         DPRINTF((DBG_SLIP, "SLIP: channel %d not connected!\n", sl->line));
 632         return(-EBUSY);
 633   }
 634   sl_free(sl);
 635 
 636   /* Free all SLIP frame buffers. */
 637   kfree(sl->rbuff);
 638   kfree(sl->xbuff);
 639   kfree(sl->cbuff);
 640   slhc_free(sl->slcomp);
 641 
 642   sl_initialize(sl, dev);
 643 
 644   DPRINTF((DBG_SLIP, "SLIP: channel %d closed.\n", sl->line));
 645   return(0);
 646 }
 647 
 648 
 649 /*
 650  * Handle the 'receiver data ready' interrupt.
 651  * This function is called by the 'tty_io' module in the kernel when
 652  * a block of SLIP data has been received, which can now be decapsulated
 653  * and sent on to some IP layer for further processing.
 654  */
 655 static void
 656 slip_recv(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 657 {
 658   unsigned char buff[128];
 659   unsigned char *p;
 660   struct slip *sl;
 661   int count, error=0;
 662   
 663   DPRINTF((DBG_SLIP, "SLIP: slip_recv(%d) called\n", tty->line));
 664   if ((sl = sl_find(tty)) == NULL) return;      /* not connected */
 665 
 666   if(sl->mtu!=sl->dev->mtu)     /* Argh! mtu change time! - costs us the packet part received at the change */
 667         sl_changedmtu(sl);
 668         
 669   /* Suck the bytes out of the TTY queues. */
 670   do {
 671         count = tty_read_raw_data(tty, buff, 128);
 672         if (count <= 0)
 673         {
 674                 count= - count;
 675                 if(count)
 676                         error=1;
 677                 break;
 678         }
 679         p = buff;
 680 #ifdef OLD      
 681         while (count--) {
 682                 c = *p++;
 683                 if (sl->escape) {
 684                         if (c == ESC_ESC)
 685                                 sl_enqueue(sl, ESC);
 686                         else if (c == ESC_END)
 687                                 sl_enqueue(sl, END);
 688                         else
 689                                 printk ("SLIP: received wrong character\n");
 690                         sl->escape = 0;
 691                 } else {
 692                         if (c == ESC)
 693                                 sl->escape = 1;
 694                         else if (c == END) {
 695                                 if (sl->rcount > 2) sl_bump(sl);
 696                                 sl_dequeue(sl, sl->rcount);
 697                                 sl->rcount = 0;
 698                         } else  sl_enqueue(sl, c);
 699                 }
 700         }
 701 #else
 702         if(sl->mode & SL_MODE_SLIP6)
 703                 slip_unesc6(sl,buff,count,error);
 704         else
 705                 slip_unesc(sl,buff,count,error);
 706 #endif          
 707   } while(1);
 708   
 709 }
 710 
 711 
 712 /*
 713  * Open the high-level part of the SLIP channel.  
 714  * This function is called by the TTY module when the
 715  * SLIP line discipline is called for.  Because we are
 716  * sure the tty line exists, we only have to link it to
 717  * a free SLIP channel...
 718  */
 719 static int
 720 slip_open(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 721 {
 722   struct slip *sl;
 723 
 724   /* First make sure we're not already connected. */
 725   if ((sl = sl_find(tty)) != NULL) {
 726         DPRINTF((DBG_SLIP, "SLIP: TTY %d already connected to %s !\n",
 727                                         tty->line, sl->dev->name));
 728         return(-EEXIST);
 729   }
 730 
 731   /* OK.  Find a free SLIP channel to use. */
 732   if ((sl = sl_alloc()) == NULL) {
 733         DPRINTF((DBG_SLIP, "SLIP: TTY %d not connected: all channels in use!\n",
 734                                                 tty->line));
 735         return(-ENFILE);
 736   }
 737   sl->tty = tty;
 738   tty_read_flush(tty);
 739   tty_write_flush(tty);
 740 
 741   /* Perform the low-level SLIP initialization. */
 742   (void) sl_open(sl->dev);
 743   DPRINTF((DBG_SLIP, "SLIP: TTY %d connected to %s.\n",
 744                                 tty->line, sl->dev->name));
 745 
 746   /* Done.  We have linked the TTY line to a channel. */
 747   return(sl->line);
 748 }
 749 
 750 
 751 /*
 752  * Close down a SLIP channel.
 753  * This means flushing out any pending queues, and then restoring the
 754  * TTY line discipline to what it was before it got hooked to SLIP
 755  * (which usually is TTY again).
 756  */
 757 static void
 758 slip_close(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 759 {
 760   struct slip *sl;
 761 
 762   /* First make sure we're connected. */
 763   if ((sl = sl_find(tty)) == NULL) {
 764         DPRINTF((DBG_SLIP, "SLIP: TTY %d not connected !\n", tty->line));
 765         return;
 766   }
 767 
 768   (void) dev_close(sl->dev);
 769   DPRINTF((DBG_SLIP, "SLIP: TTY %d disconnected from %s.\n",
 770                                         tty->line, sl->dev->name));
 771 }
 772 
 773  
 774  /************************************************************************
 775   *                     STANDARD SLIP ENCAPSULATION                     *
 776   ************************************************************************
 777   *
 778   */
 779  
 780  int
 781  slip_esc(unsigned char *s, unsigned char *d, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 782  {
 783      int count = 0;
 784  
 785      /*
 786       * Send an initial END character to flush out any
 787       * data that may have accumulated in the receiver
 788       * due to line noise.
 789       */
 790  
 791      d[count++] = END;
 792  
 793      /*
 794       * For each byte in the packet, send the appropriate
 795       * character sequence, according to the SLIP protocol.
 796       */
 797  
 798      while(len-- > 0) {
 799         switch(*s) {
 800         case END:
 801             d[count++] = ESC;
 802             d[count++] = ESC_END;
 803             break;
 804         case ESC:
 805             d[count++] = ESC;
 806             d[count++] = ESC_ESC;
 807             break;
 808         default:
 809             d[count++] = *s;
 810         }
 811         ++s;
 812      }
 813      d[count++] = END;
 814      return(count);
 815  }
 816  
 817  void
 818  slip_unesc(struct slip *sl, unsigned char *s, int count, int error)
     /* [previous][next][first][last][top][bottom][index][help] */
 819  {
 820      int i;
 821  
 822      for (i = 0; i < count; ++i, ++s) {
 823         switch(*s) {
 824         case ESC:
 825             sl->flags |= SLF_ESCAPE;
 826             break;
 827         case ESC_ESC:
 828             if (sl->flags & SLF_ESCAPE)
 829                 sl_enqueue(sl, ESC);
 830             else
 831                 sl_enqueue(sl, *s);
 832             sl->flags &= ~SLF_ESCAPE;
 833             break;
 834         case ESC_END:
 835             if (sl->flags & SLF_ESCAPE)
 836                 sl_enqueue(sl, END);
 837             else
 838                 sl_enqueue(sl, *s);
 839             sl->flags &= ~SLF_ESCAPE;
 840             break;
 841         case END:
 842             if (sl->rcount > 2) 
 843                 sl_bump(sl);
 844             sl_dequeue(sl, sl->rcount);
 845             sl->rcount = 0;
 846             sl->flags &= ~(SLF_ESCAPE | SLF_ERROR);
 847             break;
 848         default:
 849             sl_enqueue(sl, *s);
 850             sl->flags &= ~SLF_ESCAPE;
 851         }
 852      }
 853      if (error)
 854         sl->flags |= SLF_ERROR;
 855  }
 856  
 857  /************************************************************************
 858   *                      6 BIT SLIP ENCAPSULATION                       *
 859   ************************************************************************
 860   *
 861   */
 862  
 863  int
 864  slip_esc6(unsigned char *s, unsigned char *d, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 865  {
 866      int count = 0;
 867      int i;
 868      unsigned short v = 0;
 869      short bits = 0;
 870  
 871      /*
 872       * Send an initial END character to flush out any
 873       * data that may have accumulated in the receiver
 874       * due to line noise.
 875       */
 876  
 877      d[count++] = 0x70;
 878  
 879      /*
 880       * Encode the packet into printable ascii characters
 881       */
 882  
 883      for (i = 0; i < len; ++i) {
 884         v = (v << 8) | s[i];
 885         bits += 8;
 886         while (bits >= 6) {
 887             unsigned char c;
 888  
 889             bits -= 6;
 890             c = 0x30 + ((v >> bits) & 0x3F);
 891             d[count++] = c;
 892         }
 893      }
 894      if (bits) {
 895         unsigned char c;
 896  
 897         c = 0x30 + ((v << (6 - bits)) & 0x3F);
 898         d[count++] = c;
 899      }
 900      d[count++] = 0x70;
 901      return(count);
 902  }
 903  
 904  void
 905  slip_unesc6(struct slip *sl, unsigned char *s, int count, int error)
     /* [previous][next][first][last][top][bottom][index][help] */
 906  {
 907      int i;
 908      unsigned char c;
 909  
 910      for (i = 0; i < count; ++i, ++s) {
 911         if (*s == 0x70) {
 912             if (sl->rcount > 8) {       /* XXX must be 2 for compressed slip */
 913  #ifdef NOTDEF
 914                 printk("rbuff %02x %02x %02x %02x\n",
 915                     sl->rbuff[0],
 916                     sl->rbuff[1],
 917                     sl->rbuff[2],
 918                     sl->rbuff[3]
 919                 );
 920  #endif
 921                 sl_bump(sl);
 922             }
 923             sl_dequeue(sl, sl->rcount);
 924             sl->rcount = 0;
 925             sl->flags &= ~(SLF_ESCAPE | SLF_ERROR); /* SLF_ESCAPE not used */
 926             sl->xbits = 0;
 927         } else if (*s >= 0x30 && *s < 0x70) {
 928             sl->xdata = (sl->xdata << 6) | ((*s - 0x30) & 0x3F);
 929             sl->xbits += 6;
 930             if (sl->xbits >= 8) {
 931                 sl->xbits -= 8;
 932                 c = (unsigned char)(sl->xdata >> sl->xbits);
 933                 sl_enqueue(sl, c);
 934             }
 935  
 936         }
 937      }
 938      if (error)
 939         sl->flags |= SLF_ERROR;
 940  }
 941 
 942 /* Perform I/O control on an active SLIP channel. */
 943 static int
 944 slip_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 945 {
 946   struct slip *sl;
 947   int err;
 948 
 949   /* First make sure we're connected. */
 950   if ((sl = sl_find(tty)) == NULL) {
 951         DPRINTF((DBG_SLIP, "SLIP: ioctl: TTY %d not connected !\n", tty->line));
 952         return(-EINVAL);
 953   }
 954 
 955   DPRINTF((DBG_SLIP, "SLIP: ioctl(%d, 0x%X, 0x%X)\n", tty->line, cmd, arg));
 956   switch(cmd) {
 957         case SIOCGIFNAME:
 958                 err=verify_area(VERIFY_WRITE, arg, 16);
 959                 if(err)
 960                         return -err;
 961                 memcpy_tofs(arg, sl->dev->name, strlen(sl->dev->name) + 1);
 962                 return(0);
 963         case SIOCGIFENCAP:
 964                 err=verify_area(VERIFY_WRITE,arg,sizeof(long));
 965                 put_fs_long(sl->mode,(long *)arg);
 966                 return(0);
 967         case SIOCSIFENCAP:
 968                 err=verify_area(VERIFY_READ,arg,sizeof(long));
 969                 sl->mode=get_fs_long((long *)arg);
 970                 return(0);
 971         default:
 972                 return(-EINVAL);
 973   }
 974   return(-EINVAL);
 975 }
 976 
 977 
 978 /* Initialize the SLIP driver.  Called by DDI. */
 979 int
 980 slip_init(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 981 {
 982   struct slip *sl;
 983   int i;
 984 
 985   sl = &sl_ctrl[dev->base_addr];
 986 
 987   if (already++ == 0) {
 988         printk("SLIP: version %s (%d channels)\n",
 989                                 SLIP_VERSION, SL_NRUNIT);
 990         printk("CSLIP: code copyright 1989 Regents of the University of California\n");
 991         /* Fill in our LDISC request block. */
 992         sl_ldisc.flags  = 0;
 993         sl_ldisc.open   = slip_open;
 994         sl_ldisc.close  = slip_close;
 995         sl_ldisc.read   = NULL;
 996         sl_ldisc.write  = NULL;
 997         sl_ldisc.ioctl  = (int (*)(struct tty_struct *, struct file *,
 998                                    unsigned int, unsigned long)) slip_ioctl;
 999         sl_ldisc.handler = slip_recv;
1000         if ((i = tty_register_ldisc(N_SLIP, &sl_ldisc)) == 0) printk("OK\n");
1001           else printk("ERROR: %d\n", i);
1002   }
1003 
1004   /* Set up the "SLIP Control Block". */
1005   sl_initialize(sl, dev);
1006 
1007   /* Clear all statistics. */
1008   sl->rcount            = 0;                    /* SLIP receiver count  */
1009   sl->rpacket           = 0;                    /* #frames received     */
1010   sl->roverrun          = 0;                    /* "overrun" counter    */
1011   sl->spacket           = 0;                    /* #frames sent out     */
1012   sl->sbusy             = 0;                    /* "xmit busy" counter  */
1013   sl->errors            = 0;                    /* not used at present  */
1014 
1015   /* Finish setting up the DEVICE info. */
1016   dev->mtu              = SL_MTU;
1017   dev->hard_start_xmit  = sl_xmit;
1018   dev->open             = sl_open;
1019   dev->stop             = sl_close;
1020   dev->hard_header      = sl_header;
1021   dev->add_arp          = sl_add_arp;
1022   dev->type_trans       = sl_type_trans;
1023   dev->hard_header_len  = 0;
1024   dev->addr_len         = 0;
1025   dev->type             = 0;
1026   dev->queue_xmit       = dev_queue_xmit;
1027   dev->rebuild_header   = sl_rebuild_header;
1028   for (i = 0; i < DEV_NUMBUFFS; i++)
1029                 dev->buffs[i] = NULL;
1030 
1031   /* New-style flags. */
1032   dev->flags            = 0;
1033   dev->family           = AF_INET;
1034   dev->pa_addr          = 0;
1035   dev->pa_brdaddr       = 0;
1036   dev->pa_mask          = 0;
1037   dev->pa_alen          = sizeof(unsigned long);
1038 
1039   return(0);
1040 }

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