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

Cache object: 0406aade4b05758ebd14acd2721928f4


[ 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.