RFC 1055

Nonstandard for transmission of IP datagrams over serial lines: SLIP

πŸ“… published June 1988, from ietf

RFC 1055: A NONSTANDARD FOR TRANSMISSION OF IP DATAGRAMS OVER SERIAL LINES: SLIP πŸŽ€

okay bestie, this is RFC 1055 πŸ’– by J. Romkey, written for the Network Working Group in June 1988. the title is "A NONSTANDARD FOR TRANSMISSION OF IP DATAGRAMS OVER SERIAL LINES: SLIP". ngl the status is very honest: it's a nonstandard, and the memo says outright that SLIP is not an Internet standard. the header doesn't say it obsoletes or updates any other RFC, so it's just out here doing its own thing πŸ’…


INTRODUCTION ✨

okay so the TCP/IP family runs over a bunch of different network media: IEEE 802.3 (ethernet) and 802.5 (token ring) LANs, X.25 lines, satellite links, and serial lines. there are standard encapsulations for IP packets defined for lots of these, but there is NO standard for serial lines 😭. SLIP, Serial Line IP, is currently a de facto standard, and it's commonly used for point-to-point serial connections running TCP/IP. it is not an Internet standard. distribution of this memo is unlimited πŸ¦‹


HISTORY 🌸

SLIP has its origins in the 3COM UNET TCP/IP implementation from the early 1980's. it's merely a packet framing protocol: SLIP defines a sequence of characters that frame IP packets on a serial line, and nothing more. it provides no addressing, packet type identification, error detection/correction or compression mechanisms. but because the protocol does so little, it's usually very easy to implement, which is iconic ✨

around 1984, Rick Adams implemented SLIP for 4.2 Berkeley Unix and Sun Microsystems workstations and released it to the world. it quickly caught on as an easy, reliable way to connect TCP/IP hosts and routers with serial lines πŸ”₯

SLIP is commonly used on dedicated serial links and sometimes for dialup purposes, and it's usually used with line speeds between 1200bps and 19.2Kbps. it's really useful for letting mixes of hosts and routers talk to one another. host-host, host-router and router-router are all common SLIP network configurations 🧚


AVAILABILITY πŸ’œ

SLIP is available for most Berkeley UNIX-based systems. it's included in the standard 4.3BSD release from Berkeley. it's also available for Ultrix, Sun UNIX and most other Berkeley-derived UNIX systems. some terminal concentrators and IBM PC implementations support it too πŸ“

SLIP for Berkeley UNIX is available via anonymous FTP from uunet.uu.net in pub/sl.shar.Z. be sure to transfer the file in binary mode and then run it through the UNIX uncompress program. take the resulting file and use it as a shell script for the UNIX /bin/sh (for instance, /bin/sh sl.shar) 🫢


PROTOCOL πŸ‘‘

okay the SLIP protocol defines two special characters: END and ESC. END is octal 300 (decimal 192) and ESC is octal 333 (decimal 219). and yes, this ESC is NOT the ASCII ESCape character, so don't mix them up πŸ™ˆ for the rest of this, ESC means the SLIP ESC character.

to send a packet, a SLIP host just starts sending the data in the packet. if a data byte has the same code as the END character, it sends a two byte sequence of ESC and octal 334 (decimal 220) instead. if it's the same as an ESC character, it sends a two byte sequence of ESC and octal 335 (decimal 221) instead. when the last byte in the packet has been sent, an END character is transmitted. that's the whole vibe ✨

Phil Karn suggests a simple change to the algorithm, which is to begin as well as end packets with an END character. this flushes any erroneous bytes that were caused by line noise 🌈 in the normal case, the receiver just sees two back-to-back END characters, which generates a bad IP packet. if the SLIP implementation doesn't throw away the zero-length IP packet, the IP implementation certainly will. and if there was line noise, the data received because of it gets discarded without affecting the following packet. slay πŸ’…

Because there is no 'standard' SLIP specification, there is no real defined maximum packet size for SLIP. it is probably best to accept the maximum packet size used by the Berkeley UNIX SLIP drivers: 1006 bytes including the IP and transport protocol headers (not including the framing characters). therefore any new SLIP implementations should be prepared to accept 1006 byte datagrams and should not send more than 1006 bytes in a datagram πŸ’€

DEFICIENCIES πŸ₯€

there are several features that many users would like SLIP to provide which it doesn't. in all fairness, SLIP is just a very simple protocol designed quite a long time ago, when these problems weren't really important issues. these are the commonly perceived shortcomings in the existing SLIP protocol:

  • addressing:

both computers in a SLIP link need to know each other's IP addresses for routing purposes. also, when hosts use SLIP to dial up a router, the addressing scheme may be quite dynamic, and the router may need to inform the dialing host of the host's IP address. SLIP currently provides no mechanism for hosts to communicate addressing information over a SLIP connection πŸ—ΊοΈ

  • type identification:

SLIP has no type field. thus, only one protocol can run over a SLIP connection. so in a configuration of two DEC computers running both TCP/IP and DECnet, there's no hope of TCP/IP and DECnet sharing one serial line while using SLIP. while SLIP is "Serial Line IP", if a serial line connects two multi-protocol computers, those computers should be able to use more than one protocol over the line πŸ™…β€β™€οΈ

  • error detection/correction:

noisy phone lines will corrupt packets in transit. because the line speed is probably quite low (likely 2400 baud), retransmitting a packet is very expensive. error detection isn't absolutely necessary at the SLIP level, because any IP application should detect damaged packets (the IP header and UDP and TCP checksums should suffice). still, some common applications like NFS usually ignore the checksum and depend on the network media to detect damaged packets. because it takes so long to retransmit a packet that was corrupted by line noise, it would be efficient if SLIP could provide some sort of simple error correction mechanism of its own 😩

  • compression:

because dial-in lines are so slow (usually 2400bps), packet compression would cause large improvements in packet throughput. usually, streams of packets in a single TCP connection have few changed fields in the IP and TCP headers, so a simple compression algorithm might just send the changed parts of the headers instead of the complete headers πŸ“‰

some work is being done by various groups to design and implement a successor to SLIP that will address some or all of these problems. the glow-up is coming πŸ¦‹


SLIP DRIVERS πŸ§šβ€β™€οΈ

the following C language functions send and receive SLIP packets. they depend on two functions, send_char() and recv_char(), which send and receive a single character over the serial line. here's the code, bestie πŸŽ€

   /* SLIP special character codes
    */
   #define END             0300    /* indicates end of packet */
   #define ESC             0333    /* indicates byte stuffing */
   #define ESC_END         0334    /* ESC ESC_END means END data byte */
   #define ESC_ESC         0335    /* ESC ESC_ESC means ESC data byte */

   /* SEND_PACKET: sends a packet of length "len", starting at
    * location "p".
    */
   void send_packet(p, len)
           char *p;
           int len; {

     /* send an initial END character to flush out any data that may
      * have accumulated in the receiver due to line noise
      */
        send_char(END);

     /* for each byte in the packet, send the appropriate character
      * sequence
      */
           while(len--) {
                   switch(*p) {
                   /* if it's the same code as an END character, we send a
                    * special two character code so as not to make the
                    * receiver think we sent an END
                    */
                   case END:
                           send_char(ESC);
                           send_char(ESC_END);
                           break;

                   /* if it's the same code as an ESC character,
                    * we send a special two character code so as not
                    * to make the receiver think we sent an ESC
                    */
                   case ESC:
                           send_char(ESC);
                           send_char(ESC_ESC);
                           break;

                   /* otherwise, we just send the character
                    */
                   default:
                           send_char(*p);
                           }

                   p++;
                   }

           /* tell the receiver that we're done sending the packet
            */
           send_char(END);
           }

   /* RECV_PACKET: receives a packet into the buffer located at "p".
    *      If more than len bytes are received, the packet will
    *      be truncated.
    *      Returns the number of bytes stored in the buffer.
    */
   int recv_packet(p, len)
           char *p;
           int len; {
           char c;
           int received = 0;

           /* sit in a loop reading bytes until we put together
            * a whole packet.
            * Make sure not to copy them into the packet if we
            * run out of room.
            */
           while(1) {
                   /* get a character to process
                    */
                   c = recv_char();

                   /* handle bytestuffing if necessary
                    */
                   switch(c) {

                   /* if it's an END character then we're done with
                    * the packet
                    */
                   case END:
                           /* a minor optimization: if there is no
                            * data in the packet, ignore it. This is
                            * meant to avoid bothering IP with all
                            * the empty packets generated by the
                            * duplicate END characters which are in
                            * turn sent to try to detect line noise.
                            */
                           if(received)
                                   return received;
                           else
                                   break;

                   /* if it's the same code as an ESC character, wait
                    * and get another character and then figure out
                    * what to store in the packet based on that.
                    */
                   case ESC:
                           c = recv_char();

                           /* if "c" is not one of these two, then we
                            * have a protocol violation.  The best bet
                            * seems to be to leave the byte alone and
                            * just stuff it into the packet
                            */
                           switch(c) {
                           case ESC_END:
                                   c = END;
                                   break;
                           case ESC_ESC:
                                   c = ESC;
                                   break;
                                   }

                   /* here we fall into the default handler and let
                    * it store the character for us
                    */
                   default:
                           if(received < len)
                                   p[received++] = c;
                           }
                   }
           }
πŸ“¦ where this page comes from