1 /* $NetBSD: if_ppp.c,v 1.21 1995/03/08 02:56:58 cgd Exp $ */ 2 3 /* 4 * if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver. 5 * 6 * Copyright (c) 1989 Carnegie Mellon University. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms are permitted 10 * provided that the above copyright notice and this paragraph are 11 * duplicated in all such forms and that any documentation, 12 * advertising materials, and other materials related to such 13 * distribution and use acknowledge that the software was developed 14 * by Carnegie Mellon University. The name of the 15 * University may not be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 19 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 * 21 * Drew D. Perkins 22 * Carnegie Mellon University 23 * 4910 Forbes Ave. 24 * Pittsburgh, PA 15213 25 * (412) 268-8576 26 * ddp@andrew.cmu.edu 27 * 28 * Based on: 29 * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89 30 * 31 * Copyright (c) 1987 Regents of the University of California. 32 * All rights reserved. 33 * 34 * Redistribution and use in source and binary forms are permitted 35 * provided that the above copyright notice and this paragraph are 36 * duplicated in all such forms and that any documentation, 37 * advertising materials, and other materials related to such 38 * distribution and use acknowledge that the software was developed 39 * by the University of California, Berkeley. The name of the 40 * University may not be used to endorse or promote products derived 41 * from this software without specific prior written permission. 42 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 43 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 44 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 45 * 46 * Serial Line interface 47 * 48 * Rick Adams 49 * Center for Seismic Studies 50 * 1300 N 17th Street, Suite 1450 51 * Arlington, Virginia 22209 52 * (703)276-7900 53 * rick@seismo.ARPA 54 * seismo!rick 55 * 56 * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris). 57 * Converted to 4.3BSD Beta by Chris Torek. 58 * Other changes made at Berkeley, based in part on code by Kirk Smith. 59 * 60 * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com) 61 * Added VJ tcp header compression; more unified ioctls 62 * 63 * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au). 64 * Cleaned up a lot of the mbuf-related code to fix bugs that 65 * caused system crashes and packet corruption. Changed pppstart 66 * so that it doesn't just give up with a collision if the whole 67 * packet doesn't fit in the output ring buffer. 68 * 69 * Added priority queueing for interactive IP packets, following 70 * the model of if_sl.c, plus hooks for bpf. 71 * Paul Mackerras (paulus@cs.anu.edu.au). 72 */ 73 74 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */ 75 76 #include "ppp.h" 77 #if NPPP > 0 78 79 #define VJC 80 81 #include <sys/param.h> 82 #include <sys/proc.h> 83 #include <sys/mbuf.h> 84 #include <sys/buf.h> 85 #include <sys/dkstat.h> 86 #include <sys/socket.h> 87 #include <sys/ioctl.h> 88 #include <sys/file.h> 89 #include <sys/tty.h> 90 #include <sys/kernel.h> 91 #include <sys/conf.h> 92 #include <sys/vnode.h> 93 94 #include <net/if.h> 95 #include <net/if_types.h> 96 #include <net/netisr.h> 97 #include <net/route.h> 98 99 #if INET 100 #include <netinet/in.h> 101 #include <netinet/in_systm.h> 102 #include <netinet/in_var.h> 103 #include <netinet/ip.h> 104 #endif 105 106 #include "bpfilter.h" 107 #if NBPFILTER > 0 108 #include <sys/time.h> 109 #include <net/bpf.h> 110 #endif 111 112 #ifdef VJC 113 #include <net/slcompress.h> 114 #define HDROFF MAX_HDR 115 /* HDROFF should really be 128, but other parts of the system will 116 panic on TCP+IP headers bigger than MAX_HDR = MHLEN (100). */ 117 118 #else 119 #define HDROFF (0) 120 #endif 121 122 #include <net/if_ppp.h> 123 #include <machine/cpu.h> 124 125 /* This is a NetBSD-current kernel. */ 126 #define CCOUNT(q) ((q)->c_cc) 127 128 #define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */ 129 130 struct ppp_softc ppp_softc[NPPP]; 131 132 void pppattach __P((void)); 133 int pppopen __P((dev_t dev, struct tty *tp)); 134 void pppclose __P((struct tty *tp, int flag)); 135 int pppread __P((struct tty *tp, struct uio *uio, int flag)); 136 int pppwrite __P((struct tty *tp, struct uio *uio, int flag)); 137 int ppptioctl __P((struct tty *tp, u_long cmd, caddr_t data, int flag, 138 struct proc *)); 139 int pppoutput __P((struct ifnet *ifp, struct mbuf *m0, 140 struct sockaddr *dst, struct rtentry *rtp)); 141 void pppinput __P((int c, struct tty *tp)); 142 int pppioctl __P((struct ifnet *ifp, u_long cmd, caddr_t data)); 143 void pppstart __P((struct tty *tp)); 144 145 static int pppasyncstart __P((struct ppp_softc *)); 146 static u_int16_t pppfcs __P((u_int fcs, u_char *cp, int len)); 147 static int pppgetm __P((struct ppp_softc *sc)); 148 static void pppdumpm __P((struct mbuf *m0, int pktlen)); 149 static void pppdumpb __P((u_char *b, int l)); 150 static void ppplogchar __P((struct ppp_softc *, int)); 151 152 /* 153 * Some useful mbuf macros not in mbuf.h. 154 */ 155 #define M_DATASTART(m) \ 156 ((m)->m_flags & M_EXT ? (m)->m_ext.ext_buf : \ 157 (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat) 158 159 #define M_DATASIZE(m) \ 160 ((m)->m_flags & M_EXT ? (m)->m_ext.ext_size : \ 161 (m)->m_flags & M_PKTHDR ? MHLEN: MLEN) 162 163 /* 164 * The following disgusting hack gets around the problem that IP TOS 165 * can't be set yet. We want to put "interactive" traffic on a high 166 * priority queue. To decide if traffic is interactive, we check that 167 * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. 168 */ 169 static u_int16_t interactive_ports[8] = { 170 0, 513, 0, 0, 171 0, 21, 0, 23, 172 }; 173 #define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) 174 175 /* 176 * Does c need to be escaped? 177 */ 178 #define ESCAPE_P(c) (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F))) 179 180 /* 181 * Called from boot code to establish ppp interfaces. 182 */ 183 void 184 pppattach() 185 { 186 register struct ppp_softc *sc; 187 register int i = 0; 188 189 for (sc = ppp_softc; i < NPPP; sc++) { 190 sc->sc_if.if_name = "ppp"; 191 sc->sc_if.if_unit = i++; 192 sc->sc_if.if_mtu = PPP_MTU; 193 sc->sc_if.if_flags = IFF_POINTOPOINT; 194 sc->sc_if.if_type = IFT_PPP; 195 sc->sc_if.if_hdrlen = PPP_HDRLEN; 196 sc->sc_if.if_ioctl = pppioctl; 197 sc->sc_if.if_output = pppoutput; 198 sc->sc_if.if_snd.ifq_maxlen = IFQ_MAXLEN; 199 sc->sc_inq.ifq_maxlen = IFQ_MAXLEN; 200 sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN; 201 if_attach(&sc->sc_if); 202 #if NBPFILTER > 0 203 bpfattach(&sc->sc_bpf, &sc->sc_if, DLT_PPP, PPP_HDRLEN); 204 #endif 205 } 206 } 207 208 /* 209 * Allocate a ppp interface unit and initialize it. 210 */ 211 struct ppp_softc * 212 pppalloc(pid) 213 pid_t pid; 214 { 215 int nppp; 216 struct ppp_softc *sc; 217 218 for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++) 219 if (sc->sc_xfer == pid) { 220 sc->sc_xfer = 0; 221 break; 222 } 223 if (nppp >= NPPP) 224 for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++) 225 if (sc->sc_devp == NULL) 226 break; 227 if (nppp >= NPPP) 228 return NULL; 229 230 sc->sc_flags = 0; 231 sc->sc_mru = PPP_MRU; 232 #ifdef VJC 233 sl_compress_init(&sc->sc_comp, -1); 234 #endif 235 sc->sc_if.if_flags |= IFF_RUNNING; 236 237 return sc; 238 } 239 240 /* 241 * Deallocate a ppp unit. 242 */ 243 pppdealloc(sc) 244 struct ppp_softc *sc; 245 { 246 struct mbuf *m; 247 248 if_down(&sc->sc_if); 249 sc->sc_devp = NULL; 250 sc->sc_xfer = 0; 251 for (;;) { 252 IF_DEQUEUE(&sc->sc_inq, m); 253 if (m == NULL) 254 break; 255 m_freem(m); 256 } 257 for (;;) { 258 IF_DEQUEUE(&sc->sc_fastq, m); 259 if (m == NULL) 260 break; 261 m_freem(m); 262 } 263 sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING); 264 } 265 266 /* 267 * Line specific open routine for async tty devices. 268 * Attach the given tty to the first available ppp unit. 269 */ 270 /* ARGSUSED */ 271 int 272 pppopen(dev, tp) 273 dev_t dev; 274 register struct tty *tp; 275 { 276 struct proc *p = curproc; /* XXX */ 277 register struct ppp_softc *sc; 278 int error, s, i; 279 280 if (error = suser(p->p_ucred, &p->p_acflag)) 281 return (error); 282 283 if (tp->t_line == PPPDISC) { 284 sc = (struct ppp_softc *) tp->t_sc; 285 if (sc != NULL && sc->sc_devp == (void *) tp) 286 return (0); 287 } 288 289 if ((sc = pppalloc(p->p_pid)) == NULL) 290 return ENXIO; 291 292 if (sc->sc_outm != NULL) { 293 m_freem(sc->sc_outm); 294 sc->sc_outm = NULL; 295 } 296 297 pppgetm(sc); 298 299 sc->sc_ilen = 0; 300 bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap)); 301 sc->sc_asyncmap[0] = 0xffffffff; 302 sc->sc_asyncmap[3] = 0x60000000; 303 sc->sc_rasyncmap = 0; 304 sc->sc_devp = (void *) tp; 305 sc->sc_start = pppasyncstart; 306 307 tp->t_sc = (caddr_t) sc; 308 ttyflush(tp, FREAD | FWRITE); 309 310 return (0); 311 } 312 313 /* 314 * Line specific close routine. 315 * Detach the tty from the ppp unit. 316 * Mimics part of ttyclose(). 317 */ 318 void 319 pppclose(tp, flag) 320 struct tty *tp; 321 int flag; 322 { 323 register struct ppp_softc *sc; 324 struct mbuf *m; 325 int s; 326 327 ttywflush(tp); 328 s = splimp(); /* paranoid; splnet probably ok */ 329 tp->t_line = 0; 330 sc = (struct ppp_softc *)tp->t_sc; 331 if (sc != NULL) { 332 tp->t_sc = NULL; 333 if (tp == (struct tty *) sc->sc_devp) { 334 m_freem(sc->sc_outm); 335 sc->sc_outm = NULL; 336 m_freem(sc->sc_m); 337 sc->sc_m = NULL; 338 pppdealloc(sc); 339 } 340 } 341 splx(s); 342 } 343 344 /* 345 * Line specific (tty) read routine. 346 */ 347 int 348 pppread(tp, uio, flag) 349 register struct tty *tp; 350 struct uio *uio; 351 int flag; 352 { 353 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc; 354 struct mbuf *m, *m0; 355 register int s; 356 int error = 0; 357 358 if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0) 359 return 0; /* end of file */ 360 if (sc == NULL || tp != (struct tty *) sc->sc_devp) 361 return 0; 362 s = splimp(); 363 while (sc->sc_inq.ifq_head == NULL && tp->t_line == PPPDISC) { 364 if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) { 365 splx(s); 366 return (EWOULDBLOCK); 367 } 368 error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI|PCATCH, ttyin, 0); 369 if (error) { 370 splx(s); 371 return error; 372 } 373 } 374 if (tp->t_line != PPPDISC) { 375 splx(s); 376 return (-1); 377 } 378 379 /* Pull place-holder byte out of canonical queue */ 380 getc(&tp->t_canq); 381 382 /* Get the packet from the input queue */ 383 IF_DEQUEUE(&sc->sc_inq, m0); 384 splx(s); 385 386 for (m = m0; m && uio->uio_resid; m = m->m_next) 387 if (error = uiomove(mtod(m, u_char *), m->m_len, uio)) 388 break; 389 m_freem(m0); 390 return (error); 391 } 392 393 /* 394 * Line specific (tty) write routine. 395 */ 396 int 397 pppwrite(tp, uio, flag) 398 register struct tty *tp; 399 struct uio *uio; 400 int flag; 401 { 402 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc; 403 struct mbuf *m, *m0, **mp; 404 struct sockaddr dst; 405 struct ppp_header *ph1, *ph2; 406 int len, error; 407 408 if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0) 409 return 0; /* wrote 0 bytes */ 410 if (tp->t_line != PPPDISC) 411 return (EINVAL); 412 if (sc == NULL || tp != (struct tty *) sc->sc_devp) 413 return EIO; 414 if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN || 415 uio->uio_resid < PPP_HDRLEN) 416 return (EMSGSIZE); 417 for (mp = &m0; uio->uio_resid; mp = &m->m_next) { 418 MGET(m, M_WAIT, MT_DATA); 419 if ((*mp = m) == NULL) { 420 m_freem(m0); 421 return (ENOBUFS); 422 } 423 m->m_len = 0; 424 if (uio->uio_resid >= MCLBYTES / 2) 425 MCLGET(m, M_DONTWAIT); 426 len = M_TRAILINGSPACE(m); 427 if (len > uio->uio_resid) 428 len = uio->uio_resid; 429 if (error = uiomove(mtod(m, u_char *), len, uio)) { 430 m_freem(m0); 431 return (error); 432 } 433 m->m_len = len; 434 } 435 dst.sa_family = AF_UNSPEC; 436 ph1 = (struct ppp_header *) &dst.sa_data; 437 ph2 = mtod(m0, struct ppp_header *); 438 *ph1 = *ph2; 439 m0->m_data += PPP_HDRLEN; 440 m0->m_len -= PPP_HDRLEN; 441 return (pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0)); 442 } 443 444 /* 445 * Line specific (tty) ioctl routine. 446 * Provide a way to get the ppp unit number. 447 * This discipline requires that tty device drivers call 448 * the line specific l_ioctl routine from their ioctl routines. 449 */ 450 /* ARGSUSED */ 451 int 452 ppptioctl(tp, cmd, data, flag, p) 453 struct tty *tp; 454 u_long cmd; 455 caddr_t data; 456 int flag; 457 struct proc *p; 458 { 459 register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc; 460 int s, error, flags, mru; 461 462 if (sc == NULL || tp != (struct tty *) sc->sc_devp) 463 return -1; 464 465 switch (cmd) { 466 case FIONREAD: 467 *(int *)data = sc->sc_inq.ifq_len; 468 break; 469 470 case PPPIOCGUNIT: 471 *(int *)data = sc->sc_if.if_unit; 472 break; 473 474 case PPPIOCGFLAGS: 475 *(u_int *)data = sc->sc_flags; 476 break; 477 478 case PPPIOCSFLAGS: 479 if (error = suser(p->p_ucred, &p->p_acflag)) 480 return (error); 481 flags = *(int *)data & SC_MASK; 482 s = splimp(); 483 sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags; 484 splx(s); 485 break; 486 487 case PPPIOCSASYNCMAP: 488 if (error = suser(p->p_ucred, &p->p_acflag)) 489 return (error); 490 sc->sc_asyncmap[0] = *(u_int32_t *)data; 491 break; 492 493 case PPPIOCGASYNCMAP: 494 *(u_int32_t *)data = sc->sc_asyncmap[0]; 495 break; 496 497 case PPPIOCSRASYNCMAP: 498 if (error = suser(p->p_ucred, &p->p_acflag)) 499 return (error); 500 sc->sc_rasyncmap = *(u_int32_t *)data; 501 break; 502 503 case PPPIOCGRASYNCMAP: 504 *(u_int32_t *)data = sc->sc_rasyncmap; 505 break; 506 507 case PPPIOCSXASYNCMAP: 508 if (error = suser(p->p_ucred, &p->p_acflag)) 509 return (error); 510 bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap)); 511 sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */ 512 sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */ 513 sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */ 514 break; 515 516 case PPPIOCGXASYNCMAP: 517 bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap)); 518 break; 519 520 case PPPIOCSMRU: 521 if (error = suser(p->p_ucred, &p->p_acflag)) 522 return (error); 523 mru = *(int *)data; 524 if (mru >= PPP_MRU && mru <= PPP_MAXMRU) { 525 sc->sc_mru = mru; 526 pppgetm(sc); 527 } 528 break; 529 530 case PPPIOCGMRU: 531 *(int *)data = sc->sc_mru; 532 break; 533 534 #ifdef VJC 535 case PPPIOCSMAXCID: 536 if (error = suser(p->p_ucred, &p->p_acflag)) 537 return (error); 538 sl_compress_init(&sc->sc_comp, *(int *)data); 539 break; 540 #endif 541 542 case PPPIOCXFERUNIT: 543 if (error = suser(p->p_ucred, &p->p_acflag)) 544 return (error); 545 sc->sc_xfer = p->p_pid; 546 break; 547 548 default: 549 return (-1); 550 } 551 return (0); 552 } 553 554 /* 555 * FCS lookup table as calculated by genfcstab. 556 */ 557 static u_int16_t fcstab[256] = { 558 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 559 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 560 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 561 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 562 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 563 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 564 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 565 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 566 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 567 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 568 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 569 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 570 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 571 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 572 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 573 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 574 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 575 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 576 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 577 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 578 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 579 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 580 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 581 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 582 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 583 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 584 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 585 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 586 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 587 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 588 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 589 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 590 }; 591 592 /* 593 * Calculate a new FCS given the current FCS and the new data. 594 */ 595 static u_int16_t 596 pppfcs(fcs, cp, len) 597 register u_int fcs; 598 register u_char *cp; 599 register int len; 600 { 601 while (len--) 602 fcs = PPP_FCS(fcs, *cp++); 603 return (fcs); 604 } 605 606 /* 607 * Queue a packet. Start transmission if not active. 608 * Packet is placed in Information field of PPP frame. 609 */ 610 int 611 pppoutput(ifp, m0, dst, rtp) 612 struct ifnet *ifp; 613 struct mbuf *m0; 614 struct sockaddr *dst; 615 struct rtentry *rtp; 616 { 617 register struct ppp_softc *sc = &ppp_softc[ifp->if_unit]; 618 struct ppp_header *ph; 619 int protocol, address, control; 620 u_char *cp; 621 int s, error; 622 struct ip *ip; 623 struct ifqueue *ifq; 624 625 if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0 626 || (ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC) { 627 error = ENETDOWN; /* sort of */ 628 goto bad; 629 } 630 631 /* 632 * Compute PPP header. 633 */ 634 address = PPP_ALLSTATIONS; 635 control = PPP_UI; 636 ifq = &ifp->if_snd; 637 switch (dst->sa_family) { 638 #ifdef INET 639 case AF_INET: 640 protocol = PPP_IP; 641 if ((sc->sc_flags & SC_ENABLE_IP) == 0) { 642 error = ENETDOWN; 643 goto bad; 644 } 645 646 /* 647 * If this is a TCP packet to or from an "interactive" port, 648 * put the packet on the fastq instead. 649 */ 650 if ((ip = mtod(m0, struct ip *))->ip_p == IPPROTO_TCP) { 651 register int32_t p = ntohl(((int32_t *)ip)[ip->ip_hl]); 652 if (INTERACTIVE(p & 0xffff) || INTERACTIVE(p >> 16)) 653 ifq = &sc->sc_fastq; 654 } 655 break; 656 #endif 657 #ifdef NS 658 case AF_NS: 659 protocol = PPP_XNS; 660 break; 661 #endif 662 case AF_UNSPEC: 663 ph = (struct ppp_header *) dst->sa_data; 664 address = ph->ph_address; 665 control = ph->ph_control; 666 protocol = ntohs(ph->ph_protocol); 667 break; 668 default: 669 printf("ppp%d: af%d not supported\n", ifp->if_unit, dst->sa_family); 670 error = EAFNOSUPPORT; 671 goto bad; 672 } 673 674 /* 675 * Add PPP header. If no space in first mbuf, allocate another. 676 * (This assumes M_LEADINGSPACE is always 0 for a cluster mbuf.) 677 */ 678 if (M_LEADINGSPACE(m0) < PPP_HDRLEN) { 679 m0 = m_prepend(m0, PPP_HDRLEN, M_DONTWAIT); 680 if (m0 == 0) { 681 error = ENOBUFS; 682 goto bad; 683 } 684 m0->m_len = 0; 685 } else 686 m0->m_data -= PPP_HDRLEN; 687 688 cp = mtod(m0, u_char *); 689 *cp++ = address; 690 *cp++ = control; 691 *cp++ = protocol >> 8; 692 *cp++ = protocol & 0xff; 693 m0->m_len += PPP_HDRLEN; 694 695 if (sc->sc_flags & SC_LOG_OUTPKT) { 696 printf("ppp%d output: ", ifp->if_unit); 697 pppdumpm(m0, -1); 698 } 699 700 #if NBPFILTER > 0 701 /* See if bpf wants to look at the packet. */ 702 if (sc->sc_bpf) 703 bpf_mtap(sc->sc_bpf, m0); 704 #endif 705 706 /* 707 * Put the packet on the appropriate queue. 708 */ 709 s = splimp(); 710 if (IF_QFULL(ifq)) { 711 IF_DROP(ifq); 712 splx(s); 713 sc->sc_if.if_oerrors++; 714 error = ENOBUFS; 715 goto bad; 716 } 717 IF_ENQUEUE(ifq, m0); 718 719 /* 720 * Tell the device to send it out. 721 */ 722 (*sc->sc_start)(sc); 723 724 splx(s); 725 return (0); 726 727 bad: 728 m_freem(m0); 729 return (error); 730 } 731 732 /* 733 * Grab another packet off a queue and apply VJ compression, 734 * address/control and/or protocol compression if appropriate. 735 */ 736 struct mbuf * 737 ppp_dequeue(sc) 738 struct ppp_softc *sc; 739 { 740 int s; 741 struct mbuf *m, *mp; 742 u_char *cp; 743 int address, control, protocol; 744 745 s = splimp(); 746 IF_DEQUEUE(&sc->sc_fastq, m); 747 if (m == NULL) 748 IF_DEQUEUE(&sc->sc_if.if_snd, m); 749 splx(s); 750 if (m == NULL) 751 return NULL; 752 753 /* 754 * Extract the ppp header of the new packet. 755 * The ppp header will be in one mbuf. 756 */ 757 cp = mtod(m, u_char *); 758 address = cp[0]; 759 control = cp[1]; 760 protocol = (cp[2] << 8) + cp[3]; 761 762 switch (protocol) { 763 #ifdef VJC 764 case PPP_IP: 765 /* 766 * If the packet is a TCP/IP packet, see if we can compress it. 767 */ 768 if (sc->sc_flags & SC_COMP_TCP) { 769 struct ip *ip; 770 int type; 771 772 mp = m; 773 ip = (struct ip *) (cp + PPP_HDRLEN); 774 if (mp->m_len <= PPP_HDRLEN) { 775 mp = mp->m_next; 776 if (mp == NULL) 777 break; 778 ip = mtod(mp, struct ip *); 779 } 780 /* this code assumes the IP/TCP header is in one non-shared mbuf */ 781 if (ip->ip_p == IPPROTO_TCP) { 782 type = sl_compress_tcp(mp, ip, &sc->sc_comp, 783 !(sc->sc_flags & SC_NO_TCP_CCID)); 784 switch (type) { 785 case TYPE_UNCOMPRESSED_TCP: 786 protocol = PPP_VJC_UNCOMP; 787 break; 788 case TYPE_COMPRESSED_TCP: 789 protocol = PPP_VJC_COMP; 790 cp = mtod(m, u_char *); 791 cp[0] = address; /* header has moved */ 792 cp[1] = control; 793 cp[2] = 0; 794 break; 795 } 796 cp[3] = protocol; /* update protocol in PPP header */ 797 } 798 } 799 #endif /* VJC */ 800 } 801 802 /* 803 * Compress the address/control and protocol, if possible. 804 */ 805 if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS && 806 control == PPP_UI && protocol != PPP_ALLSTATIONS && 807 protocol != PPP_LCP) { 808 /* can compress address/control */ 809 m->m_data += 2; 810 m->m_len -= 2; 811 } 812 if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) { 813 /* can compress protocol */ 814 if (mtod(m, u_char *) == cp) { 815 cp[2] = cp[1]; /* move address/control up */ 816 cp[1] = cp[0]; 817 } 818 ++m->m_data; 819 --m->m_len; 820 } 821 822 return m; 823 } 824 825 /* 826 * This gets called from pppoutput when a new packet is 827 * put on a queue. 828 */ 829 static 830 pppasyncstart(sc) 831 register struct ppp_softc *sc; 832 { 833 register struct tty *tp = (struct tty *) sc->sc_devp; 834 835 pppstart(tp); 836 } 837 838 /* 839 * Start output on async tty interface. Get another datagram 840 * to send from the interface queue and start sending it. 841 */ 842 void 843 pppstart(tp) 844 register struct tty *tp; 845 { 846 register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc; 847 register struct mbuf *m; 848 register int len; 849 register u_char *start, *stop, *cp; 850 int n, s, ndone, done; 851 struct mbuf *m2; 852 853 if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0) { 854 /* sorry, I can't talk now */ 855 return; 856 } 857 if (sc == NULL || tp != (struct tty *) sc->sc_devp) { 858 (*tp->t_oproc)(tp); 859 return; 860 } 861 862 for (;;) { 863 /* 864 * If there is more in the output queue, just send it now. 865 * We are being called in lieu of ttstart and must do what 866 * it would. 867 */ 868 if (CCOUNT(&tp->t_outq) != 0 && tp->t_oproc != NULL) { 869 (*tp->t_oproc)(tp); 870 if (CCOUNT(&tp->t_outq) > PPP_HIWAT) 871 return; 872 } 873 874 /* 875 * See if we have an existing packet partly sent. 876 * If not, get a new packet and start sending it. 877 * We take packets on the priority queue ahead of those 878 * on the normal queue. 879 */ 880 m = sc->sc_outm; 881 if (m == NULL) { 882 /* 883 * Get another packet to be sent 884 */ 885 m = ppp_dequeue(sc); 886 if (m == NULL) 887 return; 888 889 /* 890 * The extra PPP_FLAG will start up a new packet, and thus 891 * will flush any accumulated garbage. We do this whenever 892 * the line may have been idle for some time. 893 */ 894 if (CCOUNT(&tp->t_outq) == 0) { 895 ++sc->sc_bytessent; 896 (void) putc(PPP_FLAG, &tp->t_outq); 897 } 898 899 /* Calculate the FCS for the first mbuf's worth. */ 900 sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len); 901 } 902 903 for (;;) { 904 start = mtod(m, u_char *); 905 len = m->m_len; 906 stop = start + len; 907 while (len > 0) { 908 /* 909 * Find out how many bytes in the string we can 910 * handle without doing something special. 911 */ 912 for (cp = start; cp < stop; cp++) 913 if (ESCAPE_P(*cp)) 914 break; 915 n = cp - start; 916 if (n) { 917 /* NetBSD (0.9 or later), 4.3-Reno or similar. */ 918 ndone = n - b_to_q(start, n, &tp->t_outq); 919 len -= ndone; 920 start += ndone; 921 sc->sc_bytessent += ndone; 922 923 if (ndone < n) 924 break; /* packet doesn't fit */ 925 } 926 /* 927 * If there are characters left in the mbuf, 928 * the first one must be special.. 929 * Put it out in a different form. 930 */ 931 if (len) { 932 if (putc(PPP_ESCAPE, &tp->t_outq)) 933 break; 934 if (putc(*start ^ PPP_TRANS, &tp->t_outq)) { 935 (void) unputc(&tp->t_outq); 936 break; 937 } 938 sc->sc_bytessent += 2; 939 start++; 940 len--; 941 } 942 } 943 /* 944 * If we didn't empty this mbuf, remember where we're up to. 945 * If we emptied the last mbuf, try to add the FCS and closing 946 * flag, and if we can't, leave sc_outm pointing to m, but with 947 * m->m_len == 0, to remind us to output the FCS and flag later. 948 */ 949 done = len == 0; 950 if (done && m->m_next == NULL) { 951 u_char *p, *q; 952 int c; 953 u_char endseq[8]; 954 955 /* 956 * We may have to escape the bytes in the FCS. 957 */ 958 p = endseq; 959 c = ~sc->sc_outfcs & 0xFF; 960 if (ESCAPE_P(c)) { 961 *p++ = PPP_ESCAPE; 962 *p++ = c ^ PPP_TRANS; 963 } else 964 *p++ = c; 965 c = (~sc->sc_outfcs >> 8) & 0xFF; 966 if (ESCAPE_P(c)) { 967 *p++ = PPP_ESCAPE; 968 *p++ = c ^ PPP_TRANS; 969 } else 970 *p++ = c; 971 *p++ = PPP_FLAG; 972 973 /* 974 * Try to output the FCS and flag. If the bytes 975 * don't all fit, back out. 976 */ 977 for (q = endseq; q < p; ++q) 978 if (putc(*q, &tp->t_outq)) { 979 done = 0; 980 for (; q > endseq; --q) 981 unputc(&tp->t_outq); 982 break; 983 } 984 } 985 986 if (!done) { 987 m->m_data = start; 988 m->m_len = len; 989 sc->sc_outm = m; 990 if (tp->t_oproc != NULL) 991 (*tp->t_oproc)(tp); 992 return; /* can't do any more at the moment */ 993 } 994 995 /* Finished with this mbuf; free it and move on. */ 996 MFREE(m, m2); 997 if (m2 == NULL) 998 break; 999 1000 m = m2; 1001 sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len); 1002 } 1003 1004 /* Finished a packet */ 1005 sc->sc_outm = NULL; 1006 sc->sc_bytessent++; /* account for closing flag */ 1007 sc->sc_if.if_opackets++; 1008 sc->sc_if.if_obytes = sc->sc_bytessent; 1009 } 1010 } 1011 1012 /* 1013 * Allocate enough mbuf to handle current MRU. 1014 */ 1015 static int 1016 pppgetm(sc) 1017 register struct ppp_softc *sc; 1018 { 1019 struct mbuf *m, **mp; 1020 int len; 1021 int s; 1022 1023 s = splimp(); 1024 mp = &sc->sc_m; 1025 for (len = HDROFF + sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){ 1026 if ((m = *mp) == NULL) { 1027 MGETHDR(m, M_DONTWAIT, MT_DATA); 1028 if (m == NULL) 1029 break; 1030 *mp = m; 1031 MCLGET(m, M_DONTWAIT); 1032 } 1033 len -= M_DATASIZE(m); 1034 mp = &m->m_next; 1035 } 1036 splx(s); 1037 return len <= 0; 1038 } 1039 1040 /* 1041 * PPP packet input routine. 1042 * The caller has checked and removed the FCS and has inserted 1043 * the address/control bytes and the protocol high byte if they 1044 * were omitted. The data in the first mbuf should start HDROFF 1045 * bytes from the beginning of the mbuf data storage area. 1046 * The return value is 1 if the packet was put on sc->sc_inq, 1047 * 0 otherwise. 1048 */ 1049 #define COMPTYPE(proto) ((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \ 1050 TYPE_UNCOMPRESSED_TCP) 1051 1052 int 1053 ppppktin(sc, m) 1054 struct ppp_softc *sc; 1055 struct mbuf *m; 1056 { 1057 struct ifqueue *inq; 1058 int s, ilen, xlen, proto, rv; 1059 u_char *cp, adrs, ctrl; 1060 struct mbuf *mp; 1061 1062 sc->sc_if.if_ipackets++; 1063 rv = 0; 1064 1065 cp = mtod(m, u_char *); 1066 adrs = cp[0]; 1067 ctrl = cp[1]; 1068 proto = (cp[2] << 8) + cp[3]; 1069 1070 ilen = 0; 1071 for (mp = m; mp != NULL; mp = mp->m_next) 1072 ilen += mp->m_len; 1073 1074 #ifdef VJC 1075 /* 1076 * See if we have a VJ-compressed packet to uncompress. 1077 */ 1078 if (proto == PPP_VJC_COMP || proto == PPP_VJC_UNCOMP) { 1079 char *pkttype = proto == PPP_VJC_COMP? "": "un"; 1080 1081 if (sc->sc_flags & SC_REJ_COMP_TCP) { 1082 if (sc->sc_flags & SC_DEBUG) 1083 printf("ppp%d: %scomp pkt w/o compression; flags 0x%x\n", 1084 sc->sc_if.if_unit, pkttype, sc->sc_flags); 1085 m_freem(m); 1086 sc->sc_if.if_ierrors++; 1087 return 0; 1088 } 1089 1090 if (proto == PPP_VJC_COMP && m->m_data - M_DATASTART(m) < MAX_HDR) { 1091 /* 1092 * We don't have room in the mbuf to decompress this packet. 1093 * XXX For now we just drop the packet. 1094 */ 1095 if (sc->sc_flags & SC_DEBUG) 1096 printf("ppp%d: no room to VJ-decompress packet\n", 1097 sc->sc_if.if_unit); 1098 m_freem(m); 1099 sc->sc_if.if_ierrors++; 1100 return 0; 1101 } 1102 1103 m->m_data += PPP_HDRLEN; 1104 m->m_len -= PPP_HDRLEN; 1105 ilen -= PPP_HDRLEN; 1106 xlen = sl_uncompress_tcp_part((u_char **)(&m->m_data), 1107 m->m_len, ilen, 1108 COMPTYPE(proto), &sc->sc_comp); 1109 1110 if (xlen == 0) { 1111 if (sc->sc_flags & SC_DEBUG) 1112 printf("ppp%d: sl_uncompress failed on type %scomp\n", 1113 sc->sc_if.if_unit, pkttype); 1114 m_freem(m); 1115 sc->sc_if.if_ierrors++; 1116 return 0; 1117 } 1118 1119 /* adjust the first mbuf by the decompressed amt */ 1120 xlen += PPP_HDRLEN; 1121 m->m_len += xlen - ilen; 1122 ilen = xlen; 1123 m->m_data -= PPP_HDRLEN; 1124 proto = PPP_IP; 1125 1126 /* put the ppp header back in place */ 1127 if (cp != mtod(m, u_char *)) { 1128 cp = mtod(m, u_char *); 1129 cp[0] = adrs; 1130 cp[1] = ctrl; 1131 cp[2] = 0; 1132 } 1133 cp[3] = PPP_IP; 1134 } 1135 #endif /* VJC */ 1136 1137 /* 1138 * If the packet will fit in a header mbuf, don't waste a 1139 * whole cluster on it. 1140 */ 1141 if (ilen <= MHLEN) { 1142 MGETHDR(mp, M_DONTWAIT, MT_DATA); 1143 if (mp != NULL) { 1144 m_copydata(m, 0, ilen, mtod(mp, caddr_t)); 1145 m_freem(m); 1146 m = mp; 1147 m->m_len = ilen; 1148 } 1149 } 1150 m->m_pkthdr.len = ilen; 1151 m->m_pkthdr.rcvif = &sc->sc_if; 1152 1153 #if NBPFILTER > 0 1154 /* See if bpf wants to look at the packet. */ 1155 if (sc->sc_bpf) 1156 bpf_mtap(sc->sc_bpf, m); 1157 #endif 1158 1159 switch (proto) { 1160 #ifdef INET 1161 case PPP_IP: 1162 /* 1163 * IP packet - take off the ppp header and pass it up to IP. 1164 */ 1165 if ((sc->sc_if.if_flags & IFF_UP) == 0 1166 || (sc->sc_flags & SC_ENABLE_IP) == 0) { 1167 /* interface is down - drop the packet. */ 1168 m_freem(m); 1169 return 0; 1170 } 1171 m->m_pkthdr.len -= PPP_HDRLEN; 1172 m->m_data += PPP_HDRLEN; 1173 m->m_len -= PPP_HDRLEN; 1174 schednetisr(NETISR_IP); 1175 inq = &ipintrq; 1176 break; 1177 #endif 1178 1179 default: 1180 /* 1181 * Some other protocol - place on input queue for read(). 1182 */ 1183 inq = &sc->sc_inq; 1184 rv = 1; 1185 break; 1186 } 1187 1188 /* 1189 * Put the packet on the appropriate input queue. 1190 */ 1191 s = splimp(); 1192 if (IF_QFULL(inq)) { 1193 IF_DROP(inq); 1194 if (sc->sc_flags & SC_DEBUG) 1195 printf("ppp%d: queue full\n", sc->sc_if.if_unit); 1196 sc->sc_if.if_ierrors++; 1197 sc->sc_if.if_iqdrops++; 1198 m_freem(m); 1199 rv = 0; 1200 } else 1201 IF_ENQUEUE(inq, m); 1202 1203 splx(s); 1204 return rv; 1205 } 1206 1207 /* 1208 * tty interface receiver interrupt. 1209 */ 1210 static unsigned paritytab[8] = { 1211 0x96696996, 0x69969669, 0x69969669, 0x96696996, 1212 0x69969669, 0x96696996, 0x96696996, 0x69969669 1213 }; 1214 1215 void 1216 pppinput(c, tp) 1217 int c; 1218 register struct tty *tp; 1219 { 1220 register struct ppp_softc *sc; 1221 struct mbuf *m; 1222 int ilen; 1223 1224 tk_nin++; 1225 sc = (struct ppp_softc *) tp->t_sc; 1226 if (sc == NULL || tp != (struct tty *) sc->sc_devp) 1227 return; 1228 1229 ++sc->sc_bytesrcvd; 1230 1231 if (c & TTY_FE) { 1232 /* framing error or overrun on this char - abort packet */ 1233 if (sc->sc_flags & SC_DEBUG) 1234 printf("ppp%d: bad char %x\n", sc->sc_if.if_unit, c); 1235 goto flush; 1236 } 1237 1238 c &= 0xff; 1239 1240 if (c & 0x80) 1241 sc->sc_flags |= SC_RCV_B7_1; 1242 else 1243 sc->sc_flags |= SC_RCV_B7_0; 1244 if (paritytab[c >> 5] & (1 << (c & 0x1F))) 1245 sc->sc_flags |= SC_RCV_ODDP; 1246 else 1247 sc->sc_flags |= SC_RCV_EVNP; 1248 1249 if (sc->sc_flags & SC_LOG_RAWIN) 1250 ppplogchar(sc, c); 1251 1252 if (c == PPP_FLAG) { 1253 ilen = sc->sc_ilen; 1254 sc->sc_ilen = 0; 1255 sc->sc_if.if_ibytes = sc->sc_bytesrcvd; 1256 1257 if (sc->sc_rawin_count > 0) 1258 ppplogchar(sc, -1); 1259 1260 /* 1261 * If SC_ESCAPED is set, then we've seen the packet 1262 * abort sequence "}~". 1263 */ 1264 if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED) 1265 || ilen > 0 && sc->sc_fcs != PPP_GOODFCS) { 1266 #ifdef VJC 1267 /* 1268 * If we've missed a packet, we must toss subsequent compressed 1269 * packets which don't have an explicit connection ID. 1270 */ 1271 sl_uncompress_tcp(NULL, 0, TYPE_ERROR, &sc->sc_comp); 1272 #endif 1273 if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){ 1274 if (sc->sc_flags & SC_DEBUG) 1275 printf("ppp%d: bad fcs %x\n", sc->sc_if.if_unit, 1276 sc->sc_fcs); 1277 sc->sc_if.if_ierrors++; 1278 } else 1279 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED); 1280 return; 1281 } 1282 1283 if (ilen < PPP_HDRLEN + PPP_FCSLEN) { 1284 if (ilen) { 1285 if (sc->sc_flags & SC_DEBUG) 1286 printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen); 1287 sc->sc_if.if_ierrors++; 1288 } 1289 return; 1290 } 1291 1292 /* 1293 * Remove FCS trailer. Somewhat painful... 1294 */ 1295 ilen -= 2; 1296 if (--sc->sc_mc->m_len == 0) { 1297 for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next) 1298 ; 1299 sc->sc_mc = m; 1300 } 1301 sc->sc_mc->m_len--; 1302 1303 /* excise this mbuf chain */ 1304 m = sc->sc_m; 1305 sc->sc_m = sc->sc_mc->m_next; 1306 sc->sc_mc->m_next = NULL; 1307 1308 if (sc->sc_flags & SC_LOG_INPKT) { 1309 printf("ppp%d: got %d bytes\n", sc->sc_if.if_unit, ilen); 1310 pppdumpm(m, ilen); 1311 } 1312 1313 if (ppppktin(sc, m)) { 1314 /* Put a placeholder byte in canq for ttselect()/ttnread(). */ 1315 putc(0, &tp->t_canq); 1316 ttwakeup(tp); 1317 } 1318 1319 pppgetm(sc); 1320 return; 1321 } 1322 1323 if (sc->sc_flags & SC_FLUSH) { 1324 if (sc->sc_flags & SC_LOG_FLUSH) 1325 ppplogchar(sc, c); 1326 return; 1327 } 1328 1329 if (c < 0x20 && (sc->sc_rasyncmap & (1 << c))) 1330 return; 1331 1332 if (sc->sc_flags & SC_ESCAPED) { 1333 sc->sc_flags &= ~SC_ESCAPED; 1334 c ^= PPP_TRANS; 1335 } else if (c == PPP_ESCAPE) { 1336 sc->sc_flags |= SC_ESCAPED; 1337 return; 1338 } 1339 1340 /* 1341 * Initialize buffer on first octet received. 1342 * First octet could be address or protocol (when compressing 1343 * address/control). 1344 * Second octet is control. 1345 * Third octet is first or second (when compressing protocol) 1346 * octet of protocol. 1347 * Fourth octet is second octet of protocol. 1348 */ 1349 if (sc->sc_ilen == 0) { 1350 /* reset the first input mbuf */ 1351 if (sc->sc_m == NULL) { 1352 pppgetm(sc); 1353 if (sc->sc_m == NULL) { 1354 if (sc->sc_flags & SC_DEBUG) 1355 printf("ppp%d: no input mbufs!\n", sc->sc_if.if_unit); 1356 goto flush; 1357 } 1358 } 1359 m = sc->sc_m; 1360 m->m_len = 0; 1361 m->m_data = M_DATASTART(sc->sc_m); 1362 if (M_DATASIZE(sc->sc_m) >= HDROFF + PPP_HDRLEN) 1363 m->m_data += HDROFF; /* allow room for VJ decompression */ 1364 sc->sc_mc = m; 1365 sc->sc_mp = mtod(m, char *); 1366 sc->sc_fcs = PPP_INITFCS; 1367 if (c != PPP_ALLSTATIONS) { 1368 if (sc->sc_flags & SC_REJ_COMP_AC) { 1369 if (sc->sc_flags & SC_DEBUG) 1370 printf("ppp%d: garbage received: 0x%x (need 0xFF)\n", 1371 sc->sc_if.if_unit, c); 1372 goto flush; 1373 } 1374 *sc->sc_mp++ = PPP_ALLSTATIONS; 1375 *sc->sc_mp++ = PPP_UI; 1376 sc->sc_ilen += 2; 1377 m->m_len += 2; 1378 } 1379 } 1380 if (sc->sc_ilen == 1 && c != PPP_UI) { 1381 if (sc->sc_flags & SC_DEBUG) 1382 printf("ppp%d: missing UI (0x3), got 0x%x\n", 1383 sc->sc_if.if_unit, c); 1384 goto flush; 1385 } 1386 if (sc->sc_ilen == 2 && (c & 1) == 1) { 1387 /* a compressed protocol */ 1388 *sc->sc_mp++ = 0; 1389 sc->sc_ilen++; 1390 sc->sc_mc->m_len++; 1391 } 1392 if (sc->sc_ilen == 3 && (c & 1) == 0) { 1393 if (sc->sc_flags & SC_DEBUG) 1394 printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit, 1395 (sc->sc_mp[-1] << 8) + c); 1396 goto flush; 1397 } 1398 1399 /* packet beyond configured mru? */ 1400 if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) { 1401 if (sc->sc_flags & SC_DEBUG) 1402 printf("ppp%d: packet too big\n", sc->sc_if.if_unit); 1403 goto flush; 1404 } 1405 1406 /* is this mbuf full? */ 1407 m = sc->sc_mc; 1408 if (M_TRAILINGSPACE(m) <= 0) { 1409 if (m->m_next == NULL) { 1410 pppgetm(sc); 1411 if (m->m_next == NULL) { 1412 if (sc->sc_flags & SC_DEBUG) 1413 printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit); 1414 goto flush; 1415 } 1416 } 1417 sc->sc_mc = m = m->m_next; 1418 m->m_len = 0; 1419 m->m_data = M_DATASTART(m); 1420 sc->sc_mp = mtod(m, char *); 1421 } 1422 1423 ++m->m_len; 1424 *sc->sc_mp++ = c; 1425 sc->sc_fcs = PPP_FCS(sc->sc_fcs, c); 1426 return; 1427 1428 flush: 1429 if (!(sc->sc_flags & SC_FLUSH)) { 1430 sc->sc_if.if_ierrors++; 1431 sc->sc_flags |= SC_FLUSH; 1432 if (sc->sc_flags & SC_LOG_FLUSH) 1433 ppplogchar(sc, c); 1434 } 1435 } 1436 1437 /* 1438 * Process an ioctl request to interface. 1439 */ 1440 pppioctl(ifp, cmd, data) 1441 register struct ifnet *ifp; 1442 u_long cmd; 1443 caddr_t data; 1444 { 1445 struct proc *p = curproc; /* XXX */ 1446 register struct ppp_softc *sc = &ppp_softc[ifp->if_unit]; 1447 register struct ifaddr *ifa = (struct ifaddr *)data; 1448 register struct ifreq *ifr = (struct ifreq *)data; 1449 int s = splimp(), error = 0; 1450 1451 1452 switch (cmd) { 1453 case SIOCSIFFLAGS: 1454 if ((ifp->if_flags & IFF_RUNNING) == 0) 1455 ifp->if_flags &= ~IFF_UP; 1456 break; 1457 1458 case SIOCSIFADDR: 1459 if (ifa->ifa_addr->sa_family != AF_INET) 1460 error = EAFNOSUPPORT; 1461 break; 1462 1463 case SIOCSIFDSTADDR: 1464 if (ifa->ifa_addr->sa_family != AF_INET) 1465 error = EAFNOSUPPORT; 1466 break; 1467 1468 case SIOCSIFMTU: 1469 if (error = suser(p->p_ucred, &p->p_acflag)) 1470 break; 1471 sc->sc_if.if_mtu = ifr->ifr_mtu; 1472 break; 1473 1474 case SIOCGIFMTU: 1475 ifr->ifr_mtu = sc->sc_if.if_mtu; 1476 break; 1477 1478 default: 1479 error = EINVAL; 1480 } 1481 splx(s); 1482 return (error); 1483 } 1484 1485 #define MAX_DUMP_BYTES 128 1486 1487 static void 1488 pppdumpm(m0, pktlen) 1489 struct mbuf *m0; 1490 int pktlen; 1491 { 1492 char buf[3*MAX_DUMP_BYTES+4]; 1493 char *bp = buf; 1494 struct mbuf *m; 1495 static char digits[] = "0123456789abcdef"; 1496 1497 for (m = m0; m && pktlen; m = m->m_next) { 1498 int l = m->m_len; 1499 u_char *rptr = (u_char *)m->m_data; 1500 1501 if (pktlen > 0) { 1502 if (l > pktlen) 1503 l = pktlen; 1504 pktlen -= l; 1505 } 1506 while (l--) { 1507 if (bp > buf + sizeof(buf) - 4) 1508 goto done; 1509 *bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */ 1510 *bp++ = digits[*rptr++ & 0xf]; 1511 } 1512 1513 if (m->m_next) { 1514 if (bp > buf + sizeof(buf) - 3) 1515 goto done; 1516 *bp++ = '|'; 1517 } else 1518 *bp++ = ' '; 1519 } 1520 done: 1521 if (m && pktlen) 1522 *bp++ = '>'; 1523 *bp = 0; 1524 printf("%s\n", buf); 1525 } 1526 1527 static void 1528 ppplogchar(sc, c) 1529 struct ppp_softc *sc; 1530 int c; 1531 { 1532 if (c >= 0) 1533 sc->sc_rawin[sc->sc_rawin_count++] = c; 1534 if (sc->sc_rawin_count >= sizeof(sc->sc_rawin) 1535 || c < 0 && sc->sc_rawin_count > 0) { 1536 printf("ppp%d input: ", sc->sc_if.if_unit); 1537 pppdumpb(sc->sc_rawin, sc->sc_rawin_count); 1538 sc->sc_rawin_count = 0; 1539 } 1540 } 1541 1542 static void 1543 pppdumpb(b, l) 1544 u_char *b; 1545 int l; 1546 { 1547 char buf[3*MAX_DUMP_BYTES+4]; 1548 char *bp = buf; 1549 static char digits[] = "0123456789abcdef"; 1550 1551 while (l--) { 1552 if (bp >= buf + sizeof(buf) - 3) { 1553 *bp++ = '>'; 1554 break; 1555 } 1556 *bp++ = digits[*b >> 4]; /* convert byte to ascii hex */ 1557 *bp++ = digits[*b++ & 0xf]; 1558 *bp++ = ' '; 1559 } 1560 1561 *bp = 0; 1562 printf("%s\n", buf); 1563 } 1564 1565 1566 #endif /* NPPP > 0 */ 1567