|
|
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:
67: /* $Header: if_sl.c,v 1.7 89/05/31 02:24:52 van Exp $ */
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;
393: if (sc->sc_ttyp->t_outq.c_cc == 0)
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: extern int cfreecount;
413:
414: for (;;) {
415: /*
416: * If there is more in the output queue, just send it now.
417: * We are being called in lieu of ttstart and must do what
418: * it would.
419: */
420: if (tp->t_outq.c_cc != 0) {
421: (*tp->t_oproc)(tp);
422: if (tp->t_outq.c_cc > SLIP_HIWAT)
423: return;
424: }
425: /*
426: * This happens briefly when the line shuts down.
427: */
428: if (sc == NULL)
429: return;
430:
431: /*
432: * Get a packet and send it to the interface.
433: */
434: s = splimp();
435: IF_DEQUEUE(&sc->sc_fastq, m);
436: if (m == NULL)
437: IF_DEQUEUE(&sc->sc_if.if_snd, m);
438: splx(s);
439: if (m == NULL)
440: return;
441: sc->sc_if.if_lastchange = time;
442: /*
443: * If system is getting low on clists, just flush our
444: * output queue (if the stuff was important, it'll get
445: * retransmitted).
446: */
447: if (cfreecount < CLISTRESERVE + SLMTU) {
448: m_freem(m);
449: sc->sc_if.if_collisions++;
450: continue;
451: }
452:
453: /*
454: * The extra FRAME_END will start up a new packet, and thus
455: * will flush any accumulated garbage. We do this whenever
456: * the line may have been idle for some time.
457: */
458: if (tp->t_outq.c_cc == 0) {
459: ++sc->sc_bytessent;
460: (void) putc(FRAME_END, &tp->t_outq);
461: }
462:
463: while (m) {
464: register u_char *ep;
465:
466: cp = mtod(m, u_char *); ep = cp + m->m_len;
467: while (cp < ep) {
468: /*
469: * Find out how many bytes in the string we can
470: * handle without doing something special.
471: */
472: register u_char *bp = cp;
473:
474: while (cp < ep) {
475: switch (*cp++) {
476: case FRAME_ESCAPE:
477: case FRAME_END:
478: --cp;
479: goto out;
480: }
481: }
482: out:
483: if (cp > bp) {
484: /*
485: * Put n characters at once
486: * into the tty output queue.
487: */
488: if (b_to_q((char *)bp, cp - bp, &tp->t_outq))
489: break;
490: sc->sc_bytessent += cp - bp;
491: }
492: /*
493: * If there are characters left in the mbuf,
494: * the first one must be special..
495: * Put it out in a different form.
496: */
497: if (cp < ep) {
498: if (putc(FRAME_ESCAPE, &tp->t_outq))
499: break;
500: if (putc(*cp++ == FRAME_ESCAPE ?
501: TRANS_FRAME_ESCAPE : TRANS_FRAME_END,
502: &tp->t_outq)) {
503: (void) unputc(&tp->t_outq);
504: break;
505: }
506: sc->sc_bytessent += 2;
507: }
508: }
509: MFREE(m, m2);
510: m = m2;
511: }
512:
513: if (putc(FRAME_END, &tp->t_outq)) {
514: /*
515: * Not enough room. Remove a char to make room
516: * and end the packet normally.
517: * If you get many collisions (more than one or two
518: * a day) you probably do not have enough clists
519: * and you should increase "nclist" in param.c.
520: */
521: (void) unputc(&tp->t_outq);
522: (void) putc(FRAME_END, &tp->t_outq);
523: sc->sc_if.if_collisions++;
524: } else {
525: ++sc->sc_bytessent;
526: sc->sc_if.if_opackets++;
527: }
528: sc->sc_if.if_obytes = sc->sc_bytessent;
529: }
530: }
531:
532: /*
533: * Copy data buffer to mbuf chain; add ifnet pointer.
534: */
535: static struct mbuf *
536: sl_btom(sc, len)
537: register struct sl_softc *sc;
538: register int len;
539: {
540: register struct mbuf *m;
541:
542: MGETHDR(m, M_DONTWAIT, MT_DATA);
543: if (m == NULL)
544: return (NULL);
545:
546: /*
547: * If we have more than MHLEN bytes, it's cheaper to
548: * queue the cluster we just filled & allocate a new one
549: * for the input buffer. Otherwise, fill the mbuf we
550: * allocated above. Note that code in the input routine
551: * guarantees that packet will fit in a cluster.
552: */
553: if (len >= MHLEN) {
554: MCLGET(m, M_DONTWAIT);
555: if ((m->m_flags & M_EXT) == 0) {
556: /*
557: * we couldn't get a cluster - if memory's this
558: * low, it's time to start dropping packets.
559: */
560: (void) m_free(m);
561: return (NULL);
562: }
563: sc->sc_ep = mtod(m, u_char *) + SLBUFSIZE;
564: m->m_data = (caddr_t)sc->sc_buf;
565: m->m_ext.ext_buf = (caddr_t)((int)sc->sc_buf &~ MCLOFSET);
566: } else
567: bcopy((caddr_t)sc->sc_buf, mtod(m, caddr_t), len);
568:
569: m->m_len = len;
570: m->m_pkthdr.len = len;
571: m->m_pkthdr.rcvif = &sc->sc_if;
572: return (m);
573: }
574:
575: /*
576: * tty interface receiver interrupt.
577: */
578: slinput(c, tp)
579: register int c;
580: register struct tty *tp;
581: {
582: register struct sl_softc *sc;
583: register struct mbuf *m;
584: register int len;
585: int s;
586:
587: tk_nin++;
588: sc = (struct sl_softc *)tp->t_sc;
589: if (sc == NULL)
590: return;
591: if (!(tp->t_state&TS_CARR_ON)) /* XXX */
592: return;
593:
594: ++sc->sc_bytesrcvd;
595: ++sc->sc_if.if_ibytes;
596: c &= 0xff; /* XXX */
597:
598: #ifdef ABT_ESC
599: if (sc->sc_flags & SC_ABORT) {
600: /* if we see an abort after "idle" time, count it */
601: if (c == ABT_ESC && time.tv_sec >= sc->sc_lasttime + ABT_WAIT) {
602: sc->sc_abortcount++;
603: /* record when the first abort escape arrived */
604: if (sc->sc_abortcount == 1)
605: sc->sc_starttime = time.tv_sec;
606: }
607: /*
608: * if we have an abort, see that we have not run out of time,
609: * or that we have an "idle" time after the complete escape
610: * sequence
611: */
612: if (sc->sc_abortcount) {
613: if (time.tv_sec >= sc->sc_starttime + ABT_RECYCLE)
614: sc->sc_abortcount = 0;
615: if (sc->sc_abortcount >= ABT_SOFT &&
616: time.tv_sec >= sc->sc_lasttime + ABT_WAIT) {
617: slclose(tp);
618: return;
619: }
620: }
621: sc->sc_lasttime = time.tv_sec;
622: }
623: #endif
624:
625: switch (c) {
626:
627: case TRANS_FRAME_ESCAPE:
628: if (sc->sc_escape)
629: c = FRAME_ESCAPE;
630: break;
631:
632: case TRANS_FRAME_END:
633: if (sc->sc_escape)
634: c = FRAME_END;
635: break;
636:
637: case FRAME_ESCAPE:
638: sc->sc_escape = 1;
639: return;
640:
641: case FRAME_END:
642: len = sc->sc_mp - sc->sc_buf;
643: if (len < 3)
644: /* less than min length packet - ignore */
645: goto newpack;
646:
647: if ((c = (*sc->sc_buf & 0xf0)) != (IPVERSION << 4)) {
648: if (c & 0x80)
649: c = TYPE_COMPRESSED_TCP;
650: else if (c == TYPE_UNCOMPRESSED_TCP)
651: *sc->sc_buf &= 0x4f; /* XXX */
652: /*
653: * We've got something that's not an IP packet.
654: * If compression is enabled, try to decompress it.
655: * Otherwise, if `auto-enable' compression is on and
656: * it's a reasonable packet, decompress it and then
657: * enable compression. Otherwise, drop it.
658: */
659: if (sc->sc_flags & SC_COMPRESS) {
660: len = sl_uncompress_tcp(&sc->sc_buf, len,
661: (u_int)c, &sc->sc_comp);
662: if (len <= 0)
663: goto error;
664: } else if ((sc->sc_flags & SC_AUTOCOMP) &&
665: c == TYPE_UNCOMPRESSED_TCP && len >= 40) {
666: len = sl_uncompress_tcp(&sc->sc_buf, len,
667: (u_int)c, &sc->sc_comp);
668: if (len <= 0)
669: goto error;
670: sc->sc_flags |= SC_COMPRESS;
671: } else
672: goto error;
673: }
674: m = sl_btom(sc, len);
675: if (m == NULL)
676: goto error;
677:
678: sc->sc_if.if_ipackets++;
679: sc->sc_if.if_lastchange = time;
680: s = splimp();
681: if (IF_QFULL(&ipintrq)) {
682: IF_DROP(&ipintrq);
683: sc->sc_if.if_ierrors++;
684: sc->sc_if.if_iqdrops++;
685: m_freem(m);
686: } else {
687: IF_ENQUEUE(&ipintrq, m);
688: schednetisr(NETISR_IP);
689: }
690: splx(s);
691: goto newpack;
692: }
693: if (sc->sc_mp < sc->sc_ep) {
694: *sc->sc_mp++ = c;
695: sc->sc_escape = 0;
696: return;
697: }
698: error:
699: sc->sc_if.if_ierrors++;
700: newpack:
701: sc->sc_mp = sc->sc_buf = sc->sc_ep - SLMAX;
702: sc->sc_escape = 0;
703: }
704:
705: /*
706: * Process an ioctl request.
707: */
708: slioctl(ifp, cmd, data)
709: register struct ifnet *ifp;
710: int cmd;
711: caddr_t data;
712: {
713: register struct ifaddr *ifa = (struct ifaddr *)data;
714: int s = splimp(), error = 0;
715:
716: switch (cmd) {
717:
718: case SIOCSIFADDR:
719: if (ifa->ifa_addr->sa_family == AF_INET)
720: ifp->if_flags |= IFF_UP;
721: else
722: error = EAFNOSUPPORT;
723: break;
724:
725: case SIOCSIFDSTADDR:
726: if (ifa->ifa_addr->sa_family != AF_INET)
727: error = EAFNOSUPPORT;
728: break;
729:
730: default:
731: error = EINVAL;
732: }
733: splx(s);
734: return (error);
735: }
736: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.