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

Cache object: bc413ccb4acb62a3b8932432904c05b2


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