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