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

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