|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
26: /*
27: * Copyright (c) 1987, 1989, 1992, 1993
28: * The Regents of the University of California. All rights reserved.
29: *
30: * Redistribution and use in source and binary forms, with or without
31: * modification, are permitted provided that the following conditions
32: * are met:
33: * 1. Redistributions of source code must retain the above copyright
34: * notice, this list of conditions and the following disclaimer.
35: * 2. Redistributions in binary form must reproduce the above copyright
36: * notice, this list of conditions and the following disclaimer in the
37: * documentation and/or other materials provided with the distribution.
38: * 3. All advertising materials mentioning features or use of this software
39: * must display the following acknowledgement:
40: * This product includes software developed by the University of
41: * California, Berkeley and its contributors.
42: * 4. 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.9 (Berkeley) 1/9/95
59: */
60:
61: /*
62: * Serial Line interface
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: * [email protected]
70: * seismo!rick
71: *
72: * Pounded on heavily by Chris Torek ([email protected], 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 ([email protected]).
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: * Note that splimp() is used throughout to block both (tty) input
89: * interrupts and network activity; thus, splimp must be >= spltty.
90: */
91:
92: #include "sl.h"
93: #if NSL > 0
94:
95: #include "bpfilter.h"
96:
97: #include <sys/param.h>
98: #include <sys/proc.h>
99: #include <sys/mbuf.h>
100: #include <sys/buf.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:
109: #include <machine/cpu.h>
110:
111: #include <net/if.h>
112: #include <net/if_types.h>
113: #include <net/netisr.h>
114: #include <net/route.h>
115:
116: #if INET
117: #include <netinet/in.h>
118: #include <netinet/in_systm.h>
119: #include <netinet/in_var.h>
120: #include <netinet/ip.h>
121: #else
122: Huh? Slip without inet?
123: #endif
124:
125: #include <net/slcompress.h>
126: #include <net/if_slvar.h>
127: #include <net/slip.h>
128:
129: #if NBPFILTER > 0
130: #include <sys/time.h>
131: #include <net/bpf.h>
132: #endif
133:
134: /*
135: * SLMAX is a hard limit on input packet size. To simplify the code
136: * and improve performance, we require that packets fit in an mbuf
137: * cluster, and if we get a compressed packet, there's enough extra
138: * room to expand the header into a max length tcp/ip header (128
139: * bytes). So, SLMAX can be at most
140: * MCLBYTES - 128
141: *
142: * SLMTU is a hard limit on output packet size. To insure good
143: * interactive response, SLMTU wants to be the smallest size that
144: * amortizes the header cost. (Remember that even with
145: * type-of-service queuing, we have to wait for any in-progress
146: * packet to finish. I.e., we wait, on the average, 1/2 * mtu /
147: * cps, where cps is the line speed in characters per second.
148: * E.g., 533ms wait for a 1024 byte MTU on a 9600 baud line. The
149: * average compressed header size is 6-8 bytes so any MTU > 90
150: * bytes will give us 90% of the line bandwidth. A 100ms wait is
151: * tolerable (500ms is not), so want an MTU around 296. (Since TCP
152: * will send 256 byte segments (to allow for 40 byte headers), the
153: * typical packet size on the wire will be around 260 bytes). In
154: * 4.3tahoe+ systems, we can set an MTU in a route so we do that &
155: * leave the interface MTU relatively high (so we don't IP fragment
156: * when acting as a gateway to someone using a stupid MTU).
157: *
158: * Similar considerations apply to SLIP_HIWAT: It's the amount of
159: * data that will be queued 'downstream' of us (i.e., in clists
160: * waiting to be picked up by the tty output interrupt). If we
161: * queue a lot of data downstream, it's immune to our t.o.s. queuing.
162: * E.g., if SLIP_HIWAT is 1024, the interactive traffic in mixed
163: * telnet/ftp will see a 1 sec wait, independent of the mtu (the
164: * wait is dependent on the ftp window size but that's typically
165: * 1k - 4k). So, we want SLIP_HIWAT just big enough to amortize
166: * the cost (in idle time on the wire) of the tty driver running
167: * off the end of its clists & having to call back slstart for a
168: * new packet. For a tty interface with any buffering at all, this
169: * cost will be zero. Even with a totally brain dead interface (like
170: * the one on a typical workstation), the cost will be <= 1 character
171: * time. So, setting SLIP_HIWAT to ~100 guarantees that we'll lose
172: * at most 1% while maintaining good interactive response.
173: */
174: #if NBPFILTER > 0
175: #define BUFOFFSET (128+sizeof(struct ifnet **)+SLIP_HDRLEN)
176: #else
177: #define BUFOFFSET (128+sizeof(struct ifnet **))
178: #endif
179: #define SLMAX (MCLBYTES - BUFOFFSET)
180: #define SLBUFSIZE (SLMAX + BUFOFFSET)
181: #define SLMTU 296
182: #define SLIP_HIWAT roundup(50,CBSIZE)
183:
184: /*
185: * SLIP ABORT ESCAPE MECHANISM:
186: * (inspired by HAYES modem escape arrangement)
187: * 1sec escape 1sec escape 1sec escape { 1sec escape 1sec escape }
188: * within window time signals a "soft" exit from slip mode by remote end
189: * if the IFF_DEBUG flag is on.
190: */
191: #define ABT_ESC '\033' /* can't be t_intr - distant host must know it*/
192: #define ABT_IDLE 1 /* in seconds - idle before an escape */
193: #define ABT_COUNT 3 /* count of escapes for abort */
194: #define ABT_WINDOW (ABT_COUNT*2+2) /* in seconds - time to count */
195:
196: struct sl_softc sl_softc[NSL];
197:
198: #define FRAME_END 0xc0 /* Frame End */
199: #define FRAME_ESCAPE 0xdb /* Frame Esc */
200: #define TRANS_FRAME_END 0xdc /* transposed frame end */
201: #define TRANS_FRAME_ESCAPE 0xdd /* transposed frame esc */
202:
203: static int slinit __P((struct sl_softc *));
204: static struct mbuf *sl_btom __P((struct sl_softc *, int));
205:
206: /*
207: * Called from boot code to establish sl interfaces.
208: */
209: void
210: slattach()
211: {
212: register struct sl_softc *sc;
213: register int i = 0;
214:
215: for (sc = sl_softc; i < NSL; sc++) {
216: sc->sc_if.if_name = "sl";
217: sc->sc_if.if_next = NULL;
218: sc->sc_if.if_unit = i++;
219: sc->sc_if.if_mtu = SLMTU;
220: sc->sc_if.if_flags =
221: IFF_POINTOPOINT | SC_AUTOCOMP | IFF_MULTICAST;
222: sc->sc_if.if_type = IFT_SLIP;
223: sc->sc_if.if_ioctl = slioctl;
224: sc->sc_if.if_output = sloutput;
225: sc->sc_if.if_snd.ifq_maxlen = 50;
226: sc->sc_fastq.ifq_maxlen = 32;
227: if_attach(&sc->sc_if);
228: #if NBPFILTER > 0
229: bpfattach(&sc->sc_bpf, &sc->sc_if, DLT_SLIP, SLIP_HDRLEN);
230: #endif
231: }
232: }
233:
234: static int
235: slinit(sc)
236: register struct sl_softc *sc;
237: {
238: register caddr_t p;
239:
240: if (sc->sc_ep == (u_char *) 0) {
241: MCLALLOC(p, M_WAIT);
242: if (p)
243: sc->sc_ep = (u_char *)p + SLBUFSIZE;
244: else {
245: printf("sl%d: can't allocate buffer\n", sc - sl_softc);
246: sc->sc_if.if_flags &= ~IFF_UP;
247: return (0);
248: }
249: }
250: sc->sc_buf = sc->sc_ep - SLMAX;
251: sc->sc_mp = sc->sc_buf;
252: sl_compress_init(&sc->sc_comp, -1);
253: return (1);
254: }
255:
256: /*
257: * Line specific open routine.
258: * Attach the given tty to the first available sl unit.
259: */
260: /* ARGSUSED */
261: int
262: slopen(dev, tp)
263: dev_t dev;
264: register struct tty *tp;
265: {
266: struct proc *p = curproc; /* XXX */
267: register struct sl_softc *sc;
268: register int nsl;
269: int error;
270: int s;
271:
272: if (error = suser(p->p_ucred, &p->p_acflag))
273: return (error);
274:
275: if (tp->t_line == SLIPDISC)
276: return (0);
277:
278: for (nsl = NSL, sc = sl_softc; --nsl >= 0; sc++)
279: if (sc->sc_ttyp == NULL) {
280: if (slinit(sc) == 0)
281: return (ENOBUFS);
282: tp->t_sc = (caddr_t)sc;
283: sc->sc_ttyp = tp;
284: sc->sc_if.if_baudrate = tp->t_ospeed;
285: ttyflush(tp, FREAD | FWRITE);
286:
287: /*
288: * make sure tty output queue is large enough
289: * to hold a full-sized packet (including frame
290: * end, and a possible extra frame end). full-sized
291: * packet occupies a max of 2*SLMTU bytes (because
292: * of possible escapes), and add two on for frame
293: * ends.
294: */
295: s = spltty();
296: if (tp->t_outq.c_cn < 2*SLMTU+2) {
297: sc->sc_oldbufsize = tp->t_outq.c_cn;
298: sc->sc_oldbufquot = tp->t_outq.c_cq != 0;
299:
300: clfree(&tp->t_outq);
301: error = clalloc(&tp->t_outq, 3*SLMTU, 0);
302: if (error) {
303: splx(s);
304: return(error);
305: }
306: } else
307: sc->sc_oldbufsize = sc->sc_oldbufquot = 0;
308: splx(s);
309:
310: return (0);
311: }
312: return (ENXIO);
313: }
314:
315: /*
316: * Line specific close routine.
317: * Detach the tty from the sl unit.
318: */
319: void
320: slclose(tp)
321: struct tty *tp;
322: {
323: register struct sl_softc *sc;
324: int s;
325:
326: ttywflush(tp);
327: s = splimp(); /* actually, max(spltty, splnet) */
328: tp->t_line = 0;
329: tp->t_state = 0;
330: sc = (struct sl_softc *)tp->t_sc;
331: if (sc != NULL) {
332: if_down(&sc->sc_if);
333: sc->sc_ttyp = NULL;
334: tp->t_sc = NULL;
335: MCLFREE((caddr_t)(sc->sc_ep - SLBUFSIZE));
336: sc->sc_ep = 0;
337: sc->sc_mp = 0;
338: sc->sc_buf = 0;
339: }
340: /* if necessary, install a new outq buffer of the appropriate size */
341: if (sc->sc_oldbufsize != 0) {
342: clfree(&tp->t_outq);
343: clalloc(&tp->t_outq, sc->sc_oldbufsize, sc->sc_oldbufquot);
344: }
345: splx(s);
346: }
347:
348: /*
349: * Line specific (tty) ioctl routine.
350: * Provide a way to get the sl unit number.
351: */
352: /* ARGSUSED */
353: int
354: sltioctl(tp, cmd, data, flag)
355: struct tty *tp;
356: u_long cmd;
357: caddr_t data;
358: int flag;
359: {
360: struct sl_softc *sc = (struct sl_softc *)tp->t_sc;
361:
362: switch (cmd) {
363: case SLIOCGUNIT:
364: *(int *)data = sc->sc_if.if_unit;
365: break;
366:
367: default:
368: return (-1);
369: }
370: return (0);
371: }
372:
373: /*
374: * Queue a packet. Start transmission if not active.
375: * Compression happens in slstart; if we do it here, IP TOS
376: * will cause us to not compress "background" packets, because
377: * ordering gets trashed. It can be done for all packets in slstart.
378: */
379: int
380: sloutput(ifp, m, dst, rtp)
381: struct ifnet *ifp;
382: register struct mbuf *m;
383: struct sockaddr *dst;
384: struct rtentry *rtp;
385: {
386: register struct sl_softc *sc = &sl_softc[ifp->if_unit];
387: register struct ip *ip;
388: register struct ifqueue *ifq;
389: int s;
390:
391: /*
392: * `Cannot happen' (see slioctl). Someday we will extend
393: * the line protocol to support other address families.
394: */
395: if (dst->sa_family != AF_INET) {
396: printf("sl%d: af%d not supported\n", sc->sc_if.if_unit,
397: dst->sa_family);
398: m_freem(m);
399: sc->sc_if.if_noproto++;
400: return (EAFNOSUPPORT);
401: }
402:
403: if (sc->sc_ttyp == NULL) {
404: m_freem(m);
405: return (ENETDOWN); /* sort of */
406: }
407: if ((sc->sc_ttyp->t_state & TS_CARR_ON) == 0 &&
408: (sc->sc_ttyp->t_cflag & CLOCAL) == 0) {
409: m_freem(m);
410: return (EHOSTUNREACH);
411: }
412: ifq = &sc->sc_if.if_snd;
413: ip = mtod(m, struct ip *);
414: if (sc->sc_if.if_flags & SC_NOICMP && ip->ip_p == IPPROTO_ICMP) {
415: m_freem(m);
416: return (ENETRESET); /* XXX ? */
417: }
418: if (ip->ip_tos & IPTOS_LOWDELAY)
419: ifq = &sc->sc_fastq;
420: s = splimp();
421: if (sc->sc_oqlen && sc->sc_ttyp->t_outq.c_cc == sc->sc_oqlen) {
422: /* if output's been stalled for too long, and restart */
423: timersub(&time, &sc->sc_if.if_lastchange, &tv);
424: if (tv.tv_sec > 0) {
425: sc->sc_otimeout++;
426: slstart(sc->sc_ttyp);
427: }
428: }
429: if (IF_QFULL(ifq)) {
430: IF_DROP(ifq);
431: m_freem(m);
432: splx(s);
433: sc->sc_if.if_oerrors++;
434: return (ENOBUFS);
435: }
436: IF_ENQUEUE(ifq, m);
437: sc->sc_if.if_lastchange = time;
438: if ((sc->sc_oqlen = sc->sc_ttyp->t_outq.c_cc) == 0)
439: slstart(sc->sc_ttyp);
440: splx(s);
441: return (0);
442: }
443:
444: /*
445: * Start output on interface. Get another datagram
446: * to send from the interface queue and map it to
447: * the interface before starting output.
448: */
449: void
450: slstart(tp)
451: register struct tty *tp;
452: {
453: register struct sl_softc *sc = (struct sl_softc *)tp->t_sc;
454: register struct mbuf *m;
455: register u_char *cp;
456: register struct ip *ip;
457: int s;
458: struct mbuf *m2;
459: #if NBPFILTER > 0
460: u_char bpfbuf[SLMTU + SLIP_HDRLEN];
461: register int len;
462: #endif
463:
464: for (;;) {
465: /*
466: * If there is more in the output queue, just send it now.
467: * We are being called in lieu of ttstart and must do what
468: * it would.
469: */
470: if (tp->t_outq.c_cc != 0) {
471: (*tp->t_oproc)(tp);
472: if (tp->t_outq.c_cc > SLIP_HIWAT)
473: return;
474: }
475: /*
476: * This happens briefly when the line shuts down.
477: */
478: if (sc == NULL)
479: return;
480:
481: /*
482: * Do not remove the packet from the IP queue if it
483: * doesn't look like the packet will fit into the
484: * current serial output queue, with a packet full of
485: * escapes this could be as bad as SLMTU*2+2.
486: */
487: if (tp->t_outq.c_cn - tp->t_outq.c_cc < 2*SLMTU+2)
488: return;
489:
490: /*
491: * Get a packet and send it to the interface.
492: */
493: s = splimp();
494: IF_DEQUEUE(&sc->sc_fastq, m);
495: if (m)
496: sc->sc_if.if_omcasts++; /* XXX */
497: else
498: IF_DEQUEUE(&sc->sc_if.if_snd, m);
499: splx(s);
500: if (m == NULL)
501: return;
502:
503: /*
504: * We do the header compression here rather than in sloutput
505: * because the packets will be out of order if we are using TOS
506: * queueing, and the connection id compression will get
507: * munged when this happens.
508: */
509: #if NBPFILTER > 0
510: if (sc->sc_bpf) {
511: /*
512: * We need to save the TCP/IP header before it's
513: * compressed. To avoid complicated code, we just
514: * copy the entire packet into a stack buffer (since
515: * this is a serial line, packets should be short
516: * and/or the copy should be negligible cost compared
517: * to the packet transmission time).
518: */
519: register struct mbuf *m1 = m;
520: register u_char *cp = bpfbuf + SLIP_HDRLEN;
521:
522: len = 0;
523: do {
524: register int mlen = m1->m_len;
525:
526: bcopy(mtod(m1, caddr_t), cp, mlen);
527: cp += mlen;
528: len += mlen;
529: } while (m1 = m1->m_next);
530: }
531: #endif
532: if ((ip = mtod(m, struct ip *))->ip_p == IPPROTO_TCP) {
533: if (sc->sc_if.if_flags & SC_COMPRESS)
534: *mtod(m, u_char *) |= sl_compress_tcp(m, ip,
535: &sc->sc_comp, 1);
536: }
537: #if NBPFILTER > 0
538: if (sc->sc_bpf) {
539: /*
540: * Put the SLIP pseudo-"link header" in place. The
541: * compressed header is now at the beginning of the
542: * mbuf.
543: */
544: bpfbuf[SLX_DIR] = SLIPDIR_OUT;
545: bcopy(mtod(m, caddr_t), &bpfbuf[SLX_CHDR], CHDR_LEN);
546: BPF_TAP(sc->sc_bpf, bpfbuf, len + SLIP_HDRLEN);
547: }
548: #endif
549: sc->sc_if.if_lastchange = time;
550:
551: /*
552: * The extra FRAME_END will start up a new packet, and thus
553: * will flush any accumulated garbage. We do this whenever
554: * the line may have been idle for some time.
555: */
556: if (tp->t_outq.c_cc == 0) {
557: ++sc->sc_if.if_obytes;
558: (void) putc(FRAME_END, &tp->t_outq);
559: }
560:
561: while (m) {
562: register u_char *ep;
563:
564: cp = mtod(m, u_char *); ep = cp + m->m_len;
565: while (cp < ep) {
566: /*
567: * Find out how many bytes in the string we can
568: * handle without doing something special.
569: */
570: register u_char *bp = cp;
571:
572: while (cp < ep) {
573: switch (*cp++) {
574: case FRAME_ESCAPE:
575: case FRAME_END:
576: --cp;
577: goto out;
578: }
579: }
580: out:
581: if (cp > bp) {
582: /*
583: * Put n characters at once
584: * into the tty output queue.
585: */
586: if (b_to_q((u_char *)bp, cp - bp,
587: &tp->t_outq))
588: break;
589: sc->sc_if.if_obytes += cp - bp;
590: }
591: /*
592: * If there are characters left in the mbuf,
593: * the first one must be special..
594: * Put it out in a different form.
595: */
596: if (cp < ep) {
597: if (putc(FRAME_ESCAPE, &tp->t_outq))
598: break;
599: if (putc(*cp++ == FRAME_ESCAPE ?
600: TRANS_FRAME_ESCAPE : TRANS_FRAME_END,
601: &tp->t_outq)) {
602: (void) unputc(&tp->t_outq);
603: break;
604: }
605: sc->sc_if.if_obytes += 2;
606: }
607: }
608: MFREE(m, m2);
609: m = m2;
610: }
611:
612: if (putc(FRAME_END, &tp->t_outq)) {
613: /*
614: * Not enough room. Remove a char to make room
615: * and end the packet normally.
616: * If you get many collisions (more than one or two
617: * a day) you probably do not have enough clists
618: * and you should increase "nclist" in param.c.
619: */
620: (void) unputc(&tp->t_outq);
621: (void) putc(FRAME_END, &tp->t_outq);
622: sc->sc_if.if_collisions++;
623: } else {
624: ++sc->sc_if.if_obytes;
625: sc->sc_if.if_opackets++;
626: }
627: }
628: }
629:
630: /*
631: * Copy data buffer to mbuf chain; add ifnet pointer.
632: */
633: static struct mbuf *
634: sl_btom(sc, len)
635: register struct sl_softc *sc;
636: register int len;
637: {
638: register struct mbuf *m;
639:
640: MGETHDR(m, M_DONTWAIT, MT_DATA);
641: if (m == NULL)
642: return (NULL);
643:
644: /*
645: * If we have more than MHLEN bytes, it's cheaper to
646: * queue the cluster we just filled & allocate a new one
647: * for the input buffer. Otherwise, fill the mbuf we
648: * allocated above. Note that code in the input routine
649: * guarantees that packet will fit in a cluster.
650: */
651: if (len >= MHLEN) {
652: MCLGET(m, M_DONTWAIT);
653: if ((m->m_flags & M_EXT) == 0) {
654: /*
655: * we couldn't get a cluster - if memory's this
656: * low, it's time to start dropping packets.
657: */
658: (void) m_free(m);
659: return (NULL);
660: }
661: sc->sc_ep = mtod(m, u_char *) + SLBUFSIZE;
662: m->m_data = (caddr_t)sc->sc_buf;
663: m->m_ext.ext_buf = (caddr_t)((long)sc->sc_buf &~ MCLOFSET);
664: } else
665: bcopy((caddr_t)sc->sc_buf, mtod(m, caddr_t), len);
666:
667: m->m_len = len;
668: m->m_pkthdr.len = len;
669: m->m_pkthdr.rcvif = &sc->sc_if;
670: return (m);
671: }
672:
673: /*
674: * tty interface receiver interrupt.
675: */
676: void
677: slinput(c, tp)
678: register int c;
679: register struct tty *tp;
680: {
681: register struct sl_softc *sc;
682: register struct mbuf *m;
683: register int len;
684: int s;
685: #if NBPFILTER > 0
686: u_char chdr[CHDR_LEN];
687: #endif
688:
689: tk_nin++;
690: sc = (struct sl_softc *)tp->t_sc;
691: if (sc == NULL)
692: return;
693: if (c & TTY_ERRORMASK || ((tp->t_state & TS_CARR_ON) == 0 &&
694: (tp->t_cflag & CLOCAL) == 0)) {
695: sc->sc_flags |= SC_ERROR;
696: return;
697: }
698: c &= TTY_CHARMASK;
699:
700: ++sc->sc_if.if_ibytes;
701:
702: if (sc->sc_if.if_flags & IFF_DEBUG) {
703:
704: if (c == ABT_ESC) {
705: /*
706: * If we have a previous abort, see whether
707: * this one is within the time limit.
708: */
709: if (sc->sc_abortcount &&
710: time.tv_sec >= sc->sc_starttime + ABT_WINDOW)
711: sc->sc_abortcount = 0;
712: /*
713: * If we see an abort after "idle" time, count it;
714: * record when the first abort escape arrived.
715: */
716: if (time.tv_sec >= sc->sc_lasttime + ABT_IDLE) {
717: if (++sc->sc_abortcount == 1)
718: sc->sc_starttime = time.tv_sec;
719: if (sc->sc_abortcount >= ABT_COUNT) {
720: slclose(tp);
721: return;
722: }
723: }
724: } else
725: sc->sc_abortcount = 0;
726: sc->sc_lasttime = time.tv_sec;
727: }
728:
729: switch (c) {
730:
731: case TRANS_FRAME_ESCAPE:
732: if (sc->sc_escape)
733: c = FRAME_ESCAPE;
734: break;
735:
736: case TRANS_FRAME_END:
737: if (sc->sc_escape)
738: c = FRAME_END;
739: break;
740:
741: case FRAME_ESCAPE:
742: sc->sc_escape = 1;
743: return;
744:
745: case FRAME_END:
746: if(sc->sc_flags & SC_ERROR) {
747: sc->sc_flags &= ~SC_ERROR;
748: goto newpack;
749: }
750: len = sc->sc_mp - sc->sc_buf;
751: if (len < 3)
752: /* less than min length packet - ignore */
753: goto newpack;
754:
755: #if NBPFILTER > 0
756: if (sc->sc_bpf) {
757: /*
758: * Save the compressed header, so we
759: * can tack it on later. Note that we
760: * will end up copying garbage in some
761: * cases but this is okay. We remember
762: * where the buffer started so we can
763: * compute the new header length.
764: */
765: bcopy(sc->sc_buf, chdr, CHDR_LEN);
766: }
767: #endif
768:
769: if ((c = (*sc->sc_buf & 0xf0)) != (IPVERSION << 4)) {
770: if (c & 0x80)
771: c = TYPE_COMPRESSED_TCP;
772: else if (c == TYPE_UNCOMPRESSED_TCP)
773: *sc->sc_buf &= 0x4f; /* XXX */
774: /*
775: * We've got something that's not an IP packet.
776: * If compression is enabled, try to decompress it.
777: * Otherwise, if `auto-enable' compression is on and
778: * it's a reasonable packet, decompress it and then
779: * enable compression. Otherwise, drop it.
780: */
781: if (sc->sc_if.if_flags & SC_COMPRESS) {
782: len = sl_uncompress_tcp(&sc->sc_buf, len,
783: (u_int)c, &sc->sc_comp);
784: if (len <= 0)
785: goto error;
786: } else if ((sc->sc_if.if_flags & SC_AUTOCOMP) &&
787: c == TYPE_UNCOMPRESSED_TCP && len >= 40) {
788: len = sl_uncompress_tcp(&sc->sc_buf, len,
789: (u_int)c, &sc->sc_comp);
790: if (len <= 0)
791: goto error;
792: sc->sc_if.if_flags |= SC_COMPRESS;
793: } else
794: goto error;
795: }
796: #if NBPFILTER > 0
797: if (sc->sc_bpf) {
798: /*
799: * Put the SLIP pseudo-"link header" in place.
800: * We couldn't do this any earlier since
801: * decompression probably moved the buffer
802: * pointer. Then, invoke BPF.
803: */
804: register u_char *hp = sc->sc_buf - SLIP_HDRLEN;
805:
806: hp[SLX_DIR] = SLIPDIR_IN;
807: bcopy(chdr, &hp[SLX_CHDR], CHDR_LEN);
808: BPF_TAP(sc->sc_bpf, hp, len + SLIP_HDRLEN);
809: }
810: #endif
811: m = sl_btom(sc, len);
812: if (m == NULL)
813: goto error;
814:
815: sc->sc_if.if_ipackets++;
816: sc->sc_if.if_lastchange = time;
817: s = splimp();
818: if (IF_QFULL(&ipintrq)) {
819: IF_DROP(&ipintrq);
820: sc->sc_if.if_ierrors++;
821: sc->sc_if.if_iqdrops++;
822: m_freem(m);
823: } else {
824: IF_ENQUEUE(&ipintrq, m);
825: schednetisr(NETISR_IP);
826: }
827: splx(s);
828: goto newpack;
829: }
830: if (sc->sc_mp < sc->sc_ep) {
831: *sc->sc_mp++ = c;
832: sc->sc_escape = 0;
833: return;
834: }
835:
836: /* can't put lower; would miss an extra frame */
837: sc->sc_flags |= SC_ERROR;
838:
839: error:
840: sc->sc_if.if_ierrors++;
841: newpack:
842: sc->sc_mp = sc->sc_buf = sc->sc_ep - SLMAX;
843: sc->sc_escape = 0;
844: }
845:
846: /*
847: * Process an ioctl request.
848: */
849: int
850: slioctl(ifp, cmd, data)
851: register struct ifnet *ifp;
852: u_long cmd;
853: caddr_t data;
854: {
855: register struct ifaddr *ifa = (struct ifaddr *)data;
856: register struct ifreq *ifr;
857: register int s = splimp(), error = 0;
858:
859: switch (cmd) {
860:
861: case SIOCSIFADDR:
862: if (ifa->ifa_addr->sa_family == AF_INET)
863: ifp->if_flags |= IFF_UP;
864: else
865: error = EAFNOSUPPORT;
866: break;
867:
868: case SIOCSIFDSTADDR:
869: if (ifa->ifa_addr->sa_family != AF_INET)
870: error = EAFNOSUPPORT;
871: break;
872:
873: case SIOCADDMULTI:
874: case SIOCDELMULTI:
875: ifr = (struct ifreq *)data;
876: if (ifr == 0) {
877: error = EAFNOSUPPORT; /* XXX */
878: break;
879: }
880: switch (ifr->ifr_addr.sa_family) {
881:
882: #if INET
883: case AF_INET:
884: break;
885: #endif
886:
887: default:
888: error = EAFNOSUPPORT;
889: break;
890: }
891: break;
892:
893: default:
894: error = EINVAL;
895: }
896: splx(s);
897: return (error);
898: }
899: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.