|
|
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.