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