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