1 /* 2 * (MPSAFE) 3 * 4 * Copyright (c) 1987, 1989, 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * @(#)if_sl.c 8.6 (Berkeley) 2/1/94 32 * $FreeBSD: src/sys/net/if_sl.c,v 1.84.2.2 2002/02/13 00:43:10 dillon Exp $ 33 */ 34 35 /* 36 * Serial Line interface 37 * 38 * Rick Adams 39 * Center for Seismic Studies 40 * 1300 N 17th Street, Suite 1450 41 * Arlington, Virginia 22209 42 * (703)276-7900 43 * rick@seismo.ARPA 44 * seismo!rick 45 * 46 * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris). 47 * N.B.: this belongs in netinet, not net, the way it stands now. 48 * Should have a link-layer type designation, but wouldn't be 49 * backwards-compatible. 50 * 51 * Converted to 4.3BSD Beta by Chris Torek. 52 * Other changes made at Berkeley, based in part on code by Kirk Smith. 53 * W. Jolitz added slip abort. 54 * 55 * Hacked almost beyond recognition by Van Jacobson (van@helios.ee.lbl.gov). 56 * Added priority queuing for "interactive" traffic; hooks for TCP 57 * header compression; ICMP filtering (at 2400 baud, some cretin 58 * pinging you can use up all your bandwidth). Made low clist behavior 59 * more robust and slightly less likely to hang serial line. 60 * Sped up a bunch of things. 61 */ 62 63 #include "use_sl.h" 64 #include "opt_inet.h" 65 66 #include <sys/param.h> 67 #include <sys/systm.h> 68 #include <sys/proc.h> 69 #include <sys/priv.h> 70 #include <sys/malloc.h> 71 #include <sys/mbuf.h> 72 #include <sys/dkstat.h> 73 #include <sys/socket.h> 74 #include <sys/sockio.h> 75 #include <sys/fcntl.h> 76 #include <sys/signalvar.h> 77 #include <sys/tty.h> 78 #include <sys/kernel.h> 79 #include <sys/sysctl.h> 80 #include <sys/conf.h> 81 82 #include <net/if.h> 83 #include <net/if_types.h> 84 #include <net/ifq_var.h> 85 #include <net/netisr.h> 86 87 #if INET 88 #include <netinet/in.h> 89 #include <netinet/in_systm.h> 90 #include <netinet/in_var.h> 91 #include <netinet/ip.h> 92 #else 93 #error "Huh? Slip without inet?" 94 #endif 95 96 #include <net/slcompress.h> 97 #include "if_slvar.h" 98 #include <net/slip.h> 99 100 #include <net/bpf.h> 101 102 static void slattach (void *); 103 PSEUDO_SET(slattach, if_sl); 104 105 /* Set to 0xC002 for broadcast instead of p-to-p */ 106 static int sliffopts = IFF_POINTOPOINT | SC_AUTOCOMP | IFF_MULTICAST; 107 SYSCTL_INT(_net, OID_AUTO, sliffopts, CTLFLAG_RW, 108 &sliffopts, 0, ""); 109 TUNABLE_INT("net.sliffopts", &sliffopts); 110 111 /* 112 * SLRMAX is a hard limit on input packet size. To simplify the code 113 * and improve performance, we require that packets fit in an mbuf 114 * cluster, and if we get a compressed packet, there's enough extra 115 * room to expand the header into a max length tcp/ip header (128 116 * bytes). So, SLRMAX can be at most 117 * MCLBYTES - 128 118 * 119 * SLMTU is the default transmit MTU. The transmit MTU should be kept 120 * small enough so that interactive use doesn't suffer, but large 121 * enough to provide good performance. 552 is a good choice for SLMTU 122 * because it is high enough to not fragment TCP packets being routed 123 * through this host. Packet fragmentation is bad with SLIP because 124 * fragment headers aren't compressed. The previous assumptions about 125 * the best MTU value don't really hold when using modern modems with 126 * BTLZ data compression because the modem buffers play a much larger 127 * role in interactive performance than the MTU. The MTU can be changed 128 * at any time to suit the specific environment with ifconfig(8), and 129 * its maximum value is defined as SLTMAX. SLTMAX must not be so large 130 * that it would overflow the stack if BPF is configured (XXX; if_ppp.c 131 * handles this better). 132 * 133 * SLIP_HIWAT is the amount of data that will be queued 'downstream' 134 * of us (i.e., in clists waiting to be picked up by the tty output 135 * interrupt). If we queue a lot of data downstream, it's immune to 136 * our t.o.s. queuing. 137 * E.g., if SLIP_HIWAT is 1024, the interactive traffic in mixed 138 * telnet/ftp will see a 1 sec wait, independent of the mtu (the 139 * wait is dependent on the ftp window size but that's typically 140 * 1k - 4k). So, we want SLIP_HIWAT just big enough to amortize 141 * the cost (in idle time on the wire) of the tty driver running 142 * off the end of its clists & having to call back slstart for a 143 * new packet. For a tty interface with any buffering at all, this 144 * cost will be zero. Even with a totally brain dead interface (like 145 * the one on a typical workstation), the cost will be <= 1 character 146 * time. So, setting SLIP_HIWAT to ~100 guarantees that we'll lose 147 * at most 1% while maintaining good interactive response. 148 */ 149 #define BUFOFFSET (128+sizeof(struct ifnet **)+SLIP_HDRLEN) 150 #define SLRMAX (MCLBYTES - BUFOFFSET) 151 #define SLBUFSIZE (SLRMAX + BUFOFFSET) 152 #ifndef SLMTU 153 #define SLMTU 552 /* default MTU */ 154 #endif 155 #define SLTMAX 1500 /* maximum MTU */ 156 #define SLIP_HIWAT 50 157 #define CLISTRESERVE 1024 /* Can't let clists get too low */ 158 159 /* 160 * SLIP ABORT ESCAPE MECHANISM: 161 * (inspired by HAYES modem escape arrangement) 162 * 1sec escape 1sec escape 1sec escape { 1sec escape 1sec escape } 163 * within window time signals a "soft" exit from slip mode by remote end 164 * if the IFF_DEBUG flag is on. 165 */ 166 #define ABT_ESC '\033' /* can't be t_intr - distant host must know it*/ 167 #define ABT_IDLE 1 /* in seconds - idle before an escape */ 168 #define ABT_COUNT 3 /* count of escapes for abort */ 169 #define ABT_WINDOW (ABT_COUNT*2+2) /* in seconds - time to count */ 170 171 static struct sl_softc sl_softc[NSL]; 172 173 #define FRAME_END 0xc0 /* Frame End */ 174 #define FRAME_ESCAPE 0xdb /* Frame Esc */ 175 #define TRANS_FRAME_END 0xdc /* transposed frame end */ 176 #define TRANS_FRAME_ESCAPE 0xdd /* transposed frame esc */ 177 178 static int slinit (struct sl_softc *); 179 static struct mbuf *sl_btom (struct sl_softc *, int); 180 static timeout_t sl_keepalive; 181 static timeout_t sl_outfill; 182 static int slclose (struct tty *,int); 183 static int slinput (int, struct tty *); 184 static int slioctl (struct ifnet *, u_long, caddr_t, struct ucred *); 185 static int sltioctl (struct tty *, u_long, caddr_t, int, struct ucred *); 186 static int slopen (cdev_t, struct tty *); 187 static int sloutput (struct ifnet *, 188 struct mbuf *, struct sockaddr *, struct rtentry *); 189 static int slstart (struct tty *); 190 191 static struct linesw slipdisc = { 192 slopen, slclose, l_noread, l_nowrite, 193 sltioctl, slinput, slstart, ttymodem, 194 FRAME_END 195 }; 196 197 /* 198 * Called from boot code to establish sl interfaces. 199 */ 200 static void 201 slattach(void *dummy) 202 { 203 struct sl_softc *sc; 204 int i = 0; 205 206 linesw[SLIPDISC] = slipdisc; 207 208 for (sc = sl_softc; i < NSL; sc++) { 209 if_initname(&(sc->sc_if), "sl", i++); 210 sc->sc_if.if_mtu = SLMTU; 211 sc->sc_if.if_flags = sliffopts; 212 sc->sc_if.if_type = IFT_SLIP; 213 sc->sc_if.if_ioctl = slioctl; 214 sc->sc_if.if_output = sloutput; 215 ifq_set_maxlen(&sc->sc_if.if_snd, 50); 216 ifq_set_ready(&sc->sc_if.if_snd); 217 sc->sc_fastq.ifq_maxlen = 32; 218 sc->sc_if.if_linkmib = sc; 219 sc->sc_if.if_linkmiblen = sizeof *sc; 220 callout_init_mp(&sc->sc_oftimeout); 221 callout_init_mp(&sc->sc_katimeout); 222 if_attach(&sc->sc_if, NULL); 223 bpfattach(&sc->sc_if, DLT_SLIP, SLIP_HDRLEN); 224 } 225 } 226 227 static int 228 slinit(struct sl_softc *sc) 229 { 230 if (sc->sc_ep == NULL) 231 sc->sc_ep = kmalloc(SLBUFSIZE, M_DEVBUF, M_WAITOK); 232 sc->sc_buf = sc->sc_ep + SLBUFSIZE - SLRMAX; 233 sc->sc_mp = sc->sc_buf; 234 sl_compress_init(&sc->sc_comp, -1); 235 236 return (1); 237 } 238 239 /* 240 * Line specific open routine. 241 * Attach the given tty to the first available sl unit. 242 */ 243 /* ARGSUSED */ 244 static int 245 slopen(cdev_t dev, struct tty *tp) 246 { 247 struct sl_softc *sc; 248 int nsl; 249 int error; 250 struct thread *td = curthread; /* XXX */ 251 252 error = priv_check(td, PRIV_ROOT); 253 if (error) 254 return (error); 255 256 lwkt_gettoken(&tty_token); 257 if (tp->t_line == SLIPDISC) { 258 lwkt_reltoken(&tty_token); 259 return (0); 260 } 261 262 for (nsl = NSL, sc = sl_softc; --nsl >= 0; sc++) { 263 if (sc->sc_ttyp == NULL && !(sc->sc_flags & SC_STATIC)) { 264 if (slinit(sc) == 0) { 265 lwkt_reltoken(&tty_token); 266 return (ENOBUFS); 267 } 268 tp->t_slsc = (caddr_t)sc; 269 sc->sc_ttyp = tp; 270 sc->sc_if.if_baudrate = tp->t_ospeed; 271 ttyflush(tp, FREAD | FWRITE); 272 273 tp->t_line = SLIPDISC; 274 /* 275 * We don't use t_canq or t_rawq, so reduce their 276 * cblock resources to 0. Reserve enough cblocks 277 * for t_outq to guarantee that we can fit a full 278 * packet if the SLIP_HIWAT check allows slstart() 279 * to loop. Use the same value for the cblock 280 * limit since the reserved blocks should always 281 * be enough. Reserving cblocks probably makes 282 * the CLISTRESERVE check unnecessary and wasteful. 283 */ 284 clist_alloc_cblocks(&tp->t_canq, 0); 285 clist_alloc_cblocks(&tp->t_outq, 286 SLIP_HIWAT + 2 * sc->sc_if.if_mtu + 1); 287 clist_alloc_cblocks(&tp->t_rawq, 0); 288 289 if_up(&sc->sc_if); 290 lwkt_reltoken(&tty_token); 291 return (0); 292 } 293 } 294 lwkt_reltoken(&tty_token); 295 296 return (ENXIO); 297 } 298 299 /* 300 * Line specific close routine. 301 * Detach the tty from the sl unit. 302 */ 303 static int 304 slclose(struct tty *tp, int flag) 305 { 306 struct sl_softc *sc; 307 308 lwkt_gettoken(&tty_token); 309 lwkt_gettoken(&tp->t_token); 310 ttyflush(tp, FREAD | FWRITE); 311 312 clist_free_cblocks(&tp->t_outq); 313 tp->t_line = 0; 314 sc = (struct sl_softc *)tp->t_slsc; 315 if (sc != NULL) { 316 if (sc->sc_outfill) { 317 sc->sc_outfill = 0; 318 callout_stop(&sc->sc_oftimeout); 319 } 320 if (sc->sc_keepalive) { 321 sc->sc_keepalive = 0; 322 callout_stop(&sc->sc_katimeout); 323 } 324 if_down(&sc->sc_if); 325 sc->sc_flags &= SC_STATIC; 326 sc->sc_ttyp = NULL; 327 tp->t_slsc = NULL; 328 if (sc->sc_ep) { 329 kfree(sc->sc_ep, M_DEVBUF); 330 sc->sc_ep = NULL; 331 } 332 sc->sc_mp = 0; 333 sc->sc_buf = 0; 334 } 335 lwkt_reltoken(&tp->t_token); 336 lwkt_reltoken(&tty_token); 337 338 return 0; 339 } 340 341 /* 342 * Line specific (tty) ioctl routine. 343 * Provide a way to get the sl unit number. 344 */ 345 /* ARGSUSED */ 346 static int 347 sltioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct ucred *cred) 348 { 349 struct sl_softc *sc = (struct sl_softc *)tp->t_slsc, *nc, *tmpnc; 350 int nsl; 351 352 lwkt_gettoken(&tty_token); 353 lwkt_gettoken(&tp->t_token); 354 355 switch (cmd) { 356 case SLIOCGUNIT: 357 *(int *)data = sc->sc_if.if_dunit; 358 break; 359 360 case SLIOCSUNIT: 361 if (sc->sc_if.if_dunit != *(u_int *)data) { 362 for (nsl = NSL, nc = sl_softc; --nsl >= 0; nc++) { 363 if ( nc->sc_if.if_dunit == *(u_int *)data 364 && nc->sc_ttyp == NULL 365 ) { 366 tmpnc = kmalloc(sizeof *tmpnc, M_TEMP, 367 M_WAITOK); 368 *tmpnc = *nc; 369 *nc = *sc; 370 nc->sc_if = tmpnc->sc_if; 371 tmpnc->sc_if = sc->sc_if; 372 *sc = *tmpnc; 373 kfree(tmpnc, M_TEMP); 374 if (sc->sc_if.if_flags & IFF_UP) { 375 if_down(&sc->sc_if); 376 if (!(nc->sc_if.if_flags & IFF_UP)) 377 if_up(&nc->sc_if); 378 } else if (nc->sc_if.if_flags & IFF_UP) 379 if_down(&nc->sc_if); 380 sc->sc_flags &= ~SC_STATIC; 381 sc->sc_flags |= (nc->sc_flags & SC_STATIC); 382 tp->t_slsc = sc = nc; 383 clist_alloc_cblocks(&tp->t_outq, 384 SLIP_HIWAT + 385 2 * sc->sc_if.if_mtu + 1); 386 sl_compress_init(&sc->sc_comp, -1); 387 goto slfound; 388 } 389 } 390 lwkt_reltoken(&tp->t_token); 391 lwkt_reltoken(&tty_token); 392 return (ENXIO); 393 } 394 slfound: 395 sc->sc_flags |= SC_STATIC; 396 break; 397 398 case SLIOCSKEEPAL: 399 sc->sc_keepalive = *(u_int *)data * hz; 400 if (sc->sc_keepalive) { 401 sc->sc_flags |= SC_KEEPALIVE; 402 callout_reset(&sc->sc_katimeout, sc->sc_keepalive, 403 sl_keepalive, sc); 404 } else { 405 if ((sc->sc_flags & SC_KEEPALIVE) != 0) { 406 callout_stop(&sc->sc_katimeout); 407 sc->sc_flags &= ~SC_KEEPALIVE; 408 } 409 } 410 break; 411 412 case SLIOCGKEEPAL: 413 *(int *)data = sc->sc_keepalive / hz; 414 break; 415 416 case SLIOCSOUTFILL: 417 sc->sc_outfill = *(u_int *)data * hz; 418 if (sc->sc_outfill) { 419 sc->sc_flags |= SC_OUTWAIT; 420 callout_reset(&sc->sc_oftimeout, sc->sc_outfill, 421 sl_outfill, sc); 422 } else { 423 if ((sc->sc_flags & SC_OUTWAIT) != 0) { 424 callout_stop(&sc->sc_oftimeout); 425 sc->sc_flags &= ~SC_OUTWAIT; 426 } 427 } 428 break; 429 430 case SLIOCGOUTFILL: 431 *(int *)data = sc->sc_outfill / hz; 432 break; 433 434 default: 435 lwkt_reltoken(&tp->t_token); 436 lwkt_reltoken(&tty_token); 437 return (ENOIOCTL); 438 } 439 lwkt_reltoken(&tp->t_token); 440 lwkt_reltoken(&tty_token); 441 442 return (0); 443 } 444 445 /* 446 * Queue a packet. Start transmission if not active. 447 * Compression happens in slstart; if we do it here, IP TOS 448 * will cause us to not compress "background" packets, because 449 * ordering gets trashed. It can be done for all packets in slstart. 450 */ 451 static int 452 sloutput_serialized(struct ifnet *ifp, struct ifaltq_subque *ifsq, 453 struct mbuf *m, struct sockaddr *dst, struct rtentry *rtp) 454 { 455 struct sl_softc *sc = &sl_softc[ifp->if_dunit]; 456 struct ip *ip; 457 int error; 458 struct altq_pktattr pktattr; 459 460 ifq_classify(&ifp->if_snd, m, dst->sa_family, &pktattr); 461 462 /* 463 * `Cannot happen' (see slioctl). Someday we will extend 464 * the line protocol to support other address families. 465 */ 466 if (dst->sa_family != AF_INET) { 467 kprintf("%s: af%d not supported\n", sc->sc_if.if_xname, 468 dst->sa_family); 469 m_freem(m); 470 IFNET_STAT_INC(&sc->sc_if, noproto, 1); 471 return (EAFNOSUPPORT); 472 } 473 474 if (sc->sc_ttyp == NULL || !(ifp->if_flags & IFF_UP)) { 475 m_freem(m); 476 return (ENETDOWN); 477 } 478 if ((sc->sc_ttyp->t_state & TS_CONNECTED) == 0) { 479 m_freem(m); 480 return (EHOSTUNREACH); 481 } 482 ip = mtod(m, struct ip *); 483 if (sc->sc_if.if_flags & SC_NOICMP && ip->ip_p == IPPROTO_ICMP) { 484 m_freem(m); 485 return (ENETRESET); /* XXX ? */ 486 } 487 488 if ((ip->ip_tos & IPTOS_LOWDELAY) && 489 !ifq_is_enabled(&sc->sc_if.if_snd)) { 490 if (IF_QFULL(&sc->sc_fastq)) { 491 IF_DROP(&sc->sc_fastq); 492 m_freem(m); 493 error = ENOBUFS; 494 } else { 495 IF_ENQUEUE(&sc->sc_fastq, m); 496 error = 0; 497 } 498 } else { 499 error = ifsq_enqueue(ifsq, m, &pktattr); 500 } 501 if (error) { 502 IFNET_STAT_INC(&sc->sc_if, oqdrops, 1); 503 return (error); 504 } 505 if (sc->sc_ttyp->t_outq.c_cc == 0) 506 slstart(sc->sc_ttyp); 507 return (0); 508 } 509 510 static int 511 sloutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 512 struct rtentry *rtp) 513 { 514 struct ifaltq_subque *ifsq = ifq_get_subq_default(&ifp->if_snd); 515 int error; 516 517 ifsq_serialize_hw(ifsq); 518 error = sloutput_serialized(ifp, ifsq, m, dst, rtp); 519 ifsq_deserialize_hw(ifsq); 520 521 return error; 522 } 523 524 /* 525 * Start output on interface. Get another datagram 526 * to send from the interface queue and map it to 527 * the interface before starting output. 528 */ 529 static int 530 slstart(struct tty *tp) 531 { 532 struct sl_softc *sc = (struct sl_softc *)tp->t_slsc; 533 struct ifaltq_subque *ifsq = ifq_get_subq_default(&sc->sc_if.if_snd); 534 struct mbuf *m; 535 u_char *cp; 536 struct ip *ip; 537 u_char bpfbuf[SLTMAX + SLIP_HDRLEN]; 538 int len = 0; 539 540 lwkt_gettoken(&tp->t_token); 541 for (;;) { 542 /* 543 * Call output process whether or not there is more in the 544 * output queue. We are being called in lieu of ttstart 545 * and must do what it would. 546 */ 547 (*tp->t_oproc)(tp); 548 549 if (tp->t_outq.c_cc != 0) { 550 if (sc != NULL) 551 sc->sc_flags &= ~SC_OUTWAIT; 552 if (tp->t_outq.c_cc > SLIP_HIWAT) { 553 lwkt_reltoken(&tp->t_token); 554 return 0; 555 } 556 } 557 558 /* 559 * This happens briefly when the line shuts down. 560 */ 561 if (sc == NULL) { 562 lwkt_reltoken(&tp->t_token); 563 return 0; 564 } 565 566 /* 567 * Get a packet and send it to the interface. 568 */ 569 IF_DEQUEUE(&sc->sc_fastq, m); 570 if (m) 571 IFNET_STAT_INC(&sc->sc_if, omcasts, 1); /* XXX */ 572 else 573 m = ifsq_dequeue(ifsq); 574 if (m == NULL) { 575 lwkt_reltoken(&tp->t_token); 576 return 0; 577 } 578 579 /* 580 * We do the header compression here rather than in sloutput 581 * because the packets will be out of order if we are using TOS 582 * queueing, and the connection id compression will get 583 * munged when this happens. 584 */ 585 if (sc->sc_if.if_bpf) { 586 /* 587 * We need to save the TCP/IP header before it's 588 * compressed. To avoid complicated code, we just 589 * copy the entire packet into a stack buffer (since 590 * this is a serial line, packets should be short 591 * and/or the copy should be negligible cost compared 592 * to the packet transmission time). 593 */ 594 struct mbuf *m1 = m; 595 u_char *cp = bpfbuf + SLIP_HDRLEN; 596 597 len = 0; 598 do { 599 int mlen = m1->m_len; 600 601 bcopy(mtod(m1, caddr_t), cp, mlen); 602 cp += mlen; 603 len += mlen; 604 } while ((m1 = m1->m_next) != NULL); 605 } 606 ip = mtod(m, struct ip *); 607 if (ip->ip_v == IPVERSION && ip->ip_p == IPPROTO_TCP) { 608 if (sc->sc_if.if_flags & SC_COMPRESS) 609 *mtod(m, u_char *) |= sl_compress_tcp(m, ip, 610 &sc->sc_comp, 1); 611 } 612 if (sc->sc_if.if_bpf) { 613 bpf_gettoken(); 614 615 if (sc->sc_if.if_bpf) { 616 /* 617 * Put the SLIP pseudo-"link header" in place. 618 * The compressed header is now at the 619 * beginning of the mbuf. 620 */ 621 bpfbuf[SLX_DIR] = SLIPDIR_OUT; 622 bcopy(mtod(m, caddr_t), &bpfbuf[SLX_CHDR], 623 CHDR_LEN); 624 bpf_tap(sc->sc_if.if_bpf, bpfbuf, 625 len + SLIP_HDRLEN); 626 } 627 628 bpf_reltoken(); 629 } 630 631 sc->sc_flags &= ~SC_OUTWAIT; 632 633 /* 634 * The extra FRAME_END will start up a new packet, and thus 635 * will flush any accumulated garbage. We do this whenever 636 * the line may have been idle for some time. 637 */ 638 if (tp->t_outq.c_cc == 0) { 639 IFNET_STAT_INC(&sc->sc_if, obytes, 1); 640 clist_putc(FRAME_END, &tp->t_outq); 641 } 642 643 while (m) { 644 u_char *ep; 645 646 cp = mtod(m, u_char *); ep = cp + m->m_len; 647 while (cp < ep) { 648 /* 649 * Find out how many bytes in the string we can 650 * handle without doing something special. 651 */ 652 u_char *bp = cp; 653 654 while (cp < ep) { 655 switch (*cp++) { 656 case FRAME_ESCAPE: 657 case FRAME_END: 658 --cp; 659 goto out; 660 } 661 } 662 out: 663 if (cp > bp) { 664 /* 665 * Put n characters at once 666 * into the tty output queue. 667 */ 668 if (clist_btoq((char *)bp, cp - bp, 669 &tp->t_outq)) { 670 break; 671 } 672 IFNET_STAT_INC(&sc->sc_if, obytes, 673 cp - bp); 674 } 675 /* 676 * If there are characters left in the mbuf, 677 * the first one must be special.. 678 * Put it out in a different form. 679 */ 680 if (cp < ep) { 681 if (clist_putc(FRAME_ESCAPE, &tp->t_outq)) 682 break; 683 if (clist_putc(*cp++ == FRAME_ESCAPE ? 684 TRANS_FRAME_ESCAPE : TRANS_FRAME_END, 685 &tp->t_outq)) { 686 clist_unputc(&tp->t_outq); 687 break; 688 } 689 IFNET_STAT_INC(&sc->sc_if, obytes, 2); 690 } 691 } 692 m = m_free(m); 693 } 694 695 if (clist_putc(FRAME_END, &tp->t_outq)) { 696 /* 697 * Not enough room. Remove a char to make room 698 * and end the packet normally. 699 * If you get many collisions (more than one or two 700 * a day) you probably do not have enough clists 701 * and you should increase "nclist" in param.c. 702 */ 703 clist_unputc(&tp->t_outq); 704 clist_putc(FRAME_END, &tp->t_outq); 705 IFNET_STAT_INC(&sc->sc_if, collisions, 1); 706 } else { 707 IFNET_STAT_INC(&sc->sc_if, obytes, 1); 708 IFNET_STAT_INC(&sc->sc_if, opackets, 1); 709 } 710 } 711 lwkt_reltoken(&tp->t_token); 712 713 return 0; 714 } 715 716 /* 717 * Copy data buffer to mbuf chain; add ifnet pointer. 718 */ 719 static struct mbuf * 720 sl_btom(struct sl_softc *sc, int len) 721 { 722 struct mbuf *m; 723 724 if (len >= MCLBYTES) 725 return (NULL); 726 727 MGETHDR(m, M_NOWAIT, MT_DATA); 728 if (m == NULL) 729 return (NULL); 730 731 /* 732 * If we have more than MHLEN bytes, it's cheaper to 733 * queue the cluster we just filled & allocate a new one 734 * for the input buffer. Otherwise, fill the mbuf we 735 * allocated above. Note that code in the input routine 736 * guarantees that packet will fit in a cluster. 737 */ 738 if (len >= MHLEN) { 739 MCLGET(m, M_NOWAIT); 740 if ((m->m_flags & M_EXT) == 0) { 741 /* 742 * we couldn't get a cluster - if memory's this 743 * low, it's time to start dropping packets. 744 */ 745 m_free(m); 746 return (NULL); 747 } 748 } 749 bcopy((caddr_t)sc->sc_buf, mtod(m, caddr_t), len); 750 m->m_len = len; 751 m->m_pkthdr.len = len; 752 m->m_pkthdr.rcvif = &sc->sc_if; 753 return (m); 754 } 755 756 /* 757 * tty interface receiver interrupt. 758 */ 759 static int 760 slinput(int c, struct tty *tp) 761 { 762 struct sl_softc *sc; 763 struct mbuf *m; 764 int len; 765 u_char chdr[CHDR_LEN]; 766 767 #if 0 768 kprintf(" %02x", (unsigned char)c); 769 if ((unsigned char)c == 0xC0) 770 kprintf("\n"); 771 #endif 772 773 lwkt_gettoken(&tp->t_token); 774 tk_nin++; 775 sc = (struct sl_softc *)tp->t_slsc; 776 if (sc == NULL) { 777 lwkt_reltoken(&tp->t_token); 778 #if 0 779 kprintf("X"); 780 #endif 781 return 0; 782 } 783 if (c & TTY_ERRORMASK || (tp->t_state & TS_CONNECTED) == 0) { 784 sc->sc_flags |= SC_ERROR; 785 lwkt_reltoken(&tp->t_token); 786 #if 0 787 kprintf("Y"); 788 #endif 789 return 0; 790 } 791 c &= TTY_CHARMASK; 792 793 IFNET_STAT_INC(&sc->sc_if, ibytes, 1); 794 795 if (sc->sc_if.if_flags & IFF_DEBUG) { 796 if (c == ABT_ESC) { 797 /* 798 * If we have a previous abort, see whether 799 * this one is within the time limit. 800 */ 801 if (sc->sc_abortcount && 802 time_uptime >= sc->sc_starttime + ABT_WINDOW) 803 sc->sc_abortcount = 0; 804 /* 805 * If we see an abort after "idle" time, count it; 806 * record when the first abort escape arrived. 807 */ 808 if (time_uptime >= sc->sc_lasttime + ABT_IDLE) { 809 if (++sc->sc_abortcount == 1) 810 sc->sc_starttime = time_uptime; 811 if (sc->sc_abortcount >= ABT_COUNT) { 812 slclose(tp,0); 813 lwkt_reltoken(&tp->t_token); 814 return 0; 815 } 816 } 817 } else 818 sc->sc_abortcount = 0; 819 sc->sc_lasttime = time_uptime; 820 } 821 822 switch (c) { 823 824 case TRANS_FRAME_ESCAPE: 825 if (sc->sc_escape) 826 c = FRAME_ESCAPE; 827 break; 828 829 case TRANS_FRAME_END: 830 if (sc->sc_escape) 831 c = FRAME_END; 832 break; 833 834 case FRAME_ESCAPE: 835 sc->sc_escape = 1; 836 lwkt_reltoken(&tp->t_token); 837 return 0; 838 839 case FRAME_END: 840 sc->sc_flags &= ~SC_KEEPALIVE; 841 if(sc->sc_flags & SC_ERROR) { 842 sc->sc_flags &= ~SC_ERROR; 843 goto newpack; 844 } 845 len = sc->sc_mp - sc->sc_buf; 846 if (len < 3) 847 /* less than min length packet - ignore */ 848 goto newpack; 849 850 if (sc->sc_if.if_bpf) { 851 /* 852 * Save the compressed header, so we 853 * can tack it on later. Note that we 854 * will end up copying garbage in some 855 * cases but this is okay. We remember 856 * where the buffer started so we can 857 * compute the new header length. 858 */ 859 bcopy(sc->sc_buf, chdr, CHDR_LEN); 860 } 861 862 if ((c = (*sc->sc_buf & 0xf0)) != (IPVERSION << 4)) { 863 if (c & 0x80) 864 c = TYPE_COMPRESSED_TCP; 865 else if (c == TYPE_UNCOMPRESSED_TCP) 866 *sc->sc_buf &= 0x4f; /* XXX */ 867 /* 868 * We've got something that's not an IP packet. 869 * If compression is enabled, try to decompress it. 870 * Otherwise, if `auto-enable' compression is on and 871 * it's a reasonable packet, decompress it and then 872 * enable compression. Otherwise, drop it. 873 */ 874 if (sc->sc_if.if_flags & SC_COMPRESS) { 875 len = sl_uncompress_tcp(&sc->sc_buf, len, 876 (u_int)c, &sc->sc_comp); 877 if (len <= 0) 878 goto error; 879 } else if ((sc->sc_if.if_flags & SC_AUTOCOMP) && 880 c == TYPE_UNCOMPRESSED_TCP && len >= 40) { 881 len = sl_uncompress_tcp(&sc->sc_buf, len, 882 (u_int)c, &sc->sc_comp); 883 if (len <= 0) 884 goto error; 885 sc->sc_if.if_flags |= SC_COMPRESS; 886 } else 887 goto error; 888 } 889 if (sc->sc_if.if_bpf) { 890 bpf_gettoken(); 891 892 if (sc->sc_if.if_bpf) { 893 /* 894 * Put the SLIP pseudo-"link header" in place. 895 * We couldn't do this any earlier since 896 * decompression probably moved the buffer 897 * pointer. Then, invoke BPF. 898 */ 899 u_char *hp = sc->sc_buf - SLIP_HDRLEN; 900 901 hp[SLX_DIR] = SLIPDIR_IN; 902 bcopy(chdr, &hp[SLX_CHDR], CHDR_LEN); 903 bpf_tap(sc->sc_if.if_bpf, hp, 904 len + SLIP_HDRLEN); 905 } 906 907 bpf_reltoken(); 908 } 909 m = sl_btom(sc, len); 910 if (m == NULL) 911 goto error; 912 913 IFNET_STAT_INC(&sc->sc_if, ipackets, 1); 914 915 if ((sc->sc_if.if_flags & IFF_UP) == 0) { 916 m_freem(m); 917 goto newpack; 918 } 919 920 if (netisr_queue(NETISR_IP, m)) { 921 IFNET_STAT_INC(&sc->sc_if, ierrors, 1); 922 IFNET_STAT_INC(&sc->sc_if, iqdrops, 1); 923 } 924 925 goto newpack; 926 } 927 if (sc->sc_mp < sc->sc_ep + SLBUFSIZE) { 928 *sc->sc_mp++ = c; 929 sc->sc_escape = 0; 930 lwkt_reltoken(&tp->t_token); 931 return 0; 932 } 933 934 /* can't put lower; would miss an extra frame */ 935 sc->sc_flags |= SC_ERROR; 936 937 error: 938 IFNET_STAT_INC(&sc->sc_if, ierrors, 1); 939 newpack: 940 sc->sc_mp = sc->sc_buf = sc->sc_ep + SLBUFSIZE - SLRMAX; 941 sc->sc_escape = 0; 942 lwkt_reltoken(&tp->t_token); 943 944 return 0; 945 } 946 947 /* 948 * Process an ioctl request. 949 */ 950 static int 951 slioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr) 952 { 953 struct ifaddr *ifa = (struct ifaddr *)data; 954 struct ifreq *ifr = (struct ifreq *)data; 955 int error = 0; 956 957 switch (cmd) { 958 959 case SIOCSIFFLAGS: 960 /* 961 * if.c will set the interface up even if we 962 * don't want it to. 963 */ 964 if (sl_softc[ifp->if_dunit].sc_ttyp == NULL) { 965 ifp->if_flags &= ~IFF_UP; 966 } 967 break; 968 case SIOCSIFADDR: 969 /* 970 * This is "historical" - set the interface up when 971 * setting the address. 972 */ 973 if (ifa->ifa_addr->sa_family == AF_INET) { 974 if (sl_softc[ifp->if_dunit].sc_ttyp != NULL) 975 ifp->if_flags |= IFF_UP; 976 } else { 977 error = EAFNOSUPPORT; 978 } 979 break; 980 981 case SIOCSIFDSTADDR: 982 if (ifa->ifa_addr->sa_family != AF_INET) 983 error = EAFNOSUPPORT; 984 break; 985 986 case SIOCADDMULTI: 987 case SIOCDELMULTI: 988 break; 989 990 case SIOCSIFMTU: 991 /* 992 * Set the interface MTU. 993 */ 994 if (ifr->ifr_mtu > SLTMAX) 995 error = EINVAL; 996 else { 997 struct tty *tp; 998 999 ifp->if_mtu = ifr->ifr_mtu; 1000 tp = sl_softc[ifp->if_dunit].sc_ttyp; 1001 if (tp != NULL) 1002 clist_alloc_cblocks(&tp->t_outq, 1003 SLIP_HIWAT + 2 * ifp->if_mtu + 1); 1004 } 1005 break; 1006 1007 default: 1008 error = EINVAL; 1009 } 1010 return (error); 1011 } 1012 1013 static void 1014 sl_keepalive(void *chan) 1015 { 1016 struct sl_softc *sc = chan; 1017 struct tty *tp = sc->sc_ttyp; 1018 struct pgrp *pg; 1019 1020 lwkt_gettoken(&tp->t_token); 1021 if (sc->sc_keepalive) { 1022 if (sc->sc_flags & SC_KEEPALIVE) { 1023 pg = sc->sc_ttyp->t_pgrp; 1024 if (pg) { 1025 pgref(pg); 1026 pgsignal (pg, SIGURG, 1); 1027 pgrel(pg); 1028 } 1029 } else { 1030 sc->sc_flags |= SC_KEEPALIVE; 1031 } 1032 callout_reset(&sc->sc_katimeout, sc->sc_keepalive, 1033 sl_keepalive, sc); 1034 } else { 1035 sc->sc_flags &= ~SC_KEEPALIVE; 1036 } 1037 lwkt_reltoken(&tp->t_token); 1038 } 1039 1040 static void 1041 sl_outfill(void *chan) 1042 { 1043 struct sl_softc *sc = chan; 1044 struct tty *tp = sc->sc_ttyp; 1045 1046 lwkt_gettoken(&tp->t_token); 1047 1048 if (sc->sc_outfill && tp != NULL) { 1049 if (sc->sc_flags & SC_OUTWAIT) { 1050 IFNET_STAT_INC(&sc->sc_if, obytes, 1); 1051 clist_putc(FRAME_END, &tp->t_outq); 1052 (*tp->t_oproc)(tp); 1053 } else 1054 sc->sc_flags |= SC_OUTWAIT; 1055 callout_reset(&sc->sc_oftimeout, sc->sc_outfill, 1056 sl_outfill, sc); 1057 } else { 1058 sc->sc_flags &= ~SC_OUTWAIT; 1059 } 1060 lwkt_reltoken(&tp->t_token); 1061 } 1062 1063 MODULE_VERSION(if_sl, 1); 1064