1 /* 2 * Copyright (c) 1987, 1989, 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)if_sl.c 8.9 (Berkeley) 01/09/95 8 */ 9 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 * 21 * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris). 22 * N.B.: this belongs in netinet, not net, the way it stands now. 23 * Should have a link-layer type designation, but wouldn't be 24 * backwards-compatible. 25 * 26 * Converted to 4.3BSD Beta by Chris Torek. 27 * Other changes made at Berkeley, based in part on code by Kirk Smith. 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. 39 */ 40 41 #include "sl.h" 42 #if NSL > 0 43 44 #include "bpfilter.h" 45 46 #include <sys/param.h> 47 #include <sys/proc.h> 48 #include <sys/mbuf.h> 49 #include <sys/buf.h> 50 #include <sys/dkstat.h> 51 #include <sys/socket.h> 52 #include <sys/ioctl.h> 53 #include <sys/file.h> 54 #include <sys/tty.h> 55 #include <sys/kernel.h> 56 #include <sys/conf.h> 57 58 #include <machine/cpu.h> 59 60 #include <net/if.h> 61 #include <net/if_types.h> 62 #include <net/netisr.h> 63 #include <net/route.h> 64 65 #if INET 66 #include <netinet/in.h> 67 #include <netinet/in_systm.h> 68 #include <netinet/in_var.h> 69 #include <netinet/ip.h> 70 #else 71 Huh? Slip without inet? 72 #endif 73 74 #include <net/slcompress.h> 75 #include <net/if_slvar.h> 76 #include <net/slip.h> 77 78 #if NBPFILTER > 0 79 #include <sys/time.h> 80 #include <net/bpf.h> 81 #endif 82 83 /* 84 * SLMAX is a hard limit on input packet size. To simplify the code 85 * and improve performance, we require that packets fit in an mbuf 86 * cluster, and if we get a compressed packet, there's enough extra 87 * room to expand the header into a max length tcp/ip header (128 88 * bytes). So, SLMAX can be at most 89 * MCLBYTES - 128 90 * 91 * SLMTU is a hard limit on output packet size. To insure good 92 * interactive response, SLMTU wants to be the smallest size that 93 * amortizes the header cost. (Remember that even with 94 * type-of-service queuing, we have to wait for any in-progress 95 * packet to finish. I.e., we wait, on the average, 1/2 * mtu / 96 * cps, where cps is the line speed in characters per second. 97 * E.g., 533ms wait for a 1024 byte MTU on a 9600 baud line. The 98 * average compressed header size is 6-8 bytes so any MTU > 90 99 * bytes will give us 90% of the line bandwidth. A 100ms wait is 100 * tolerable (500ms is not), so want an MTU around 296. (Since TCP 101 * will send 256 byte segments (to allow for 40 byte headers), the 102 * typical packet size on the wire will be around 260 bytes). In 103 * 4.3tahoe+ systems, we can set an MTU in a route so we do that & 104 * leave the interface MTU relatively high (so we don't IP fragment 105 * when acting as a gateway to someone using a stupid MTU). 106 * 107 * Similar considerations apply to SLIP_HIWAT: It's the amount of 108 * data that will be queued 'downstream' of us (i.e., in clists 109 * waiting to be picked up by the tty output interrupt). If we 110 * queue a lot of data downstream, it's immune to our t.o.s. queuing. 111 * E.g., if SLIP_HIWAT is 1024, the interactive traffic in mixed 112 * telnet/ftp will see a 1 sec wait, independent of the mtu (the 113 * wait is dependent on the ftp window size but that's typically 114 * 1k - 4k). So, we want SLIP_HIWAT just big enough to amortize 115 * the cost (in idle time on the wire) of the tty driver running 116 * off the end of its clists & having to call back slstart for a 117 * new packet. For a tty interface with any buffering at all, this 118 * cost will be zero. Even with a totally brain dead interface (like 119 * the one on a typical workstation), the cost will be <= 1 character 120 * time. So, setting SLIP_HIWAT to ~100 guarantees that we'll lose 121 * at most 1% while maintaining good interactive response. 122 */ 123 #if NBPFILTER > 0 124 #define BUFOFFSET (128+sizeof(struct ifnet **)+SLIP_HDRLEN) 125 #else 126 #define BUFOFFSET (128+sizeof(struct ifnet **)) 127 #endif 128 #define SLMAX (MCLBYTES - BUFOFFSET) 129 #define SLBUFSIZE (SLMAX + BUFOFFSET) 130 #define SLMTU 296 131 #define SLIP_HIWAT roundup(50,CBSIZE) 132 #define CLISTRESERVE 1024 /* Can't let clists get too low */ 133 134 /* 135 * SLIP ABORT ESCAPE MECHANISM: 136 * (inspired by HAYES modem escape arrangement) 137 * 1sec escape 1sec escape 1sec escape { 1sec escape 1sec escape } 138 * within window time signals a "soft" exit from slip mode by remote end 139 * if the IFF_DEBUG flag is on. 140 */ 141 #define ABT_ESC '\033' /* can't be t_intr - distant host must know it*/ 142 #define ABT_IDLE 1 /* in seconds - idle before an escape */ 143 #define ABT_COUNT 3 /* count of escapes for abort */ 144 #define ABT_WINDOW (ABT_COUNT*2+2) /* in seconds - time to count */ 145 146 struct sl_softc sl_softc[NSL]; 147 148 #define FRAME_END 0xc0 /* Frame End */ 149 #define FRAME_ESCAPE 0xdb /* Frame Esc */ 150 #define TRANS_FRAME_END 0xdc /* transposed frame end */ 151 #define TRANS_FRAME_ESCAPE 0xdd /* transposed frame esc */ 152 153 static int slinit __P((struct sl_softc *)); 154 static struct mbuf *sl_btom __P((struct sl_softc *, int)); 155 156 /* 157 * Called from boot code to establish sl interfaces. 158 */ 159 void 160 slattach() 161 { 162 register struct sl_softc *sc; 163 register int i = 0; 164 165 for (sc = sl_softc; i < NSL; sc++) { 166 sc->sc_if.if_name = "sl"; 167 sc->sc_if.if_next = NULL; 168 sc->sc_if.if_unit = i++; 169 sc->sc_if.if_mtu = SLMTU; 170 sc->sc_if.if_flags = 171 IFF_POINTOPOINT | SC_AUTOCOMP | IFF_MULTICAST; 172 sc->sc_if.if_type = IFT_SLIP; 173 sc->sc_if.if_ioctl = slioctl; 174 sc->sc_if.if_output = sloutput; 175 sc->sc_if.if_snd.ifq_maxlen = 50; 176 sc->sc_fastq.ifq_maxlen = 32; 177 if_attach(&sc->sc_if); 178 #if NBPFILTER > 0 179 bpfattach(&sc->sc_bpf, &sc->sc_if, DLT_SLIP, SLIP_HDRLEN); 180 #endif 181 } 182 } 183 184 static int 185 slinit(sc) 186 register struct sl_softc *sc; 187 { 188 register caddr_t p; 189 190 if (sc->sc_ep == (u_char *) 0) { 191 MCLALLOC(p, M_WAIT); 192 if (p) 193 sc->sc_ep = (u_char *)p + SLBUFSIZE; 194 else { 195 printf("sl%d: can't allocate buffer\n", sc - sl_softc); 196 sc->sc_if.if_flags &= ~IFF_UP; 197 return (0); 198 } 199 } 200 sc->sc_buf = sc->sc_ep - SLMAX; 201 sc->sc_mp = sc->sc_buf; 202 sl_compress_init(&sc->sc_comp); 203 return (1); 204 } 205 206 /* 207 * Line specific open routine. 208 * Attach the given tty to the first available sl unit. 209 */ 210 /* ARGSUSED */ 211 int 212 slopen(dev, tp) 213 dev_t dev; 214 register struct tty *tp; 215 { 216 struct proc *p = curproc; /* XXX */ 217 register struct sl_softc *sc; 218 register int nsl; 219 int error; 220 int s; 221 222 if (error = suser(p->p_ucred, &p->p_acflag)) 223 return (error); 224 225 if (tp->t_line == SLIPDISC) 226 return (0); 227 228 for (nsl = NSL, sc = sl_softc; --nsl >= 0; sc++) 229 if (sc->sc_ttyp == NULL) { 230 if (slinit(sc) == 0) 231 return (ENOBUFS); 232 tp->t_sc = (caddr_t)sc; 233 sc->sc_ttyp = tp; 234 sc->sc_if.if_baudrate = tp->t_ospeed; 235 s = spltty(); 236 tp->t_state |= TS_ISOPEN | TS_XCLUDE; 237 splx(s); 238 ttyflush(tp, FREAD | FWRITE); 239 return (0); 240 } 241 return (ENXIO); 242 } 243 244 /* 245 * Line specific close routine. 246 * Detach the tty from the sl unit. 247 */ 248 void 249 slclose(tp) 250 struct tty *tp; 251 { 252 register struct sl_softc *sc; 253 int s; 254 255 ttywflush(tp); 256 s = splimp(); /* actually, max(spltty, splnet) */ 257 tp->t_line = 0; 258 tp->t_state = 0; 259 sc = (struct sl_softc *)tp->t_sc; 260 if (sc != NULL) { 261 if_down(&sc->sc_if); 262 sc->sc_ttyp = NULL; 263 tp->t_sc = NULL; 264 MCLFREE((caddr_t)(sc->sc_ep - SLBUFSIZE)); 265 sc->sc_ep = 0; 266 sc->sc_mp = 0; 267 sc->sc_buf = 0; 268 } 269 splx(s); 270 } 271 272 /* 273 * Line specific (tty) ioctl routine. 274 * Provide a way to get the sl unit number. 275 */ 276 /* ARGSUSED */ 277 int 278 sltioctl(tp, cmd, data, flag) 279 struct tty *tp; 280 u_long cmd; 281 caddr_t data; 282 int flag; 283 { 284 struct sl_softc *sc = (struct sl_softc *)tp->t_sc; 285 286 switch (cmd) { 287 case SLIOCGUNIT: 288 *(int *)data = sc->sc_if.if_unit; 289 break; 290 291 default: 292 return (-1); 293 } 294 return (0); 295 } 296 297 /* 298 * Queue a packet. Start transmission if not active. 299 * Compression happens in slstart; if we do it here, IP TOS 300 * will cause us to not compress "background" packets, because 301 * ordering gets trashed. It can be done for all packets in slstart. 302 */ 303 int 304 sloutput(ifp, m, dst, rtp) 305 struct ifnet *ifp; 306 register struct mbuf *m; 307 struct sockaddr *dst; 308 struct rtentry *rtp; 309 { 310 register struct sl_softc *sc = &sl_softc[ifp->if_unit]; 311 register struct ip *ip; 312 register struct ifqueue *ifq; 313 int s; 314 315 /* 316 * `Cannot happen' (see slioctl). Someday we will extend 317 * the line protocol to support other address families. 318 */ 319 if (dst->sa_family != AF_INET) { 320 printf("sl%d: af%d not supported\n", sc->sc_if.if_unit, 321 dst->sa_family); 322 m_freem(m); 323 sc->sc_if.if_noproto++; 324 return (EAFNOSUPPORT); 325 } 326 327 if (sc->sc_ttyp == NULL) { 328 m_freem(m); 329 return (ENETDOWN); /* sort of */ 330 } 331 if ((sc->sc_ttyp->t_state & TS_CARR_ON) == 0 && 332 (sc->sc_ttyp->t_cflag & CLOCAL) == 0) { 333 m_freem(m); 334 return (EHOSTUNREACH); 335 } 336 ifq = &sc->sc_if.if_snd; 337 ip = mtod(m, struct ip *); 338 if (sc->sc_if.if_flags & SC_NOICMP && ip->ip_p == IPPROTO_ICMP) { 339 m_freem(m); 340 return (ENETRESET); /* XXX ? */ 341 } 342 if (ip->ip_tos & IPTOS_LOWDELAY) 343 ifq = &sc->sc_fastq; 344 s = splimp(); 345 if (IF_QFULL(ifq)) { 346 IF_DROP(ifq); 347 m_freem(m); 348 splx(s); 349 sc->sc_if.if_oerrors++; 350 return (ENOBUFS); 351 } 352 IF_ENQUEUE(ifq, m); 353 sc->sc_if.if_lastchange = time; 354 if (sc->sc_ttyp->t_outq.c_cc == 0) 355 slstart(sc->sc_ttyp); 356 splx(s); 357 return (0); 358 } 359 360 /* 361 * Start output on interface. Get another datagram 362 * to send from the interface queue and map it to 363 * the interface before starting output. 364 */ 365 void 366 slstart(tp) 367 register struct tty *tp; 368 { 369 register struct sl_softc *sc = (struct sl_softc *)tp->t_sc; 370 register struct mbuf *m; 371 register u_char *cp; 372 register struct ip *ip; 373 int s; 374 struct mbuf *m2; 375 #if NBPFILTER > 0 376 u_char bpfbuf[SLMTU + SLIP_HDRLEN]; 377 register int len; 378 #endif 379 extern int cfreecount; 380 381 for (;;) { 382 /* 383 * If there is more in the output queue, just send it now. 384 * We are being called in lieu of ttstart and must do what 385 * it would. 386 */ 387 if (tp->t_outq.c_cc != 0) { 388 (*tp->t_oproc)(tp); 389 if (tp->t_outq.c_cc > SLIP_HIWAT) 390 return; 391 } 392 /* 393 * This happens briefly when the line shuts down. 394 */ 395 if (sc == NULL) 396 return; 397 398 /* 399 * Get a packet and send it to the interface. 400 */ 401 s = splimp(); 402 IF_DEQUEUE(&sc->sc_fastq, m); 403 if (m) 404 sc->sc_if.if_omcasts++; /* XXX */ 405 else 406 IF_DEQUEUE(&sc->sc_if.if_snd, m); 407 splx(s); 408 if (m == NULL) 409 return; 410 411 /* 412 * We do the header compression here rather than in sloutput 413 * because the packets will be out of order if we are using TOS 414 * queueing, and the connection id compression will get 415 * munged when this happens. 416 */ 417 #if NBPFILTER > 0 418 if (sc->sc_bpf) { 419 /* 420 * We need to save the TCP/IP header before it's 421 * compressed. To avoid complicated code, we just 422 * copy the entire packet into a stack buffer (since 423 * this is a serial line, packets should be short 424 * and/or the copy should be negligible cost compared 425 * to the packet transmission time). 426 */ 427 register struct mbuf *m1 = m; 428 register u_char *cp = bpfbuf + SLIP_HDRLEN; 429 430 len = 0; 431 do { 432 register int mlen = m1->m_len; 433 434 bcopy(mtod(m1, caddr_t), cp, mlen); 435 cp += mlen; 436 len += mlen; 437 } while (m1 = m1->m_next); 438 } 439 #endif 440 if ((ip = mtod(m, struct ip *))->ip_p == IPPROTO_TCP) { 441 if (sc->sc_if.if_flags & SC_COMPRESS) 442 *mtod(m, u_char *) |= sl_compress_tcp(m, ip, 443 &sc->sc_comp, 1); 444 } 445 #if NBPFILTER > 0 446 if (sc->sc_bpf) { 447 /* 448 * Put the SLIP pseudo-"link header" in place. The 449 * compressed header is now at the beginning of the 450 * mbuf. 451 */ 452 bpfbuf[SLX_DIR] = SLIPDIR_OUT; 453 bcopy(mtod(m, caddr_t), &bpfbuf[SLX_CHDR], CHDR_LEN); 454 bpf_tap(sc->sc_bpf, bpfbuf, len + SLIP_HDRLEN); 455 } 456 #endif 457 sc->sc_if.if_lastchange = time; 458 459 /* 460 * If system is getting low on clists, just flush our 461 * output queue (if the stuff was important, it'll get 462 * retransmitted). 463 */ 464 if (cfreecount < CLISTRESERVE + SLMTU) { 465 m_freem(m); 466 sc->sc_if.if_collisions++; 467 continue; 468 } 469 /* 470 * The extra FRAME_END will start up a new packet, and thus 471 * will flush any accumulated garbage. We do this whenever 472 * the line may have been idle for some time. 473 */ 474 if (tp->t_outq.c_cc == 0) { 475 ++sc->sc_if.if_obytes; 476 (void) putc(FRAME_END, &tp->t_outq); 477 } 478 479 while (m) { 480 register u_char *ep; 481 482 cp = mtod(m, u_char *); ep = cp + m->m_len; 483 while (cp < ep) { 484 /* 485 * Find out how many bytes in the string we can 486 * handle without doing something special. 487 */ 488 register u_char *bp = cp; 489 490 while (cp < ep) { 491 switch (*cp++) { 492 case FRAME_ESCAPE: 493 case FRAME_END: 494 --cp; 495 goto out; 496 } 497 } 498 out: 499 if (cp > bp) { 500 /* 501 * Put n characters at once 502 * into the tty output queue. 503 */ 504 if (b_to_q((char *)bp, cp - bp, 505 &tp->t_outq)) 506 break; 507 sc->sc_if.if_obytes += cp - bp; 508 } 509 /* 510 * If there are characters left in the mbuf, 511 * the first one must be special.. 512 * Put it out in a different form. 513 */ 514 if (cp < ep) { 515 if (putc(FRAME_ESCAPE, &tp->t_outq)) 516 break; 517 if (putc(*cp++ == FRAME_ESCAPE ? 518 TRANS_FRAME_ESCAPE : TRANS_FRAME_END, 519 &tp->t_outq)) { 520 (void) unputc(&tp->t_outq); 521 break; 522 } 523 sc->sc_if.if_obytes += 2; 524 } 525 } 526 MFREE(m, m2); 527 m = m2; 528 } 529 530 if (putc(FRAME_END, &tp->t_outq)) { 531 /* 532 * Not enough room. Remove a char to make room 533 * and end the packet normally. 534 * If you get many collisions (more than one or two 535 * a day) you probably do not have enough clists 536 * and you should increase "nclist" in param.c. 537 */ 538 (void) unputc(&tp->t_outq); 539 (void) putc(FRAME_END, &tp->t_outq); 540 sc->sc_if.if_collisions++; 541 } else { 542 ++sc->sc_if.if_obytes; 543 sc->sc_if.if_opackets++; 544 } 545 } 546 } 547 548 /* 549 * Copy data buffer to mbuf chain; add ifnet pointer. 550 */ 551 static struct mbuf * 552 sl_btom(sc, len) 553 register struct sl_softc *sc; 554 register int len; 555 { 556 register struct mbuf *m; 557 558 MGETHDR(m, M_DONTWAIT, MT_DATA); 559 if (m == NULL) 560 return (NULL); 561 562 /* 563 * If we have more than MHLEN bytes, it's cheaper to 564 * queue the cluster we just filled & allocate a new one 565 * for the input buffer. Otherwise, fill the mbuf we 566 * allocated above. Note that code in the input routine 567 * guarantees that packet will fit in a cluster. 568 */ 569 if (len >= MHLEN) { 570 MCLGET(m, M_DONTWAIT); 571 if ((m->m_flags & M_EXT) == 0) { 572 /* 573 * we couldn't get a cluster - if memory's this 574 * low, it's time to start dropping packets. 575 */ 576 (void) m_free(m); 577 return (NULL); 578 } 579 sc->sc_ep = mtod(m, u_char *) + SLBUFSIZE; 580 m->m_data = (caddr_t)sc->sc_buf; 581 m->m_ext.ext_buf = (caddr_t)((int)sc->sc_buf &~ MCLOFSET); 582 } else 583 bcopy((caddr_t)sc->sc_buf, mtod(m, caddr_t), len); 584 585 m->m_len = len; 586 m->m_pkthdr.len = len; 587 m->m_pkthdr.rcvif = &sc->sc_if; 588 return (m); 589 } 590 591 /* 592 * tty interface receiver interrupt. 593 */ 594 void 595 slinput(c, tp) 596 register int c; 597 register struct tty *tp; 598 { 599 register struct sl_softc *sc; 600 register struct mbuf *m; 601 register int len; 602 int s; 603 #if NBPFILTER > 0 604 u_char chdr[CHDR_LEN]; 605 #endif 606 607 tk_nin++; 608 sc = (struct sl_softc *)tp->t_sc; 609 if (sc == NULL) 610 return; 611 if ((c & TTY_ERRORMASK) || ((tp->t_state & TS_CARR_ON) == 0 && 612 (tp->t_cflag & CLOCAL) == 0)) { 613 sc->sc_flags |= SC_ERROR; 614 return; 615 } 616 c &= TTY_CHARMASK; 617 618 ++sc->sc_if.if_ibytes; 619 620 if (sc->sc_if.if_flags & IFF_DEBUG) { 621 if (c == ABT_ESC) { 622 /* 623 * If we have a previous abort, see whether 624 * this one is within the time limit. 625 */ 626 if (sc->sc_abortcount && 627 time.tv_sec >= sc->sc_starttime + ABT_WINDOW) 628 sc->sc_abortcount = 0; 629 /* 630 * If we see an abort after "idle" time, count it; 631 * record when the first abort escape arrived. 632 */ 633 if (time.tv_sec >= sc->sc_lasttime + ABT_IDLE) { 634 if (++sc->sc_abortcount == 1) 635 sc->sc_starttime = time.tv_sec; 636 if (sc->sc_abortcount >= ABT_COUNT) { 637 slclose(tp); 638 return; 639 } 640 } 641 } else 642 sc->sc_abortcount = 0; 643 sc->sc_lasttime = time.tv_sec; 644 } 645 646 switch (c) { 647 648 case TRANS_FRAME_ESCAPE: 649 if (sc->sc_escape) 650 c = FRAME_ESCAPE; 651 break; 652 653 case TRANS_FRAME_END: 654 if (sc->sc_escape) 655 c = FRAME_END; 656 break; 657 658 case FRAME_ESCAPE: 659 sc->sc_escape = 1; 660 return; 661 662 case FRAME_END: 663 if(sc->sc_flags & SC_ERROR) { 664 sc->sc_flags &= ~SC_ERROR; 665 goto newpack; 666 } 667 len = sc->sc_mp - sc->sc_buf; 668 if (len < 3) 669 /* less than min length packet - ignore */ 670 goto newpack; 671 672 #if NBPFILTER > 0 673 if (sc->sc_bpf) { 674 /* 675 * Save the compressed header, so we 676 * can tack it on later. Note that we 677 * will end up copying garbage in some 678 * cases but this is okay. We remember 679 * where the buffer started so we can 680 * compute the new header length. 681 */ 682 bcopy(sc->sc_buf, chdr, CHDR_LEN); 683 } 684 #endif 685 686 if ((c = (*sc->sc_buf & 0xf0)) != (IPVERSION << 4)) { 687 if (c & 0x80) 688 c = TYPE_COMPRESSED_TCP; 689 else if (c == TYPE_UNCOMPRESSED_TCP) 690 *sc->sc_buf &= 0x4f; /* XXX */ 691 /* 692 * We've got something that's not an IP packet. 693 * If compression is enabled, try to decompress it. 694 * Otherwise, if `auto-enable' compression is on and 695 * it's a reasonable packet, decompress it and then 696 * enable compression. Otherwise, drop it. 697 */ 698 if (sc->sc_if.if_flags & SC_COMPRESS) { 699 len = sl_uncompress_tcp(&sc->sc_buf, len, 700 (u_int)c, &sc->sc_comp); 701 if (len <= 0) 702 goto error; 703 } else if ((sc->sc_if.if_flags & SC_AUTOCOMP) && 704 c == TYPE_UNCOMPRESSED_TCP && len >= 40) { 705 len = sl_uncompress_tcp(&sc->sc_buf, len, 706 (u_int)c, &sc->sc_comp); 707 if (len <= 0) 708 goto error; 709 sc->sc_if.if_flags |= SC_COMPRESS; 710 } else 711 goto error; 712 } 713 #if NBPFILTER > 0 714 if (sc->sc_bpf) { 715 /* 716 * Put the SLIP pseudo-"link header" in place. 717 * We couldn't do this any earlier since 718 * decompression probably moved the buffer 719 * pointer. Then, invoke BPF. 720 */ 721 register u_char *hp = sc->sc_buf - SLIP_HDRLEN; 722 723 hp[SLX_DIR] = SLIPDIR_IN; 724 bcopy(chdr, &hp[SLX_CHDR], CHDR_LEN); 725 bpf_tap(sc->sc_bpf, hp, len + SLIP_HDRLEN); 726 } 727 #endif 728 m = sl_btom(sc, len); 729 if (m == NULL) 730 goto error; 731 732 sc->sc_if.if_ipackets++; 733 sc->sc_if.if_lastchange = time; 734 s = splimp(); 735 if (IF_QFULL(&ipintrq)) { 736 IF_DROP(&ipintrq); 737 sc->sc_if.if_ierrors++; 738 sc->sc_if.if_iqdrops++; 739 m_freem(m); 740 } else { 741 IF_ENQUEUE(&ipintrq, m); 742 schednetisr(NETISR_IP); 743 } 744 splx(s); 745 goto newpack; 746 } 747 if (sc->sc_mp < sc->sc_ep) { 748 *sc->sc_mp++ = c; 749 sc->sc_escape = 0; 750 return; 751 } 752 753 /* can't put lower; would miss an extra frame */ 754 sc->sc_flags |= SC_ERROR; 755 756 error: 757 sc->sc_if.if_ierrors++; 758 newpack: 759 sc->sc_mp = sc->sc_buf = sc->sc_ep - SLMAX; 760 sc->sc_escape = 0; 761 } 762 763 /* 764 * Process an ioctl request. 765 */ 766 int 767 slioctl(ifp, cmd, data) 768 register struct ifnet *ifp; 769 u_long cmd; 770 caddr_t data; 771 { 772 register struct ifaddr *ifa = (struct ifaddr *)data; 773 register struct ifreq *ifr; 774 register int s = splimp(), error = 0; 775 776 switch (cmd) { 777 778 case SIOCSIFADDR: 779 if (ifa->ifa_addr->sa_family == AF_INET) 780 ifp->if_flags |= IFF_UP; 781 else 782 error = EAFNOSUPPORT; 783 break; 784 785 case SIOCSIFDSTADDR: 786 if (ifa->ifa_addr->sa_family != AF_INET) 787 error = EAFNOSUPPORT; 788 break; 789 790 case SIOCADDMULTI: 791 case SIOCDELMULTI: 792 ifr = (struct ifreq *)data; 793 if (ifr == 0) { 794 error = EAFNOSUPPORT; /* XXX */ 795 break; 796 } 797 switch (ifr->ifr_addr.sa_family) { 798 799 #ifdef INET 800 case AF_INET: 801 break; 802 #endif 803 804 default: 805 error = EAFNOSUPPORT; 806 break; 807 } 808 break; 809 810 default: 811 error = EINVAL; 812 } 813 splx(s); 814 return (error); 815 } 816 #endif 817