|
|
1.1 root 1: /*
2: * Copyright (c) 1987, 1989 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
33: * @(#)if_sl.c 7.22 (Berkeley) 4/20/91
34: */
35:
36: /*
37: * Serial Line interface
38: *
39: * Rick Adams
40: * Center for Seismic Studies
41: * 1300 N 17th Street, Suite 1450
42: * Arlington, Virginia 22209
43: * (703)276-7900
44: * [email protected]
45: * seismo!rick
46: *
47: * Pounded on heavily by Chris Torek ([email protected], umcp-cs!chris).
48: * N.B.: this belongs in netinet, not net, the way it stands now.
49: * Should have a link-layer type designation, but wouldn't be
50: * backwards-compatible.
51: *
52: * Converted to 4.3BSD Beta by Chris Torek.
53: * Other changes made at Berkeley, based in part on code by Kirk Smith.
54: * W. Jolitz added slip abort.
55: *
56: * Hacked almost beyond recognition by Van Jacobson ([email protected]).
57: * Added priority queuing for "interactive" traffic; hooks for TCP
58: * header compression; ICMP filtering (at 2400 baud, some cretin
59: * pinging you can use up all your bandwidth). Made low clist behavior
60: * more robust and slightly less likely to hang serial line.
61: * Sped up a bunch of things.
62: *
63: * Note that splimp() is used throughout to block both (tty) input
64: * interrupts and network activity; thus, splimp must be >= spltty.
65: */
66:
1.1.1.2 root 67: /* $Header: /usr/bill/working/sys/net/RCS/if_sl.c,v 1.2 92/01/15 17:36:38 william Exp $ */
1.1 root 68: /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
69:
70: #include "sl.h"
71: #if NSL > 0
72:
73: #include "param.h"
74: #include "proc.h"
75: #include "mbuf.h"
76: #include "buf.h"
77: #include "dkstat.h"
78: #include "socket.h"
79: #include "ioctl.h"
80: #include "file.h"
81: #include "tty.h"
82: #include "kernel.h"
83: #include "conf.h"
84:
85: #include "if.h"
86: #include "if_types.h"
87: #include "netisr.h"
88: #include "route.h"
89: #if INET
90: #include "netinet/in.h"
91: #include "netinet/in_systm.h"
92: #include "netinet/in_var.h"
93: #include "netinet/ip.h"
94: #else
95: Huh? Slip without inet?
96: #endif
97:
98: #include "machine/mtpr.h"
99:
100: #include "slcompress.h"
101: #include "if_slvar.h"
102:
103: /*
104: * SLMAX is a hard limit on input packet size. To simplify the code
105: * and improve performance, we require that packets fit in an mbuf
106: * cluster, and if we get a compressed packet, there's enough extra
107: * room to expand the header into a max length tcp/ip header (128
108: * bytes). So, SLMAX can be at most
109: * MCLBYTES - 128
110: *
111: * SLMTU is a hard limit on output packet size. To insure good
112: * interactive response, SLMTU wants to be the smallest size that
113: * amortizes the header cost. (Remember that even with
114: * type-of-service queuing, we have to wait for any in-progress
115: * packet to finish. I.e., we wait, on the average, 1/2 * mtu /
116: * cps, where cps is the line speed in characters per second.
117: * E.g., 533ms wait for a 1024 byte MTU on a 9600 baud line. The
118: * average compressed header size is 6-8 bytes so any MTU > 90
119: * bytes will give us 90% of the line bandwidth. A 100ms wait is
120: * tolerable (500ms is not), so want an MTU around 296. (Since TCP
121: * will send 256 byte segments (to allow for 40 byte headers), the
122: * typical packet size on the wire will be around 260 bytes). In
123: * 4.3tahoe+ systems, we can set an MTU in a route so we do that &
124: * leave the interface MTU relatively high (so we don't IP fragment
125: * when acting as a gateway to someone using a stupid MTU).
126: *
127: * Similar considerations apply to SLIP_HIWAT: It's the amount of
128: * data that will be queued 'downstream' of us (i.e., in clists
129: * waiting to be picked up by the tty output interrupt). If we
130: * queue a lot of data downstream, it's immune to our t.o.s. queuing.
131: * E.g., if SLIP_HIWAT is 1024, the interactive traffic in mixed
132: * telnet/ftp will see a 1 sec wait, independent of the mtu (the
133: * wait is dependent on the ftp window size but that's typically
134: * 1k - 4k). So, we want SLIP_HIWAT just big enough to amortize
135: * the cost (in idle time on the wire) of the tty driver running
136: * off the end of its clists & having to call back slstart for a
137: * new packet. For a tty interface with any buffering at all, this
138: * cost will be zero. Even with a totally brain dead interface (like
139: * the one on a typical workstation), the cost will be <= 1 character
140: * time. So, setting SLIP_HIWAT to ~100 guarantees that we'll lose
141: * at most 1% while maintaining good interactive response.
142: */
143: #define BUFOFFSET 128
144: #define SLMAX (MCLBYTES - BUFOFFSET)
145: #define SLBUFSIZE (SLMAX + BUFOFFSET)
146: #define SLMTU 296
147: #define SLIP_HIWAT roundup(50,CBSIZE)
148: #define CLISTRESERVE 1024 /* Can't let clists get too low */
149:
150: /*
151: * SLIP ABORT ESCAPE MECHANISM:
152: * (inspired by HAYES modem escape arrangement)
153: * 1sec escape 1sec escape 1sec escape { 1sec escape 1sec escape }
154: * signals a "soft" exit from slip mode by usermode process
155: */
156:
157: #define ABT_ESC '\033' /* can't be t_intr - distant host must know it*/
158: #define ABT_WAIT 1 /* in seconds - idle before an escape & after */
159: #define ABT_RECYCLE (5*2+2) /* in seconds - time window processing abort */
160:
161: #define ABT_SOFT 3 /* count of escapes */
162:
163: /*
164: * The following disgusting hack gets around the problem that IP TOS
165: * can't be set yet. We want to put "interactive" traffic on a high
166: * priority queue. To decide if traffic is interactive, we check that
167: * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control.
168: */
169: static u_short interactive_ports[8] = {
170: 0, 513, 0, 0,
171: 0, 21, 0, 23,
172: };
173: #define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p))
174:
175: struct sl_softc sl_softc[NSL];
176:
177: #define FRAME_END 0xc0 /* Frame End */
178: #define FRAME_ESCAPE 0xdb /* Frame Esc */
179: #define TRANS_FRAME_END 0xdc /* transposed frame end */
180: #define TRANS_FRAME_ESCAPE 0xdd /* transposed frame esc */
181:
182: #define t_sc T_LINEP
183:
184: int sloutput(), slioctl(), ttrstrt();
185: extern struct timeval time;
186:
187: /*
188: * Called from boot code to establish sl interfaces.
189: */
190: slattach()
191: {
192: register struct sl_softc *sc;
193: register int i = 0;
194:
195: for (sc = sl_softc; i < NSL; sc++) {
196: sc->sc_if.if_name = "sl";
197: sc->sc_if.if_unit = i++;
198: sc->sc_if.if_mtu = SLMTU;
199: sc->sc_if.if_flags = IFF_POINTOPOINT;
200: sc->sc_if.if_type = IFT_SLIP;
201: sc->sc_if.if_ioctl = slioctl;
202: sc->sc_if.if_output = sloutput;
203: sc->sc_if.if_snd.ifq_maxlen = 50;
204: sc->sc_fastq.ifq_maxlen = 32;
205: if_attach(&sc->sc_if);
206: }
207: }
208:
209: static int
210: slinit(sc)
211: register struct sl_softc *sc;
212: {
213: register caddr_t p;
214:
215: if (sc->sc_ep == (u_char *) 0) {
216: MCLALLOC(p, M_WAIT);
217: if (p)
218: sc->sc_ep = (u_char *)p + SLBUFSIZE;
219: else {
220: printf("sl%d: can't allocate buffer\n", sc - sl_softc);
221: sc->sc_if.if_flags &= ~IFF_UP;
222: return (0);
223: }
224: }
225: sc->sc_buf = sc->sc_ep - SLMAX;
226: sc->sc_mp = sc->sc_buf;
227: sl_compress_init(&sc->sc_comp);
228: return (1);
229: }
230:
231: /*
232: * Line specific open routine.
233: * Attach the given tty to the first available sl unit.
234: */
235: /* ARGSUSED */
236: slopen(dev, tp)
237: dev_t dev;
238: register struct tty *tp;
239: {
240: struct proc *p = curproc; /* XXX */
241: register struct sl_softc *sc;
242: register int nsl;
243: int error;
244:
245: if (error = suser(p->p_ucred, &p->p_acflag))
246: return (error);
247:
248: if (tp->t_line == SLIPDISC)
249: return (0);
250:
251: for (nsl = NSL, sc = sl_softc; --nsl >= 0; sc++)
252: if (sc->sc_ttyp == NULL) {
253: if (slinit(sc) == 0)
254: return (ENOBUFS);
255: tp->t_sc = (caddr_t)sc;
256: sc->sc_ttyp = tp;
257: sc->sc_if.if_baudrate = tp->t_ospeed;
258: ttyflush(tp, FREAD | FWRITE);
259: return (0);
260: }
261: return (ENXIO);
262: }
263:
264: /*
265: * Line specific close routine.
266: * Detach the tty from the sl unit.
267: * Mimics part of ttyclose().
268: */
269: slclose(tp)
270: struct tty *tp;
271: {
272: register struct sl_softc *sc;
273: int s;
274:
275: ttywflush(tp);
276: s = splimp(); /* actually, max(spltty, splnet) */
277: tp->t_line = 0;
278: sc = (struct sl_softc *)tp->t_sc;
279: if (sc != NULL) {
280: if_down(&sc->sc_if);
281: sc->sc_ttyp = NULL;
282: tp->t_sc = NULL;
283: MCLFREE((caddr_t)(sc->sc_ep - SLBUFSIZE));
284: sc->sc_ep = 0;
285: sc->sc_mp = 0;
286: sc->sc_buf = 0;
287: }
288: splx(s);
289: }
290:
291: /*
292: * Line specific (tty) ioctl routine.
293: * Provide a way to get the sl unit number.
294: */
295: /* ARGSUSED */
296: sltioctl(tp, cmd, data, flag)
297: struct tty *tp;
298: caddr_t data;
299: {
300: struct sl_softc *sc = (struct sl_softc *)tp->t_sc;
301: int s;
302:
303: switch (cmd) {
304: case SLIOCGUNIT:
305: *(int *)data = sc->sc_if.if_unit;
306: break;
307:
308: case SLIOCGFLAGS:
309: *(int *)data = sc->sc_flags;
310: break;
311:
312: case SLIOCSFLAGS:
313: #define SC_MASK 0xffff
314: s = splimp();
315: sc->sc_flags =
316: (sc->sc_flags &~ SC_MASK) | ((*(int *)data) & SC_MASK);
317: splx(s);
318: break;
319:
320: default:
321: return (-1);
322: }
323: return (0);
324: }
325:
326: /*
327: * Queue a packet. Start transmission if not active.
328: */
329: sloutput(ifp, m, dst)
330: struct ifnet *ifp;
331: register struct mbuf *m;
332: struct sockaddr *dst;
333: {
334: register struct sl_softc *sc = &sl_softc[ifp->if_unit];
335: register struct ip *ip;
336: register struct ifqueue *ifq;
337: int s;
338:
339: /*
340: * `Cannot happen' (see slioctl). Someday we will extend
341: * the line protocol to support other address families.
342: */
343: if (dst->sa_family != AF_INET) {
344: printf("sl%d: af%d not supported\n", sc->sc_if.if_unit,
345: dst->sa_family);
346: m_freem(m);
347: return (EAFNOSUPPORT);
348: }
349:
350: if (sc->sc_ttyp == NULL) {
351: m_freem(m);
352: return (ENETDOWN); /* sort of */
353: }
354: if ((sc->sc_ttyp->t_state & TS_CARR_ON) == 0) {
355: m_freem(m);
356: return (EHOSTUNREACH);
357: }
358: ifq = &sc->sc_if.if_snd;
359: if ((ip = mtod(m, struct ip *))->ip_p == IPPROTO_TCP) {
360: register int p = ((int *)ip)[ip->ip_hl];
361:
362: if (INTERACTIVE(p & 0xffff) || INTERACTIVE(p >> 16)) {
363: ifq = &sc->sc_fastq;
364: p = 1;
365: } else
366: p = 0;
367:
368: if (sc->sc_flags & SC_COMPRESS) {
369: /*
370: * The last parameter turns off connection id
371: * compression for background traffic: Since
372: * fastq traffic can jump ahead of the background
373: * traffic, we don't know what order packets will
374: * go on the line.
375: */
376: p = sl_compress_tcp(m, ip, &sc->sc_comp, p);
377: *mtod(m, u_char *) |= p;
378: }
379: } else if (sc->sc_flags & SC_NOICMP && ip->ip_p == IPPROTO_ICMP) {
380: m_freem(m);
381: return (0);
382: }
383: s = splimp();
384: if (IF_QFULL(ifq)) {
385: IF_DROP(ifq);
386: m_freem(m);
387: splx(s);
388: sc->sc_if.if_oerrors++;
389: return (ENOBUFS);
390: }
391: IF_ENQUEUE(ifq, m);
392: sc->sc_if.if_lastchange = time;
1.1.1.2 root 393: if (RB_LEN(&sc->sc_ttyp->t_out) == 0)
1.1 root 394: slstart(sc->sc_ttyp);
395: splx(s);
396: return (0);
397: }
398:
399: /*
400: * Start output on interface. Get another datagram
401: * to send from the interface queue and map it to
402: * the interface before starting output.
403: */
404: slstart(tp)
405: register struct tty *tp;
406: {
407: register struct sl_softc *sc = (struct sl_softc *)tp->t_sc;
408: register struct mbuf *m;
409: register u_char *cp;
410: int s;
411: struct mbuf *m2;
412:
413: for (;;) {
414: /*
415: * If there is more in the output queue, just send it now.
416: * We are being called in lieu of ttstart and must do what
417: * it would.
418: */
1.1.1.2 root 419: if (RB_LEN(&tp->t_out) != 0) {
1.1 root 420: (*tp->t_oproc)(tp);
1.1.1.2 root 421: if (RB_LEN(&tp->t_out) > SLIP_HIWAT)
1.1 root 422: return;
423: }
424: /*
425: * This happens briefly when the line shuts down.
426: */
427: if (sc == NULL)
428: return;
429:
430: /*
431: * Get a packet and send it to the interface.
432: */
433: s = splimp();
434: IF_DEQUEUE(&sc->sc_fastq, m);
435: if (m == NULL)
436: IF_DEQUEUE(&sc->sc_if.if_snd, m);
437: splx(s);
438: if (m == NULL)
439: return;
440: sc->sc_if.if_lastchange = time;
441: /*
442: * If system is getting low on clists, just flush our
443: * output queue (if the stuff was important, it'll get
444: * retransmitted).
445: */
1.1.1.3 ! root 446: if (RBSZ - RB_LEN(&tp->t_out) < SLMTU) {
1.1 root 447: m_freem(m);
448: sc->sc_if.if_collisions++;
449: continue;
450: }
451:
452: /*
453: * The extra FRAME_END will start up a new packet, and thus
454: * will flush any accumulated garbage. We do this whenever
455: * the line may have been idle for some time.
456: */
1.1.1.2 root 457: if (RB_LEN(&tp->t_out) == 0) {
1.1 root 458: ++sc->sc_bytessent;
1.1.1.2 root 459: (void) putc(FRAME_END, &tp->t_out);
1.1 root 460: }
461:
462: while (m) {
463: register u_char *ep;
464:
465: cp = mtod(m, u_char *); ep = cp + m->m_len;
466: while (cp < ep) {
467: /*
468: * Find out how many bytes in the string we can
469: * handle without doing something special.
470: */
471: register u_char *bp = cp;
472:
473: while (cp < ep) {
474: switch (*cp++) {
475: case FRAME_ESCAPE:
476: case FRAME_END:
477: --cp;
478: goto out;
479: }
480: }
481: out:
482: if (cp > bp) {
1.1.1.2 root 483: int cc;
1.1 root 484: /*
485: * Put n characters at once
486: * into the tty output queue.
487: */
1.1.1.2 root 488: #ifdef was
1.1 root 489: if (b_to_q((char *)bp, cp - bp, &tp->t_outq))
490: break;
1.1.1.3 ! root 491: sc->sc_bytessent += cp - bp;
1.1.1.2 root 492: #else
1.1.1.3 ! root 493: #ifdef works
1.1.1.2 root 494: if (cc = RB_CONTIGPUT(&tp->t_out)) {
495: cc = min (cc, cp - bp);
496: bcopy((char *)bp,
497: tp->t_out.rb_tl, cc);
498: tp->t_out.rb_tl =
499: RB_ROLLOVER(&tp->t_out, tp->t_out.rb_tl + cc);
1.1.1.3 ! root 500: sc->sc_bytessent += cc;
! 501: bp += cc;
1.1.1.2 root 502: } else
503: break;
1.1.1.3 ! root 504: if (cp > bp && cc = RB_CONTIGPUT(&tp->t_out)) {
! 505: cc = min (cc, cp - bp);
! 506: bcopy((char *)bp,
! 507: tp->t_out.rb_tl, cc);
! 508: tp->t_out.rb_tl =
! 509: RB_ROLLOVER(&tp->t_out, tp->t_out.rb_tl + cc);
! 510: sc->sc_bytessent += cc;
! 511: bp += cc;
! 512: } else
! 513: break;
! 514: #else
! 515: while (cp > bp && (cc = RB_CONTIGPUT(&tp->t_out))) {
! 516: cc = min (cc, cp - bp);
! 517: bcopy((char *)bp,
! 518: tp->t_out.rb_tl, cc);
! 519: tp->t_out.rb_tl =
! 520: RB_ROLLOVER(&tp->t_out, tp->t_out.rb_tl + cc);
! 521: sc->sc_bytessent += cc;
! 522: bp += cc;
! 523: }
! 524: #endif
1.1.1.2 root 525: #endif
1.1 root 526: }
527: /*
528: * If there are characters left in the mbuf,
529: * the first one must be special..
530: * Put it out in a different form.
531: */
532: if (cp < ep) {
1.1.1.2 root 533: if (putc(FRAME_ESCAPE, &tp->t_out))
1.1 root 534: break;
535: if (putc(*cp++ == FRAME_ESCAPE ?
536: TRANS_FRAME_ESCAPE : TRANS_FRAME_END,
1.1.1.2 root 537: &tp->t_out)) {
538: (void) unputc(&tp->t_out);
1.1 root 539: break;
540: }
541: sc->sc_bytessent += 2;
542: }
543: }
544: MFREE(m, m2);
545: m = m2;
546: }
547:
1.1.1.2 root 548: if (putc(FRAME_END, &tp->t_out)) {
1.1 root 549: /*
550: * Not enough room. Remove a char to make room
551: * and end the packet normally.
552: * If you get many collisions (more than one or two
553: * a day) you probably do not have enough clists
554: * and you should increase "nclist" in param.c.
555: */
1.1.1.2 root 556: (void) unputc(&tp->t_out);
557: (void) putc(FRAME_END, &tp->t_out);
1.1 root 558: sc->sc_if.if_collisions++;
559: } else {
560: ++sc->sc_bytessent;
561: sc->sc_if.if_opackets++;
562: }
563: sc->sc_if.if_obytes = sc->sc_bytessent;
564: }
565: }
566:
567: /*
568: * Copy data buffer to mbuf chain; add ifnet pointer.
569: */
570: static struct mbuf *
571: sl_btom(sc, len)
572: register struct sl_softc *sc;
573: register int len;
574: {
575: register struct mbuf *m;
576:
577: MGETHDR(m, M_DONTWAIT, MT_DATA);
578: if (m == NULL)
579: return (NULL);
580:
581: /*
582: * If we have more than MHLEN bytes, it's cheaper to
583: * queue the cluster we just filled & allocate a new one
584: * for the input buffer. Otherwise, fill the mbuf we
585: * allocated above. Note that code in the input routine
586: * guarantees that packet will fit in a cluster.
587: */
588: if (len >= MHLEN) {
589: MCLGET(m, M_DONTWAIT);
590: if ((m->m_flags & M_EXT) == 0) {
591: /*
592: * we couldn't get a cluster - if memory's this
593: * low, it's time to start dropping packets.
594: */
595: (void) m_free(m);
596: return (NULL);
597: }
598: sc->sc_ep = mtod(m, u_char *) + SLBUFSIZE;
599: m->m_data = (caddr_t)sc->sc_buf;
600: m->m_ext.ext_buf = (caddr_t)((int)sc->sc_buf &~ MCLOFSET);
601: } else
602: bcopy((caddr_t)sc->sc_buf, mtod(m, caddr_t), len);
603:
604: m->m_len = len;
605: m->m_pkthdr.len = len;
606: m->m_pkthdr.rcvif = &sc->sc_if;
607: return (m);
608: }
609:
610: /*
611: * tty interface receiver interrupt.
612: */
613: slinput(c, tp)
614: register int c;
615: register struct tty *tp;
616: {
617: register struct sl_softc *sc;
618: register struct mbuf *m;
619: register int len;
620: int s;
621:
622: tk_nin++;
623: sc = (struct sl_softc *)tp->t_sc;
624: if (sc == NULL)
625: return;
626: if (!(tp->t_state&TS_CARR_ON)) /* XXX */
627: return;
628:
629: ++sc->sc_bytesrcvd;
630: ++sc->sc_if.if_ibytes;
631: c &= 0xff; /* XXX */
632:
633: #ifdef ABT_ESC
634: if (sc->sc_flags & SC_ABORT) {
635: /* if we see an abort after "idle" time, count it */
636: if (c == ABT_ESC && time.tv_sec >= sc->sc_lasttime + ABT_WAIT) {
637: sc->sc_abortcount++;
638: /* record when the first abort escape arrived */
639: if (sc->sc_abortcount == 1)
640: sc->sc_starttime = time.tv_sec;
641: }
642: /*
643: * if we have an abort, see that we have not run out of time,
644: * or that we have an "idle" time after the complete escape
645: * sequence
646: */
647: if (sc->sc_abortcount) {
648: if (time.tv_sec >= sc->sc_starttime + ABT_RECYCLE)
649: sc->sc_abortcount = 0;
650: if (sc->sc_abortcount >= ABT_SOFT &&
651: time.tv_sec >= sc->sc_lasttime + ABT_WAIT) {
652: slclose(tp);
653: return;
654: }
655: }
656: sc->sc_lasttime = time.tv_sec;
657: }
658: #endif
659:
660: switch (c) {
661:
662: case TRANS_FRAME_ESCAPE:
663: if (sc->sc_escape)
664: c = FRAME_ESCAPE;
665: break;
666:
667: case TRANS_FRAME_END:
668: if (sc->sc_escape)
669: c = FRAME_END;
670: break;
671:
672: case FRAME_ESCAPE:
673: sc->sc_escape = 1;
674: return;
675:
676: case FRAME_END:
677: len = sc->sc_mp - sc->sc_buf;
678: if (len < 3)
679: /* less than min length packet - ignore */
680: goto newpack;
681:
682: if ((c = (*sc->sc_buf & 0xf0)) != (IPVERSION << 4)) {
683: if (c & 0x80)
684: c = TYPE_COMPRESSED_TCP;
685: else if (c == TYPE_UNCOMPRESSED_TCP)
686: *sc->sc_buf &= 0x4f; /* XXX */
687: /*
688: * We've got something that's not an IP packet.
689: * If compression is enabled, try to decompress it.
690: * Otherwise, if `auto-enable' compression is on and
691: * it's a reasonable packet, decompress it and then
692: * enable compression. Otherwise, drop it.
693: */
694: if (sc->sc_flags & SC_COMPRESS) {
695: len = sl_uncompress_tcp(&sc->sc_buf, len,
696: (u_int)c, &sc->sc_comp);
697: if (len <= 0)
698: goto error;
699: } else if ((sc->sc_flags & SC_AUTOCOMP) &&
700: c == TYPE_UNCOMPRESSED_TCP && len >= 40) {
701: len = sl_uncompress_tcp(&sc->sc_buf, len,
702: (u_int)c, &sc->sc_comp);
703: if (len <= 0)
704: goto error;
705: sc->sc_flags |= SC_COMPRESS;
706: } else
707: goto error;
708: }
709: m = sl_btom(sc, len);
710: if (m == NULL)
711: goto error;
712:
713: sc->sc_if.if_ipackets++;
714: sc->sc_if.if_lastchange = time;
715: s = splimp();
716: if (IF_QFULL(&ipintrq)) {
717: IF_DROP(&ipintrq);
718: sc->sc_if.if_ierrors++;
719: sc->sc_if.if_iqdrops++;
720: m_freem(m);
721: } else {
722: IF_ENQUEUE(&ipintrq, m);
723: schednetisr(NETISR_IP);
724: }
725: splx(s);
726: goto newpack;
727: }
728: if (sc->sc_mp < sc->sc_ep) {
729: *sc->sc_mp++ = c;
730: sc->sc_escape = 0;
731: return;
732: }
733: error:
734: sc->sc_if.if_ierrors++;
735: newpack:
736: sc->sc_mp = sc->sc_buf = sc->sc_ep - SLMAX;
737: sc->sc_escape = 0;
738: }
739:
740: /*
741: * Process an ioctl request.
742: */
743: slioctl(ifp, cmd, data)
744: register struct ifnet *ifp;
745: int cmd;
746: caddr_t data;
747: {
748: register struct ifaddr *ifa = (struct ifaddr *)data;
749: int s = splimp(), error = 0;
750:
751: switch (cmd) {
752:
753: case SIOCSIFADDR:
754: if (ifa->ifa_addr->sa_family == AF_INET)
755: ifp->if_flags |= IFF_UP;
756: else
757: error = EAFNOSUPPORT;
758: break;
759:
760: case SIOCSIFDSTADDR:
761: if (ifa->ifa_addr->sa_family != AF_INET)
762: error = EAFNOSUPPORT;
763: break;
764:
765: default:
766: error = EINVAL;
767: }
768: splx(s);
769: return (error);
770: }
771: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.