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