|
|
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.2 ! root 446: if (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.2 ! root 491: #else
! 492: if (cc = RB_CONTIGPUT(&tp->t_out)) {
! 493: cc = min (cc, cp - bp);
! 494: bcopy((char *)bp,
! 495: tp->t_out.rb_tl, cc);
! 496: tp->t_out.rb_tl =
! 497: RB_ROLLOVER(&tp->t_out, tp->t_out.rb_tl + cc);
! 498: } else
! 499: break;
! 500: #endif
1.1 root 501: sc->sc_bytessent += cp - bp;
502: }
503: /*
504: * If there are characters left in the mbuf,
505: * the first one must be special..
506: * Put it out in a different form.
507: */
508: if (cp < ep) {
1.1.1.2 ! root 509: if (putc(FRAME_ESCAPE, &tp->t_out))
1.1 root 510: break;
511: if (putc(*cp++ == FRAME_ESCAPE ?
512: TRANS_FRAME_ESCAPE : TRANS_FRAME_END,
1.1.1.2 ! root 513: &tp->t_out)) {
! 514: (void) unputc(&tp->t_out);
1.1 root 515: break;
516: }
517: sc->sc_bytessent += 2;
518: }
519: }
520: MFREE(m, m2);
521: m = m2;
522: }
523:
1.1.1.2 ! root 524: if (putc(FRAME_END, &tp->t_out)) {
1.1 root 525: /*
526: * Not enough room. Remove a char to make room
527: * and end the packet normally.
528: * If you get many collisions (more than one or two
529: * a day) you probably do not have enough clists
530: * and you should increase "nclist" in param.c.
531: */
1.1.1.2 ! root 532: (void) unputc(&tp->t_out);
! 533: (void) putc(FRAME_END, &tp->t_out);
1.1 root 534: sc->sc_if.if_collisions++;
535: } else {
536: ++sc->sc_bytessent;
537: sc->sc_if.if_opackets++;
538: }
539: sc->sc_if.if_obytes = sc->sc_bytessent;
540: }
541: }
542:
543: /*
544: * Copy data buffer to mbuf chain; add ifnet pointer.
545: */
546: static struct mbuf *
547: sl_btom(sc, len)
548: register struct sl_softc *sc;
549: register int len;
550: {
551: register struct mbuf *m;
552:
553: MGETHDR(m, M_DONTWAIT, MT_DATA);
554: if (m == NULL)
555: return (NULL);
556:
557: /*
558: * If we have more than MHLEN bytes, it's cheaper to
559: * queue the cluster we just filled & allocate a new one
560: * for the input buffer. Otherwise, fill the mbuf we
561: * allocated above. Note that code in the input routine
562: * guarantees that packet will fit in a cluster.
563: */
564: if (len >= MHLEN) {
565: MCLGET(m, M_DONTWAIT);
566: if ((m->m_flags & M_EXT) == 0) {
567: /*
568: * we couldn't get a cluster - if memory's this
569: * low, it's time to start dropping packets.
570: */
571: (void) m_free(m);
572: return (NULL);
573: }
574: sc->sc_ep = mtod(m, u_char *) + SLBUFSIZE;
575: m->m_data = (caddr_t)sc->sc_buf;
576: m->m_ext.ext_buf = (caddr_t)((int)sc->sc_buf &~ MCLOFSET);
577: } else
578: bcopy((caddr_t)sc->sc_buf, mtod(m, caddr_t), len);
579:
580: m->m_len = len;
581: m->m_pkthdr.len = len;
582: m->m_pkthdr.rcvif = &sc->sc_if;
583: return (m);
584: }
585:
586: /*
587: * tty interface receiver interrupt.
588: */
589: slinput(c, tp)
590: register int c;
591: register struct tty *tp;
592: {
593: register struct sl_softc *sc;
594: register struct mbuf *m;
595: register int len;
596: int s;
597:
598: tk_nin++;
599: sc = (struct sl_softc *)tp->t_sc;
600: if (sc == NULL)
601: return;
602: if (!(tp->t_state&TS_CARR_ON)) /* XXX */
603: return;
604:
605: ++sc->sc_bytesrcvd;
606: ++sc->sc_if.if_ibytes;
607: c &= 0xff; /* XXX */
608:
609: #ifdef ABT_ESC
610: if (sc->sc_flags & SC_ABORT) {
611: /* if we see an abort after "idle" time, count it */
612: if (c == ABT_ESC && time.tv_sec >= sc->sc_lasttime + ABT_WAIT) {
613: sc->sc_abortcount++;
614: /* record when the first abort escape arrived */
615: if (sc->sc_abortcount == 1)
616: sc->sc_starttime = time.tv_sec;
617: }
618: /*
619: * if we have an abort, see that we have not run out of time,
620: * or that we have an "idle" time after the complete escape
621: * sequence
622: */
623: if (sc->sc_abortcount) {
624: if (time.tv_sec >= sc->sc_starttime + ABT_RECYCLE)
625: sc->sc_abortcount = 0;
626: if (sc->sc_abortcount >= ABT_SOFT &&
627: time.tv_sec >= sc->sc_lasttime + ABT_WAIT) {
628: slclose(tp);
629: return;
630: }
631: }
632: sc->sc_lasttime = time.tv_sec;
633: }
634: #endif
635:
636: switch (c) {
637:
638: case TRANS_FRAME_ESCAPE:
639: if (sc->sc_escape)
640: c = FRAME_ESCAPE;
641: break;
642:
643: case TRANS_FRAME_END:
644: if (sc->sc_escape)
645: c = FRAME_END;
646: break;
647:
648: case FRAME_ESCAPE:
649: sc->sc_escape = 1;
650: return;
651:
652: case FRAME_END:
653: len = sc->sc_mp - sc->sc_buf;
654: if (len < 3)
655: /* less than min length packet - ignore */
656: goto newpack;
657:
658: if ((c = (*sc->sc_buf & 0xf0)) != (IPVERSION << 4)) {
659: if (c & 0x80)
660: c = TYPE_COMPRESSED_TCP;
661: else if (c == TYPE_UNCOMPRESSED_TCP)
662: *sc->sc_buf &= 0x4f; /* XXX */
663: /*
664: * We've got something that's not an IP packet.
665: * If compression is enabled, try to decompress it.
666: * Otherwise, if `auto-enable' compression is on and
667: * it's a reasonable packet, decompress it and then
668: * enable compression. Otherwise, drop it.
669: */
670: if (sc->sc_flags & SC_COMPRESS) {
671: len = sl_uncompress_tcp(&sc->sc_buf, len,
672: (u_int)c, &sc->sc_comp);
673: if (len <= 0)
674: goto error;
675: } else if ((sc->sc_flags & SC_AUTOCOMP) &&
676: c == TYPE_UNCOMPRESSED_TCP && len >= 40) {
677: len = sl_uncompress_tcp(&sc->sc_buf, len,
678: (u_int)c, &sc->sc_comp);
679: if (len <= 0)
680: goto error;
681: sc->sc_flags |= SC_COMPRESS;
682: } else
683: goto error;
684: }
685: m = sl_btom(sc, len);
686: if (m == NULL)
687: goto error;
688:
689: sc->sc_if.if_ipackets++;
690: sc->sc_if.if_lastchange = time;
691: s = splimp();
692: if (IF_QFULL(&ipintrq)) {
693: IF_DROP(&ipintrq);
694: sc->sc_if.if_ierrors++;
695: sc->sc_if.if_iqdrops++;
696: m_freem(m);
697: } else {
698: IF_ENQUEUE(&ipintrq, m);
699: schednetisr(NETISR_IP);
700: }
701: splx(s);
702: goto newpack;
703: }
704: if (sc->sc_mp < sc->sc_ep) {
705: *sc->sc_mp++ = c;
706: sc->sc_escape = 0;
707: return;
708: }
709: error:
710: sc->sc_if.if_ierrors++;
711: newpack:
712: sc->sc_mp = sc->sc_buf = sc->sc_ep - SLMAX;
713: sc->sc_escape = 0;
714: }
715:
716: /*
717: * Process an ioctl request.
718: */
719: slioctl(ifp, cmd, data)
720: register struct ifnet *ifp;
721: int cmd;
722: caddr_t data;
723: {
724: register struct ifaddr *ifa = (struct ifaddr *)data;
725: int s = splimp(), error = 0;
726:
727: switch (cmd) {
728:
729: case SIOCSIFADDR:
730: if (ifa->ifa_addr->sa_family == AF_INET)
731: ifp->if_flags |= IFF_UP;
732: else
733: error = EAFNOSUPPORT;
734: break;
735:
736: case SIOCSIFDSTADDR:
737: if (ifa->ifa_addr->sa_family != AF_INET)
738: error = EAFNOSUPPORT;
739: break;
740:
741: default:
742: error = EINVAL;
743: }
744: splx(s);
745: return (error);
746: }
747: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.