1 /* $OpenBSD: if_pppx.c,v 1.76 2020/02/20 16:56:52 visa Exp $ */ 2 3 /* 4 * Copyright (c) 2010 Claudio Jeker <claudio@openbsd.org> 5 * Copyright (c) 2010 David Gwynne <dlg@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /*- 21 * Copyright (c) 2009 Internet Initiative Japan Inc. 22 * All rights reserved. 23 * 24 * Redistribution and use in source and binary forms, with or without 25 * modification, are permitted provided that the following conditions 26 * are met: 27 * 1. Redistributions of source code must retain the above copyright 28 * notice, this list of conditions and the following disclaimer. 29 * 2. Redistributions in binary form must reproduce the above copyright 30 * notice, this list of conditions and the following disclaimer in the 31 * documentation and/or other materials provided with the distribution. 32 * 33 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 34 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 35 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 36 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 37 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 38 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 39 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 40 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 41 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 42 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 43 * SUCH DAMAGE. 44 */ 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/buf.h> 48 #include <sys/kernel.h> 49 #include <sys/malloc.h> 50 #include <sys/device.h> 51 #include <sys/conf.h> 52 #include <sys/queue.h> 53 #include <sys/rwlock.h> 54 #include <sys/pool.h> 55 #include <sys/mbuf.h> 56 #include <sys/errno.h> 57 #include <sys/protosw.h> 58 #include <sys/socket.h> 59 #include <sys/ioctl.h> 60 #include <sys/vnode.h> 61 #include <sys/poll.h> 62 #include <sys/selinfo.h> 63 64 #include <net/if.h> 65 #include <net/if_types.h> 66 #include <net/netisr.h> 67 #include <netinet/in.h> 68 #include <netinet/if_ether.h> 69 #include <net/if_dl.h> 70 71 #include <netinet/in_var.h> 72 #include <netinet/ip.h> 73 #include <netinet/ip_var.h> 74 75 #ifdef INET6 76 #include <netinet6/in6_var.h> 77 #include <netinet/ip6.h> 78 #include <netinet6/nd6.h> 79 #endif /* INET6 */ 80 81 #include "bpfilter.h" 82 #if NBPFILTER > 0 83 #include <net/bpf.h> 84 #endif 85 86 #include "pf.h" 87 #if NPF > 0 88 #include <net/pfvar.h> 89 #endif 90 91 #include <net/ppp_defs.h> 92 #include <net/ppp-comp.h> 93 #include <crypto/arc4.h> 94 95 #ifdef PIPEX 96 #include <net/radix.h> 97 #include <net/pipex.h> 98 #include <net/pipex_local.h> 99 #else 100 #error PIPEX option not enabled 101 #endif 102 103 #ifdef PPPX_DEBUG 104 #define PPPX_D_INIT (1<<0) 105 106 int pppxdebug = 0; 107 108 #define DPRINTF(_m, _p...) do { \ 109 if (ISSET(pppxdebug, (_m))) \ 110 printf(_p); \ 111 } while (0) 112 #else 113 #define DPRINTF(_m, _p...) /* _m, _p */ 114 #endif 115 116 117 struct pppx_if; 118 119 struct pppx_dev { 120 LIST_ENTRY(pppx_dev) pxd_entry; 121 int pxd_unit; 122 123 /* kq shizz */ 124 struct selinfo pxd_rsel; 125 struct mutex pxd_rsel_mtx; 126 struct selinfo pxd_wsel; 127 struct mutex pxd_wsel_mtx; 128 129 /* queue of packets for userland to service - protected by splnet */ 130 struct mbuf_queue pxd_svcq; 131 int pxd_waiting; 132 LIST_HEAD(,pppx_if) pxd_pxis; 133 }; 134 135 struct rwlock pppx_devs_lk = RWLOCK_INITIALIZER("pppxdevs"); 136 LIST_HEAD(, pppx_dev) pppx_devs = LIST_HEAD_INITIALIZER(pppx_devs); 137 struct pool *pppx_if_pl; 138 139 struct pppx_dev *pppx_dev_lookup(dev_t); 140 struct pppx_dev *pppx_dev2pxd(dev_t); 141 142 struct pppx_if_key { 143 int pxik_session_id; 144 int pxik_protocol; 145 }; 146 147 struct pppx_if { 148 struct pppx_if_key pxi_key; /* must be first in the struct */ 149 150 RBT_ENTRY(pppx_if) pxi_entry; 151 LIST_ENTRY(pppx_if) pxi_list; 152 153 int pxi_ready; 154 155 int pxi_unit; 156 struct ifnet pxi_if; 157 struct pppx_dev *pxi_dev; 158 struct pipex_session pxi_session; 159 struct pipex_iface_context pxi_ifcontext; 160 }; 161 162 static inline int 163 pppx_if_cmp(const struct pppx_if *a, const struct pppx_if *b) 164 { 165 return memcmp(&a->pxi_key, &b->pxi_key, sizeof(a->pxi_key)); 166 } 167 168 struct rwlock pppx_ifs_lk = RWLOCK_INITIALIZER("pppxifs"); 169 RBT_HEAD(pppx_ifs, pppx_if) pppx_ifs = RBT_INITIALIZER(&pppx_ifs); 170 RBT_PROTOTYPE(pppx_ifs, pppx_if, pxi_entry, pppx_if_cmp); 171 172 int pppx_if_next_unit(void); 173 struct pppx_if *pppx_if_find(struct pppx_dev *, int, int); 174 int pppx_add_session(struct pppx_dev *, 175 struct pipex_session_req *); 176 int pppx_del_session(struct pppx_dev *, 177 struct pipex_session_close_req *); 178 int pppx_set_session_descr(struct pppx_dev *, 179 struct pipex_session_descr_req *); 180 181 void pppx_if_destroy(struct pppx_dev *, struct pppx_if *); 182 void pppx_if_start(struct ifnet *); 183 int pppx_if_output(struct ifnet *, struct mbuf *, 184 struct sockaddr *, struct rtentry *); 185 int pppx_if_ioctl(struct ifnet *, u_long, caddr_t); 186 187 188 void pppxattach(int); 189 190 void filt_pppx_rdetach(struct knote *); 191 int filt_pppx_read(struct knote *, long); 192 193 const struct filterops pppx_rd_filtops = { 194 .f_flags = FILTEROP_ISFD, 195 .f_attach = NULL, 196 .f_detach = filt_pppx_rdetach, 197 .f_event = filt_pppx_read, 198 }; 199 200 void filt_pppx_wdetach(struct knote *); 201 int filt_pppx_write(struct knote *, long); 202 203 const struct filterops pppx_wr_filtops = { 204 .f_flags = FILTEROP_ISFD, 205 .f_attach = NULL, 206 .f_detach = filt_pppx_wdetach, 207 .f_event = filt_pppx_write, 208 }; 209 210 struct pppx_dev * 211 pppx_dev_lookup(dev_t dev) 212 { 213 struct pppx_dev *pxd; 214 int unit = minor(dev); 215 216 /* must hold pppx_devs_lk */ 217 218 LIST_FOREACH(pxd, &pppx_devs, pxd_entry) { 219 if (pxd->pxd_unit == unit) 220 return (pxd); 221 } 222 223 return (NULL); 224 } 225 226 struct pppx_dev * 227 pppx_dev2pxd(dev_t dev) 228 { 229 struct pppx_dev *pxd; 230 231 rw_enter_read(&pppx_devs_lk); 232 pxd = pppx_dev_lookup(dev); 233 rw_exit_read(&pppx_devs_lk); 234 235 return (pxd); 236 } 237 238 void 239 pppxattach(int n) 240 { 241 pipex_init(); 242 } 243 244 int 245 pppxopen(dev_t dev, int flags, int mode, struct proc *p) 246 { 247 struct pppx_dev *pxd; 248 int rv = 0; 249 250 rv = rw_enter(&pppx_devs_lk, RW_WRITE | RW_INTR); 251 if (rv != 0) 252 return (rv); 253 254 pxd = pppx_dev_lookup(dev); 255 if (pxd != NULL) { 256 rv = EBUSY; 257 goto out; 258 } 259 260 if (LIST_EMPTY(&pppx_devs) && pppx_if_pl == NULL) { 261 pppx_if_pl = malloc(sizeof(*pppx_if_pl), M_DEVBUF, M_WAITOK); 262 pool_init(pppx_if_pl, sizeof(struct pppx_if), 0, IPL_NONE, 263 PR_WAITOK, "pppxif", NULL); 264 } 265 266 pxd = malloc(sizeof(*pxd), M_DEVBUF, M_WAITOK | M_ZERO); 267 268 pxd->pxd_unit = minor(dev); 269 mtx_init(&pxd->pxd_rsel_mtx, IPL_NET); 270 mtx_init(&pxd->pxd_wsel_mtx, IPL_NET); 271 LIST_INIT(&pxd->pxd_pxis); 272 273 mq_init(&pxd->pxd_svcq, 128, IPL_NET); 274 LIST_INSERT_HEAD(&pppx_devs, pxd, pxd_entry); 275 276 out: 277 rw_exit(&pppx_devs_lk); 278 return (rv); 279 } 280 281 int 282 pppxread(dev_t dev, struct uio *uio, int ioflag) 283 { 284 struct pppx_dev *pxd = pppx_dev2pxd(dev); 285 struct mbuf *m, *m0; 286 int error = 0; 287 size_t len; 288 289 if (!pxd) 290 return (ENXIO); 291 292 while ((m0 = mq_dequeue(&pxd->pxd_svcq)) == NULL) { 293 if (ISSET(ioflag, IO_NDELAY)) 294 return (EWOULDBLOCK); 295 296 NET_LOCK(); 297 pxd->pxd_waiting = 1; 298 error = rwsleep_nsec(pxd, &netlock, 299 (PZERO + 1)|PCATCH, "pppxread", INFSLP); 300 NET_UNLOCK(); 301 if (error != 0) { 302 return (error); 303 } 304 } 305 306 while (m0 != NULL && uio->uio_resid > 0 && error == 0) { 307 len = ulmin(uio->uio_resid, m0->m_len); 308 if (len != 0) 309 error = uiomove(mtod(m0, caddr_t), len, uio); 310 m = m_free(m0); 311 m0 = m; 312 } 313 314 m_freem(m0); 315 316 return (error); 317 } 318 319 int 320 pppxwrite(dev_t dev, struct uio *uio, int ioflag) 321 { 322 struct pppx_dev *pxd = pppx_dev2pxd(dev); 323 struct pppx_hdr *th; 324 struct pppx_if *pxi; 325 uint32_t proto; 326 struct mbuf *top, **mp, *m; 327 int tlen; 328 int error = 0; 329 size_t mlen; 330 331 if (uio->uio_resid < sizeof(*th) + sizeof(uint32_t) || 332 uio->uio_resid > MCLBYTES) 333 return (EMSGSIZE); 334 335 tlen = uio->uio_resid; 336 337 MGETHDR(m, M_DONTWAIT, MT_DATA); 338 if (m == NULL) 339 return (ENOBUFS); 340 mlen = MHLEN; 341 if (uio->uio_resid >= MINCLSIZE) { 342 MCLGET(m, M_DONTWAIT); 343 if (!(m->m_flags & M_EXT)) { 344 m_free(m); 345 return (ENOBUFS); 346 } 347 mlen = MCLBYTES; 348 } 349 350 top = NULL; 351 mp = ⊤ 352 353 while (error == 0 && uio->uio_resid > 0) { 354 m->m_len = ulmin(mlen, uio->uio_resid); 355 error = uiomove(mtod (m, caddr_t), m->m_len, uio); 356 *mp = m; 357 mp = &m->m_next; 358 if (error == 0 && uio->uio_resid > 0) { 359 MGET(m, M_DONTWAIT, MT_DATA); 360 if (m == NULL) { 361 error = ENOBUFS; 362 break; 363 } 364 mlen = MLEN; 365 if (uio->uio_resid >= MINCLSIZE) { 366 MCLGET(m, M_DONTWAIT); 367 if (!(m->m_flags & M_EXT)) { 368 error = ENOBUFS; 369 m_free(m); 370 break; 371 } 372 mlen = MCLBYTES; 373 } 374 } 375 } 376 377 if (error) { 378 m_freem(top); 379 return (error); 380 } 381 382 top->m_pkthdr.len = tlen; 383 384 /* Find the interface */ 385 th = mtod(top, struct pppx_hdr *); 386 m_adj(top, sizeof(struct pppx_hdr)); 387 pxi = pppx_if_find(pxd, th->pppx_id, th->pppx_proto); 388 if (pxi == NULL) { 389 m_freem(top); 390 return (EINVAL); 391 } 392 top->m_pkthdr.ph_ifidx = pxi->pxi_if.if_index; 393 394 #if NBPFILTER > 0 395 if (pxi->pxi_if.if_bpf) 396 bpf_mtap(pxi->pxi_if.if_bpf, top, BPF_DIRECTION_IN); 397 #endif 398 /* strip the tunnel header */ 399 proto = ntohl(*(uint32_t *)(th + 1)); 400 m_adj(top, sizeof(uint32_t)); 401 402 NET_LOCK(); 403 404 switch (proto) { 405 case AF_INET: 406 ipv4_input(&pxi->pxi_if, top); 407 break; 408 #ifdef INET6 409 case AF_INET6: 410 ipv6_input(&pxi->pxi_if, top); 411 break; 412 #endif 413 default: 414 m_freem(top); 415 error = EAFNOSUPPORT; 416 break; 417 } 418 419 NET_UNLOCK(); 420 421 return (error); 422 } 423 424 int 425 pppxioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) 426 { 427 struct pppx_dev *pxd = pppx_dev2pxd(dev); 428 int error = 0; 429 430 NET_LOCK(); 431 switch (cmd) { 432 case PIPEXSMODE: 433 /* 434 * npppd always enables on open, and only disables before 435 * closing. we cheat and let open and close do that, so lie 436 * to npppd. 437 */ 438 break; 439 case PIPEXGMODE: 440 *(int *)addr = 1; 441 break; 442 443 case PIPEXASESSION: 444 error = pppx_add_session(pxd, 445 (struct pipex_session_req *)addr); 446 break; 447 448 case PIPEXDSESSION: 449 error = pppx_del_session(pxd, 450 (struct pipex_session_close_req *)addr); 451 break; 452 453 case PIPEXCSESSION: 454 error = pipex_config_session( 455 (struct pipex_session_config_req *)addr); 456 break; 457 458 case PIPEXGSTAT: 459 error = pipex_get_stat((struct pipex_session_stat_req *)addr); 460 break; 461 462 case PIPEXGCLOSED: 463 error = pipex_get_closed((struct pipex_session_list_req *)addr); 464 break; 465 466 case PIPEXSIFDESCR: 467 error = pppx_set_session_descr(pxd, 468 (struct pipex_session_descr_req *)addr); 469 break; 470 471 case FIONBIO: 472 break; 473 case FIONREAD: 474 *(int *)addr = mq_hdatalen(&pxd->pxd_svcq); 475 break; 476 477 default: 478 error = ENOTTY; 479 break; 480 } 481 NET_UNLOCK(); 482 483 return (error); 484 } 485 486 int 487 pppxpoll(dev_t dev, int events, struct proc *p) 488 { 489 struct pppx_dev *pxd = pppx_dev2pxd(dev); 490 int revents = 0; 491 492 if (events & (POLLIN | POLLRDNORM)) { 493 if (!mq_empty(&pxd->pxd_svcq)) 494 revents |= events & (POLLIN | POLLRDNORM); 495 } 496 if (events & (POLLOUT | POLLWRNORM)) 497 revents |= events & (POLLOUT | POLLWRNORM); 498 499 if (revents == 0) { 500 if (events & (POLLIN | POLLRDNORM)) 501 selrecord(p, &pxd->pxd_rsel); 502 } 503 504 return (revents); 505 } 506 507 int 508 pppxkqfilter(dev_t dev, struct knote *kn) 509 { 510 struct pppx_dev *pxd = pppx_dev2pxd(dev); 511 struct mutex *mtx; 512 struct klist *klist; 513 514 switch (kn->kn_filter) { 515 case EVFILT_READ: 516 mtx = &pxd->pxd_rsel_mtx; 517 klist = &pxd->pxd_rsel.si_note; 518 kn->kn_fop = &pppx_rd_filtops; 519 break; 520 case EVFILT_WRITE: 521 mtx = &pxd->pxd_wsel_mtx; 522 klist = &pxd->pxd_wsel.si_note; 523 kn->kn_fop = &pppx_wr_filtops; 524 break; 525 default: 526 return (EINVAL); 527 } 528 529 kn->kn_hook = (caddr_t)pxd; 530 531 mtx_enter(mtx); 532 SLIST_INSERT_HEAD(klist, kn, kn_selnext); 533 mtx_leave(mtx); 534 535 return (0); 536 } 537 538 void 539 filt_pppx_rdetach(struct knote *kn) 540 { 541 struct pppx_dev *pxd = (struct pppx_dev *)kn->kn_hook; 542 struct klist *klist = &pxd->pxd_rsel.si_note; 543 544 mtx_enter(&pxd->pxd_rsel_mtx); 545 SLIST_REMOVE(klist, kn, knote, kn_selnext); 546 mtx_leave(&pxd->pxd_rsel_mtx); 547 } 548 549 int 550 filt_pppx_read(struct knote *kn, long hint) 551 { 552 struct pppx_dev *pxd = (struct pppx_dev *)kn->kn_hook; 553 554 kn->kn_data = mq_hdatalen(&pxd->pxd_svcq); 555 556 return (kn->kn_data > 0); 557 } 558 559 void 560 filt_pppx_wdetach(struct knote *kn) 561 { 562 struct pppx_dev *pxd = (struct pppx_dev *)kn->kn_hook; 563 struct klist *klist = &pxd->pxd_wsel.si_note; 564 565 mtx_enter(&pxd->pxd_wsel_mtx); 566 SLIST_REMOVE(klist, kn, knote, kn_selnext); 567 mtx_leave(&pxd->pxd_wsel_mtx); 568 } 569 570 int 571 filt_pppx_write(struct knote *kn, long hint) 572 { 573 /* We're always ready to accept a write. */ 574 return (1); 575 } 576 577 int 578 pppxclose(dev_t dev, int flags, int mode, struct proc *p) 579 { 580 struct pppx_dev *pxd; 581 struct pppx_if *pxi; 582 583 rw_enter_write(&pppx_devs_lk); 584 585 pxd = pppx_dev_lookup(dev); 586 587 /* XXX */ 588 NET_LOCK(); 589 while ((pxi = LIST_FIRST(&pxd->pxd_pxis))) 590 pppx_if_destroy(pxd, pxi); 591 NET_UNLOCK(); 592 593 LIST_REMOVE(pxd, pxd_entry); 594 595 mq_purge(&pxd->pxd_svcq); 596 597 free(pxd, M_DEVBUF, sizeof(*pxd)); 598 599 if (LIST_EMPTY(&pppx_devs)) { 600 pool_destroy(pppx_if_pl); 601 free(pppx_if_pl, M_DEVBUF, sizeof(*pppx_if_pl)); 602 pppx_if_pl = NULL; 603 } 604 605 rw_exit_write(&pppx_devs_lk); 606 return (0); 607 } 608 609 int 610 pppx_if_next_unit(void) 611 { 612 struct pppx_if *pxi; 613 int unit = 0; 614 615 rw_assert_wrlock(&pppx_ifs_lk); 616 617 /* this is safe without splnet since we're not modifying it */ 618 do { 619 int found = 0; 620 RBT_FOREACH(pxi, pppx_ifs, &pppx_ifs) { 621 if (pxi->pxi_unit == unit) { 622 found = 1; 623 break; 624 } 625 } 626 627 if (found == 0) 628 break; 629 unit++; 630 } while (unit > 0); 631 632 return (unit); 633 } 634 635 struct pppx_if * 636 pppx_if_find(struct pppx_dev *pxd, int session_id, int protocol) 637 { 638 struct pppx_if *s, *p; 639 s = malloc(sizeof(*s), M_DEVBUF, M_WAITOK | M_ZERO); 640 641 s->pxi_key.pxik_session_id = session_id; 642 s->pxi_key.pxik_protocol = protocol; 643 644 rw_enter_read(&pppx_ifs_lk); 645 p = RBT_FIND(pppx_ifs, &pppx_ifs, s); 646 if (p && p->pxi_ready == 0) 647 p = NULL; 648 rw_exit_read(&pppx_ifs_lk); 649 650 free(s, M_DEVBUF, sizeof(*s)); 651 return (p); 652 } 653 654 int 655 pppx_add_session(struct pppx_dev *pxd, struct pipex_session_req *req) 656 { 657 struct pppx_if *pxi; 658 struct pipex_session *session; 659 struct pipex_hash_head *chain; 660 struct ifnet *ifp; 661 int unit, error = 0; 662 struct in_ifaddr *ia; 663 struct sockaddr_in ifaddr; 664 #ifdef PIPEX_PPPOE 665 struct ifnet *over_ifp = NULL; 666 #endif 667 668 switch (req->pr_protocol) { 669 #ifdef PIPEX_PPPOE 670 case PIPEX_PROTO_PPPOE: 671 over_ifp = ifunit(req->pr_proto.pppoe.over_ifname); 672 if (over_ifp == NULL) 673 return (EINVAL); 674 if (req->pr_peer_address.ss_family != AF_UNSPEC) 675 return (EINVAL); 676 break; 677 #endif 678 #ifdef PIPEX_PPTP 679 case PIPEX_PROTO_PPTP: 680 #endif 681 #ifdef PIPEX_L2TP 682 case PIPEX_PROTO_L2TP: 683 #endif 684 switch (req->pr_peer_address.ss_family) { 685 case AF_INET: 686 if (req->pr_peer_address.ss_len != sizeof(struct sockaddr_in)) 687 return (EINVAL); 688 break; 689 #ifdef INET6 690 case AF_INET6: 691 if (req->pr_peer_address.ss_len != sizeof(struct sockaddr_in6)) 692 return (EINVAL); 693 break; 694 #endif 695 default: 696 return (EPROTONOSUPPORT); 697 } 698 if (req->pr_peer_address.ss_family != 699 req->pr_local_address.ss_family || 700 req->pr_peer_address.ss_len != 701 req->pr_local_address.ss_len) 702 return (EINVAL); 703 break; 704 default: 705 return (EPROTONOSUPPORT); 706 } 707 708 pxi = pool_get(pppx_if_pl, PR_WAITOK | PR_ZERO); 709 if (pxi == NULL) 710 return (ENOMEM); 711 712 session = &pxi->pxi_session; 713 ifp = &pxi->pxi_if; 714 715 /* fake a pipex interface context */ 716 session->pipex_iface = &pxi->pxi_ifcontext; 717 session->pipex_iface->ifnet_this = ifp; 718 session->pipex_iface->pipexmode = PIPEX_ENABLED; 719 720 /* setup session */ 721 session->state = PIPEX_STATE_OPENED; 722 session->protocol = req->pr_protocol; 723 session->session_id = req->pr_session_id; 724 session->peer_session_id = req->pr_peer_session_id; 725 session->peer_mru = req->pr_peer_mru; 726 session->timeout_sec = req->pr_timeout_sec; 727 session->ppp_flags = req->pr_ppp_flags; 728 session->ppp_id = req->pr_ppp_id; 729 730 session->ip_forward = 1; 731 732 session->ip_address.sin_family = AF_INET; 733 session->ip_address.sin_len = sizeof(struct sockaddr_in); 734 session->ip_address.sin_addr = req->pr_ip_address; 735 736 session->ip_netmask.sin_family = AF_INET; 737 session->ip_netmask.sin_len = sizeof(struct sockaddr_in); 738 session->ip_netmask.sin_addr = req->pr_ip_netmask; 739 740 if (session->ip_netmask.sin_addr.s_addr == 0L) 741 session->ip_netmask.sin_addr.s_addr = 0xffffffffL; 742 session->ip_address.sin_addr.s_addr &= 743 session->ip_netmask.sin_addr.s_addr; 744 745 if (req->pr_peer_address.ss_len > 0) 746 memcpy(&session->peer, &req->pr_peer_address, 747 MIN(req->pr_peer_address.ss_len, sizeof(session->peer))); 748 if (req->pr_local_address.ss_len > 0) 749 memcpy(&session->local, &req->pr_local_address, 750 MIN(req->pr_local_address.ss_len, sizeof(session->local))); 751 #ifdef PIPEX_PPPOE 752 if (req->pr_protocol == PIPEX_PROTO_PPPOE) 753 session->proto.pppoe.over_ifidx = over_ifp->if_index; 754 #endif 755 #ifdef PIPEX_PPTP 756 if (req->pr_protocol == PIPEX_PROTO_PPTP) { 757 struct pipex_pptp_session *sess_pptp = &session->proto.pptp; 758 759 sess_pptp->snd_gap = 0; 760 sess_pptp->rcv_gap = 0; 761 sess_pptp->snd_una = req->pr_proto.pptp.snd_una; 762 sess_pptp->snd_nxt = req->pr_proto.pptp.snd_nxt; 763 sess_pptp->rcv_nxt = req->pr_proto.pptp.rcv_nxt; 764 sess_pptp->rcv_acked = req->pr_proto.pptp.rcv_acked; 765 766 sess_pptp->winsz = req->pr_proto.pptp.winsz; 767 sess_pptp->maxwinsz = req->pr_proto.pptp.maxwinsz; 768 sess_pptp->peer_maxwinsz = req->pr_proto.pptp.peer_maxwinsz; 769 /* last ack number */ 770 sess_pptp->ul_snd_una = sess_pptp->snd_una - 1; 771 } 772 #endif 773 #ifdef PIPEX_L2TP 774 if (req->pr_protocol == PIPEX_PROTO_L2TP) { 775 struct pipex_l2tp_session *sess_l2tp = &session->proto.l2tp; 776 777 /* session keys */ 778 sess_l2tp->tunnel_id = req->pr_proto.l2tp.tunnel_id; 779 sess_l2tp->peer_tunnel_id = req->pr_proto.l2tp.peer_tunnel_id; 780 781 /* protocol options */ 782 sess_l2tp->option_flags = req->pr_proto.l2tp.option_flags; 783 784 /* initial state of dynamic context */ 785 sess_l2tp->ns_gap = sess_l2tp->nr_gap = 0; 786 sess_l2tp->ns_nxt = req->pr_proto.l2tp.ns_nxt; 787 sess_l2tp->nr_nxt = req->pr_proto.l2tp.nr_nxt; 788 sess_l2tp->ns_una = req->pr_proto.l2tp.ns_una; 789 sess_l2tp->nr_acked = req->pr_proto.l2tp.nr_acked; 790 /* last ack number */ 791 sess_l2tp->ul_ns_una = sess_l2tp->ns_una - 1; 792 } 793 #endif 794 #ifdef PIPEX_MPPE 795 if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ACCEPTED) != 0) 796 pipex_session_init_mppe_recv(session, 797 req->pr_mppe_recv.stateless, req->pr_mppe_recv.keylenbits, 798 req->pr_mppe_recv.master_key); 799 if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ENABLED) != 0) 800 pipex_session_init_mppe_send(session, 801 req->pr_mppe_send.stateless, req->pr_mppe_send.keylenbits, 802 req->pr_mppe_send.master_key); 803 804 if (pipex_session_is_mppe_required(session)) { 805 if (!pipex_session_is_mppe_enabled(session) || 806 !pipex_session_is_mppe_accepted(session)) { 807 pool_put(pppx_if_pl, pxi); 808 return (EINVAL); 809 } 810 } 811 #endif 812 813 /* try to set the interface up */ 814 rw_enter_write(&pppx_ifs_lk); 815 unit = pppx_if_next_unit(); 816 if (unit < 0) { 817 pool_put(pppx_if_pl, pxi); 818 error = ENOMEM; 819 rw_exit_write(&pppx_ifs_lk); 820 goto out; 821 } 822 823 pxi->pxi_unit = unit; 824 pxi->pxi_key.pxik_session_id = req->pr_session_id; 825 pxi->pxi_key.pxik_protocol = req->pr_protocol; 826 pxi->pxi_dev = pxd; 827 828 /* this is safe without splnet since we're not modifying it */ 829 if (RBT_FIND(pppx_ifs, &pppx_ifs, pxi) != NULL) { 830 pool_put(pppx_if_pl, pxi); 831 error = EADDRINUSE; 832 rw_exit_write(&pppx_ifs_lk); 833 goto out; 834 } 835 836 if (RBT_INSERT(pppx_ifs, &pppx_ifs, pxi) != NULL) 837 panic("%s: pppx_ifs modified while lock was held", __func__); 838 LIST_INSERT_HEAD(&pxd->pxd_pxis, pxi, pxi_list); 839 rw_exit_write(&pppx_ifs_lk); 840 841 snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d", "pppx", unit); 842 ifp->if_mtu = req->pr_peer_mru; /* XXX */ 843 ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST | IFF_UP; 844 ifp->if_start = pppx_if_start; 845 ifp->if_output = pppx_if_output; 846 ifp->if_ioctl = pppx_if_ioctl; 847 ifp->if_rtrequest = p2p_rtrequest; 848 ifp->if_type = IFT_PPP; 849 IFQ_SET_MAXLEN(&ifp->if_snd, 1); 850 ifp->if_softc = pxi; 851 /* ifp->if_rdomain = req->pr_rdomain; */ 852 853 /* hook up pipex context */ 854 chain = PIPEX_ID_HASHTABLE(session->session_id); 855 LIST_INSERT_HEAD(chain, session, id_chain); 856 LIST_INSERT_HEAD(&pipex_session_list, session, session_list); 857 switch (req->pr_protocol) { 858 case PIPEX_PROTO_PPTP: 859 case PIPEX_PROTO_L2TP: 860 chain = PIPEX_PEER_ADDR_HASHTABLE( 861 pipex_sockaddr_hash_key(&session->peer.sa)); 862 LIST_INSERT_HEAD(chain, session, peer_addr_chain); 863 break; 864 } 865 866 /* if first session is added, start timer */ 867 if (LIST_NEXT(session, session_list) == NULL) 868 pipex_timer_start(); 869 870 /* XXXSMP breaks atomicity */ 871 NET_UNLOCK(); 872 if_attach(ifp); 873 NET_LOCK(); 874 875 if_addgroup(ifp, "pppx"); 876 if_alloc_sadl(ifp); 877 878 #if NBPFILTER > 0 879 bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(u_int32_t)); 880 #endif 881 SET(ifp->if_flags, IFF_RUNNING); 882 883 /* XXX ipv6 support? how does the caller indicate it wants ipv6 884 * instead of ipv4? 885 */ 886 memset(&ifaddr, 0, sizeof(ifaddr)); 887 ifaddr.sin_family = AF_INET; 888 ifaddr.sin_len = sizeof(ifaddr); 889 ifaddr.sin_addr = req->pr_ip_srcaddr; 890 891 ia = malloc(sizeof (*ia), M_IFADDR, M_WAITOK | M_ZERO); 892 893 ia->ia_addr.sin_family = AF_INET; 894 ia->ia_addr.sin_len = sizeof(struct sockaddr_in); 895 ia->ia_addr.sin_addr = req->pr_ip_srcaddr; 896 897 ia->ia_dstaddr.sin_family = AF_INET; 898 ia->ia_dstaddr.sin_len = sizeof(struct sockaddr_in); 899 ia->ia_dstaddr.sin_addr = req->pr_ip_address; 900 901 ia->ia_sockmask.sin_family = AF_INET; 902 ia->ia_sockmask.sin_len = sizeof(struct sockaddr_in); 903 ia->ia_sockmask.sin_addr = req->pr_ip_netmask; 904 905 ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr); 906 ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr); 907 ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask); 908 ia->ia_ifa.ifa_ifp = ifp; 909 910 ia->ia_netmask = ia->ia_sockmask.sin_addr.s_addr; 911 912 error = in_ifinit(ifp, ia, &ifaddr, 1); 913 if (error) { 914 printf("pppx: unable to set addresses for %s, error=%d\n", 915 ifp->if_xname, error); 916 } else { 917 if_addrhooks_run(ifp); 918 } 919 rw_enter_write(&pppx_ifs_lk); 920 pxi->pxi_ready = 1; 921 rw_exit_write(&pppx_ifs_lk); 922 923 out: 924 return (error); 925 } 926 927 int 928 pppx_del_session(struct pppx_dev *pxd, struct pipex_session_close_req *req) 929 { 930 struct pppx_if *pxi; 931 932 pxi = pppx_if_find(pxd, req->pcr_session_id, req->pcr_protocol); 933 if (pxi == NULL) 934 return (EINVAL); 935 936 req->pcr_stat = pxi->pxi_session.stat; 937 938 pppx_if_destroy(pxd, pxi); 939 return (0); 940 } 941 942 int 943 pppx_set_session_descr(struct pppx_dev *pxd, 944 struct pipex_session_descr_req *req) 945 { 946 struct pppx_if *pxi; 947 948 pxi = pppx_if_find(pxd, req->pdr_session_id, req->pdr_protocol); 949 if (pxi == NULL) 950 return (EINVAL); 951 952 (void)memset(pxi->pxi_if.if_description, 0, IFDESCRSIZE); 953 strlcpy(pxi->pxi_if.if_description, req->pdr_descr, IFDESCRSIZE); 954 955 return (0); 956 } 957 958 void 959 pppx_if_destroy(struct pppx_dev *pxd, struct pppx_if *pxi) 960 { 961 struct ifnet *ifp; 962 struct pipex_session *session; 963 964 NET_ASSERT_LOCKED(); 965 session = &pxi->pxi_session; 966 ifp = &pxi->pxi_if; 967 968 LIST_REMOVE(session, id_chain); 969 LIST_REMOVE(session, session_list); 970 switch (session->protocol) { 971 case PIPEX_PROTO_PPTP: 972 case PIPEX_PROTO_L2TP: 973 LIST_REMOVE((struct pipex_session *)session, 974 peer_addr_chain); 975 break; 976 } 977 978 /* if final session is destroyed, stop timer */ 979 if (LIST_EMPTY(&pipex_session_list)) 980 pipex_timer_stop(); 981 982 /* XXXSMP breaks atomicity */ 983 NET_UNLOCK(); 984 if_detach(ifp); 985 NET_LOCK(); 986 987 rw_enter_write(&pppx_ifs_lk); 988 if (RBT_REMOVE(pppx_ifs, &pppx_ifs, pxi) == NULL) 989 panic("%s: pppx_ifs modified while lock was held", __func__); 990 LIST_REMOVE(pxi, pxi_list); 991 rw_exit_write(&pppx_ifs_lk); 992 993 pool_put(pppx_if_pl, pxi); 994 } 995 996 void 997 pppx_if_start(struct ifnet *ifp) 998 { 999 struct pppx_if *pxi = (struct pppx_if *)ifp->if_softc; 1000 struct mbuf *m; 1001 int proto; 1002 1003 if (!ISSET(ifp->if_flags, IFF_RUNNING)) 1004 return; 1005 1006 for (;;) { 1007 IFQ_DEQUEUE(&ifp->if_snd, m); 1008 1009 if (m == NULL) 1010 break; 1011 1012 proto = *mtod(m, int *); 1013 m_adj(m, sizeof(proto)); 1014 1015 ifp->if_obytes += m->m_pkthdr.len; 1016 ifp->if_opackets++; 1017 1018 pipex_ppp_output(m, &pxi->pxi_session, proto); 1019 } 1020 } 1021 1022 int 1023 pppx_if_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 1024 struct rtentry *rt) 1025 { 1026 struct pppx_if *pxi = (struct pppx_if *)ifp->if_softc; 1027 struct pppx_hdr *th; 1028 int error = 0; 1029 int proto; 1030 1031 NET_ASSERT_LOCKED(); 1032 1033 if (!ISSET(ifp->if_flags, IFF_UP)) { 1034 m_freem(m); 1035 error = ENETDOWN; 1036 goto out; 1037 } 1038 1039 #if NBPFILTER > 0 1040 if (ifp->if_bpf) 1041 bpf_mtap_af(ifp->if_bpf, dst->sa_family, m, BPF_DIRECTION_OUT); 1042 #endif 1043 if (pipex_enable) { 1044 switch (dst->sa_family) { 1045 #ifdef INET6 1046 case AF_INET6: 1047 proto = PPP_IPV6; 1048 break; 1049 #endif 1050 case AF_INET: 1051 proto = PPP_IP; 1052 break; 1053 default: 1054 m_freem(m); 1055 error = EPFNOSUPPORT; 1056 goto out; 1057 } 1058 } else 1059 proto = htonl(dst->sa_family); 1060 1061 M_PREPEND(m, sizeof(int), M_DONTWAIT); 1062 if (m == NULL) { 1063 error = ENOBUFS; 1064 goto out; 1065 } 1066 *mtod(m, int *) = proto; 1067 1068 if (pipex_enable) 1069 error = if_enqueue(ifp, m); 1070 else { 1071 M_PREPEND(m, sizeof(struct pppx_hdr), M_DONTWAIT); 1072 if (m == NULL) { 1073 error = ENOBUFS; 1074 goto out; 1075 } 1076 th = mtod(m, struct pppx_hdr *); 1077 th->pppx_proto = 0; /* not used */ 1078 th->pppx_id = pxi->pxi_session.ppp_id; 1079 rw_enter_read(&pppx_devs_lk); 1080 error = mq_enqueue(&pxi->pxi_dev->pxd_svcq, m); 1081 if (error == 0) { 1082 if (pxi->pxi_dev->pxd_waiting) { 1083 wakeup((caddr_t)pxi->pxi_dev); 1084 pxi->pxi_dev->pxd_waiting = 0; 1085 } 1086 selwakeup(&pxi->pxi_dev->pxd_rsel); 1087 } 1088 rw_exit_read(&pppx_devs_lk); 1089 } 1090 1091 out: 1092 if (error) 1093 ifp->if_oerrors++; 1094 return (error); 1095 } 1096 1097 int 1098 pppx_if_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr) 1099 { 1100 struct pppx_if *pxi = (struct pppx_if *)ifp->if_softc; 1101 struct ifreq *ifr = (struct ifreq *)addr; 1102 int error = 0; 1103 1104 switch (cmd) { 1105 case SIOCSIFADDR: 1106 break; 1107 1108 case SIOCSIFFLAGS: 1109 break; 1110 1111 case SIOCADDMULTI: 1112 case SIOCDELMULTI: 1113 break; 1114 1115 case SIOCSIFMTU: 1116 if (ifr->ifr_mtu < 512 || 1117 ifr->ifr_mtu > pxi->pxi_session.peer_mru) 1118 error = EINVAL; 1119 else 1120 ifp->if_mtu = ifr->ifr_mtu; 1121 break; 1122 1123 default: 1124 error = ENOTTY; 1125 break; 1126 } 1127 1128 return (error); 1129 } 1130 1131 RBT_GENERATE(pppx_ifs, pppx_if, pxi_entry, pppx_if_cmp); 1132 1133 /* 1134 * pppac(4) - PPP Access Concentrator interface 1135 */ 1136 1137 #include <net/if_tun.h> 1138 1139 struct pppac_softc { 1140 struct ifnet sc_if; 1141 unsigned int sc_dead; 1142 dev_t sc_dev; 1143 LIST_ENTRY(pppac_softc) 1144 sc_entry; 1145 1146 struct mutex sc_rsel_mtx; 1147 struct selinfo sc_rsel; 1148 struct mutex sc_wsel_mtx; 1149 struct selinfo sc_wsel; 1150 1151 struct pipex_iface_context 1152 sc_pipex_iface; 1153 1154 struct mbuf_queue 1155 sc_mq; 1156 }; 1157 1158 LIST_HEAD(pppac_list, pppac_softc); 1159 1160 static void filt_pppac_rdetach(struct knote *); 1161 static int filt_pppac_read(struct knote *, long); 1162 1163 static const struct filterops pppac_rd_filtops = { 1164 1, 1165 NULL, 1166 filt_pppac_rdetach, 1167 filt_pppac_read 1168 }; 1169 1170 static void filt_pppac_wdetach(struct knote *); 1171 static int filt_pppac_write(struct knote *, long); 1172 1173 static const struct filterops pppac_wr_filtops = { 1174 1, 1175 NULL, 1176 filt_pppac_wdetach, 1177 filt_pppac_write 1178 }; 1179 1180 static struct pppac_list pppac_devs = LIST_HEAD_INITIALIZER(pppac_devs); 1181 1182 static int pppac_ioctl(struct ifnet *, u_long, caddr_t); 1183 1184 static int pppac_output(struct ifnet *, struct mbuf *, struct sockaddr *, 1185 struct rtentry *); 1186 static void pppac_start(struct ifnet *); 1187 1188 static inline struct pppac_softc * 1189 pppac_lookup(dev_t dev) 1190 { 1191 struct pppac_softc *sc; 1192 1193 LIST_FOREACH(sc, &pppac_devs, sc_entry) { 1194 if (sc->sc_dev == dev) 1195 return (sc); 1196 } 1197 1198 return (NULL); 1199 } 1200 1201 void 1202 pppacattach(int n) 1203 { 1204 pipex_init(); /* to be sure, to be sure */ 1205 } 1206 1207 int 1208 pppacopen(dev_t dev, int flags, int mode, struct proc *p) 1209 { 1210 struct pppac_softc *sc; 1211 struct ifnet *ifp; 1212 1213 sc = pppac_lookup(dev); 1214 if (sc != NULL) 1215 return (EBUSY); 1216 1217 sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); 1218 sc->sc_dev = dev; 1219 1220 mtx_init(&sc->sc_rsel_mtx, IPL_SOFTNET); 1221 mtx_init(&sc->sc_wsel_mtx, IPL_SOFTNET); 1222 mq_init(&sc->sc_mq, IFQ_MAXLEN, IPL_SOFTNET); 1223 1224 LIST_INSERT_HEAD(&pppac_devs, sc, sc_entry); 1225 1226 ifp = &sc->sc_if; 1227 snprintf(ifp->if_xname, sizeof(ifp->if_xname), "pppac%u", minor(dev)); 1228 1229 ifp->if_softc = sc; 1230 ifp->if_type = IFT_L3IPVLAN; 1231 ifp->if_hdrlen = sizeof(uint32_t); /* for BPF */; 1232 ifp->if_mtu = MAXMCLBYTES - sizeof(uint32_t); 1233 ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST; 1234 ifp->if_xflags = IFXF_CLONED; 1235 ifp->if_rtrequest = p2p_rtrequest; /* XXX */ 1236 ifp->if_output = pppac_output; 1237 ifp->if_start = pppac_start; 1238 ifp->if_ioctl = pppac_ioctl; 1239 1240 if_counters_alloc(ifp); 1241 if_attach(ifp); 1242 if_alloc_sadl(ifp); 1243 1244 #if NBPFILTER > 0 1245 bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(uint32_t)); 1246 #endif 1247 1248 pipex_iface_init(&sc->sc_pipex_iface, ifp); 1249 1250 return (0); 1251 } 1252 1253 int 1254 pppacread(dev_t dev, struct uio *uio, int ioflag) 1255 { 1256 struct pppac_softc *sc = pppac_lookup(dev); 1257 struct ifnet *ifp = &sc->sc_if; 1258 struct mbuf *m0, *m; 1259 int error = 0; 1260 size_t len; 1261 1262 if (!ISSET(ifp->if_flags, IFF_RUNNING)) 1263 return (EHOSTDOWN); 1264 1265 m0 = mq_dequeue(&sc->sc_mq); 1266 if (m0 == NULL) { 1267 if (ISSET(ioflag, IO_NDELAY)) 1268 return (EWOULDBLOCK); 1269 1270 do { 1271 error = tsleep_nsec(sc, (PZERO + 1)|PCATCH, 1272 "pppacrd", INFSLP); 1273 if (error != 0) 1274 return (error); 1275 1276 m0 = mq_dequeue(&sc->sc_mq); 1277 } while (m0 == NULL); 1278 } 1279 1280 m = m0; 1281 while (uio->uio_resid > 0) { 1282 len = ulmin(uio->uio_resid, m->m_len); 1283 if (len != 0) { 1284 error = uiomove(mtod(m, caddr_t), len, uio); 1285 if (error != 0) 1286 break; 1287 } 1288 1289 m = m->m_next; 1290 if (m == NULL) 1291 break; 1292 } 1293 m_freem(m0); 1294 1295 return (error); 1296 } 1297 1298 int 1299 pppacwrite(dev_t dev, struct uio *uio, int ioflag) 1300 { 1301 struct pppac_softc *sc = pppac_lookup(dev); 1302 struct ifnet *ifp = &sc->sc_if; 1303 uint32_t proto; 1304 int error; 1305 struct mbuf *m; 1306 1307 if (!ISSET(ifp->if_flags, IFF_RUNNING)) 1308 return (EHOSTDOWN); 1309 1310 if (uio->uio_resid < ifp->if_hdrlen || uio->uio_resid > MAXMCLBYTES) 1311 return (EMSGSIZE); 1312 1313 m = m_gethdr(M_DONTWAIT, MT_DATA); 1314 if (m == NULL) 1315 return (ENOMEM); 1316 1317 if (uio->uio_resid > MINCLSIZE) { 1318 m_clget(m, M_WAITOK, uio->uio_resid); 1319 if (!ISSET(m->m_flags, M_EXT)) { 1320 m_free(m); 1321 return (ENOMEM); 1322 } 1323 } 1324 1325 m->m_pkthdr.len = m->m_len = uio->uio_resid; 1326 1327 error = uiomove(mtod(m, void *), m->m_len, uio); 1328 if (error != 0) { 1329 m_freem(m); 1330 return (error); 1331 } 1332 1333 #if NBPFILTER > 0 1334 if (ifp->if_bpf) 1335 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN); 1336 #endif 1337 1338 /* strip the tunnel header */ 1339 proto = ntohl(*mtod(m, uint32_t *)); 1340 m_adj(m, sizeof(uint32_t)); 1341 1342 m->m_flags &= ~(M_MCAST|M_BCAST); 1343 m->m_pkthdr.ph_ifidx = ifp->if_index; 1344 m->m_pkthdr.ph_rtableid = ifp->if_rdomain; 1345 1346 #if NPF > 0 1347 pf_pkt_addr_changed(m); 1348 #endif 1349 1350 counters_pkt(ifp->if_counters, 1351 ifc_ipackets, ifc_ibytes, m->m_pkthdr.len); 1352 1353 NET_LOCK(); 1354 1355 switch (proto) { 1356 case AF_INET: 1357 ipv4_input(ifp, m); 1358 break; 1359 #ifdef INET6 1360 case AF_INET6: 1361 ipv6_input(ifp, m); 1362 break; 1363 #endif 1364 default: 1365 m_freem(m); 1366 error = EAFNOSUPPORT; 1367 break; 1368 } 1369 1370 NET_UNLOCK(); 1371 1372 return (error); 1373 } 1374 1375 int 1376 pppacioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) 1377 { 1378 struct pppac_softc *sc = pppac_lookup(dev); 1379 int error = 0; 1380 1381 switch (cmd) { 1382 case TUNSIFMODE: /* make npppd happy */ 1383 break; 1384 1385 case FIONBIO: 1386 break; 1387 case FIONREAD: 1388 *(int *)data = mq_hdatalen(&sc->sc_mq); 1389 break; 1390 1391 default: 1392 error = pipex_ioctl(&sc->sc_pipex_iface, cmd, data); 1393 break; 1394 } 1395 1396 return (error); 1397 } 1398 1399 int 1400 pppacpoll(dev_t dev, int events, struct proc *p) 1401 { 1402 struct pppac_softc *sc = pppac_lookup(dev); 1403 int revents = 0; 1404 1405 if (events & (POLLIN | POLLRDNORM)) { 1406 if (!mq_empty(&sc->sc_mq)) 1407 revents |= events & (POLLIN | POLLRDNORM); 1408 } 1409 if (events & (POLLOUT | POLLWRNORM)) 1410 revents |= events & (POLLOUT | POLLWRNORM); 1411 1412 if (revents == 0) { 1413 if (events & (POLLIN | POLLRDNORM)) 1414 selrecord(p, &sc->sc_rsel); 1415 } 1416 1417 return (revents); 1418 } 1419 1420 int 1421 pppackqfilter(dev_t dev, struct knote *kn) 1422 { 1423 struct pppac_softc *sc = pppac_lookup(dev); 1424 struct mutex *mtx; 1425 struct klist *klist; 1426 1427 switch (kn->kn_filter) { 1428 case EVFILT_READ: 1429 mtx = &sc->sc_rsel_mtx; 1430 klist = &sc->sc_rsel.si_note; 1431 kn->kn_fop = &pppac_rd_filtops; 1432 break; 1433 case EVFILT_WRITE: 1434 mtx = &sc->sc_wsel_mtx; 1435 klist = &sc->sc_wsel.si_note; 1436 kn->kn_fop = &pppac_wr_filtops; 1437 break; 1438 default: 1439 return (EINVAL); 1440 } 1441 1442 kn->kn_hook = sc; 1443 1444 mtx_enter(mtx); 1445 SLIST_INSERT_HEAD(klist, kn, kn_selnext); 1446 mtx_leave(mtx); 1447 1448 return (0); 1449 } 1450 1451 static void 1452 filt_pppac_rdetach(struct knote *kn) 1453 { 1454 struct pppac_softc *sc = kn->kn_hook; 1455 struct klist *klist = &sc->sc_rsel.si_note; 1456 1457 mtx_enter(&sc->sc_rsel_mtx); 1458 SLIST_REMOVE(klist, kn, knote, kn_selnext); 1459 mtx_leave(&sc->sc_rsel_mtx); 1460 } 1461 1462 static int 1463 filt_pppac_read(struct knote *kn, long hint) 1464 { 1465 struct pppac_softc *sc = kn->kn_hook; 1466 1467 kn->kn_data = mq_hdatalen(&sc->sc_mq); 1468 1469 return (kn->kn_data > 0); 1470 } 1471 1472 static void 1473 filt_pppac_wdetach(struct knote *kn) 1474 { 1475 struct pppac_softc *sc = kn->kn_hook; 1476 struct klist *klist = &sc->sc_wsel.si_note; 1477 1478 mtx_enter(&sc->sc_wsel_mtx); 1479 SLIST_REMOVE(klist, kn, knote, kn_selnext); 1480 mtx_leave(&sc->sc_wsel_mtx); 1481 } 1482 1483 static int 1484 filt_pppac_write(struct knote *kn, long hint) 1485 { 1486 /* We're always ready to accept a write. */ 1487 return (1); 1488 } 1489 1490 int 1491 pppacclose(dev_t dev, int flags, int mode, struct proc *p) 1492 { 1493 struct pppac_softc *sc = pppac_lookup(dev); 1494 struct ifnet *ifp = &sc->sc_if; 1495 int s; 1496 1497 NET_LOCK(); 1498 sc->sc_dead = 1; 1499 CLR(ifp->if_flags, IFF_RUNNING); 1500 NET_UNLOCK(); 1501 1502 s = splhigh(); 1503 klist_invalidate(&sc->sc_rsel.si_note); 1504 klist_invalidate(&sc->sc_wsel.si_note); 1505 splx(s); 1506 1507 pipex_iface_fini(&sc->sc_pipex_iface); 1508 1509 if_detach(ifp); 1510 1511 LIST_REMOVE(sc, sc_entry); 1512 free(sc, M_DEVBUF, sizeof(*sc)); 1513 1514 return (0); 1515 } 1516 1517 static int 1518 pppac_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 1519 { 1520 struct pppac_softc *sc = ifp->if_softc; 1521 /* struct ifreq *ifr = (struct ifreq *)data; */ 1522 int error = 0; 1523 1524 if (sc->sc_dead) 1525 return (ENXIO); 1526 1527 switch (cmd) { 1528 case SIOCSIFADDR: 1529 SET(ifp->if_flags, IFF_UP); /* XXX cry cry */ 1530 /* FALLTHROUGH */ 1531 case SIOCSIFFLAGS: 1532 if (ISSET(ifp->if_flags, IFF_UP)) 1533 SET(ifp->if_flags, IFF_RUNNING); 1534 else 1535 CLR(ifp->if_flags, IFF_RUNNING); 1536 break; 1537 case SIOCSIFMTU: 1538 break; 1539 case SIOCADDMULTI: 1540 case SIOCDELMULTI: 1541 /* XXX */ 1542 break; 1543 1544 default: 1545 error = ENOTTY; 1546 break; 1547 } 1548 1549 return (error); 1550 } 1551 1552 static int 1553 pppac_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 1554 struct rtentry *rt) 1555 { 1556 int error; 1557 1558 if (!ISSET(ifp->if_flags, IFF_RUNNING)) { 1559 error = EHOSTDOWN; 1560 goto drop; 1561 } 1562 1563 switch (dst->sa_family) { 1564 case AF_INET: 1565 #ifdef INET6 1566 case AF_INET6: 1567 #endif 1568 break; 1569 default: 1570 error = EAFNOSUPPORT; 1571 goto drop; 1572 } 1573 1574 m->m_pkthdr.ph_family = dst->sa_family; 1575 1576 return (if_enqueue(ifp, m)); 1577 1578 drop: 1579 m_freem(m); 1580 return (error); 1581 } 1582 1583 static void 1584 pppac_start(struct ifnet *ifp) 1585 { 1586 struct pppac_softc *sc = ifp->if_softc; 1587 struct mbuf *m; 1588 1589 while ((m = ifq_dequeue(&ifp->if_snd)) != NULL) { 1590 #if NBPFILTER > 0 1591 if (ifp->if_bpf) { 1592 bpf_mtap_af(ifp->if_bpf, m->m_pkthdr.ph_family, m, 1593 BPF_DIRECTION_OUT); 1594 } 1595 #endif 1596 1597 m = pipex_output(m, m->m_pkthdr.ph_family, 0, 1598 &sc->sc_pipex_iface); 1599 if (m == NULL) 1600 continue; 1601 1602 m = m_prepend(m, sizeof(uint32_t), M_DONTWAIT); 1603 if (m == NULL) { 1604 /* oh well */ 1605 continue; 1606 } 1607 *mtod(m, uint32_t *) = htonl(m->m_pkthdr.ph_family); 1608 1609 mq_enqueue(&sc->sc_mq, m); /* qdrop */ 1610 } 1611 1612 if (!mq_empty(&sc->sc_mq)) { 1613 KERNEL_ASSERT_LOCKED(); 1614 wakeup(sc); 1615 selwakeup(&sc->sc_rsel); 1616 } 1617 } 1618