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

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