root/net/if_strip.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. stripattach
  2. stripinit
  3. stripopen
  4. stripclose
  5. striptioctl
  6. strip_sendbody
  7. strip_send
  8. stripoutput
  9. stripstart
  10. strip_btom
  11. stripinput
  12. stripioctl
  13. strip_resetradio
  14. strip_proberadio
  15. strip_timeout
  16. strip_watchdog
  17. strip_newpacket
  18. Stuff_Diff
  19. Stuff_DiffZero
  20. Stuff_Same
  21. Stuff_Zero
  22. Stuff_NoCode
  23. Stuff_CodeMask
  24. Stuff_CountMask
  25. Stuff_MaxCount
  26. Stuff_Magic
  27. StuffingCode
  28. StuffData
  29. UnStuffData
  30. RecvErr
  31. RecvErr_Message

    1 /*      $OpenBSD: if_strip.c,v 1.32 2006/03/25 22:41:47 djm Exp $       */
    2 /*      $NetBSD: if_strip.c,v 1.2.4.3 1996/08/03 00:58:32 jtc Exp $     */
    3 /*      from: NetBSD: if_sl.c,v 1.38 1996/02/13 22:00:23 christos Exp $ */
    4 
    5 /*
    6  * Copyright 1996 The Board of Trustees of The Leland Stanford
    7  * Junior University. All Rights Reserved.
    8  *
    9  * Permission to use, copy, modify, and distribute this
   10  * software and its documentation for any purpose and without
   11  * fee is hereby granted, provided that the above copyright
   12  * notice appear in all copies.  Stanford University
   13  * makes no representations about the suitability of this
   14  * software for any purpose.  It is provided "as is" without
   15  * express or implied warranty.
   16  *
   17  *
   18  * This driver was contributed by Jonathan Stone.
   19  *
   20  * Starmode Radio IP interface (STRIP) for Metricom wireless radio.
   21  * This STRIP driver assumes address resolution of IP addresses to
   22  * Metricom MAC addresses is done via local link-level routes.
   23  * The link-level addresses are entered as an 8-digit packed BCD number.
   24  * To add a route for a radio at IP address 10.1.2.3, with radio
   25  * address '1234-5678', reachable via interface st0, use the command 
   26  *
   27  *      route add -host 10.1.2.3  -link st0:12:34:56:78
   28  */
   29 
   30 
   31 /*
   32  * Copyright (c) 1987, 1989, 1992, 1993
   33  *      The Regents of the University of California.  All rights reserved.
   34  *
   35  * Redistribution and use in source and binary forms, with or without
   36  * modification, are permitted provided that the following conditions
   37  * are met:
   38  * 1. Redistributions of source code must retain the above copyright
   39  *    notice, this list of conditions and the following disclaimer.
   40  * 2. Redistributions in binary form must reproduce the above copyright
   41  *    notice, this list of conditions and the following disclaimer in the
   42  *    documentation and/or other materials provided with the distribution.
   43  * 3. Neither the name of the University nor the names of its contributors
   44  *    may be used to endorse or promote products derived from this software
   45  *    without specific prior written permission.
   46  *
   47  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   48  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   49  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   50  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   51  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   52  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   53  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   54  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   55  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   56  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   57  * SUCH DAMAGE.
   58  *
   59  *      @(#)if_sl.c     8.6 (Berkeley) 2/1/94
   60  */
   61 
   62 /*
   63  * Derived from: Serial Line interface written by Rick Adams (rick@seismo.gov)
   64  *
   65  * Rick Adams
   66  * Center for Seismic Studies
   67  * 1300 N 17th Street, Suite 1450
   68  * Arlington, Virginia 22209
   69  * (703)276-7900
   70  * rick@seismo.ARPA
   71  * seismo!rick
   72  *
   73  * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
   74  * N.B.: this belongs in netinet, not net, the way it stands now.
   75  * Should have a link-layer type designation, but wouldn't be
   76  * backwards-compatible.
   77  *
   78  * Converted to 4.3BSD Beta by Chris Torek.
   79  * Other changes made at Berkeley, based in part on code by Kirk Smith.
   80  * W. Jolitz added slip abort.
   81  *
   82  * Hacked almost beyond recognition by Van Jacobson (van@helios.ee.lbl.gov).
   83  * Added priority queuing for "interactive" traffic; hooks for TCP
   84  * header compression; ICMP filtering (at 2400 baud, some cretin
   85  * pinging you can use up all your bandwidth).  Made low clist behavior
   86  * more robust and slightly less likely to hang serial line.
   87  * Sped up a bunch of things.
   88  */
   89 
   90 #include "strip.h"
   91 #if NSTRIP > 0
   92 
   93 #include "bpfilter.h"
   94 
   95 #include <sys/param.h>
   96 #include <sys/proc.h>
   97 #include <sys/mbuf.h>
   98 #include <sys/dkstat.h>
   99 #include <sys/socket.h>
  100 #include <sys/ioctl.h>
  101 #include <sys/file.h>
  102 #include <sys/tty.h>
  103 #include <sys/kernel.h>
  104 #include <sys/conf.h>
  105 #if defined(__NetBSD__) || defined(__OpenBSD__)
  106 #include <sys/systm.h>
  107 #endif
  108 #include <sys/syslog.h>
  109 
  110 #include <machine/cpu.h>
  111 
  112 #include <net/if.h>
  113 #include <net/if_dl.h>
  114 #include <net/if_types.h>
  115 #include <net/netisr.h>
  116 #include <net/route.h>
  117 
  118 #if INET
  119 #include <netinet/in.h>
  120 #include <netinet/in_systm.h>
  121 #include <netinet/in_var.h>
  122 #include <netinet/ip.h>
  123 #else
  124 #error Starmode Radio IP configured without configuring inet?
  125 #endif
  126 
  127 #include <net/slcompress.h>
  128 #include <net/if_stripvar.h>
  129 #include <net/slip.h>
  130 
  131 #if defined(__NetBSD__) || defined(__OpenBSD__) /* XXX -- jrs */
  132 typedef u_char ttychar_t;
  133 #else
  134 typedef char ttychar_t;
  135 #endif
  136 
  137 #if NBPFILTER > 0
  138 #include <sys/time.h>
  139 #include <net/bpf.h>
  140 #endif
  141 
  142 /*
  143  * SLMAX is a hard limit on input packet size.  To simplify the code
  144  * and improve performance, we require that packets fit in an mbuf
  145  * cluster, and if we get a compressed packet, there's enough extra
  146  * room to expand the header into a max length tcp/ip header (128
  147  * bytes).  So, SLMAX can be at most
  148  *      MCLBYTES - 128
  149  *
  150  * SLMTU is a hard limit on output packet size.  To insure good
  151  * interactive response, SLMTU wants to be the smallest size that
  152  * amortizes the header cost.  Remember that even with
  153  * type-of-service queuing, we have to wait for any in-progress
  154  * packet to finish.  I.e., we wait, on the average, 1/2 * mtu /
  155  * cps, where cps is the line speed in characters per second.
  156  * E.g., 533ms wait for a 1024 byte MTU on a 9600 baud line.  The
  157  * average compressed header size is 6-8 bytes so any MTU > 90
  158  * bytes will give us 90% of the line bandwidth.  A 100ms wait is
  159  * tolerable (500ms is not), so want an MTU around 296.  (Since TCP
  160  * will send 256 byte segments (to allow for 40 byte headers), the
  161  * typical packet size on the wire will be around 260 bytes).  In
  162  * 4.3tahoe+ systems, we can set an MTU in a route so we do that &
  163  * leave the interface MTU relatively high (so we don't IP fragment
  164  * when acting as a gateway to someone using a stupid MTU).
  165  *
  166  * Similar considerations apply to SLIP_HIWAT:  It's the amount of
  167  * data that will be queued 'downstream' of us (i.e., in clists
  168  * waiting to be picked up by the tty output interrupt).  If we
  169  * queue a lot of data downstream, it's immune to our t.o.s. queuing.
  170  * E.g., if SLIP_HIWAT is 1024, the interactive traffic in mixed
  171  * telnet/ftp will see a 1 sec wait, independent of the mtu (the
  172  * wait is dependent on the ftp window size but that's typically
  173  * 1k - 4k).  So, we want SLIP_HIWAT just big enough to amortize
  174  * the cost (in idle time on the wire) of the tty driver running
  175  * off the end of its clists & having to call back slstart for a
  176  * new packet.  For a tty interface with any buffering at all, this
  177  * cost will be zero.  Even with a totally brain dead interface (like
  178  * the one on a typical workstation), the cost will be <= 1 character
  179  * time.  So, setting SLIP_HIWAT to ~100 guarantees that we'll lose
  180  * at most 1% while maintaining good interactive response.
  181  */
  182 #if NBPFILTER > 0
  183 #define BUFOFFSET       (128+sizeof(struct ifnet **)+SLIP_HDRLEN)
  184 #else
  185 #define BUFOFFSET       (128+sizeof(struct ifnet **))
  186 #endif
  187 #define SLMAX           (MCLBYTES - BUFOFFSET)
  188 #define SLBUFSIZE       (SLMAX + BUFOFFSET)
  189 #ifdef SLMTU
  190 #undef SLMTU
  191 #endif
  192 #define SLMTU           1100 /* XXX -- appromaximated. 1024 may be safer. */
  193 
  194 #define STRIP_MTU_ONWIRE (SLMTU + 20 + STRIP_HDRLEN) /* (2*SLMTU+2 in sl.c */
  195 
  196 
  197 
  198 #define SLIP_HIWAT      roundup(50,CBSIZE)
  199 
  200 /* This is a NetBSD-1.0 or later kernel. */
  201 #define CCOUNT(q)       ((q)->c_cc)
  202 
  203 
  204 #if !(defined(__NetBSD__) || defined(__OpenBSD__))      /* XXX - cgd */
  205 #define CLISTRESERVE    1024    /* Can't let clists get too low */
  206 #endif  /* !__NetBSD__ */
  207 
  208 /*
  209  * SLIP ABORT ESCAPE MECHANISM:
  210  *      (inspired by HAYES modem escape arrangement)
  211  *      1sec escape 1sec escape 1sec escape { 1sec escape 1sec escape }
  212  *      within window time signals a "soft" exit from slip mode by remote end
  213  *      if the IFF_DEBUG flag is on.
  214  */
  215 #define ABT_ESC         '\033'  /* can't be t_intr - distant host must know it*/
  216 #define ABT_IDLE        1       /* in seconds - idle before an escape */
  217 #define ABT_COUNT       3       /* count of escapes for abort */
  218 #define ABT_WINDOW      (ABT_COUNT*2+2) /* in seconds - time to count */
  219 
  220 struct st_softc st_softc[NSTRIP];
  221 
  222 #define STRIP_FRAME_END         0x0D            /* carriage return */
  223 
  224 
  225 static int stripinit(struct st_softc *);
  226 static  struct mbuf *strip_btom(struct st_softc *, int);
  227 
  228 /*
  229  * STRIP header: '*' + modem address (dddd-dddd) + '*' + mactype ('SIP0')
  230  * A Metricom packet looks like this: *<address>*<key><payload><CR>
  231  *   eg. *0000-1164*SIP0<payload><CR>
  232  *
  233  */
  234 
  235 #define STRIP_ENCAP_SIZE(X) ((36) + (X)*65/64 + 2)
  236 #define STRIP_HDRLEN 15
  237 #define STRIP_MAC_ADDR_LEN 9
  238 
  239 /*
  240  * Star mode packet header.
  241  * (may be used for encapsulations other than STRIP.)
  242  */
  243 #define STARMODE_ADDR_LEN 11
  244 struct st_header {
  245         u_char starmode_addr[STARMODE_ADDR_LEN];
  246         u_char starmode_type[4];
  247 };
  248 
  249 /*
  250  * Forward declarations for Metricom-specific functions.
  251  * Ideally, these would be in a library and shared across
  252  * different STRIP implementations: *BSD, Linux, etc.
  253  *
  254  */
  255 static u_char *UnStuffData(u_char *src, u_char *end, u_char
  256                                 *dest, u_long dest_length); 
  257 
  258 static u_char *StuffData(u_char *src, u_long length, u_char *dest,
  259                               u_char **code_ptr_ptr);
  260 
  261 static void RecvErr(char *msg, struct st_softc *sc);
  262 static void RecvErr_Message(struct st_softc *strip_info,
  263                                 u_char *sendername, u_char *msg);
  264 void    strip_resetradio(struct st_softc *sc, struct tty *tp);
  265 void    strip_proberadio(struct st_softc *sc, struct tty *tp);
  266 void    strip_watchdog(struct ifnet *ifp);
  267 void    strip_sendbody(struct st_softc *sc, struct mbuf *m);
  268 int     strip_newpacket(struct st_softc *sc, u_char *ptr, u_char *end);
  269 struct mbuf * strip_send(struct st_softc *sc, struct mbuf *m0);
  270 
  271 void strip_timeout(void *x);
  272 
  273 
  274 
  275 #ifdef DEBUG
  276 #define DPRINTF(x)      printf x
  277 #else
  278 #define DPRINTF(x)
  279 #endif
  280 
  281 
  282 
  283 /*
  284  * Radio reset macros.
  285  * The Metricom radios are not particularly well-designed for
  286  * use in packet mode (starmode).  There's no easy way to tell
  287  * when the radio is in starmode.  Worse, when the radios are reset
  288  * or power-cycled, they come back up in Hayes AT-emulation mode,
  289  * and there's no good way for this driver to tell.
  290  * We deal with this by peridically tickling the radio
  291  * with an invalid starmode command.  If the radio doesn't
  292  * respond with an error, the driver knows to reset the radio.
  293  */
  294 
  295 /* Radio-reset finite state machine (if_watchdog) callback rate, in seconds */
  296 #define STRIP_WATCHDOG_INTERVAL 5
  297 
  298 /* Period between intrusive radio probes, in seconds */
  299 #define ST_PROBE_INTERVAL 10
  300 
  301 /* Grace period for radio to answer probe, in seconds */
  302 #define ST_PROBERESPONSE_INTERVAL 2
  303 
  304 /* Be less agressive about repeated resetting. */
  305 #define STRIP_RESET_INTERVAL 5
  306 
  307 /*
  308  * We received a response from the radio that indicates it's in
  309  * star mode.  Clear any pending probe or reset timer.
  310  * Don't  probe radio again for standard polling interval.
  311  */
  312 #define CLEAR_RESET_TIMER(sc) \
  313  do {\
  314     (sc)->sc_state = ST_ALIVE;  \
  315     (sc)->sc_statetimo = time_second + ST_PROBE_INTERVAL;       \
  316 } while (0)
  317 
  318 /*
  319  * we received a response from the radio that indicates it's crashed
  320  * out of starmode into Hayse mode. Reset it ASAP.
  321  */
  322 #define FORCE_RESET(sc) \
  323  do {\
  324     (sc)->sc_statetimo = time_second - 1; \
  325     (sc)->sc_state = ST_DEAD;   \
  326     /*(sc)->sc_if.if_timer = 0;*/ \
  327  } while (0)
  328 
  329 #define RADIO_PROBE_TIMEOUT(sc) \
  330          ((sc)-> sc_statetimo > time_second)
  331 
  332 
  333 
  334 /*
  335  * Called from boot code to establish sl interfaces.
  336  */
  337 void
  338 stripattach(n)
  339         int n;
  340 {
  341         struct st_softc *sc;
  342         int i = 0;
  343 
  344         for (sc = st_softc; i < NSTRIP; sc++) {
  345                 timeout_set(&sc->sc_timo, strip_timeout, sc);
  346                 sc->sc_unit = i;                /* XXX */
  347                 snprintf(sc->sc_if.if_xname, sizeof sc->sc_if.if_xname,
  348                     "strip%d", i++);
  349                 sc->sc_if.if_softc = sc;
  350                 sc->sc_if.if_mtu = SLMTU;
  351                 sc->sc_if.if_flags = 0;
  352                 sc->sc_if.if_type = IFT_OTHER;
  353 #if 0
  354                 sc->sc_if.if_flags |= SC_AUTOCOMP /* | IFF_POINTOPOINT | IFF_MULTICAST*/;
  355 #endif
  356                 sc->sc_if.if_type = IFT_SLIP;
  357                 sc->sc_if.if_ioctl = stripioctl;
  358                 sc->sc_if.if_output = stripoutput;
  359                 IFQ_SET_MAXLEN(&sc->sc_if.if_snd, 50);
  360                 sc->sc_fastq.ifq_maxlen = 32;
  361 
  362                 sc->sc_if.if_watchdog = strip_watchdog;
  363                 sc->sc_if.if_timer = STRIP_WATCHDOG_INTERVAL;
  364                 IFQ_SET_READY(&sc->sc_if.if_snd);
  365                 if_attach(&sc->sc_if);
  366                 if_alloc_sadl(&sc->sc_if);
  367 #if NBPFILTER > 0
  368                 bpfattach(&sc->sc_bpf, &sc->sc_if, DLT_SLIP, SLIP_HDRLEN);
  369 #endif
  370         }
  371 }
  372 
  373 static int
  374 stripinit(sc)
  375         struct st_softc *sc;
  376 {
  377         caddr_t p;
  378 
  379         if (sc->sc_ep == (u_char *) 0) {
  380                 MCLALLOC(p, M_WAIT);
  381                 if (p)
  382                         sc->sc_ep = (u_char *)p + SLBUFSIZE;
  383                 else {
  384                         addlog("%s: can't allocate buffer\n",
  385                                sc->sc_if.if_xname);
  386                         sc->sc_if.if_flags &= ~IFF_UP;
  387                         return (0);
  388                 }
  389         }
  390 
  391         /* Get contiguous buffer in which to de-bytestuff/rll-decode input */
  392         if (sc->sc_rxbuf == (u_char *) 0) {
  393                 MCLALLOC(p, M_WAIT);
  394                 if (p)
  395                         sc->sc_rxbuf = (u_char *)p + SLBUFSIZE - SLMAX;
  396                 else {
  397                         addlog("%s: can't allocate input buffer\n",
  398                                sc->sc_if.if_xname);
  399                         sc->sc_if.if_flags &= ~IFF_UP;
  400                         return (0);
  401                 }
  402         }
  403 
  404         /* Get contiguous buffer in which to bytestuff/rll-encode output */
  405         if (sc->sc_txbuf == (u_char *) 0) {
  406                 MCLALLOC(p, M_WAIT);
  407                 if (p)
  408                         sc->sc_txbuf = (u_char *)p + SLBUFSIZE - SLMAX;
  409                 else {
  410                         addlog("%s: can't allocate buffer\n",
  411                                 sc->sc_if.if_xname);
  412                         
  413                         sc->sc_if.if_flags &= ~IFF_UP;
  414                         return (0);
  415                 }
  416         }
  417 
  418         sc->sc_buf = sc->sc_ep - SLMAX;
  419         sc->sc_mp = sc->sc_buf;
  420         sl_compress_init(&sc->sc_comp);
  421 
  422         /* Initialize radio probe/reset state machine */
  423         sc->sc_state = ST_DEAD;         /* assumet the worst. */
  424         sc->sc_statetimo = time_second; /* do reset immediately */
  425 
  426         return (1);
  427 }
  428 
  429 /*
  430  * Line specific open routine.
  431  * Attach the given tty to the first available sl unit.
  432  */
  433 /* ARGSUSED */
  434 int
  435 stripopen(dev, tp)
  436         dev_t dev;
  437         struct tty *tp;
  438 {
  439         struct proc *p = curproc;               /* XXX */
  440         struct st_softc *sc;
  441         int nstrip;
  442         int error;
  443 #if defined(__NetBSD__) || defined(__OpenBSD__)
  444         int s;
  445 #endif
  446 
  447         if ((error = suser(p, 0)) != 0)
  448                 return (error);
  449 
  450         if (tp->t_line == STRIPDISC)
  451                 return (0);
  452 
  453         for (nstrip = NSTRIP, sc = st_softc; --nstrip >= 0; sc++)
  454                 if (sc->sc_ttyp == NULL) {
  455                         if (stripinit(sc) == 0)
  456                                 return (ENOBUFS);
  457                         tp->t_sc = (caddr_t)sc;
  458                         sc->sc_ttyp = tp;
  459                         sc->sc_if.if_baudrate = tp->t_ospeed;
  460                         ttyflush(tp, FREAD | FWRITE);
  461 #if defined(__NetBSD__) || defined(__OpenBSD__)
  462                         /*
  463                          * Make sure tty output queue is large enough
  464                          * to hold a full-sized packet (including frame
  465                          * end, and a possible extra frame end).
  466                          * A   full-sized   of 65/64) *SLMTU bytes (because
  467                          * of escapes and clever RLL bytestuffing),
  468                          * plus frame header, and add two on for frame ends.
  469                          */
  470                         s = spltty();
  471                         if (tp->t_outq.c_cn < STRIP_MTU_ONWIRE) {
  472                                 sc->sc_oldbufsize = tp->t_outq.c_cn;
  473                                 sc->sc_oldbufquot = tp->t_outq.c_cq != 0;
  474 
  475                                 clfree(&tp->t_outq);
  476                                 error = clalloc(&tp->t_outq, 3*SLMTU, 0);
  477                                 if (error) {
  478                                         splx(s);
  479                                         return (error);
  480                                 }
  481                         } else
  482                                 sc->sc_oldbufsize = sc->sc_oldbufquot = 0;
  483                         splx(s);
  484 #endif /* __NetBSD__ */
  485                         s = spltty();
  486                         strip_resetradio(sc, tp);
  487                         splx(s);
  488 
  489                         return (0);
  490                 }
  491         return (ENXIO);
  492 }
  493 
  494 /*
  495  * Line specific close routine.
  496  * Detach the tty from the strip unit.
  497  */
  498 void
  499 stripclose(tp)
  500         struct tty *tp;
  501 {
  502         struct st_softc *sc;
  503         int s;
  504 
  505         ttywflush(tp);
  506 
  507         s = spltty();
  508         tp->t_line = 0;
  509         sc = (struct st_softc *)tp->t_sc;
  510         if (sc != NULL) {
  511                 if_down(&sc->sc_if);
  512                 sc->sc_ttyp = NULL;
  513                 tp->t_sc = NULL;
  514                 MCLFREE((caddr_t)(sc->sc_ep - SLBUFSIZE));
  515                 MCLFREE((caddr_t)(sc->sc_rxbuf - SLBUFSIZE + SLMAX)); /* XXX */
  516                 MCLFREE((caddr_t)(sc->sc_txbuf - SLBUFSIZE + SLMAX)); /* XXX */
  517                 sc->sc_ep = 0;
  518                 sc->sc_mp = 0;
  519                 sc->sc_buf = 0;
  520                 sc->sc_rxbuf = 0;
  521                 sc->sc_txbuf = 0;
  522 
  523                 if (sc->sc_flags & SC_TIMEOUT) {
  524                         timeout_del(&sc->sc_timo);
  525                         sc->sc_flags &= ~SC_TIMEOUT;
  526                 }
  527         }
  528 #if defined(__NetBSD__) || defined(__OpenBSD__)
  529         /* if necessary, install a new outq buffer of the appropriate size */
  530         if (sc->sc_oldbufsize != 0) {
  531                 clfree(&tp->t_outq);
  532                 clalloc(&tp->t_outq, sc->sc_oldbufsize, sc->sc_oldbufquot);
  533         }
  534 #endif
  535         splx(s);
  536 }
  537 
  538 /*
  539  * Line specific (tty) ioctl routine.
  540  * Provide a way to get the sl unit number.
  541  */
  542 /* ARGSUSED */
  543 int
  544 striptioctl(tp, cmd, data, flag)
  545         struct tty *tp;
  546         u_long cmd;
  547         caddr_t data;
  548         int flag;
  549 {
  550         struct st_softc *sc = (struct st_softc *)tp->t_sc;
  551 
  552         switch (cmd) {
  553         case SLIOCGUNIT:
  554                 *(int *)data = sc->sc_unit;
  555                 break;
  556 
  557         default:
  558                 return (-1);
  559         }
  560         return (0);
  561 }
  562 
  563 /*
  564  * Take an mbuf chain  containing a STRIP packet (no link-level header),
  565  * byte-stuff (escape) it, and enqueue it on the tty send queue.
  566  */
  567 void
  568 strip_sendbody(sc, m)
  569         struct st_softc  *sc;
  570         struct mbuf *m;
  571 {
  572         struct tty *tp = sc->sc_ttyp;
  573         u_char *dp = sc->sc_txbuf;
  574         struct mbuf *m2;
  575         int len;
  576         u_char  *rllstate_ptr = NULL;
  577 
  578         while (m) {
  579                 /*
  580                  * Byte-stuff/run-length encode this mbuf's data into the
  581                  * output buffer.
  582                  * XXX
  583                  * Note that chained calls to stuffdata()
  584                  * require that the stuffed data be left in the
  585                  * output buffer until the entire packet is encoded.
  586                  */
  587                 dp = StuffData(mtod(m, u_char *), m->m_len, dp, &rllstate_ptr);
  588 
  589                 MFREE(m, m2);
  590                 m = m2;
  591         }
  592 
  593         /*
  594          * Put the entire stuffed packet into the tty output queue.
  595          */
  596         len = dp - sc->sc_txbuf;
  597         if (b_to_q((ttychar_t *)sc->sc_txbuf,
  598                            len, &tp->t_outq)) {
  599                         if (sc->sc_if.if_flags & IFF_DEBUG)
  600                                 addlog("%s: tty output overflow\n",
  601                                          sc->sc_if.if_xname);
  602                         goto bad;
  603                 }
  604                 sc->sc_if.if_obytes += len;
  605 
  606         return;
  607 
  608 bad:
  609         m_freem(m);
  610         return;
  611 }
  612 
  613 
  614 /* 
  615  *  Prepend a STRIP header to the packet.
  616  * (based on 4.4bsd if_ppp)
  617  *
  618  * XXX manipulates tty queues with putc.
  619  * must be called at spl >= spltty.
  620  */
  621 struct mbuf *
  622 strip_send(sc, m0)
  623     struct st_softc *sc;
  624     struct mbuf *m0;
  625 {
  626         struct tty *tp = sc->sc_ttyp;
  627         struct st_header *hdr;
  628 
  629         /*
  630          * Send starmode header (unstuffed).
  631          */
  632         hdr = mtod(m0, struct st_header *);
  633         if (b_to_q((ttychar_t *)hdr, STRIP_HDRLEN, &tp->t_outq)) {
  634                 if (sc->sc_if.if_flags & IFF_DEBUG)
  635                         addlog("%s: outq overflow writing header\n",
  636                                  sc->sc_if.if_xname);
  637                 m_freem(m0);
  638                 return 0;
  639         }
  640 
  641         /* The header has been enqueued in clear;  undo the M_PREPEND() of the header. */
  642         m0->m_data += sizeof(struct st_header);
  643         m0->m_len -= sizeof(struct st_header);
  644         if (m0->m_flags & M_PKTHDR) {
  645                 m0->m_pkthdr.len -= sizeof(struct st_header);
  646         }
  647 #ifdef DIAGNOSTIC
  648          else
  649                 addlog("%s: strip_send: missing pkthdr, %d remains\n",
  650                 sc->sc_if.if_xname,  m0->m_len); /*XXX*/
  651 #endif
  652 
  653         /*
  654          * If M_PREPEND() had to prepend a new mbuf, it is now empty.
  655          * Discard it.
  656          */
  657         if (m0->m_len == 0) {
  658                 struct mbuf *m;
  659                 MFREE(m0, m);
  660                 m0 = m;
  661         }
  662 
  663         /* Byte-stuff and run-length encode the remainder of the packet. */
  664         strip_sendbody(sc, m0);
  665 
  666         if (putc(STRIP_FRAME_END, &tp->t_outq)) {
  667                 /*
  668                  * Not enough room.  Remove a char to make room
  669                  * and end the packet normally.
  670                  * If you get many collisions (more than one or two
  671                  * a day) you probably do not have enough clists
  672                  * and you should increase "nclist" in param.c.
  673                  */
  674                 (void) unputc(&tp->t_outq);
  675                 (void) putc(STRIP_FRAME_END, &tp->t_outq);
  676                 sc->sc_if.if_collisions++;
  677         } else {
  678                 ++sc->sc_if.if_obytes;
  679                 sc->sc_if.if_opackets++;
  680         }
  681 
  682         /*
  683          * If a radio  probe is due now, append it to this packet  rather
  684          * than waiting until  the watchdog routine next runs.
  685          */
  686         if (time_second >= sc->sc_statetimo && sc->sc_state == ST_ALIVE)
  687                 strip_proberadio(sc, tp);
  688 
  689         return (m0);
  690 }
  691 
  692 
  693 
  694 /*
  695  * Queue a packet.  Start transmission if not active.
  696  * Compression happens in slstart; if we do it here, IP TOS
  697  * will cause us to not compress "background" packets, because
  698  * ordering gets trashed.  It can be done for all packets in slstart.
  699  */
  700 int
  701 stripoutput(ifp, m, dst, rt)
  702         struct ifnet *ifp;
  703         struct mbuf *m;
  704         struct sockaddr *dst;
  705         struct rtentry *rt;
  706 {
  707         struct st_softc *sc = ifp->if_softc;
  708         struct ip *ip;
  709         struct ifqueue *ifq;
  710         struct st_header *shp;
  711         u_char *dldst;          /* link-level next-hop */
  712         int s;
  713         u_char dl_addrbuf[STARMODE_ADDR_LEN+1];
  714 
  715         /*
  716          * Verify tty line is up and alive.
  717          */
  718         if (sc->sc_ttyp == NULL) {
  719                 m_freem(m);
  720                 return (ENETDOWN);      /* sort of */
  721         }
  722         if ((sc->sc_ttyp->t_state & TS_CARR_ON) == 0 &&
  723             (sc->sc_ttyp->t_cflag & CLOCAL) == 0) {
  724                 m_freem(m);
  725                 return (EHOSTUNREACH);
  726         }
  727 
  728 #define SDL(a)          ((struct sockaddr_dl *) (a))
  729 
  730 #ifdef DEBUG
  731            if (rt) {
  732                 printf("stripout, rt: dst af%d gw af%d",
  733                        rt_key(rt)->sa_family,
  734                        rt->rt_gateway->sa_family);
  735                 if (rt_key(rt)->sa_family == AF_INET)
  736                   printf(" dst %x",
  737                          ((struct sockaddr_in *)rt_key(rt))->sin_addr.s_addr);
  738                 printf("\n");
  739         }
  740 #endif
  741 
  742         switch (dst->sa_family) {
  743         case AF_INET:
  744                 if (rt != NULL && rt->rt_gwroute != NULL)
  745                         rt = rt->rt_gwroute;
  746 
  747                 /* assume rt is never NULL */
  748                 if (rt == NULL || rt->rt_gateway->sa_family != AF_LINK
  749                     || SDL(rt->rt_gateway)->sdl_alen != ifp->if_addrlen) {
  750                         DPRINTF(("strip: could not arp starmode addr %x\n",
  751                          ((struct sockaddr_in *)dst)->sin_addr.s_addr));
  752                         m_freem(m);
  753                         return (EHOSTUNREACH);
  754                 }
  755                 /*bcopy(LLADDR(SDL(rt->rt_gateway)), dldst, ifp->if_addrlen);*/
  756                 dldst = LLADDR(SDL(rt->rt_gateway));
  757                 break;
  758 
  759         case AF_LINK:
  760                 /*bcopy(LLADDR(SDL(rt->rt_gateway)), dldst, ifp->if_addrlen);*/
  761                 dldst = LLADDR(SDL(dst));
  762                 break;
  763 
  764         default:
  765                 /*
  766                  * `Cannot happen' (see stripioctl).  Someday we will extend
  767                  * the line protocol to support other address families.
  768                  */
  769                 addlog("%s: af %d not supported\n", sc->sc_if.if_xname,
  770                         dst->sa_family);
  771                 m_freem(m);
  772                 sc->sc_if.if_noproto++;
  773                 return (EAFNOSUPPORT);
  774         }
  775         
  776         ifq = NULL;
  777         ip = mtod(m, struct ip *);
  778         if (sc->sc_if.if_flags & SC_NOICMP && ip->ip_p == IPPROTO_ICMP) {
  779                 m_freem(m);
  780                 return (ENETRESET);             /* XXX ? */
  781         }
  782         if ((ip->ip_tos & IPTOS_LOWDELAY)
  783 #ifdef ALTQ
  784             && ALTQ_IS_ENABLED(&sc->sc_if.if_snd) == 0
  785 #endif
  786                 )
  787                 ifq = &sc->sc_fastq;
  788 
  789         /*
  790          * Add local net header.  If no space in first mbuf,
  791          * add another.
  792          */
  793         M_PREPEND(m, sizeof(struct st_header), M_DONTWAIT);
  794         if (m == 0) {
  795                 DPRINTF(("strip: could not prepend starmode header\n"));
  796                 return (ENOBUFS);
  797         }
  798 
  799 
  800         /*
  801          * Unpack BCD route entry into an ASCII starmode address.
  802          */
  803 
  804         dl_addrbuf[0] = '*';
  805 
  806         dl_addrbuf[1] = ((dldst[0] >> 4) & 0x0f) + '0';
  807         dl_addrbuf[2] = ((dldst[0]     ) & 0x0f) + '0';
  808 
  809         dl_addrbuf[3] = ((dldst[1] >> 4) & 0x0f) + '0';
  810         dl_addrbuf[4] = ((dldst[1]     ) & 0x0f) + '0';
  811 
  812         dl_addrbuf[5] = '-';
  813 
  814         dl_addrbuf[6] = ((dldst[2] >> 4) & 0x0f) + '0';
  815         dl_addrbuf[7] = ((dldst[2]     ) & 0x0f) + '0';
  816 
  817         dl_addrbuf[8] = ((dldst[3] >> 4) & 0x0f) + '0';
  818         dl_addrbuf[9] = ((dldst[3]     ) & 0x0f) + '0';
  819 
  820         dl_addrbuf[10] = '*';
  821         dl_addrbuf[11] = 0;
  822         dldst = dl_addrbuf;
  823 
  824         shp = mtod(m, struct st_header *);
  825         bcopy((caddr_t)"SIP0", (caddr_t)shp->starmode_type,
  826                 sizeof(shp->starmode_type));
  827 
  828         bcopy((caddr_t)dldst, (caddr_t)shp->starmode_addr,
  829                 sizeof (shp->starmode_addr));
  830 
  831         s = spltty();
  832         if (sc->sc_oqlen && sc->sc_ttyp->t_outq.c_cc == sc->sc_oqlen) {
  833                 struct timeval tv, tm;
  834 
  835                 /* if output's been stalled for too long, and restart */
  836                 getmicrotime(&tm);
  837                 timersub(&tm, &sc->sc_lastpacket, &tv);
  838                 if (tv.tv_sec > 0) {
  839                         DPRINTF(("stripoutput: stalled, resetting\n"));
  840                         sc->sc_otimeout++;
  841                         stripstart(sc->sc_ttyp);
  842                 }
  843         }
  844 
  845         (void) splnet();
  846         if (ifq != NULL) {
  847                 if (IF_QFULL(ifq)) {
  848                         IF_DROP(ifq);
  849                         m_freem(m);
  850                         error = ENOBUFS;
  851                 } else {
  852                         IF_ENQUEUE(ifq, m);
  853                         error = 0;
  854                 }
  855         } else
  856                 IFQ_ENQUEUE(&sc->sc_if.if_snd, m, NULL, error);
  857         if (error) {
  858                 splx(s);
  859                 sc->sc_if.if_oerrors++;
  860                 return (error);
  861         }
  862 
  863         (void) spltty();
  864         getmicrotime(&sc->sc_lastpacket);
  865         if ((sc->sc_oqlen = sc->sc_ttyp->t_outq.c_cc) == 0) {
  866                 stripstart(sc->sc_ttyp);
  867         }
  868 
  869         /*
  870          * slip doesn't call its start routine unconditionally (again)
  871          * here, but doing so apepars to reduce latency.
  872          */
  873          stripstart(sc->sc_ttyp);
  874 
  875         splx(s);
  876         return (0);
  877 }
  878 
  879 
  880 /*
  881  * Start output on interface.  Get another datagram
  882  * to send from the interface queue and map it to
  883  * the interface before starting output.
  884  *
  885  */
  886 void
  887 stripstart(tp)
  888         struct tty *tp;
  889 {
  890         struct st_softc *sc = (struct st_softc *)tp->t_sc;
  891         struct mbuf *m;
  892         struct ip *ip;
  893         int s;
  894 #if NBPFILTER > 0
  895         u_char bpfbuf[SLMTU + SLIP_HDRLEN];
  896         int len = 0;
  897 #endif
  898 #if !(defined(__NetBSD__) || defined(__OpenBSD__))              /* XXX - cgd */
  899         extern int cfreecount;
  900 #endif
  901 
  902 
  903         /*
  904          * Ppp checks that strip is still the line discipline,
  905          * and if not, calls t_oproc here.  sl.c  does not.
  906          * PPP is newer...
  907          */
  908 
  909         if (((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
  910             || sc == NULL || tp != (struct tty *) sc->sc_ttyp) {
  911                 if (tp->t_oproc != NULL)
  912                         (*tp->t_oproc)(tp);
  913                 if (sc && (sc->sc_if.if_flags & IFF_DEBUG))
  914                         addlog("%s: late call to stripstart\n ",
  915                                sc->sc_if.if_xname);
  916         }
  917 
  918         /* Start any pending output asap */
  919         if (CCOUNT(&tp->t_outq) != 0) {
  920                 (*tp->t_oproc)(tp);
  921         }
  922 
  923         while (CCOUNT(&tp->t_outq) < SLIP_HIWAT) {
  924 
  925                 /*
  926                  * This happens briefly when the line shuts down.
  927                  */
  928                 if (sc == NULL) {
  929                         return;
  930                 }
  931 
  932 #if defined(__NetBSD__) || defined(__OpenBSD__)         /* XXX - cgd */
  933                 /*
  934                  * Do not remove the packet from the IP queue if it
  935                  * doesn't look like the packet will fit into the
  936                  * current serial output queue, with a packet full of
  937                  * escapes this could be as bad as STRIP_MTU_ONWIRE
  938                  * (for slip, SLMTU*2+2, for STRIP, header + 20 bytes).
  939                  * Also allow  4 bytes in case we need to send a probe
  940                  * to the radio.
  941                  */
  942                 if (tp->t_outq.c_cn - tp->t_outq.c_cc < STRIP_MTU_ONWIRE + 4)
  943                         return;
  944 #endif /* __NetBSD__ */
  945                 /*
  946                  * Get a packet and send it to the interface.
  947                  */
  948                 s = splnet();
  949                 IF_DEQUEUE(&sc->sc_fastq, m);
  950                 if (m)
  951                         sc->sc_if.if_omcasts++;         /* XXX */
  952                 else
  953                         IFQ_DEQUEUE(&sc->sc_if.if_snd, m);
  954                 splx(s);
  955                 if (m == NULL) {
  956                         return;
  957                 }
  958                 /*
  959                  * We do the header compression here rather than in stripoutput
  960                  * because the packets will be out of order if we are using TOS
  961                  * queueing, and the connection id compression will get
  962                  * munged when this happens.
  963                  */
  964 #if NBPFILTER > 0
  965                 if (sc->sc_bpf) {
  966                         /*
  967                          * We need to save the TCP/IP header before it's
  968                          * compressed.  To avoid complicated code, we just
  969                          * copy the entire packet into a stack buffer (since
  970                          * this is a serial line, packets should be short
  971                          * and/or the copy should be negligible cost compared
  972                          * to the packet transmission time).
  973                          */
  974                         struct mbuf *m1 = m;
  975                         u_char *cp = bpfbuf + SLIP_HDRLEN;
  976 
  977                         len = 0;
  978                         do {
  979                                 int mlen = m1->m_len;
  980 
  981                                 bcopy(mtod(m1, caddr_t), cp, mlen);
  982                                 cp += mlen;
  983                                 len += mlen;
  984                         } while ((m1 = m1->m_next) != NULL);
  985                 }
  986 #endif
  987                 if ((ip = mtod(m, struct ip *))->ip_p == IPPROTO_TCP) {
  988                         if (sc->sc_if.if_flags & SC_COMPRESS)
  989                                 *mtod(m, u_char *) |= sl_compress_tcp(m, ip,
  990                                     &sc->sc_comp, 1);
  991                 }
  992 #if NBPFILTER > 0
  993                 if (sc->sc_bpf) {
  994                         u_char *cp = bpfbuf + STRIP_HDRLEN;
  995                         /*
  996                          * Put the SLIP pseudo-"link header" in place.  The
  997                          * compressed header is now at the beginning of the
  998                          * mbuf.
  999                          */
 1000                         cp[SLX_DIR] = SLIPDIR_OUT;
 1001 
 1002                         bcopy(mtod(m, caddr_t)+STRIP_HDRLEN, &cp[SLX_CHDR], CHDR_LEN);
 1003                         bpf_tap(sc->sc_bpf, cp, len + SLIP_HDRLEN,
 1004                             BPF_DIRECTION_OUT);
 1005                 }
 1006 #endif
 1007                 getmicrotime(&sc->sc_lastpacket);
 1008 
 1009 #if !(defined(__NetBSD__) || defined(__OpenBSD__))              /* XXX - cgd */
 1010                 /*
 1011                  * If system is getting low on clists, just flush our
 1012                  * output queue (if the stuff was important, it'll get
 1013                  * retransmitted).
 1014                  */
 1015                 if (cfreecount < CLISTRESERVE + SLMTU) {
 1016                         m_freem(m);
 1017                         sc->sc_if.if_collisions++;
 1018                         continue;
 1019                 }
 1020 #endif /* !__NetBSD__ */
 1021 
 1022                 if (strip_send(sc, m) == NULL) {
 1023                         DPRINTF(("stripsend: failed to send pkt\n")); /*XXX*/
 1024                 }
 1025         }
 1026 
 1027 
 1028 #if 0
 1029         /* schedule timeout to start output */
 1030         if ((sc->sc_flags & SC_TIMEOUT) == 0) {
 1031                 timeout_add(&sc->sc_timo, hz);
 1032                 sc->sc_flags |= SC_TIMEOUT;
 1033         }
 1034 #endif
 1035 
 1036 #if 0
 1037         /*
 1038          * This timeout is needed for operation on a pseudo-tty,
 1039          * because the pty code doesn't call our start routine
 1040          * after it has drained the t_outq.
 1041          */
 1042         if ((sc->sc_flags & SC_TIMEOUT) == 0) {
 1043                 timeout_add(&sc->sc_timo, hz);
 1044                 sc->sc_flags |= SC_TIMEOUT;
 1045         }
 1046 #endif
 1047 
 1048     /*
 1049      * XXX ppp calls oproc at the end of its loop, but slip
 1050      * does it at the beginning.  We do both.
 1051      */
 1052 
 1053     /*
 1054      * If there is stuff in the output queue, send it now.
 1055      * We are being called in lieu of ttstart and must do what it would.
 1056      */
 1057     if (tp->t_oproc != NULL)
 1058         (*tp->t_oproc)(tp);
 1059 }
 1060 
 1061 
 1062 
 1063 /*
 1064  * Copy data buffer to mbuf chain; add ifnet pointer.
 1065  */
 1066 static struct mbuf *
 1067 strip_btom(sc, len)
 1068         struct st_softc *sc;
 1069         int len;
 1070 {
 1071         struct mbuf *m;
 1072 
 1073         MGETHDR(m, M_DONTWAIT, MT_DATA);
 1074         if (m == NULL)
 1075                 return (NULL);
 1076 
 1077         /*
 1078          * If we have more than MHLEN bytes, it's cheaper to
 1079          * queue the cluster we just filled & allocate a new one
 1080          * for the input buffer.  Otherwise, fill the mbuf we
 1081          * allocated above.  Note that code in the input routine
 1082          * guarantees that packet will fit in a cluster.
 1083          */
 1084         if (len >= MHLEN) {
 1085                 MCLGET(m, M_DONTWAIT);
 1086                 if ((m->m_flags & M_EXT) == 0) {
 1087                         /*
 1088                          * we couldn't get a cluster - if memory's this
 1089                          * low, it's time to start dropping packets.
 1090                          */
 1091                         (void) m_free(m);
 1092                         return (NULL);
 1093                 }
 1094                 sc->sc_ep = mtod(m, u_char *) + SLBUFSIZE;
 1095                 m->m_data = (caddr_t)sc->sc_buf;
 1096                 m->m_ext.ext_buf = (caddr_t)((long)sc->sc_buf &~ MCLOFSET);
 1097         } else
 1098                 bcopy((caddr_t)sc->sc_buf, mtod(m, caddr_t), len);
 1099 
 1100         m->m_len = len;
 1101         m->m_pkthdr.len = len;
 1102         m->m_pkthdr.rcvif = &sc->sc_if;
 1103         return (m);
 1104 }
 1105 
 1106 /*
 1107  * tty interface receiver interrupt.
 1108  *
 1109  * Called with a single char from the tty receiver interrupt; put
 1110  * the char into the buffer containing a partial packet. If the
 1111  * char is a packet delimiter, decapsulate the packet, wrap it in
 1112  * an mbuf, and put it on the protocol input queue.
 1113 */
 1114 void
 1115 stripinput(c, tp)
 1116         int c;
 1117         struct tty *tp;
 1118 {
 1119         struct st_softc *sc;
 1120         struct mbuf *m;
 1121         int len;
 1122         int s;
 1123 #if NBPFILTER > 0
 1124         u_char chdr[CHDR_LEN];
 1125 #endif
 1126 
 1127         tk_nin++;
 1128         sc = (struct st_softc *)tp->t_sc;
 1129         if (sc == NULL)
 1130                 return;
 1131         if (c & TTY_ERRORMASK || ((tp->t_state & TS_CARR_ON) == 0 &&
 1132             (tp->t_cflag & CLOCAL) == 0)) {
 1133                 sc->sc_flags |= SC_ERROR;
 1134                 DPRINTF(("strip: input, error %x\n", c));        /* XXX */
 1135                 return;
 1136         }
 1137         c &= TTY_CHARMASK;
 1138 
 1139         ++sc->sc_if.if_ibytes;
 1140 
 1141         /*
 1142          * Accumulate characters until we see a frame terminator (\r).
 1143          */
 1144         switch (c) {
 1145 
 1146         case '\n':
 1147                 /*
 1148                  * Error message strings from the modem are terminated with
 1149                  * \r\n. This driver interprets the  \r as a packet terminator.
 1150                  * If the first character in a packet is a \n, drop it.
 1151                  * (it can never be the first char of a vaild frame).
 1152                  */
 1153                 if (sc->sc_mp - sc->sc_buf == 0)
 1154                         break;
 1155 
 1156         /* Fall through to */
 1157 
 1158         default:
 1159                 if (sc->sc_mp < sc->sc_ep) {
 1160                         *sc->sc_mp++ = c;
 1161                 } else {
 1162                         sc->sc_flags |= SC_ERROR;
 1163                         goto error;
 1164                 }
 1165                 return;
 1166 
 1167         case STRIP_FRAME_END:
 1168                 break;
 1169         }
 1170 
 1171 
 1172         /*
 1173          * We only reach here if we see a CR delimiting a packet.
 1174          */
 1175 
 1176 
 1177         len = sc->sc_mp - sc->sc_buf;
 1178 
 1179 #ifdef XDEBUG
 1180         if (len < 15 || sc->sc_flags & SC_ERROR)
 1181                 addlog("stripinput: end of pkt, len %d, err %d\n",
 1182                          len, sc->sc_flags & SC_ERROR); /*XXX*/
 1183 #endif
 1184         if(sc->sc_flags & SC_ERROR) {
 1185                 sc->sc_flags &= ~SC_ERROR;
 1186                 addlog("%s: sc error flag set. terminating packet\n",
 1187                         sc->sc_if.if_xname);
 1188                 goto newpack;
 1189         }
 1190 
 1191         /*
 1192          * We have a frame.
 1193          * Process an IP packet, ARP packet, AppleTalk packet,
 1194          * AT command resposne, or Starmode error.
 1195          */
 1196         len = strip_newpacket(sc, sc->sc_buf, sc->sc_mp);
 1197         if (len <= 1)
 1198                 /* less than min length packet - ignore */
 1199                 goto newpack;
 1200 
 1201 
 1202 #if NBPFILTER > 0
 1203         if (sc->sc_bpf) {
 1204                 /*
 1205                  * Save the compressed header, so we
 1206                  * can tack it on later.  Note that we
 1207                  * will end up copying garbage in some
 1208                  * cases but this is okay.  We remember
 1209                  * where the buffer started so we can
 1210                  * compute the new header length.
 1211                  */
 1212                 bcopy(sc->sc_buf, chdr, CHDR_LEN);
 1213         }
 1214 #endif
 1215 
 1216         if ((c = (*sc->sc_buf & 0xf0)) != (IPVERSION << 4)) {
 1217                 if (c & 0x80)
 1218                         c = TYPE_COMPRESSED_TCP;
 1219                 else if (c == TYPE_UNCOMPRESSED_TCP)
 1220                         *sc->sc_buf &= 0x4f; /* XXX */
 1221                 /*
 1222                  * We've got something that's not an IP packet.
 1223                  * If compression is enabled, try to decompress it.
 1224                  * Otherwise, if `auto-enable' compression is on and
 1225                  * it's a reasonable packet, decompress it and then
 1226                  * enable compression.  Otherwise, drop it.
 1227                  */
 1228                 if (sc->sc_if.if_flags & SC_COMPRESS) {
 1229                         len = sl_uncompress_tcp(&sc->sc_buf, len,
 1230                                                 (u_int)c, &sc->sc_comp);
 1231                         if (len <= 0)
 1232                                 goto error;
 1233                 } else if ((sc->sc_if.if_flags & SC_AUTOCOMP) &&
 1234                     c == TYPE_UNCOMPRESSED_TCP && len >= 40) {
 1235                         len = sl_uncompress_tcp(&sc->sc_buf, len,
 1236                                                 (u_int)c, &sc->sc_comp);
 1237                         if (len <= 0)
 1238                                 goto error;
 1239                         sc->sc_if.if_flags |= SC_COMPRESS;
 1240                 } else
 1241                         goto error;
 1242         }
 1243 
 1244 #if NBPFILTER > 0
 1245         if (sc->sc_bpf) {
 1246                 /*
 1247                  * Put the SLIP pseudo-"link header" in place.
 1248                  * We couldn't do this any earlier since
 1249                  * decompression probably moved the buffer
 1250                  * pointer.  Then, invoke BPF.
 1251                  */
 1252                 u_char *hp = sc->sc_buf - SLIP_HDRLEN;
 1253 
 1254                 hp[SLX_DIR] = SLIPDIR_IN;
 1255                 bcopy(chdr, &hp[SLX_CHDR], CHDR_LEN);
 1256                 bpf_tap(sc->sc_bpf, hp, len + SLIP_HDRLEN, BPF_DIRECTION_IN);
 1257         }
 1258 #endif
 1259         m = strip_btom(sc, len);
 1260         if (m == NULL) {
 1261                 goto error;
 1262         }
 1263 
 1264         sc->sc_if.if_ipackets++;
 1265         getmicrotime(&sc->sc_lastpacket);
 1266         s = splnet();
 1267         if (IF_QFULL(&ipintrq)) {
 1268                 IF_DROP(&ipintrq);
 1269                 sc->sc_if.if_ierrors++;
 1270                 sc->sc_if.if_iqdrops++;
 1271                 if (!ipintrq.ifq_congestion)
 1272                         if_congestion(&ipintrq);
 1273                 m_freem(m);
 1274         } else {
 1275                 IF_ENQUEUE(&ipintrq, m);
 1276                 schednetisr(NETISR_IP);
 1277         }
 1278         splx(s);
 1279         goto newpack;
 1280 
 1281 error:
 1282         sc->sc_if.if_ierrors++;
 1283 
 1284 newpack:
 1285 
 1286         sc->sc_mp = sc->sc_buf = sc->sc_ep - SLMAX;
 1287 }
 1288 
 1289 /*
 1290  * Process an ioctl request.
 1291  */
 1292 int
 1293 stripioctl(ifp, cmd, data)
 1294         struct ifnet *ifp;
 1295         u_long cmd;
 1296         caddr_t data;
 1297 {
 1298         struct ifaddr *ifa = (struct ifaddr *)data;
 1299         struct ifreq *ifr;
 1300         int s = splnet(), error = 0;
 1301 
 1302         switch (cmd) {
 1303 
 1304         case SIOCSIFADDR:
 1305                 if (ifa->ifa_addr->sa_family == AF_INET)
 1306                         ifp->if_flags |= IFF_UP;
 1307                 else
 1308                         error = EAFNOSUPPORT;
 1309                 break;
 1310 
 1311         case SIOCSIFDSTADDR:
 1312                 if (ifa->ifa_addr->sa_family != AF_INET)
 1313                         error = EAFNOSUPPORT;
 1314                 break;
 1315 
 1316         case SIOCADDMULTI:
 1317         case SIOCDELMULTI:
 1318                 ifr = (struct ifreq *)data;
 1319                 if (ifr == 0) {
 1320                         error = EAFNOSUPPORT;           /* XXX */
 1321                         break;
 1322                 }
 1323                 switch (ifr->ifr_addr.sa_family) {
 1324 
 1325 #ifdef INET
 1326                 case AF_INET:
 1327                         break;
 1328 #endif
 1329 
 1330                 default:
 1331                         error = EAFNOSUPPORT;
 1332                         break;
 1333                 }
 1334                 break;
 1335 
 1336         default:
 1337 
 1338 #ifdef DEBUG
 1339           addlog("stripioctl: unknown request 0x%lx\n", cmd);
 1340 #endif
 1341                 error = EINVAL;
 1342         }
 1343         splx(s);
 1344         return (error);
 1345 }
 1346 
 1347 
 1348 /*
 1349  * Strip subroutines
 1350  */
 1351 
 1352 /*
 1353  * Set a radio into starmode.
 1354  * XXX must be called at spltty() or higher (e.g., splvm()
 1355  */
 1356 void
 1357 strip_resetradio(sc, tp)
 1358         struct st_softc *sc;
 1359         struct tty *tp;
 1360 {
 1361 #if 0
 1362         static ttychar_t InitString[] =
 1363                 "\r\n\r\n\r\nat\r\n\r\n\r\nate0dt**starmode\r\n**\r\n";
 1364 #else
 1365         static ttychar_t InitString[] =
 1366                 "\r\rat\r\r\rate0q1dt**starmode\r**\r";
 1367 #endif
 1368         int i;
 1369 
 1370         /*
 1371          * XXX Perhaps flush  tty output queue?
 1372          */
 1373 
 1374         if (tp == NULL)
 1375                 return;
 1376 
 1377         if ((i = b_to_q(InitString, sizeof(InitString) - 1, &tp->t_outq))) {
 1378                 addlog("resetradio: %d chars didn't fit in tty queue\n", i);
 1379                 return;
 1380         }
 1381         sc->sc_if.if_obytes += sizeof(InitString) - 1;
 1382 
 1383         /*
 1384          * Assume the radio is still dead, so we can detect repeated
 1385          * resets (perhaps the radio is disconnected, powered off, or
 1386          * is so badlyhung it needs  powercycling.
 1387          */
 1388         sc->sc_state = ST_DEAD;
 1389         getmicrotime(&sc->sc_lastpacket);
 1390         sc->sc_statetimo = time_second + STRIP_RESET_INTERVAL;
 1391 
 1392         /*
 1393          * XXX Does calling the tty output routine now help resets?
 1394          */
 1395         (*sc->sc_ttyp->t_oproc)(tp);
 1396 }
 1397 
 1398 
 1399 /*
 1400  * Send an invalid starmode packet to the radio, to induce an error message
 1401  * indicating the radio is in starmode.
 1402  * Update the state machine to indicate a response is expected.
 1403  * Either the radio answers, which will be caught by the parser,
 1404  * or the watchdog will start resetting.
 1405  *
 1406  * NOTE: drops chars directly on the tty output queue.
 1407  * should be caled at spl >= spltty.
 1408  */
 1409 void
 1410 strip_proberadio(sc, tp)
 1411         struct st_softc *sc;
 1412         struct tty *tp;
 1413 {
 1414 
 1415         int overflow;
 1416         char *strip_probestr = "**";
 1417 
 1418         if (sc->sc_if.if_flags & IFF_DEBUG)
 1419                 addlog("%s: attempting to probe radio\n", sc->sc_if.if_xname);
 1420 
 1421         if (tp == NULL) {
 1422                 addlog("%s: no tty attached\n", sc->sc_if.if_xname);
 1423                 return;
 1424         }
 1425 
 1426         overflow = b_to_q((ttychar_t *)strip_probestr, 2, &tp->t_outq);
 1427         if (overflow == 0) {
 1428                 if (sc->sc_if.if_flags & IFF_DEBUG)
 1429                         addlog("%s:: sent probe  to radio\n",
 1430                                sc->sc_if.if_xname);
 1431                 /* Go to probe-sent state, set timeout accordingly. */
 1432                 sc->sc_state = ST_PROBE_SENT;
 1433                 sc->sc_statetimo = time_second + ST_PROBERESPONSE_INTERVAL;
 1434         } else {
 1435                 addlog("%s: incomplete probe, tty queue %d bytes overfull\n",
 1436                         sc->sc_if.if_xname, overflow);
 1437         }
 1438 }
 1439 
 1440 
 1441 #ifdef DEBUG
 1442 static char *strip_statenames[] = {
 1443         "Alive",
 1444         "Probe sent, awaiting answer",
 1445         "Probe not answered, resetting"
 1446 };
 1447 #endif
 1448 
 1449 
 1450 /*
 1451  * Timeout routine -- try to start more output.
 1452  * Will be needed to make strip work on ptys.
 1453  */
 1454 void
 1455 strip_timeout(x)
 1456     void *x;
 1457 {
 1458     struct st_softc *sc = (struct st_softc *) x;
 1459     struct tty *tp =  sc->sc_ttyp;
 1460     int s;
 1461 
 1462     s = spltty();
 1463     sc->sc_flags &= ~SC_TIMEOUT;
 1464     stripstart(tp);
 1465     splx(s);
 1466 }
 1467 
 1468         
 1469 /*
 1470  * Strip watchdog routine.
 1471  * The radio hardware is balky. When sent long packets or bursts of small
 1472  * packets, the radios crash and reboots into Hayes-emulation mode.
 1473  * The transmit-side machinery, the error parser, and strip_watchdog()
 1474  * implement a simple finite state machine.
 1475  *
 1476  * We attempt to send a probe to the radio every ST_PROBE seconds. There
 1477  * is no direct way to tell if the radio is in starmode, so we send it a
 1478  * malformed starmode packet -- a frame with no destination address --
 1479  * and expect to an "name missing" error response from the radio within
 1480  * 1 second. If we hear such a response, we assume the radio is alive
 1481  * for the next ST_PROBE seconds.
 1482  * If we don't hear a starmode-error response from  the radio, we reset it.
 1483  *
 1484  * Probes, and parsing of error responses,  are normally done inside the send
 1485  * and receive side respectively. This watchdog routine examines the
 1486  * state-machine variables. If there are no packets to send to the radio
 1487  * during an entire probe interval, strip_output  will not be called,
 1488  * so we send a probe on its behalf.
 1489  */
 1490 void
 1491 strip_watchdog(ifp)
 1492         struct ifnet *ifp;
 1493 {
 1494         struct st_softc *sc = ifp->if_softc;
 1495         struct tty *tp =  sc->sc_ttyp;
 1496 
 1497 #ifdef DEBUG
 1498         if (ifp->if_flags & IFF_DEBUG)
 1499                 addlog("\n%s: in watchdog, state %s timeout %ld\n",
 1500                        ifp->if_xname,
 1501                        ((unsigned) sc->sc_state < 3) ?
 1502                        strip_statenames[sc->sc_state] : "<<illegal state>>",
 1503                        sc->sc_statetimo - time_second);
 1504 #endif
 1505 
 1506         /*
 1507          * If time in this state hasn't yet expired, return.
 1508          */
 1509         if ((ifp->if_flags & IFF_UP) ==  0 || sc->sc_statetimo > time_second) {
 1510                 goto done;
 1511         }
 1512 
 1513         /*
 1514          * The time in the current state has expired.
 1515          * Take appropriate action and advance FSA to the next state.
 1516          */
 1517         switch (sc->sc_state) {
 1518               case ST_ALIVE:
 1519                 /*
 1520                  * A probe is due but we haven't piggybacked one on a packet.
 1521                  * Send a probe now.
 1522                  */
 1523                 if (tp == NULL)
 1524                         break;
 1525                 strip_proberadio(sc, sc->sc_ttyp);
 1526                 (*tp->t_oproc)(tp);
 1527                 break;
 1528 
 1529               case ST_PROBE_SENT:
 1530                 /*
 1531                  * Probe sent but no response within timeout. Reset.
 1532                  */
 1533                 addlog("%s: no answer to probe, resetting radio\n",
 1534                        ifp->if_xname);
 1535                 strip_resetradio(sc, sc->sc_ttyp);
 1536                 ifp->if_oerrors++;
 1537                 break;
 1538 
 1539               case ST_DEAD:
 1540                 /*
 1541                  * The radio has been sent a reset but didn't respond.
 1542                  * XXX warn user to remove AC adaptor and battery,
 1543                  * wait  5 secs, and replace.
 1544                  */
 1545                 addlog("%s: radio reset but not responding, Trying again\n",
 1546                        ifp->if_xname);
 1547                 strip_resetradio(sc, sc->sc_ttyp);
 1548                 ifp->if_oerrors++;
 1549                 break;
 1550 
 1551               default:
 1552                 /* Cannot happen. To be safe, do  a reset. */
 1553                 addlog("%s: %s %d, resetting\n",
 1554                        sc->sc_if.if_xname,
 1555                        "radio-reset finite-state machine in invalid state",
 1556                        sc->sc_state);
 1557                 strip_resetradio(sc, sc->sc_ttyp);
 1558                 sc->sc_state = ST_DEAD;
 1559                 break;
 1560         }
 1561 
 1562       done:
 1563         ifp->if_timer = STRIP_WATCHDOG_INTERVAL;
 1564         return;
 1565 }
 1566 
 1567 
 1568 /*
 1569  * The following bytestuffing and run-length encoding/decoding
 1570  * fucntions are  taken, with permission from Stuart Cheshire,
 1571  * from  the MosquitonNet strip  driver for Linux.
 1572  * XXX Linux style left intact, to ease folding in updates from
 1573  * the Mosquitonet group.
 1574  */
 1575 
 1576 
 1577 /*
 1578  * Process a received packet.
 1579  */
 1580 int
 1581 strip_newpacket(sc, ptr, end)
 1582         struct st_softc *sc;
 1583         u_char *ptr, *end;
 1584 {
 1585         int len = ptr - end;
 1586         u_char *name, *name_end;
 1587         u_int packetlen;
 1588 
 1589         /* Ignore empty lines */
 1590         if (len == 0) return 0;
 1591 
 1592         /* Catch 'OK' responses which show radio has fallen out of starmode */
 1593         if (len >= 2 && ptr[0] == 'O' && ptr[1] == 'K') {
 1594                 addlog("%s: Radio is back in AT command mode: will reset\n",
 1595                         sc->sc_if.if_xname);
 1596                 FORCE_RESET(sc);                /* Do reset ASAP */
 1597         return 0;
 1598         }
 1599 
 1600         /* Check for start of address marker, and then skip over it */
 1601         if (*ptr != '*') {
 1602                 /* Catch other error messages */
 1603                 if (ptr[0] == 'E' && ptr[1] == 'R' && ptr[2] == 'R' && ptr[3] == '_')
 1604                         RecvErr_Message(sc, NULL, ptr+4);
 1605                          /* XXX what should the message above be? */
 1606                 else {
 1607                         RecvErr("No initial *", sc);
 1608                         addlog("(len = %d)\n", len);
 1609                      }
 1610                 return 0;
 1611         }
 1612 
 1613         /* skip the '*' */
 1614         ptr++;
 1615 
 1616         /* Skip the return address */
 1617         name = ptr;
 1618         while (ptr < end && *ptr != '*')
 1619                 ptr++;
 1620 
 1621         /* Check for end of address marker, and skip over it */
 1622         if (ptr == end) {
 1623                 RecvErr("No second *", sc);
 1624                 return 0;
 1625         }
 1626         name_end = ptr++;
 1627 
 1628         /* Check for SRIP key, and skip over it */
 1629         if (ptr[0] != 'S' || ptr[1] != 'I' || ptr[2] != 'P' || ptr[3] != '0') {
 1630                 if (ptr[0] == 'E' && ptr[1] == 'R' && ptr[2] == 'R' &&
 1631                     ptr[3] == '_') { 
 1632                         *name_end = 0;
 1633                         RecvErr_Message(sc, name, ptr+4);
 1634                  }
 1635                 else RecvErr("No SRIP key", sc);
 1636                 return 0;
 1637         }
 1638         ptr += 4;
 1639 
 1640         /* Decode start of the IP packet header */
 1641         ptr = UnStuffData(ptr, end, sc->sc_rxbuf, 4);
 1642         if (ptr == 0) {
 1643                 RecvErr("Runt packet (hdr)", sc);
 1644                 return 0;
 1645         }
 1646 
 1647         /*
 1648          * The STRIP bytestuff/RLL encoding has no explicit length
 1649          * of the decoded packet.  Decode start of IP header, get the
 1650          * IP header length and decode that many bytes in total.
 1651          */
 1652         packetlen = ((u_short)sc->sc_rxbuf[2] << 8) | sc->sc_rxbuf[3];
 1653 
 1654 #ifdef DIAGNOSTIC
 1655 /*      addlog("Packet %02x.%02x.%02x.%02x\n",
 1656                 sc->sc_rxbuf[0], sc->sc_rxbuf[1],
 1657                 sc->sc_rxbuf[2], sc->sc_rxbuf[3]);
 1658         addlog("Got %d byte packet\n", packetlen); */
 1659 #endif
 1660 
 1661         /* Decode remainder of the IP packer */
 1662         ptr = UnStuffData(ptr, end, sc->sc_rxbuf+4, packetlen-4);
 1663         if (ptr == 0) {
 1664                 RecvErr("Short packet", sc);
 1665                 return 0;
 1666         }
 1667 
 1668         /* XXX redundant copy */
 1669         bcopy(sc->sc_rxbuf, sc->sc_buf, packetlen );
 1670         return (packetlen);
 1671 }
 1672 
 1673 
 1674 /*
 1675  * Stuffing scheme:
 1676  * 00    Unused (reserved character)
 1677  * 01-3F Run of 2-64 different characters
 1678  * 40-7F Run of 1-64 different characters plus a single zero at the end
 1679  * 80-BF Run of 1-64 of the same character
 1680  * C0-FF Run of 1-64 zeroes (ASCII 0)
 1681 */
 1682 typedef enum
 1683 {
 1684         Stuff_Diff      = 0x00,
 1685         Stuff_DiffZero  = 0x40,
 1686         Stuff_Same      = 0x80,
 1687         Stuff_Zero      = 0xC0,
 1688         Stuff_NoCode    = 0xFF,         /* Special code, meaning no code selected */
 1689         
 1690         Stuff_CodeMask  = 0xC0,
 1691         Stuff_CountMask = 0x3F,
 1692         Stuff_MaxCount  = 0x3F,
 1693         Stuff_Magic     = 0x0D          /* The value we are eliminating */
 1694 } StuffingCode;
 1695 
 1696 /*
 1697  * StuffData encodes the data starting at "src" for "length" bytes.
 1698  * It writes it to the buffer pointed to by "dest" (which must be at least
 1699  * as long as 1 + 65/64 of the input length). The output may be up to 1.6%
 1700  * larger than the input for pathological input, but will usually be smaller.
 1701  * StuffData returns the new value of the dest pointer as its result.
 1702  *
 1703  * "code_ptr_ptr" points to a "u_char *" which is used to hold
 1704  * encoding state between calls, allowing an encoded packet to be
 1705  * incrementally built up from small parts.
 1706  * On the first call, the "u_char *" pointed to should be initialized
 1707  * to NULL;  between subsequent calls the calling routine should leave
 1708  * the value alone and simply pass it back unchanged so that the
 1709  * encoder can recover its current state.
 1710  */ 
 1711 
 1712 #define StuffData_FinishBlock(X) \
 1713         (*code_ptr = (X) ^ Stuff_Magic, code = Stuff_NoCode)
 1714 
 1715 static u_char *
 1716 StuffData(u_char *src, u_long length, u_char *dest, u_char **code_ptr_ptr)
 1717 {
 1718         u_char *end = src + length;
 1719         u_char *code_ptr = *code_ptr_ptr;
 1720         u_char code = Stuff_NoCode, count = 0;
 1721         
 1722         if (!length) return (dest);
 1723         
 1724         if (code_ptr) { /* Recover state from last call, if applicable */
 1725                 code  = (*code_ptr ^ Stuff_Magic) & Stuff_CodeMask;
 1726                 count = (*code_ptr ^ Stuff_Magic) & Stuff_CountMask;
 1727         }
 1728 
 1729         while (src < end) {
 1730                 switch (code) {
 1731                 /*
 1732                  * Stuff_NoCode: If no current code, select one
 1733                  */
 1734                 case Stuff_NoCode:
 1735                         code_ptr = dest++;      /* Record where we're going to put this code */
 1736                         count = 0;              /* Reset the count (zero means one instance) */
 1737                                                         /* Tentatively start a new block */
 1738                         if (*src == 0) {
 1739                                 code = Stuff_Zero;
 1740                                 src++;
 1741                         } else {
 1742                                 code = Stuff_Same;
 1743                                 *dest++ = *src++ ^ Stuff_Magic;
 1744                         }
 1745                         /* Note: We optimistically assume run of same -- which will be */
 1746                         /* fixed later in Stuff_Same if it turns out not to be true. */
 1747                         break;
 1748 
 1749                 /*
 1750                  * Stuff_Zero: We already have at least one zero encoded
 1751                  */
 1752                 case Stuff_Zero:
 1753                         
 1754                         /* If another zero, count it, else finish this code block */
 1755                         if (*src == 0) {
 1756                                 count++;
 1757                                 src++;
 1758                         } else
 1759                                 StuffData_FinishBlock(Stuff_Zero + count);
 1760                         break;
 1761 
 1762                 /*
 1763                  * Stuff_Same: We already have at least one byte encoded
 1764                  */
 1765                 case Stuff_Same:
 1766                         /* If another one the same, count it */
 1767                         if ((*src ^ Stuff_Magic) == code_ptr[1]) {
 1768                                 count++;
 1769                                 src++;
 1770                                 break;
 1771                         }
 1772                         /* else, this byte does not match this block. */
 1773                         /* If we already have two or more bytes encoded, finish this code block */
 1774                         if (count) {
 1775                                 StuffData_FinishBlock(Stuff_Same + count);
 1776                                 break;
 1777                         }
 1778                         /* else, we only have one so far, so switch to Stuff_Diff code */
 1779                         code = Stuff_Diff; /* and fall through to Stuff_Diff case below */
 1780 
 1781                 case Stuff_Diff:        /* Stuff_Diff: We have at least two *different* bytes encoded */
 1782                         /* If this is a zero, must encode a Stuff_DiffZero, and begin a new block */
 1783                         if (*src == 0)
 1784                                 StuffData_FinishBlock(Stuff_DiffZero + count);
 1785                         /* else, if we have three in a row, it is worth starting a Stuff_Same block */
 1786                         else if ((*src ^ Stuff_Magic) == dest[-1] && dest[-1] == dest[-2])
 1787                                 {
 1788                                 code += count-2;
 1789                                 if (code == Stuff_Diff)
 1790                                         code = Stuff_Same;
 1791                                 StuffData_FinishBlock(code);
 1792                                 code_ptr = dest-2;
 1793                                 /* dest[-1] already holds the correct value */
 1794                                 count = 2;              /* 2 means three bytes encoded */
 1795                                 code = Stuff_Same;
 1796                                 }
 1797                         /* else, another different byte, so add it to the block */
 1798                         else {
 1799                                 *dest++ = *src ^ Stuff_Magic;
 1800                                 count++;
 1801                         }
 1802                         src++;  /* Consume the byte */
 1803                         break;
 1804                 }
 1805 
 1806                 if (count == Stuff_MaxCount)
 1807                         StuffData_FinishBlock(code + count);
 1808                 }
 1809         if (code == Stuff_NoCode)
 1810                 *code_ptr_ptr = NULL;
 1811         else {
 1812                 *code_ptr_ptr = code_ptr;
 1813                 StuffData_FinishBlock(code + count);
 1814         }
 1815 
 1816         return (dest);
 1817 }
 1818 
 1819 
 1820 
 1821 /*
 1822  * UnStuffData decodes the data at "src", up to (but not including)
 1823  * "end".  It writes the decoded data into the buffer pointed to by
 1824  * "dst", up to a  maximum of "dst_length", and returns the new
 1825  * value of "src" so that a follow-on call can read more data,
 1826  * continuing from where the first left off. 
 1827  *
 1828  * There are three types of results:
 1829  * 1. The source data runs out before extracting "dst_length" bytes:
 1830  *    UnStuffData returns NULL to indicate failure.
 1831  * 2. The source data produces exactly "dst_length" bytes:
 1832  *    UnStuffData returns new_src = end to indicate that all bytes
 1833  *    were consumed. 
 1834  * 3. "dst_length" bytes are extracted, with more
 1835  *     remaining. UnStuffData returns new_src < end to indicate that
 1836  *     there are more bytes to be read.
 1837  *
 1838  * Note: The decoding may be dstructive, in that it may alter the
 1839  * source data in the process of decoding it (this is necessary to
 1840  * allow a follow-on  call to resume correctly).
 1841  */
 1842 
 1843 static u_char *
 1844 UnStuffData(u_char *src, u_char *end, u_char *dst, u_long dst_length)
 1845 {
 1846         u_char *dst_end = dst + dst_length;
 1847 
 1848         /* Sanity check */
 1849         if (!src || !end || !dst || !dst_length)
 1850                 return (NULL);
 1851 
 1852         while (src < end && dst < dst_end)
 1853         {
 1854                 int count = (*src ^ Stuff_Magic) & Stuff_CountMask;
 1855                 switch ((*src ^ Stuff_Magic) & Stuff_CodeMask)
 1856                         {
 1857                         case Stuff_Diff:
 1858                                 if (src+1+count >= end)
 1859                                         return (NULL);
 1860                                 do
 1861                                 {
 1862                                         *dst++ = *++src ^ Stuff_Magic;
 1863                                 }
 1864                                 while(--count >= 0 && dst < dst_end);
 1865                                 if (count < 0)
 1866                                         src += 1;
 1867                                 else
 1868                                  if (count == 0)
 1869                                         *src = Stuff_Same ^ Stuff_Magic;
 1870                                 else
 1871                                         *src = (Stuff_Diff + count) ^ Stuff_Magic;
 1872                                 break;
 1873                         case Stuff_DiffZero:
 1874                                 if (src+1+count >= end)
 1875                                         return (NULL);
 1876                                 do
 1877                                 {
 1878                                         *dst++ = *++src ^ Stuff_Magic;
 1879                                 }
 1880                                 while(--count >= 0 && dst < dst_end);
 1881                                 if (count < 0)
 1882                                         *src = Stuff_Zero ^ Stuff_Magic;
 1883                                 else
 1884                                         *src = (Stuff_DiffZero + count) ^ Stuff_Magic;
 1885                                 break;
 1886                         case Stuff_Same:
 1887                                 if (src+1 >= end)
 1888                                         return (NULL);
 1889                                 do
 1890                                 {
 1891                                         *dst++ = src[1] ^ Stuff_Magic;
 1892                                 }
 1893                                 while(--count >= 0 && dst < dst_end);
 1894                                 if (count < 0)
 1895                                         src += 2;
 1896                                 else
 1897                                         *src = (Stuff_Same + count) ^ Stuff_Magic;
 1898                                 break;
 1899                         case Stuff_Zero:
 1900                                 do
 1901                                 {
 1902                                         *dst++ = 0;
 1903                                 }
 1904                                 while(--count >= 0 && dst < dst_end);
 1905                                 if (count < 0)
 1906                                         src += 1;
 1907                                 else
 1908                                         *src = (Stuff_Zero + count) ^ Stuff_Magic;
 1909                                 break;
 1910                         }
 1911         }
 1912 
 1913         if (dst < dst_end)
 1914                 return (NULL);
 1915         else
 1916                 return (src);
 1917 }
 1918 
 1919 
 1920 
 1921 /*
 1922  * Log an error mesesage (for a packet received with errors?)
 1923  * from the STRIP driver.
 1924  */
 1925 static void
 1926 RecvErr(msg, sc)
 1927         char *msg;
 1928         struct st_softc *sc;
 1929 {
 1930         static const int MAX_RecErr = 80;
 1931         u_char *ptr = sc->sc_buf;
 1932         u_char *end = sc->sc_mp;
 1933         u_char pkt_text[MAX_RecErr], *p = pkt_text;
 1934         *p++ = '\"';
 1935         while (ptr < end && p < &pkt_text[MAX_RecErr-4]) {
 1936                 if (*ptr == '\\') {
 1937                         *p++ = '\\';
 1938                         *p++ = '\\';
 1939                 } else if (*ptr >= 32 && *ptr <= 126)
 1940                         *p++ = *ptr;
 1941                 else {
 1942                         sprintf(p, "\\%02x", *ptr);
 1943                         p+= 3;
 1944                 }
 1945                 ptr++;
 1946         }
 1947 
 1948         if (ptr == end) *p++ = '\"';
 1949         *p++ = 0;
 1950         addlog("%s: %13s : %s\n", sc->sc_if.if_xname, msg, pkt_text);
 1951 
 1952         sc->sc_if.if_ierrors++;
 1953 }
 1954 
 1955 
 1956 /*
 1957  * Parse an error message from the radio.
 1958  */
 1959 static void
 1960 RecvErr_Message(strip_info, sendername, msg)
 1961         struct st_softc *strip_info;
 1962         u_char *sendername;
 1963         /*const*/ u_char *msg;
 1964 {
 1965         static const char ERR_001[] = "001"; /* Not in StarMode! */
 1966         static const char ERR_002[] = "002"; /* Remap handle */
 1967         static const char ERR_003[] = "003"; /* Can't resolve name */
 1968         static const char ERR_004[] = "004"; /* Name too small or missing */
 1969         static const char ERR_005[] = "005"; /* Bad count specification */
 1970         static const char ERR_006[] = "006"; /* Header too big */
 1971         static const char ERR_007[] = "007"; /* Body too big */
 1972         static const char ERR_008[] = "008"; /* Bad character in name */
 1973         static const char ERR_009[] = "009"; /* No count or line terminator */
 1974 
 1975         char * if_name;
 1976 
 1977         if_name = strip_info->sc_if.if_xname;
 1978 
 1979         if (!strncmp(msg, ERR_001, sizeof(ERR_001)-1))
 1980         {
 1981                 RecvErr("radio error message:", strip_info);
 1982                 addlog("%s: Radio %s is not in StarMode\n",
 1983                         if_name, sendername);
 1984         }
 1985         else if (!strncmp(msg, ERR_002, sizeof(ERR_002)-1))
 1986         {
 1987                 RecvErr("radio error message:", strip_info);
 1988 #ifdef notyet           /*Kernel doesn't have scanf!*/
 1989                 int handle;
 1990                 u_char newname[64];
 1991                 sscanf(msg, "ERR_002 Remap handle &%d to name %s", &handle, newname);
 1992                 addlog("%s: Radio name %s is handle %d\n",
 1993                         if_name, newname, handle);
 1994 #endif
 1995         }
 1996         else if (!strncmp(msg, ERR_003, sizeof(ERR_003)-1))
 1997         {
 1998                 RecvErr("radio error message:", strip_info);
 1999                 addlog("%s: Destination radio name is unknown\n", if_name);
 2000         }
 2001         else if (!strncmp(msg, ERR_004, sizeof(ERR_004)-1)) {
 2002                 /*
 2003                  * The radio reports it got a badly-framed starmode packet
 2004                  * from us; so it must me in starmode.
 2005                  */
 2006                 if (strip_info->sc_if.if_flags & IFF_DEBUG)
 2007                         addlog("%s: radio responded to probe\n", if_name);
 2008                 if (strip_info->sc_state == ST_DEAD) {
 2009                         /* A successful reset... */
 2010                         addlog("%s: Radio back in starmode\n", if_name);
 2011                 }
 2012                 CLEAR_RESET_TIMER(strip_info);
 2013         }
 2014         else if (!strncmp(msg, ERR_005, sizeof(ERR_005)-1))
 2015                 RecvErr("radio error message:", strip_info);
 2016         else if (!strncmp(msg, ERR_006, sizeof(ERR_006)-1))
 2017                 RecvErr("radio error message:", strip_info);
 2018         else if (!strncmp(msg, ERR_007, sizeof(ERR_007)-1))
 2019          {
 2020                 /*
 2021                  *      Note: This error knocks the radio back into
 2022                  *      command mode.
 2023                  */
 2024                 RecvErr("radio error message:", strip_info);
 2025                 addlog("%s: Error! Packet size too big for radio.",
 2026                         if_name);
 2027                 FORCE_RESET(strip_info);
 2028         }
 2029         else if (!strncmp(msg, ERR_008, sizeof(ERR_008)-1))
 2030         {
 2031                 RecvErr("radio error message:", strip_info);
 2032                 addlog("%s: Radio name contains illegal character\n",
 2033                         if_name);
 2034         }
 2035         else if (!strncmp(msg, ERR_009, sizeof(ERR_009)-1))
 2036                 RecvErr("radio error message:", strip_info);
 2037         else {
 2038                 addlog("failed to parse ]%3s[\n", msg);
 2039                 RecvErr("unparsed radio error message:", strip_info);
 2040         }
 2041 }
 2042 
 2043 #endif /* NSTRIP > 0 */

/* [<][>][^][v][top][bottom][index][help] */