The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net/if_sl.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1987, 1989, 1992, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *      This product includes software developed by the University of
   16  *      California, Berkeley and its contributors.
   17  * 4. Neither the name of the University nor the names of its contributors
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  *
   33  *      @(#)if_sl.c     8.6 (Berkeley) 2/1/94
   34  * $FreeBSD: src/sys/net/if_sl.c,v 1.45.2.4 1999/09/05 08:17:46 peter Exp $
   35  */
   36 
   37 /*
   38  * Serial Line interface
   39  *
   40  * Rick Adams
   41  * Center for Seismic Studies
   42  * 1300 N 17th Street, Suite 1450
   43  * Arlington, Virginia 22209
   44  * (703)276-7900
   45  * rick@seismo.ARPA
   46  * seismo!rick
   47  *
   48  * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
   49  * N.B.: this belongs in netinet, not net, the way it stands now.
   50  * Should have a link-layer type designation, but wouldn't be
   51  * backwards-compatible.
   52  *
   53  * Converted to 4.3BSD Beta by Chris Torek.
   54  * Other changes made at Berkeley, based in part on code by Kirk Smith.
   55  * W. Jolitz added slip abort.
   56  *
   57  * Hacked almost beyond recognition by Van Jacobson (van@helios.ee.lbl.gov).
   58  * Added priority queuing for "interactive" traffic; hooks for TCP
   59  * header compression; ICMP filtering (at 2400 baud, some cretin
   60  * pinging you can use up all your bandwidth).  Made low clist behavior
   61  * more robust and slightly less likely to hang serial line.
   62  * Sped up a bunch of things.
   63  *
   64  * Note that splimp() is used throughout to block both (tty) input
   65  * interrupts and network activity; thus, splimp must be >= spltty.
   66  */
   67 
   68 #include "sl.h"
   69 #if NSL > 0
   70 
   71 #include "bpfilter.h"
   72 
   73 #include <sys/param.h>
   74 #include <sys/systm.h>
   75 #include <sys/proc.h>
   76 #include <sys/malloc.h>
   77 #include <sys/mbuf.h>
   78 #include <sys/buf.h>
   79 #include <sys/dkstat.h>
   80 #include <sys/socket.h>
   81 #include <sys/ioctl.h>
   82 #include <sys/file.h>
   83 #include <sys/signalvar.h>
   84 #include <sys/tty.h>
   85 #include <sys/clist.h>
   86 #include <sys/kernel.h>
   87 #include <sys/conf.h>
   88 
   89 #include <net/if.h>
   90 #include <net/if_types.h>
   91 #include <net/netisr.h>
   92 #include <net/route.h>
   93 
   94 #if INET
   95 #include <netinet/in.h>
   96 #include <netinet/in_systm.h>
   97 #include <netinet/in_var.h>
   98 #include <netinet/ip.h>
   99 #else
  100 Huh? Slip without inet?
  101 #endif
  102 
  103 #include <net/slcompress.h>
  104 #include <net/if_slvar.h>
  105 #include <net/slip.h>
  106 
  107 #if NBPFILTER > 0
  108 #include <sys/time.h>
  109 #include <net/bpf.h>
  110 #endif
  111 
  112 static void slattach __P((void *));
  113 PSEUDO_SET(slattach, if_sl);
  114 
  115 /*
  116  * SLRMAX is a hard limit on input packet size.  To simplify the code
  117  * and improve performance, we require that packets fit in an mbuf
  118  * cluster, and if we get a compressed packet, there's enough extra
  119  * room to expand the header into a max length tcp/ip header (128
  120  * bytes).  So, SLRMAX can be at most
  121  *      MCLBYTES - 128
  122  *
  123  * SLMTU is the default transmit MTU. The transmit MTU should be kept
  124  * small enough so that interactive use doesn't suffer, but large
  125  * enough to provide good performance. 552 is a good choice for SLMTU
  126  * because it is high enough to not fragment TCP packets being routed
  127  * through this host. Packet fragmentation is bad with SLIP because
  128  * fragment headers aren't compressed. The previous assumptions about
  129  * the best MTU value don't really hold when using modern modems with
  130  * BTLZ data compression because the modem buffers play a much larger
  131  * role in interactive performance than the MTU. The MTU can be changed
  132  * at any time to suit the specific environment with ifconfig(8), and
  133  * its maximum value is defined as SLTMAX. SLTMAX must not be so large
  134  * that it would overflow the stack if BPF is configured (XXX; if_ppp.c
  135  * handles this better).
  136  *
  137  * SLIP_HIWAT is the amount of data that will be queued 'downstream'
  138  * of us (i.e., in clists waiting to be picked up by the tty output
  139  * interrupt).  If we queue a lot of data downstream, it's immune to
  140  * our t.o.s. queuing.
  141  * E.g., if SLIP_HIWAT is 1024, the interactive traffic in mixed
  142  * telnet/ftp will see a 1 sec wait, independent of the mtu (the
  143  * wait is dependent on the ftp window size but that's typically
  144  * 1k - 4k).  So, we want SLIP_HIWAT just big enough to amortize
  145  * the cost (in idle time on the wire) of the tty driver running
  146  * off the end of its clists & having to call back slstart for a
  147  * new packet.  For a tty interface with any buffering at all, this
  148  * cost will be zero.  Even with a totally brain dead interface (like
  149  * the one on a typical workstation), the cost will be <= 1 character
  150  * time.  So, setting SLIP_HIWAT to ~100 guarantees that we'll lose
  151  * at most 1% while maintaining good interactive response.
  152  */
  153 #if NBPFILTER > 0
  154 #define BUFOFFSET       (128+sizeof(struct ifnet **)+SLIP_HDRLEN)
  155 #else
  156 #define BUFOFFSET       (128+sizeof(struct ifnet **))
  157 #endif
  158 #define SLRMAX          (MCLBYTES - BUFOFFSET)
  159 #define SLBUFSIZE       (SLRMAX + BUFOFFSET)
  160 #ifndef SLMTU
  161 #define SLMTU           552             /* default MTU */
  162 #endif
  163 #define SLTMAX          1500            /* maximum MTU */
  164 #define SLIP_HIWAT      roundup(50,CBSIZE)
  165 #define CLISTRESERVE    1024            /* Can't let clists get too low */
  166 
  167 /*
  168  * SLIP ABORT ESCAPE MECHANISM:
  169  *      (inspired by HAYES modem escape arrangement)
  170  *      1sec escape 1sec escape 1sec escape { 1sec escape 1sec escape }
  171  *      within window time signals a "soft" exit from slip mode by remote end
  172  *      if the IFF_DEBUG flag is on.
  173  */
  174 #define ABT_ESC         '\033'  /* can't be t_intr - distant host must know it*/
  175 #define ABT_IDLE        1       /* in seconds - idle before an escape */
  176 #define ABT_COUNT       3       /* count of escapes for abort */
  177 #define ABT_WINDOW      (ABT_COUNT*2+2) /* in seconds - time to count */
  178 
  179 struct sl_softc sl_softc[NSL];
  180 
  181 #define FRAME_END               0xc0            /* Frame End */
  182 #define FRAME_ESCAPE            0xdb            /* Frame Esc */
  183 #define TRANS_FRAME_END         0xdc            /* transposed frame end */
  184 #define TRANS_FRAME_ESCAPE      0xdd            /* transposed frame esc */
  185 
  186 static int slinit __P((struct sl_softc *));
  187 static struct mbuf *sl_btom __P((struct sl_softc *, int));
  188 static timeout_t sl_keepalive;
  189 static timeout_t sl_outfill;
  190 static int      slclose __P((struct tty *,int));
  191 static int      slinput __P((int, struct tty *));
  192 static int      slioctl __P((struct ifnet *, int, caddr_t));
  193 static int      sltioctl __P((struct tty *, int, caddr_t, int, struct proc *));
  194 static int      slopen __P((dev_t, struct tty *));
  195 static int      sloutput __P((struct ifnet *,
  196             struct mbuf *, struct sockaddr *, struct rtentry *));
  197 static int      slstart __P((struct tty *));
  198 
  199 static struct linesw slipdisc = {
  200         slopen,         slclose,        l_noread,       l_nowrite,
  201         sltioctl,       slinput,        slstart,        ttymodem
  202 };
  203 
  204 /*
  205  * Called from boot code to establish sl interfaces.
  206  */
  207 static void
  208 slattach(dummy)
  209         void *dummy;
  210 {
  211         register struct sl_softc *sc;
  212         register int i = 0;
  213 
  214         linesw[SLIPDISC] = slipdisc;
  215 
  216         for (sc = sl_softc; i < NSL; sc++) {
  217                 sc->sc_if.if_name = "sl";
  218                 sc->sc_if.if_next = NULL;
  219                 sc->sc_if.if_unit = i++;
  220                 sc->sc_if.if_mtu = SLMTU;
  221                 sc->sc_if.if_flags =
  222                     IFF_POINTOPOINT | SC_AUTOCOMP | IFF_MULTICAST;
  223                 sc->sc_if.if_type = IFT_SLIP;
  224                 sc->sc_if.if_ioctl = slioctl;
  225                 sc->sc_if.if_output = sloutput;
  226                 sc->sc_if.if_snd.ifq_maxlen = 50;
  227                 sc->sc_fastq.ifq_maxlen = 32;
  228                 sc->sc_if.if_linkmib = sc;
  229                 sc->sc_if.if_linkmiblen = sizeof *sc;
  230                 if_attach(&sc->sc_if);
  231 #if NBPFILTER > 0
  232                 bpfattach(&sc->sc_if, DLT_SLIP, SLIP_HDRLEN);
  233 #endif
  234         }
  235 }
  236 
  237 static int
  238 slinit(sc)
  239         register struct sl_softc *sc;
  240 {
  241         register caddr_t p;
  242 
  243         if (sc->sc_ep == (u_char *) 0) {
  244                 MCLALLOC(p, M_WAIT);
  245                 if (p)
  246                         sc->sc_ep = (u_char *)p + SLBUFSIZE;
  247                 else {
  248                         printf("sl%d: can't allocate buffer\n", sc - sl_softc);
  249                         return (0);
  250                 }
  251         }
  252         sc->sc_buf = sc->sc_ep - SLRMAX;
  253         sc->sc_mp = sc->sc_buf;
  254         sl_compress_init(&sc->sc_comp, -1);
  255         return (1);
  256 }
  257 
  258 /*
  259  * Line specific open routine.
  260  * Attach the given tty to the first available sl unit.
  261  */
  262 /* ARGSUSED */
  263 static int
  264 slopen(dev, tp)
  265         dev_t dev;
  266         register struct tty *tp;
  267 {
  268         struct proc *p = curproc;               /* XXX */
  269         register struct sl_softc *sc;
  270         register int nsl;
  271         int s, error;
  272 
  273         error = suser(p->p_ucred, &p->p_acflag);
  274         if (error)
  275                 return (error);
  276 
  277         if (tp->t_line == SLIPDISC)
  278                 return (0);
  279 
  280         for (nsl = NSL, sc = sl_softc; --nsl >= 0; sc++)
  281                 if (sc->sc_ttyp == NULL && !(sc->sc_flags & SC_STATIC)) {
  282                         if (slinit(sc) == 0)
  283                                 return (ENOBUFS);
  284                         tp->t_sc = (caddr_t)sc;
  285                         sc->sc_ttyp = tp;
  286                         sc->sc_if.if_baudrate = tp->t_ospeed;
  287                         ttyflush(tp, FREAD | FWRITE);
  288 
  289                         tp->t_line = SLIPDISC;
  290                         /*
  291                          * We don't use t_canq or t_rawq, so reduce their
  292                          * cblock resources to 0.  Reserve enough cblocks
  293                          * for t_outq to guarantee that we can fit a full
  294                          * packet if the SLIP_HIWAT check allows slstart()
  295                          * to loop.  Use the same value for the cblock
  296                          * limit since the reserved blocks should always
  297                          * be enough.  Reserving cblocks probably makes
  298                          * the CLISTRESERVE check unnecessary and wasteful.
  299                          */
  300                         clist_alloc_cblocks(&tp->t_canq, 0, 0);
  301                         clist_alloc_cblocks(&tp->t_outq,
  302                             SLIP_HIWAT + 2 * sc->sc_if.if_mtu + 1,
  303                             SLIP_HIWAT + 2 * sc->sc_if.if_mtu + 1);
  304                         clist_alloc_cblocks(&tp->t_rawq, 0, 0);
  305 
  306                         s = splnet();
  307                         if_up(&sc->sc_if);
  308                         splx(s);
  309                         return (0);
  310                 }
  311         return (ENXIO);
  312 }
  313 
  314 /*
  315  * Line specific close routine.
  316  * Detach the tty from the sl unit.
  317  */
  318 static int
  319 slclose(tp,flag)
  320         struct tty *tp;
  321         int flag;
  322 {
  323         register struct sl_softc *sc;
  324         int s;
  325 
  326         ttyflush(tp, FREAD | FWRITE);
  327         /*
  328          * XXX the placement of the following spl is misleading.  tty
  329          * interrupts must be blocked across line discipline switches
  330          * and throughout closes to avoid races.
  331          */
  332         s = splimp();           /* actually, max(spltty, splnet) */
  333         clist_free_cblocks(&tp->t_outq);
  334         tp->t_line = 0;
  335         sc = (struct sl_softc *)tp->t_sc;
  336         if (sc != NULL) {
  337                 if (sc->sc_outfill) {
  338                         sc->sc_outfill = 0;
  339                         untimeout(sl_outfill, sc);
  340                 }
  341                 if (sc->sc_keepalive) {
  342                         sc->sc_keepalive = 0;
  343                         untimeout(sl_keepalive, sc);
  344                 }
  345                 if_down(&sc->sc_if);
  346                 sc->sc_flags &= SC_STATIC;
  347                 sc->sc_ttyp = NULL;
  348                 tp->t_sc = NULL;
  349                 MCLFREE((caddr_t)(sc->sc_ep - SLBUFSIZE));
  350                 sc->sc_ep = 0;
  351                 sc->sc_mp = 0;
  352                 sc->sc_buf = 0;
  353         }
  354         splx(s);
  355         return 0;
  356 }
  357 
  358 /*
  359  * Line specific (tty) ioctl routine.
  360  * Provide a way to get the sl unit number.
  361  */
  362 /* ARGSUSED */
  363 static int
  364 sltioctl(tp, cmd, data, flag, p)
  365         struct tty *tp;
  366         int cmd;
  367         caddr_t data;
  368         int flag;
  369         struct proc *p;
  370 {
  371         struct sl_softc *sc = (struct sl_softc *)tp->t_sc, *nc, *tmpnc;
  372         int s, nsl;
  373 
  374         s = splimp();
  375         switch (cmd) {
  376         case SLIOCGUNIT:
  377                 *(int *)data = sc->sc_if.if_unit;
  378                 break;
  379 
  380         case SLIOCSUNIT:
  381                 if (sc->sc_if.if_unit != *(u_int *)data) {
  382                         for (nsl = NSL, nc = sl_softc; --nsl >= 0; nc++) {
  383                                 if (   nc->sc_if.if_unit == *(u_int *)data
  384                                     && nc->sc_ttyp == NULL
  385                                    ) {
  386                                         tmpnc = malloc(sizeof *tmpnc, M_TEMP,
  387                                                        M_WAITOK);
  388                                         *tmpnc = *nc;
  389                                         *nc = *sc;
  390                                         nc->sc_if = tmpnc->sc_if;
  391                                         tmpnc->sc_if = sc->sc_if;
  392                                         *sc = *tmpnc;
  393                                         free(tmpnc, M_TEMP);
  394                                         if (sc->sc_if.if_flags & IFF_UP) {
  395                                                 if_down(&sc->sc_if);
  396                                                 if (!(nc->sc_if.if_flags & IFF_UP))
  397                                                         if_up(&nc->sc_if);
  398                                         } else if (nc->sc_if.if_flags & IFF_UP)
  399                                                 if_down(&nc->sc_if);
  400                                         sc->sc_flags &= ~SC_STATIC;
  401                                         sc->sc_flags |= (nc->sc_flags & SC_STATIC);
  402                                         tp->t_sc = sc = nc;
  403                                         goto slfound;
  404                                 }
  405                         }
  406                         splx(s);
  407                         return (ENXIO);
  408                 }
  409         slfound:
  410                 sc->sc_flags |= SC_STATIC;
  411                 break;
  412 
  413         case SLIOCSKEEPAL:
  414                 sc->sc_keepalive = *(u_int *)data * hz;
  415                 if (sc->sc_keepalive) {
  416                         sc->sc_flags |= SC_KEEPALIVE;
  417                         timeout(sl_keepalive, sc, sc->sc_keepalive);
  418                 } else {
  419                         sc->sc_flags &= ~SC_KEEPALIVE;
  420                         untimeout(sl_keepalive, sc);
  421                 }
  422                 break;
  423 
  424         case SLIOCGKEEPAL:
  425                 *(int *)data = sc->sc_keepalive / hz;
  426                 break;
  427 
  428         case SLIOCSOUTFILL:
  429                 sc->sc_outfill = *(u_int *)data * hz;
  430                 if (sc->sc_outfill) {
  431                         sc->sc_flags |= SC_OUTWAIT;
  432                         timeout(sl_outfill, sc, sc->sc_outfill);
  433                 } else {
  434                         sc->sc_flags &= ~SC_OUTWAIT;
  435                         untimeout(sl_outfill, sc);
  436                 }
  437                 break;
  438 
  439         case SLIOCGOUTFILL:
  440                 *(int *)data = sc->sc_outfill / hz;
  441                 break;
  442 
  443         default:
  444                 splx(s);
  445                 return (-1);
  446         }
  447         splx(s);
  448         return (0);
  449 }
  450 
  451 /*
  452  * Queue a packet.  Start transmission if not active.
  453  * Compression happens in slstart; if we do it here, IP TOS
  454  * will cause us to not compress "background" packets, because
  455  * ordering gets trashed.  It can be done for all packets in slstart.
  456  */
  457 static int
  458 sloutput(ifp, m, dst, rtp)
  459         struct ifnet *ifp;
  460         register struct mbuf *m;
  461         struct sockaddr *dst;
  462         struct rtentry *rtp;
  463 {
  464         register struct sl_softc *sc = &sl_softc[ifp->if_unit];
  465         register struct ip *ip;
  466         register struct ifqueue *ifq;
  467         int s;
  468 
  469         /*
  470          * `Cannot happen' (see slioctl).  Someday we will extend
  471          * the line protocol to support other address families.
  472          */
  473         if (dst->sa_family != AF_INET) {
  474                 printf("sl%d: af%d not supported\n", sc->sc_if.if_unit,
  475                         dst->sa_family);
  476                 m_freem(m);
  477                 sc->sc_if.if_noproto++;
  478                 return (EAFNOSUPPORT);
  479         }
  480 
  481         if (sc->sc_ttyp == NULL || !(ifp->if_flags & IFF_UP)) {
  482                 m_freem(m);
  483                 return (ENETDOWN);
  484         }
  485         if ((sc->sc_ttyp->t_state & TS_CONNECTED) == 0) {
  486                 m_freem(m);
  487                 return (EHOSTUNREACH);
  488         }
  489         ifq = &sc->sc_if.if_snd;
  490         ip = mtod(m, struct ip *);
  491         if (sc->sc_if.if_flags & SC_NOICMP && ip->ip_p == IPPROTO_ICMP) {
  492                 m_freem(m);
  493                 return (ENETRESET);             /* XXX ? */
  494         }
  495         if (ip->ip_tos & IPTOS_LOWDELAY)
  496                 ifq = &sc->sc_fastq;
  497         s = splimp();
  498         if (IF_QFULL(ifq)) {
  499                 IF_DROP(ifq);
  500                 m_freem(m);
  501                 splx(s);
  502                 sc->sc_if.if_oerrors++;
  503                 return (ENOBUFS);
  504         }
  505         IF_ENQUEUE(ifq, m);
  506         if (sc->sc_ttyp->t_outq.c_cc == 0)
  507                 slstart(sc->sc_ttyp);
  508         splx(s);
  509         return (0);
  510 }
  511 
  512 /*
  513  * Start output on interface.  Get another datagram
  514  * to send from the interface queue and map it to
  515  * the interface before starting output.
  516  */
  517 static int
  518 slstart(tp)
  519         register struct tty *tp;
  520 {
  521         register struct sl_softc *sc = (struct sl_softc *)tp->t_sc;
  522         register struct mbuf *m;
  523         register u_char *cp;
  524         register struct ip *ip;
  525         int s;
  526         struct mbuf *m2;
  527 #if NBPFILTER > 0
  528         u_char bpfbuf[SLTMAX + SLIP_HDRLEN];
  529         register int len = 0;
  530 #endif
  531 
  532         for (;;) {
  533                 /*
  534                  * Call output process whether or not there is more in the
  535                  * output queue.  We are being called in lieu of ttstart
  536                  * and must do what it would.
  537                  */
  538                 (*tp->t_oproc)(tp);
  539 
  540                 if (tp->t_outq.c_cc != 0) {
  541                         if (sc != NULL)
  542                                 sc->sc_flags &= ~SC_OUTWAIT;
  543                         if (tp->t_outq.c_cc > SLIP_HIWAT)
  544                                 return 0;
  545                 }
  546 
  547                 /*
  548                  * This happens briefly when the line shuts down.
  549                  */
  550                 if (sc == NULL)
  551                         return 0;
  552 
  553                 /*
  554                  * Get a packet and send it to the interface.
  555                  */
  556                 s = splimp();
  557                 IF_DEQUEUE(&sc->sc_fastq, m);
  558                 if (m)
  559                         sc->sc_if.if_omcasts++;         /* XXX */
  560                 else
  561                         IF_DEQUEUE(&sc->sc_if.if_snd, m);
  562                 splx(s);
  563                 if (m == NULL)
  564                         return 0;
  565 
  566                 /*
  567                  * We do the header compression here rather than in sloutput
  568                  * because the packets will be out of order if we are using TOS
  569                  * queueing, and the connection id compression will get
  570                  * munged when this happens.
  571                  */
  572 #if NBPFILTER > 0
  573                 if (sc->sc_if.if_bpf) {
  574                         /*
  575                          * We need to save the TCP/IP header before it's
  576                          * compressed.  To avoid complicated code, we just
  577                          * copy the entire packet into a stack buffer (since
  578                          * this is a serial line, packets should be short
  579                          * and/or the copy should be negligible cost compared
  580                          * to the packet transmission time).
  581                          */
  582                         register struct mbuf *m1 = m;
  583                         register u_char *cp = bpfbuf + SLIP_HDRLEN;
  584 
  585                         len = 0;
  586                         do {
  587                                 register int mlen = m1->m_len;
  588 
  589                                 bcopy(mtod(m1, caddr_t), cp, mlen);
  590                                 cp += mlen;
  591                                 len += mlen;
  592                         } while (m1 = m1->m_next);
  593                 }
  594 #endif
  595                 ip = mtod(m, struct ip *);
  596                 if (ip->ip_v == IPVERSION && ip->ip_p == IPPROTO_TCP) {
  597                         if (sc->sc_if.if_flags & SC_COMPRESS)
  598                                 *mtod(m, u_char *) |= sl_compress_tcp(m, ip,
  599                                     &sc->sc_comp, 1);
  600                 }
  601 #if NBPFILTER > 0
  602                 if (sc->sc_if.if_bpf) {
  603                         /*
  604                          * Put the SLIP pseudo-"link header" in place.  The
  605                          * compressed header is now at the beginning of the
  606                          * mbuf.
  607                          */
  608                         bpfbuf[SLX_DIR] = SLIPDIR_OUT;
  609                         bcopy(mtod(m, caddr_t), &bpfbuf[SLX_CHDR], CHDR_LEN);
  610                         bpf_tap(&sc->sc_if, bpfbuf, len + SLIP_HDRLEN);
  611                 }
  612 #endif
  613 
  614                 /*
  615                  * If system is getting low on clists, just flush our
  616                  * output queue (if the stuff was important, it'll get
  617                  * retransmitted). Note that SLTMAX is used instead of
  618                  * the current if_mtu setting because connections that
  619                  * have already been established still use the original
  620                  * (possibly larger) mss.
  621                  */
  622                 if (cfreecount < CLISTRESERVE + SLTMAX) {
  623                         m_freem(m);
  624                         sc->sc_if.if_collisions++;
  625                         continue;
  626                 }
  627 
  628                 sc->sc_flags &= ~SC_OUTWAIT;
  629                 /*
  630                  * The extra FRAME_END will start up a new packet, and thus
  631                  * will flush any accumulated garbage.  We do this whenever
  632                  * the line may have been idle for some time.
  633                  */
  634                 if (tp->t_outq.c_cc == 0) {
  635                         ++sc->sc_if.if_obytes;
  636                         (void) putc(FRAME_END, &tp->t_outq);
  637                 }
  638 
  639                 while (m) {
  640                         register u_char *ep;
  641 
  642                         cp = mtod(m, u_char *); ep = cp + m->m_len;
  643                         while (cp < ep) {
  644                                 /*
  645                                  * Find out how many bytes in the string we can
  646                                  * handle without doing something special.
  647                                  */
  648                                 register u_char *bp = cp;
  649 
  650                                 while (cp < ep) {
  651                                         switch (*cp++) {
  652                                         case FRAME_ESCAPE:
  653                                         case FRAME_END:
  654                                                 --cp;
  655                                                 goto out;
  656                                         }
  657                                 }
  658                                 out:
  659                                 if (cp > bp) {
  660                                         /*
  661                                          * Put n characters at once
  662                                          * into the tty output queue.
  663                                          */
  664                                         if (b_to_q((char *)bp, cp - bp,
  665                                             &tp->t_outq))
  666                                                 break;
  667                                         sc->sc_if.if_obytes += cp - bp;
  668                                 }
  669                                 /*
  670                                  * If there are characters left in the mbuf,
  671                                  * the first one must be special..
  672                                  * Put it out in a different form.
  673                                  */
  674                                 if (cp < ep) {
  675                                         if (putc(FRAME_ESCAPE, &tp->t_outq))
  676                                                 break;
  677                                         if (putc(*cp++ == FRAME_ESCAPE ?
  678                                            TRANS_FRAME_ESCAPE : TRANS_FRAME_END,
  679                                            &tp->t_outq)) {
  680                                                 (void) unputc(&tp->t_outq);
  681                                                 break;
  682                                         }
  683                                         sc->sc_if.if_obytes += 2;
  684                                 }
  685                         }
  686                         MFREE(m, m2);
  687                         m = m2;
  688                 }
  689 
  690                 if (putc(FRAME_END, &tp->t_outq)) {
  691                         /*
  692                          * Not enough room.  Remove a char to make room
  693                          * and end the packet normally.
  694                          * If you get many collisions (more than one or two
  695                          * a day) you probably do not have enough clists
  696                          * and you should increase "nclist" in param.c.
  697                          */
  698                         (void) unputc(&tp->t_outq);
  699                         (void) putc(FRAME_END, &tp->t_outq);
  700                         sc->sc_if.if_collisions++;
  701                 } else {
  702                         ++sc->sc_if.if_obytes;
  703                         sc->sc_if.if_opackets++;
  704                 }
  705         }
  706         return 0;
  707 }
  708 
  709 /*
  710  * Copy data buffer to mbuf chain; add ifnet pointer.
  711  */
  712 static struct mbuf *
  713 sl_btom(sc, len)
  714         register struct sl_softc *sc;
  715         register int len;
  716 {
  717         register struct mbuf *m;
  718 
  719         MGETHDR(m, M_DONTWAIT, MT_DATA);
  720         if (m == NULL)
  721                 return (NULL);
  722 
  723         /*
  724          * If we have more than MHLEN bytes, it's cheaper to
  725          * queue the cluster we just filled & allocate a new one
  726          * for the input buffer.  Otherwise, fill the mbuf we
  727          * allocated above.  Note that code in the input routine
  728          * guarantees that packet will fit in a cluster.
  729          */
  730         if (len >= MHLEN) {
  731                 MCLGET(m, M_DONTWAIT);
  732                 if ((m->m_flags & M_EXT) == 0) {
  733                         /*
  734                          * we couldn't get a cluster - if memory's this
  735                          * low, it's time to start dropping packets.
  736                          */
  737                         (void) m_free(m);
  738                         return (NULL);
  739                 }
  740                 sc->sc_ep = mtod(m, u_char *) + SLBUFSIZE;
  741                 m->m_data = (caddr_t)sc->sc_buf;
  742                 m->m_ext.ext_buf = (caddr_t)((int)sc->sc_buf &~ MCLOFSET);
  743         } else
  744                 bcopy((caddr_t)sc->sc_buf, mtod(m, caddr_t), len);
  745 
  746         m->m_len = len;
  747         m->m_pkthdr.len = len;
  748         m->m_pkthdr.rcvif = &sc->sc_if;
  749         return (m);
  750 }
  751 
  752 /*
  753  * tty interface receiver interrupt.
  754  */
  755 static int
  756 slinput(c, tp)
  757         register int c;
  758         register struct tty *tp;
  759 {
  760         register struct sl_softc *sc;
  761         register struct mbuf *m;
  762         register int len;
  763         int s;
  764 #if NBPFILTER > 0
  765         u_char chdr[CHDR_LEN];
  766 #endif
  767 
  768         tk_nin++;
  769         sc = (struct sl_softc *)tp->t_sc;
  770         if (sc == NULL)
  771                 return 0;
  772         if (c & TTY_ERRORMASK || (tp->t_state & TS_CONNECTED) == 0) {
  773                 sc->sc_flags |= SC_ERROR;
  774                 return 0;
  775         }
  776         c &= TTY_CHARMASK;
  777 
  778         ++sc->sc_if.if_ibytes;
  779 
  780         if (sc->sc_if.if_flags & IFF_DEBUG) {
  781                 if (c == ABT_ESC) {
  782                         /*
  783                          * If we have a previous abort, see whether
  784                          * this one is within the time limit.
  785                          */
  786                         if (sc->sc_abortcount &&
  787                             time.tv_sec >= sc->sc_starttime + ABT_WINDOW)
  788                                 sc->sc_abortcount = 0;
  789                         /*
  790                          * If we see an abort after "idle" time, count it;
  791                          * record when the first abort escape arrived.
  792                          */
  793                         if (time.tv_sec >= sc->sc_lasttime + ABT_IDLE) {
  794                                 if (++sc->sc_abortcount == 1)
  795                                         sc->sc_starttime = time.tv_sec;
  796                                 if (sc->sc_abortcount >= ABT_COUNT) {
  797                                         slclose(tp,0);
  798                                         return 0;
  799                                 }
  800                         }
  801                 } else
  802                         sc->sc_abortcount = 0;
  803                 sc->sc_lasttime = time.tv_sec;
  804         }
  805 
  806         switch (c) {
  807 
  808         case TRANS_FRAME_ESCAPE:
  809                 if (sc->sc_escape)
  810                         c = FRAME_ESCAPE;
  811                 break;
  812 
  813         case TRANS_FRAME_END:
  814                 if (sc->sc_escape)
  815                         c = FRAME_END;
  816                 break;
  817 
  818         case FRAME_ESCAPE:
  819                 sc->sc_escape = 1;
  820                 return 0;
  821 
  822         case FRAME_END:
  823                 sc->sc_flags &= ~SC_KEEPALIVE;
  824                 if(sc->sc_flags & SC_ERROR) {
  825                         sc->sc_flags &= ~SC_ERROR;
  826                         goto newpack;
  827                 }
  828                 len = sc->sc_mp - sc->sc_buf;
  829                 if (len < 3)
  830                         /* less than min length packet - ignore */
  831                         goto newpack;
  832 
  833 #if NBPFILTER > 0
  834                 if (sc->sc_if.if_bpf) {
  835                         /*
  836                          * Save the compressed header, so we
  837                          * can tack it on later.  Note that we
  838                          * will end up copying garbage in some
  839                          * cases but this is okay.  We remember
  840                          * where the buffer started so we can
  841                          * compute the new header length.
  842                          */
  843                         bcopy(sc->sc_buf, chdr, CHDR_LEN);
  844                 }
  845 #endif
  846 
  847                 if ((c = (*sc->sc_buf & 0xf0)) != (IPVERSION << 4)) {
  848                         if (c & 0x80)
  849                                 c = TYPE_COMPRESSED_TCP;
  850                         else if (c == TYPE_UNCOMPRESSED_TCP)
  851                                 *sc->sc_buf &= 0x4f; /* XXX */
  852                         /*
  853                          * We've got something that's not an IP packet.
  854                          * If compression is enabled, try to decompress it.
  855                          * Otherwise, if `auto-enable' compression is on and
  856                          * it's a reasonable packet, decompress it and then
  857                          * enable compression.  Otherwise, drop it.
  858                          */
  859                         if (sc->sc_if.if_flags & SC_COMPRESS) {
  860                                 len = sl_uncompress_tcp(&sc->sc_buf, len,
  861                                                         (u_int)c, &sc->sc_comp);
  862                                 if (len <= 0)
  863                                         goto error;
  864                         } else if ((sc->sc_if.if_flags & SC_AUTOCOMP) &&
  865                             c == TYPE_UNCOMPRESSED_TCP && len >= 40) {
  866                                 len = sl_uncompress_tcp(&sc->sc_buf, len,
  867                                                         (u_int)c, &sc->sc_comp);
  868                                 if (len <= 0)
  869                                         goto error;
  870                                 sc->sc_if.if_flags |= SC_COMPRESS;
  871                         } else
  872                                 goto error;
  873                 }
  874 #if NBPFILTER > 0
  875                 if (sc->sc_if.if_bpf) {
  876                         /*
  877                          * Put the SLIP pseudo-"link header" in place.
  878                          * We couldn't do this any earlier since
  879                          * decompression probably moved the buffer
  880                          * pointer.  Then, invoke BPF.
  881                          */
  882                         register u_char *hp = sc->sc_buf - SLIP_HDRLEN;
  883 
  884                         hp[SLX_DIR] = SLIPDIR_IN;
  885                         bcopy(chdr, &hp[SLX_CHDR], CHDR_LEN);
  886                         bpf_tap(&sc->sc_if, hp, len + SLIP_HDRLEN);
  887                 }
  888 #endif
  889                 m = sl_btom(sc, len);
  890                 if (m == NULL)
  891                         goto error;
  892 
  893                 sc->sc_if.if_ipackets++;
  894 
  895                 if ((sc->sc_if.if_flags & IFF_UP) == 0) {
  896                         m_freem(m);
  897                         goto newpack;
  898                 }
  899 
  900                 s = splimp();
  901                 if (IF_QFULL(&ipintrq)) {
  902                         IF_DROP(&ipintrq);
  903                         sc->sc_if.if_ierrors++;
  904                         sc->sc_if.if_iqdrops++;
  905                         m_freem(m);
  906                 } else {
  907                         IF_ENQUEUE(&ipintrq, m);
  908                         schednetisr(NETISR_IP);
  909                 }
  910                 splx(s);
  911                 goto newpack;
  912         }
  913         if (sc->sc_mp < sc->sc_ep) {
  914                 *sc->sc_mp++ = c;
  915                 sc->sc_escape = 0;
  916                 return 0;
  917         }
  918 
  919         /* can't put lower; would miss an extra frame */
  920         sc->sc_flags |= SC_ERROR;
  921 
  922 error:
  923         sc->sc_if.if_ierrors++;
  924 newpack:
  925         sc->sc_mp = sc->sc_buf = sc->sc_ep - SLRMAX;
  926         sc->sc_escape = 0;
  927         return 0;
  928 }
  929 
  930 /*
  931  * Process an ioctl request.
  932  */
  933 static int
  934 slioctl(ifp, cmd, data)
  935         register struct ifnet *ifp;
  936         int cmd;
  937         caddr_t data;
  938 {
  939         register struct ifaddr *ifa = (struct ifaddr *)data;
  940         register struct ifreq *ifr = (struct ifreq *)data;
  941         register int s, error = 0;
  942 
  943         s = splimp();
  944 
  945         switch (cmd) {
  946 
  947         case SIOCSIFFLAGS:
  948                 /*
  949                  * if.c will set the interface up even if we
  950                  * don't want it to.
  951                  */
  952                 if (sl_softc[ifp->if_unit].sc_ttyp == NULL) {
  953                         ifp->if_flags &= ~IFF_UP;
  954                 }
  955                 break;
  956         case SIOCSIFADDR:
  957                 /*
  958                  * This is "historical" - set the interface up when
  959                  * setting the address.
  960                  */
  961                 if (ifa->ifa_addr->sa_family == AF_INET) {
  962                         if (sl_softc[ifp->if_unit].sc_ttyp != NULL)
  963                                 if_up(ifp);
  964                 } else {
  965                         error = EAFNOSUPPORT;
  966                 }
  967                 break;
  968 
  969         case SIOCSIFDSTADDR:
  970                 if (ifa->ifa_addr->sa_family != AF_INET)
  971                         error = EAFNOSUPPORT;
  972                 break;
  973 
  974         case SIOCADDMULTI:
  975         case SIOCDELMULTI:
  976                 if (ifr == 0) {
  977                         error = EAFNOSUPPORT;           /* XXX */
  978                         break;
  979                 }
  980                 switch (ifr->ifr_addr.sa_family) {
  981 
  982 #ifdef INET
  983                 case AF_INET:
  984                         break;
  985 #endif
  986 
  987                 default:
  988                         error = EAFNOSUPPORT;
  989                         break;
  990                 }
  991                 break;
  992 
  993         case SIOCSIFMTU:
  994                 /*
  995                  * Set the interface MTU.
  996                  */
  997                 if (ifr->ifr_mtu > SLTMAX)
  998                         error = EINVAL;
  999                 else {
 1000                         struct tty *tp;
 1001 
 1002                         ifp->if_mtu = ifr->ifr_mtu;
 1003                         tp = sl_softc[ifp->if_unit].sc_ttyp;
 1004                         if (tp != NULL)
 1005                                 clist_alloc_cblocks(&tp->t_outq,
 1006                                     SLIP_HIWAT + 2 * ifp->if_mtu + 1,
 1007                                     SLIP_HIWAT + 2 * ifp->if_mtu + 1);
 1008                 }
 1009                 break;
 1010 
 1011         default:
 1012                 error = EINVAL;
 1013         }
 1014         splx(s);
 1015         return (error);
 1016 }
 1017 
 1018 static void
 1019 sl_keepalive(chan)
 1020         void *chan;
 1021 {
 1022         struct sl_softc *sc = chan;
 1023 
 1024         if (sc->sc_keepalive) {
 1025                 if (sc->sc_flags & SC_KEEPALIVE)
 1026                         pgsignal (sc->sc_ttyp->t_pgrp, SIGURG, 1);
 1027                 else
 1028                         sc->sc_flags |= SC_KEEPALIVE;
 1029                 timeout(sl_keepalive, sc, sc->sc_keepalive);
 1030         } else {
 1031                 sc->sc_flags &= ~SC_KEEPALIVE;
 1032                 untimeout(sl_keepalive, sc);
 1033         }
 1034 }
 1035 
 1036 static void
 1037 sl_outfill(chan)
 1038         void *chan;
 1039 {
 1040         struct sl_softc *sc = chan;
 1041         register struct tty *tp = sc->sc_ttyp;
 1042         int s;
 1043 
 1044         if (sc->sc_outfill && tp != NULL) {
 1045                 if (sc->sc_flags & SC_OUTWAIT) {
 1046                         s = splimp ();
 1047                         ++sc->sc_if.if_obytes;
 1048                         (void) putc(FRAME_END, &tp->t_outq);
 1049                         (*tp->t_oproc)(tp);
 1050                         splx (s);
 1051                 } else
 1052                         sc->sc_flags |= SC_OUTWAIT;
 1053                 timeout(sl_outfill, sc, sc->sc_outfill);
 1054         } else {
 1055                 sc->sc_flags &= ~SC_OUTWAIT;
 1056                 untimeout(sl_outfill, sc);
 1057         }
 1058 }
 1059 
 1060 #endif

Cache object: 57752a19b1a6e143113b7b10c94aaaca


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.