]>
git.saurik.com Git - apple/xnu.git/blob - bsd/net/if_sl.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
24 * Copyright (c) 1987, 1989, 1992, 1993
25 * The Regents of the University of California. All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
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.
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
55 * @(#)if_sl.c 8.9 (Berkeley) 1/9/95
59 * Serial Line interface
62 * Center for Seismic Studies
63 * 1300 N 17th Street, Suite 1450
64 * Arlington, Virginia 22209
69 * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, 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.
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.
78 * Hacked almost beyond recognition by Van Jacobson (van@helios.ee.lbl.gov).
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.
85 * Note that splimp() is used throughout to block both (tty) input
86 * interrupts and network activity; thus, splimp must be >= spltty.
94 #include <sys/param.h>
98 #include <sys/dkstat.h>
99 #include <sys/socket.h>
100 #include <sys/ioctl.h>
101 #include <sys/file.h>
103 #include <sys/kernel.h>
104 #include <sys/conf.h>
106 #include <kern/cpu_number.h>
109 #include <net/if_types.h>
110 #include <net/netisr.h>
111 #include <net/route.h>
114 #include <netinet/in.h>
115 #include <netinet/in_systm.h>
116 #include <netinet/in_var.h>
117 #include <netinet/ip.h>
119 Huh
? Slip without inet
?
122 #include <net/slcompress.h>
123 #include <net/if_slvar.h>
124 #include <net/slip.h>
127 #include <sys/time.h>
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
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).
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.
172 #define BUFOFFSET (128+sizeof(struct ifnet **)+SLIP_HDRLEN)
174 #define BUFOFFSET (128+sizeof(struct ifnet **))
176 #define SLMAX (MCLBYTES - BUFOFFSET)
177 #define SLBUFSIZE (SLMAX + BUFOFFSET)
179 #define SLIP_HIWAT roundup(50,CBSIZE)
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.
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 */
193 struct sl_softc sl_softc
[NSL
];
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 */
200 static int slinit
__P((struct sl_softc
*));
201 static struct mbuf
*sl_btom
__P((struct sl_softc
*, int));
204 * Called from boot code to establish sl interfaces.
209 register struct sl_softc
*sc
;
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
;
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
);
227 bpfattach(&sc
->sc_bpf
, &sc
->sc_if
, DLT_SLIP
, SLIP_HDRLEN
);
234 register struct sl_softc
*sc
;
238 if (sc
->sc_ep
== (u_char
*) 0) {
241 sc
->sc_ep
= (u_char
*)p
+ SLBUFSIZE
;
243 printf("sl%d: can't allocate buffer\n", sc
- sl_softc
);
244 sc
->sc_if
.if_flags
&= ~IFF_UP
;
248 sc
->sc_buf
= sc
->sc_ep
- SLMAX
;
249 sc
->sc_mp
= sc
->sc_buf
;
250 sl_compress_init(&sc
->sc_comp
, -1);
255 * Line specific open routine.
256 * Attach the given tty to the first available sl unit.
262 register struct tty
*tp
;
264 struct proc
*p
= curproc
; /* XXX */
265 register struct sl_softc
*sc
;
270 if (error
= suser(p
->p_ucred
, &p
->p_acflag
))
273 if (tp
->t_line
== SLIPDISC
)
276 for (nsl
= NSL
, sc
= sl_softc
; --nsl
>= 0; sc
++)
277 if (sc
->sc_ttyp
== NULL
) {
280 tp
->t_sc
= (caddr_t
)sc
;
282 sc
->sc_if
.if_baudrate
= tp
->t_ospeed
;
283 ttyflush(tp
, FREAD
| FWRITE
);
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
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;
299 error
= clalloc(&tp
->t_outq
, 3*SLMTU
, 0);
305 sc
->sc_oldbufsize
= sc
->sc_oldbufquot
= 0;
314 * Line specific close routine.
315 * Detach the tty from the sl unit.
321 register struct sl_softc
*sc
;
325 s
= splimp(); /* actually, max(spltty, splnet) */
328 sc
= (struct sl_softc
*)tp
->t_sc
;
333 MCLFREE((caddr_t
)(sc
->sc_ep
- SLBUFSIZE
));
338 /* if necessary, install a new outq buffer of the appropriate size */
339 if (sc
->sc_oldbufsize
!= 0) {
341 clalloc(&tp
->t_outq
, sc
->sc_oldbufsize
, sc
->sc_oldbufquot
);
347 * Line specific (tty) ioctl routine.
348 * Provide a way to get the sl unit number.
352 sltioctl(tp
, cmd
, data
, flag
)
358 struct sl_softc
*sc
= (struct sl_softc
*)tp
->t_sc
;
362 *(int *)data
= sc
->sc_if
.if_unit
;
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.
378 sloutput(ifp
, m
, dst
, rtp
)
380 register struct mbuf
*m
;
381 struct sockaddr
*dst
;
384 register struct sl_softc
*sc
= &sl_softc
[ifp
->if_unit
];
385 register struct ip
*ip
;
386 register struct ifqueue
*ifq
;
390 * `Cannot happen' (see slioctl). Someday we will extend
391 * the line protocol to support other address families.
393 if (dst
->sa_family
!= AF_INET
) {
394 printf("sl%d: af%d not supported\n", sc
->sc_if
.if_unit
,
397 sc
->sc_if
.if_noproto
++;
398 return (EAFNOSUPPORT
);
401 if (sc
->sc_ttyp
== NULL
) {
403 return (ENETDOWN
); /* sort of */
405 if ((sc
->sc_ttyp
->t_state
& TS_CARR_ON
) == 0 &&
406 (sc
->sc_ttyp
->t_cflag
& CLOCAL
) == 0) {
408 return (EHOSTUNREACH
);
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
) {
414 return (ENETRESET
); /* XXX ? */
416 if (ip
->ip_tos
& IPTOS_LOWDELAY
)
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
);
424 slstart(sc
->sc_ttyp
);
431 sc
->sc_if
.if_oerrors
++;
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
);
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.
449 register struct tty
*tp
;
451 register struct sl_softc
*sc
= (struct sl_softc
*)tp
->t_sc
;
452 register struct mbuf
*m
;
454 register struct ip
*ip
;
458 u_char bpfbuf
[SLMTU
+ SLIP_HDRLEN
];
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
468 if (tp
->t_outq
.c_cc
!= 0) {
470 if (tp
->t_outq
.c_cc
> SLIP_HIWAT
)
474 * This happens briefly when the line shuts down.
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.
485 if (tp
->t_outq
.c_cn
- tp
->t_outq
.c_cc
< 2*SLMTU
+2)
489 * Get a packet and send it to the interface.
492 IF_DEQUEUE(&sc
->sc_fastq
, m
);
494 sc
->sc_if
.if_omcasts
++; /* XXX */
496 IF_DEQUEUE(&sc
->sc_if
.if_snd
, m
);
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.
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).
517 register struct mbuf
*m1
= m
;
518 register u_char
*cp
= bpfbuf
+ SLIP_HDRLEN
;
522 register int mlen
= m1
->m_len
;
524 bcopy(mtod(m1
, caddr_t
), cp
, mlen
);
527 } while (m1
= m1
->m_next
);
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
,
538 * Put the SLIP pseudo-"link header" in place. The
539 * compressed header is now at the beginning of the
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
);
547 sc
->sc_if
.if_lastchange
= time
;
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.
554 if (tp
->t_outq
.c_cc
== 0) {
555 ++sc
->sc_if
.if_obytes
;
556 (void) putc(FRAME_END
, &tp
->t_outq
);
562 cp
= mtod(m
, u_char
*); ep
= cp
+ m
->m_len
;
565 * Find out how many bytes in the string we can
566 * handle without doing something special.
568 register u_char
*bp
= cp
;
581 * Put n characters at once
582 * into the tty output queue.
584 if (b_to_q((u_char
*)bp
, cp
- bp
,
587 sc
->sc_if
.if_obytes
+= cp
- bp
;
590 * If there are characters left in the mbuf,
591 * the first one must be special..
592 * Put it out in a different form.
595 if (putc(FRAME_ESCAPE
, &tp
->t_outq
))
597 if (putc(*cp
++ == FRAME_ESCAPE
?
598 TRANS_FRAME_ESCAPE
: TRANS_FRAME_END
,
600 (void) unputc(&tp
->t_outq
);
603 sc
->sc_if
.if_obytes
+= 2;
610 if (putc(FRAME_END
, &tp
->t_outq
)) {
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.
618 (void) unputc(&tp
->t_outq
);
619 (void) putc(FRAME_END
, &tp
->t_outq
);
620 sc
->sc_if
.if_collisions
++;
622 ++sc
->sc_if
.if_obytes
;
623 sc
->sc_if
.if_opackets
++;
629 * Copy data buffer to mbuf chain; add ifnet pointer.
633 register struct sl_softc
*sc
;
636 register struct mbuf
*m
;
638 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
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.
650 MCLGET(m
, M_DONTWAIT
);
651 if ((m
->m_flags
& M_EXT
) == 0) {
653 * we couldn't get a cluster - if memory's this
654 * low, it's time to start dropping packets.
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
);
663 bcopy((caddr_t
)sc
->sc_buf
, mtod(m
, caddr_t
), len
);
666 m
->m_pkthdr
.len
= len
;
667 m
->m_pkthdr
.rcvif
= &sc
->sc_if
;
672 * tty interface receiver interrupt.
677 register struct tty
*tp
;
679 register struct sl_softc
*sc
;
680 register struct mbuf
*m
;
684 u_char chdr
[CHDR_LEN
];
688 sc
= (struct sl_softc
*)tp
->t_sc
;
691 if (c
& TTY_ERRORMASK
|| ((tp
->t_state
& TS_CARR_ON
) == 0 &&
692 (tp
->t_cflag
& CLOCAL
) == 0)) {
693 sc
->sc_flags
|= SC_ERROR
;
698 ++sc
->sc_if
.if_ibytes
;
700 if (sc
->sc_if
.if_flags
& IFF_DEBUG
) {
704 * If we have a previous abort, see whether
705 * this one is within the time limit.
707 if (sc
->sc_abortcount
&&
708 time
.tv_sec
>= sc
->sc_starttime
+ ABT_WINDOW
)
709 sc
->sc_abortcount
= 0;
711 * If we see an abort after "idle" time, count it;
712 * record when the first abort escape arrived.
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
) {
723 sc
->sc_abortcount
= 0;
724 sc
->sc_lasttime
= time
.tv_sec
;
729 case TRANS_FRAME_ESCAPE
:
734 case TRANS_FRAME_END
:
744 if(sc
->sc_flags
& SC_ERROR
) {
745 sc
->sc_flags
&= ~SC_ERROR
;
748 len
= sc
->sc_mp
- sc
->sc_buf
;
750 /* less than min length packet - ignore */
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.
763 bcopy(sc
->sc_buf
, chdr
, CHDR_LEN
);
767 if ((c
= (*sc
->sc_buf
& 0xf0)) != (IPVERSION
<< 4)) {
769 c
= TYPE_COMPRESSED_TCP
;
770 else if (c
== TYPE_UNCOMPRESSED_TCP
)
771 *sc
->sc_buf
&= 0x4f; /* XXX */
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.
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
);
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
);
790 sc
->sc_if
.if_flags
|= SC_COMPRESS
;
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.
802 register u_char
*hp
= sc
->sc_buf
- SLIP_HDRLEN
;
804 hp
[SLX_DIR
] = SLIPDIR_IN
;
805 bcopy(chdr
, &hp
[SLX_CHDR
], CHDR_LEN
);
806 BPF_TAP(sc
->sc_bpf
, hp
, len
+ SLIP_HDRLEN
);
809 m
= sl_btom(sc
, len
);
813 sc
->sc_if
.if_ipackets
++;
814 sc
->sc_if
.if_lastchange
= time
;
816 if (IF_QFULL(&ipintrq
)) {
818 sc
->sc_if
.if_ierrors
++;
819 sc
->sc_if
.if_iqdrops
++;
822 IF_ENQUEUE(&ipintrq
, m
);
823 schednetisr(NETISR_IP
);
828 if (sc
->sc_mp
< sc
->sc_ep
) {
834 /* can't put lower; would miss an extra frame */
835 sc
->sc_flags
|= SC_ERROR
;
838 sc
->sc_if
.if_ierrors
++;
840 sc
->sc_mp
= sc
->sc_buf
= sc
->sc_ep
- SLMAX
;
845 * Process an ioctl request.
848 slioctl(ifp
, cmd
, data
)
849 register struct ifnet
*ifp
;
853 register struct ifaddr
*ifa
= (struct ifaddr
*)data
;
854 register struct ifreq
*ifr
;
855 register int s
= splimp(), error
= 0;
860 if (ifa
->ifa_addr
->sa_family
== AF_INET
)
861 ifp
->if_flags
|= IFF_UP
;
863 error
= EAFNOSUPPORT
;
867 if (ifa
->ifa_addr
->sa_family
!= AF_INET
)
868 error
= EAFNOSUPPORT
;
873 ifr
= (struct ifreq
*)data
;
875 error
= EAFNOSUPPORT
; /* XXX */
878 switch (ifr
->ifr_addr
.sa_family
) {
886 error
= EAFNOSUPPORT
;