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.7 (Berkeley) 08/05/94 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 221 if (error = suser(p->p_ucred, &p->p_acflag)) 222 return (error); 223 224 if (tp->t_line == SLIPDISC) 225 return (0); 226 227 for (nsl = NSL, sc = sl_softc; --nsl >= 0; sc++) 228 if (sc->sc_ttyp == NULL) { 229 if (slinit(sc) == 0) 230 return (ENOBUFS); 231 tp->t_sc = (caddr_t)sc; 232 sc->sc_ttyp = tp; 233 sc->sc_if.if_baudrate = tp->t_ospeed; 234 ttyflush(tp, FREAD | FWRITE); 235 return (0); 236 } 237 return (ENXIO); 238 } 239 240 /* 241 * Line specific close routine. 242 * Detach the tty from the sl unit. 243 */ 244 void 245 slclose(tp) 246 struct tty *tp; 247 { 248 register struct sl_softc *sc; 249 int s; 250 251 ttywflush(tp); 252 s = splimp(); /* actually, max(spltty, splnet) */ 253 tp->t_line = 0; 254 sc = (struct sl_softc *)tp->t_sc; 255 if (sc != NULL) { 256 if_down(&sc->sc_if); 257 sc->sc_ttyp = NULL; 258 tp->t_sc = NULL; 259 MCLFREE((caddr_t)(sc->sc_ep - SLBUFSIZE)); 260 sc->sc_ep = 0; 261 sc->sc_mp = 0; 262 sc->sc_buf = 0; 263 } 264 splx(s); 265 } 266 267 /* 268 * Line specific (tty) ioctl routine. 269 * Provide a way to get the sl unit number. 270 */ 271 /* ARGSUSED */ 272 int 273 sltioctl(tp, cmd, data, flag) 274 struct tty *tp; 275 int cmd; 276 caddr_t data; 277 int flag; 278 { 279 struct sl_softc *sc = (struct sl_softc *)tp->t_sc; 280 281 switch (cmd) { 282 case SLIOCGUNIT: 283 *(int *)data = sc->sc_if.if_unit; 284 break; 285 286 default: 287 return (-1); 288 } 289 return (0); 290 } 291 292 /* 293 * Queue a packet. Start transmission if not active. 294 * Compression happens in slstart; if we do it here, IP TOS 295 * will cause us to not compress "background" packets, because 296 * ordering gets trashed. It can be done for all packets in slstart. 297 */ 298 int 299 sloutput(ifp, m, dst, rtp) 300 struct ifnet *ifp; 301 register struct mbuf *m; 302 struct sockaddr *dst; 303 struct rtentry *rtp; 304 { 305 register struct sl_softc *sc = &sl_softc[ifp->if_unit]; 306 register struct ip *ip; 307 register struct ifqueue *ifq; 308 int s; 309 310 /* 311 * `Cannot happen' (see slioctl). Someday we will extend 312 * the line protocol to support other address families. 313 */ 314 if (dst->sa_family != AF_INET) { 315 printf("sl%d: af%d not supported\n", sc->sc_if.if_unit, 316 dst->sa_family); 317 m_freem(m); 318 sc->sc_if.if_noproto++; 319 return (EAFNOSUPPORT); 320 } 321 322 if (sc->sc_ttyp == NULL) { 323 m_freem(m); 324 return (ENETDOWN); /* sort of */ 325 } 326 if ((sc->sc_ttyp->t_state & TS_CARR_ON) == 0 && 327 (sc->sc_ttyp->t_cflag & CLOCAL) == 0) { 328 m_freem(m); 329 return (EHOSTUNREACH); 330 } 331 ifq = &sc->sc_if.if_snd; 332 ip = mtod(m, struct ip *); 333 if (sc->sc_if.if_flags & SC_NOICMP && ip->ip_p == IPPROTO_ICMP) { 334 m_freem(m); 335 return (ENETRESET); /* XXX ? */ 336 } 337 if (ip->ip_tos & IPTOS_LOWDELAY) 338 ifq = &sc->sc_fastq; 339 s = splimp(); 340 if (IF_QFULL(ifq)) { 341 IF_DROP(ifq); 342 m_freem(m); 343 splx(s); 344 sc->sc_if.if_oerrors++; 345 return (ENOBUFS); 346 } 347 IF_ENQUEUE(ifq, m); 348 sc->sc_if.if_lastchange = time; 349 if (sc->sc_ttyp->t_outq.c_cc == 0) 350 slstart(sc->sc_ttyp); 351 splx(s); 352 return (0); 353 } 354 355 /* 356 * Start output on interface. Get another datagram 357 * to send from the interface queue and map it to 358 * the interface before starting output. 359 */ 360 void 361 slstart(tp) 362 register struct tty *tp; 363 { 364 register struct sl_softc *sc = (struct sl_softc *)tp->t_sc; 365 register struct mbuf *m; 366 register u_char *cp; 367 register struct ip *ip; 368 int s; 369 struct mbuf *m2; 370 #if NBPFILTER > 0 371 u_char bpfbuf[SLMTU + SLIP_HDRLEN]; 372 register int len; 373 #endif 374 extern int cfreecount; 375 376 for (;;) { 377 /* 378 * If there is more in the output queue, just send it now. 379 * We are being called in lieu of ttstart and must do what 380 * it would. 381 */ 382 if (tp->t_outq.c_cc != 0) { 383 (*tp->t_oproc)(tp); 384 if (tp->t_outq.c_cc > SLIP_HIWAT) 385 return; 386 } 387 /* 388 * This happens briefly when the line shuts down. 389 */ 390 if (sc == NULL) 391 return; 392 393 /* 394 * Get a packet and send it to the interface. 395 */ 396 s = splimp(); 397 IF_DEQUEUE(&sc->sc_fastq, m); 398 if (m) 399 sc->sc_if.if_omcasts++; /* XXX */ 400 else 401 IF_DEQUEUE(&sc->sc_if.if_snd, m); 402 splx(s); 403 if (m == NULL) 404 return; 405 406 /* 407 * We do the header compression here rather than in sloutput 408 * because the packets will be out of order if we are using TOS 409 * queueing, and the connection id compression will get 410 * munged when this happens. 411 */ 412 #if NBPFILTER > 0 413 if (sc->sc_bpf) { 414 /* 415 * We need to save the TCP/IP header before it's 416 * compressed. To avoid complicated code, we just 417 * copy the entire packet into a stack buffer (since 418 * this is a serial line, packets should be short 419 * and/or the copy should be negligible cost compared 420 * to the packet transmission time). 421 */ 422 register struct mbuf *m1 = m; 423 register u_char *cp = bpfbuf + SLIP_HDRLEN; 424 425 len = 0; 426 do { 427 register int mlen = m1->m_len; 428 429 bcopy(mtod(m1, caddr_t), cp, mlen); 430 cp += mlen; 431 len += mlen; 432 } while (m1 = m1->m_next); 433 } 434 #endif 435 if ((ip = mtod(m, struct ip *))->ip_p == IPPROTO_TCP) { 436 if (sc->sc_if.if_flags & SC_COMPRESS) 437 *mtod(m, u_char *) |= sl_compress_tcp(m, ip, 438 &sc->sc_comp, 1); 439 } 440 #if NBPFILTER > 0 441 if (sc->sc_bpf) { 442 /* 443 * Put the SLIP pseudo-"link header" in place. The 444 * compressed header is now at the beginning of the 445 * mbuf. 446 */ 447 bpfbuf[SLX_DIR] = SLIPDIR_OUT; 448 bcopy(mtod(m, caddr_t), &bpfbuf[SLX_CHDR], CHDR_LEN); 449 bpf_tap(sc->sc_bpf, bpfbuf, len + SLIP_HDRLEN); 450 } 451 #endif 452 sc->sc_if.if_lastchange = time; 453 454 /* 455 * If system is getting low on clists, just flush our 456 * output queue (if the stuff was important, it'll get 457 * retransmitted). 458 */ 459 if (cfreecount < CLISTRESERVE + SLMTU) { 460 m_freem(m); 461 sc->sc_if.if_collisions++; 462 continue; 463 } 464 /* 465 * The extra FRAME_END will start up a new packet, and thus 466 * will flush any accumulated garbage. We do this whenever 467 * the line may have been idle for some time. 468 */ 469 if (tp->t_outq.c_cc == 0) { 470 ++sc->sc_if.if_obytes; 471 (void) putc(FRAME_END, &tp->t_outq); 472 } 473 474 while (m) { 475 register u_char *ep; 476 477 cp = mtod(m, u_char *); ep = cp + m->m_len; 478 while (cp < ep) { 479 /* 480 * Find out how many bytes in the string we can 481 * handle without doing something special. 482 */ 483 register u_char *bp = cp; 484 485 while (cp < ep) { 486 switch (*cp++) { 487 case FRAME_ESCAPE: 488 case FRAME_END: 489 --cp; 490 goto out; 491 } 492 } 493 out: 494 if (cp > bp) { 495 /* 496 * Put n characters at once 497 * into the tty output queue. 498 */ 499 if (b_to_q((char *)bp, cp - bp, 500 &tp->t_outq)) 501 break; 502 sc->sc_if.if_obytes += cp - bp; 503 } 504 /* 505 * If there are characters left in the mbuf, 506 * the first one must be special.. 507 * Put it out in a different form. 508 */ 509 if (cp < ep) { 510 if (putc(FRAME_ESCAPE, &tp->t_outq)) 511 break; 512 if (putc(*cp++ == FRAME_ESCAPE ? 513 TRANS_FRAME_ESCAPE : TRANS_FRAME_END, 514 &tp->t_outq)) { 515 (void) unputc(&tp->t_outq); 516 break; 517 } 518 sc->sc_if.if_obytes += 2; 519 } 520 } 521 MFREE(m, m2); 522 m = m2; 523 } 524 525 if (putc(FRAME_END, &tp->t_outq)) { 526 /* 527 * Not enough room. Remove a char to make room 528 * and end the packet normally. 529 * If you get many collisions (more than one or two 530 * a day) you probably do not have enough clists 531 * and you should increase "nclist" in param.c. 532 */ 533 (void) unputc(&tp->t_outq); 534 (void) putc(FRAME_END, &tp->t_outq); 535 sc->sc_if.if_collisions++; 536 } else { 537 ++sc->sc_if.if_obytes; 538 sc->sc_if.if_opackets++; 539 } 540 } 541 } 542 543 /* 544 * Copy data buffer to mbuf chain; add ifnet pointer. 545 */ 546 static struct mbuf * 547 sl_btom(sc, len) 548 register struct sl_softc *sc; 549 register int len; 550 { 551 register struct mbuf *m; 552 553 MGETHDR(m, M_DONTWAIT, MT_DATA); 554 if (m == NULL) 555 return (NULL); 556 557 /* 558 * If we have more than MHLEN bytes, it's cheaper to 559 * queue the cluster we just filled & allocate a new one 560 * for the input buffer. Otherwise, fill the mbuf we 561 * allocated above. Note that code in the input routine 562 * guarantees that packet will fit in a cluster. 563 */ 564 if (len >= MHLEN) { 565 MCLGET(m, M_DONTWAIT); 566 if ((m->m_flags & M_EXT) == 0) { 567 /* 568 * we couldn't get a cluster - if memory's this 569 * low, it's time to start dropping packets. 570 */ 571 (void) m_free(m); 572 return (NULL); 573 } 574 sc->sc_ep = mtod(m, u_char *) + SLBUFSIZE; 575 m->m_data = (caddr_t)sc->sc_buf; 576 m->m_ext.ext_buf = (caddr_t)((int)sc->sc_buf &~ MCLOFSET); 577 } else 578 bcopy((caddr_t)sc->sc_buf, mtod(m, caddr_t), len); 579 580 m->m_len = len; 581 m->m_pkthdr.len = len; 582 m->m_pkthdr.rcvif = &sc->sc_if; 583 return (m); 584 } 585 586 /* 587 * tty interface receiver interrupt. 588 */ 589 void 590 slinput(c, tp) 591 register int c; 592 register struct tty *tp; 593 { 594 register struct sl_softc *sc; 595 register struct mbuf *m; 596 register int len; 597 int s; 598 #if NBPFILTER > 0 599 u_char chdr[CHDR_LEN]; 600 #endif 601 602 tk_nin++; 603 sc = (struct sl_softc *)tp->t_sc; 604 if (sc == NULL) 605 return; 606 if (c & TTY_ERRORMASK || ((tp->t_state & TS_CARR_ON) == 0 && 607 (tp->t_cflag & CLOCAL) == 0)) { 608 sc->sc_flags |= SC_ERROR; 609 return; 610 } 611 c &= TTY_CHARMASK; 612 613 ++sc->sc_if.if_ibytes; 614 615 if (sc->sc_if.if_flags & IFF_DEBUG) { 616 if (c == ABT_ESC) { 617 /* 618 * If we have a previous abort, see whether 619 * this one is within the time limit. 620 */ 621 if (sc->sc_abortcount && 622 time.tv_sec >= sc->sc_starttime + ABT_WINDOW) 623 sc->sc_abortcount = 0; 624 /* 625 * If we see an abort after "idle" time, count it; 626 * record when the first abort escape arrived. 627 */ 628 if (time.tv_sec >= sc->sc_lasttime + ABT_IDLE) { 629 if (++sc->sc_abortcount == 1) 630 sc->sc_starttime = time.tv_sec; 631 if (sc->sc_abortcount >= ABT_COUNT) { 632 slclose(tp); 633 return; 634 } 635 } 636 } else 637 sc->sc_abortcount = 0; 638 sc->sc_lasttime = time.tv_sec; 639 } 640 641 switch (c) { 642 643 case TRANS_FRAME_ESCAPE: 644 if (sc->sc_escape) 645 c = FRAME_ESCAPE; 646 break; 647 648 case TRANS_FRAME_END: 649 if (sc->sc_escape) 650 c = FRAME_END; 651 break; 652 653 case FRAME_ESCAPE: 654 sc->sc_escape = 1; 655 return; 656 657 case FRAME_END: 658 if(sc->sc_flags & SC_ERROR) { 659 sc->sc_flags &= ~SC_ERROR; 660 goto newpack; 661 } 662 len = sc->sc_mp - sc->sc_buf; 663 if (len < 3) 664 /* less than min length packet - ignore */ 665 goto newpack; 666 667 #if NBPFILTER > 0 668 if (sc->sc_bpf) { 669 /* 670 * Save the compressed header, so we 671 * can tack it on later. Note that we 672 * will end up copying garbage in some 673 * cases but this is okay. We remember 674 * where the buffer started so we can 675 * compute the new header length. 676 */ 677 bcopy(sc->sc_buf, chdr, CHDR_LEN); 678 } 679 #endif 680 681 if ((c = (*sc->sc_buf & 0xf0)) != (IPVERSION << 4)) { 682 if (c & 0x80) 683 c = TYPE_COMPRESSED_TCP; 684 else if (c == TYPE_UNCOMPRESSED_TCP) 685 *sc->sc_buf &= 0x4f; /* XXX */ 686 /* 687 * We've got something that's not an IP packet. 688 * If compression is enabled, try to decompress it. 689 * Otherwise, if `auto-enable' compression is on and 690 * it's a reasonable packet, decompress it and then 691 * enable compression. Otherwise, drop it. 692 */ 693 if (sc->sc_if.if_flags & SC_COMPRESS) { 694 len = sl_uncompress_tcp(&sc->sc_buf, len, 695 (u_int)c, &sc->sc_comp); 696 if (len <= 0) 697 goto error; 698 } else if ((sc->sc_if.if_flags & SC_AUTOCOMP) && 699 c == TYPE_UNCOMPRESSED_TCP && len >= 40) { 700 len = sl_uncompress_tcp(&sc->sc_buf, len, 701 (u_int)c, &sc->sc_comp); 702 if (len <= 0) 703 goto error; 704 sc->sc_if.if_flags |= SC_COMPRESS; 705 } else 706 goto error; 707 } 708 #if NBPFILTER > 0 709 if (sc->sc_bpf) { 710 /* 711 * Put the SLIP pseudo-"link header" in place. 712 * We couldn't do this any earlier since 713 * decompression probably moved the buffer 714 * pointer. Then, invoke BPF. 715 */ 716 register u_char *hp = sc->sc_buf - SLIP_HDRLEN; 717 718 hp[SLX_DIR] = SLIPDIR_IN; 719 bcopy(chdr, &hp[SLX_CHDR], CHDR_LEN); 720 bpf_tap(sc->sc_bpf, hp, len + SLIP_HDRLEN); 721 } 722 #endif 723 m = sl_btom(sc, len); 724 if (m == NULL) 725 goto error; 726 727 sc->sc_if.if_ipackets++; 728 sc->sc_if.if_lastchange = time; 729 s = splimp(); 730 if (IF_QFULL(&ipintrq)) { 731 IF_DROP(&ipintrq); 732 sc->sc_if.if_ierrors++; 733 sc->sc_if.if_iqdrops++; 734 m_freem(m); 735 } else { 736 IF_ENQUEUE(&ipintrq, m); 737 schednetisr(NETISR_IP); 738 } 739 splx(s); 740 goto newpack; 741 } 742 if (sc->sc_mp < sc->sc_ep) { 743 *sc->sc_mp++ = c; 744 sc->sc_escape = 0; 745 return; 746 } 747 748 /* can't put lower; would miss an extra frame */ 749 sc->sc_flags |= SC_ERROR; 750 751 error: 752 sc->sc_if.if_ierrors++; 753 newpack: 754 sc->sc_mp = sc->sc_buf = sc->sc_ep - SLMAX; 755 sc->sc_escape = 0; 756 } 757 758 /* 759 * Process an ioctl request. 760 */ 761 int 762 slioctl(ifp, cmd, data) 763 register struct ifnet *ifp; 764 int cmd; 765 caddr_t data; 766 { 767 register struct ifaddr *ifa = (struct ifaddr *)data; 768 register struct ifreq *ifr; 769 register int s = splimp(), error = 0; 770 771 switch (cmd) { 772 773 case SIOCSIFADDR: 774 if (ifa->ifa_addr->sa_family == AF_INET) 775 ifp->if_flags |= IFF_UP; 776 else 777 error = EAFNOSUPPORT; 778 break; 779 780 case SIOCSIFDSTADDR: 781 if (ifa->ifa_addr->sa_family != AF_INET) 782 error = EAFNOSUPPORT; 783 break; 784 785 case SIOCADDMULTI: 786 case SIOCDELMULTI: 787 ifr = (struct ifreq *)data; 788 if (ifr == 0) { 789 error = EAFNOSUPPORT; /* XXX */ 790 break; 791 } 792 switch (ifr->ifr_addr.sa_family) { 793 794 #ifdef INET 795 case AF_INET: 796 break; 797 #endif 798 799 default: 800 error = EAFNOSUPPORT; 801 break; 802 } 803 break; 804 805 default: 806 error = EINVAL; 807 } 808 splx(s); 809 return (error); 810 } 811 #endif 812