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