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