1 /* $OpenBSD: if_pppx.c,v 1.120 2022/07/18 10:55:20 mvs 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/pool.h> 54 #include <sys/mbuf.h> 55 #include <sys/errno.h> 56 #include <sys/socket.h> 57 #include <sys/ioctl.h> 58 #include <sys/vnode.h> 59 #include <sys/selinfo.h> 60 61 #include <net/if.h> 62 #include <net/if_types.h> 63 #include <netinet/in.h> 64 #include <netinet/if_ether.h> 65 #include <net/if_dl.h> 66 67 #include <netinet/in_var.h> 68 #include <netinet/ip.h> 69 #include <netinet/ip_var.h> 70 71 #ifdef INET6 72 #include <netinet6/in6_var.h> 73 #include <netinet/ip6.h> 74 #include <netinet6/nd6.h> 75 #endif /* INET6 */ 76 77 #include "bpfilter.h" 78 #if NBPFILTER > 0 79 #include <net/bpf.h> 80 #endif 81 82 #include "pf.h" 83 #if NPF > 0 84 #include <net/pfvar.h> 85 #endif 86 87 #include <net/ppp_defs.h> 88 #include <net/ppp-comp.h> 89 #include <crypto/arc4.h> 90 91 #ifdef PIPEX 92 #include <net/radix.h> 93 #include <net/pipex.h> 94 #include <net/pipex_local.h> 95 #else 96 #error PIPEX option not enabled 97 #endif 98 99 #ifdef PPPX_DEBUG 100 #define PPPX_D_INIT (1<<0) 101 102 int pppxdebug = 0; 103 104 #define DPRINTF(_m, _p...) do { \ 105 if (ISSET(pppxdebug, (_m))) \ 106 printf(_p); \ 107 } while (0) 108 #else 109 #define DPRINTF(_m, _p...) /* _m, _p */ 110 #endif 111 112 113 struct pppx_if; 114 115 /* 116 * Locks used to protect struct members and global data 117 * I immutable after creation 118 * K kernel lock 119 * N net lock 120 */ 121 122 struct pppx_dev { 123 LIST_ENTRY(pppx_dev) pxd_entry; /* [K] */ 124 int pxd_unit; /* [I] */ 125 126 /* kq shizz */ 127 struct selinfo pxd_rsel; 128 struct mutex pxd_rsel_mtx; 129 struct selinfo pxd_wsel; 130 struct mutex pxd_wsel_mtx; 131 132 /* queue of packets for userland to service - protected by splnet */ 133 struct mbuf_queue pxd_svcq; 134 int pxd_waiting; /* [N] */ 135 LIST_HEAD(,pppx_if) pxd_pxis; /* [N] */ 136 }; 137 138 LIST_HEAD(, pppx_dev) pppx_devs = 139 LIST_HEAD_INITIALIZER(pppx_devs); /* [K] */ 140 struct pool pppx_if_pl; 141 142 struct pppx_dev *pppx_dev_lookup(dev_t); 143 struct pppx_dev *pppx_dev2pxd(dev_t); 144 145 struct pppx_if_key { 146 int pxik_session_id; /* [I] */ 147 int pxik_protocol; /* [I] */ 148 }; 149 150 struct pppx_if { 151 struct pppx_if_key pxi_key; /* [I] must be first 152 in the struct */ 153 154 RBT_ENTRY(pppx_if) pxi_entry; /* [N] */ 155 LIST_ENTRY(pppx_if) pxi_list; /* [N] */ 156 157 int pxi_ready; /* [N] */ 158 159 int pxi_unit; /* [I] */ 160 struct ifnet pxi_if; 161 struct pppx_dev *pxi_dev; /* [I] */ 162 struct pipex_session *pxi_session; /* [I] */ 163 }; 164 165 static inline int 166 pppx_if_cmp(const struct pppx_if *a, const struct pppx_if *b) 167 { 168 return memcmp(&a->pxi_key, &b->pxi_key, sizeof(a->pxi_key)); 169 } 170 171 RBT_HEAD(pppx_ifs, pppx_if) pppx_ifs = RBT_INITIALIZER(&pppx_ifs); /* [N] */ 172 RBT_PROTOTYPE(pppx_ifs, pppx_if, pxi_entry, pppx_if_cmp); 173 174 int pppx_if_next_unit(void); 175 struct pppx_if *pppx_if_find(struct pppx_dev *, int, int); 176 int pppx_add_session(struct pppx_dev *, 177 struct pipex_session_req *); 178 int pppx_del_session(struct pppx_dev *, 179 struct pipex_session_close_req *); 180 int pppx_set_session_descr(struct pppx_dev *, 181 struct pipex_session_descr_req *); 182 183 void pppx_if_destroy(struct pppx_dev *, struct pppx_if *); 184 void pppx_if_qstart(struct ifqueue *); 185 int pppx_if_output(struct ifnet *, struct mbuf *, 186 struct sockaddr *, struct rtentry *); 187 int pppx_if_ioctl(struct ifnet *, u_long, caddr_t); 188 189 190 void pppxattach(int); 191 192 void filt_pppx_rdetach(struct knote *); 193 int filt_pppx_read(struct knote *, long); 194 195 const struct filterops pppx_rd_filtops = { 196 .f_flags = FILTEROP_ISFD, 197 .f_attach = NULL, 198 .f_detach = filt_pppx_rdetach, 199 .f_event = filt_pppx_read, 200 }; 201 202 void filt_pppx_wdetach(struct knote *); 203 int filt_pppx_write(struct knote *, long); 204 205 const struct filterops pppx_wr_filtops = { 206 .f_flags = FILTEROP_ISFD, 207 .f_attach = NULL, 208 .f_detach = filt_pppx_wdetach, 209 .f_event = filt_pppx_write, 210 }; 211 212 struct pppx_dev * 213 pppx_dev_lookup(dev_t dev) 214 { 215 struct pppx_dev *pxd; 216 int unit = minor(dev); 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 pxd = pppx_dev_lookup(dev); 232 233 return (pxd); 234 } 235 236 void 237 pppxattach(int n) 238 { 239 pool_init(&pppx_if_pl, sizeof(struct pppx_if), 0, IPL_NONE, 240 PR_WAITOK, "pppxif", NULL); 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 249 pxd = malloc(sizeof(*pxd), M_DEVBUF, M_WAITOK | M_ZERO); 250 if (pppx_dev_lookup(dev) != NULL) { 251 free(pxd, M_DEVBUF, sizeof(*pxd)); 252 return (EBUSY); 253 } 254 255 pxd->pxd_unit = minor(dev); 256 mtx_init(&pxd->pxd_rsel_mtx, IPL_NET); 257 mtx_init(&pxd->pxd_wsel_mtx, IPL_NET); 258 LIST_INIT(&pxd->pxd_pxis); 259 260 mq_init(&pxd->pxd_svcq, 128, IPL_NET); 261 LIST_INSERT_HEAD(&pppx_devs, pxd, pxd_entry); 262 263 return 0; 264 } 265 266 int 267 pppxread(dev_t dev, struct uio *uio, int ioflag) 268 { 269 struct pppx_dev *pxd = pppx_dev2pxd(dev); 270 struct mbuf *m, *m0; 271 int error = 0; 272 size_t len; 273 274 if (!pxd) 275 return (ENXIO); 276 277 while ((m0 = mq_dequeue(&pxd->pxd_svcq)) == NULL) { 278 if (ISSET(ioflag, IO_NDELAY)) 279 return (EWOULDBLOCK); 280 281 NET_LOCK(); 282 pxd->pxd_waiting = 1; 283 error = rwsleep_nsec(pxd, &netlock, 284 (PZERO + 1)|PCATCH, "pppxread", INFSLP); 285 NET_UNLOCK(); 286 if (error != 0) { 287 return (error); 288 } 289 } 290 291 while (m0 != NULL && uio->uio_resid > 0 && error == 0) { 292 len = ulmin(uio->uio_resid, m0->m_len); 293 if (len != 0) 294 error = uiomove(mtod(m0, caddr_t), len, uio); 295 m = m_free(m0); 296 m0 = m; 297 } 298 299 m_freem(m0); 300 301 return (error); 302 } 303 304 int 305 pppxwrite(dev_t dev, struct uio *uio, int ioflag) 306 { 307 struct pppx_dev *pxd = pppx_dev2pxd(dev); 308 struct pppx_hdr *th; 309 struct pppx_if *pxi; 310 uint32_t proto; 311 struct mbuf *top, **mp, *m; 312 int tlen; 313 int error = 0; 314 size_t mlen; 315 316 if (uio->uio_resid < sizeof(*th) + sizeof(uint32_t) || 317 uio->uio_resid > MCLBYTES) 318 return (EMSGSIZE); 319 320 tlen = uio->uio_resid; 321 322 MGETHDR(m, M_DONTWAIT, MT_DATA); 323 if (m == NULL) 324 return (ENOBUFS); 325 mlen = MHLEN; 326 if (uio->uio_resid > MHLEN) { 327 MCLGET(m, M_DONTWAIT); 328 if (!(m->m_flags & M_EXT)) { 329 m_free(m); 330 return (ENOBUFS); 331 } 332 mlen = MCLBYTES; 333 } 334 335 top = NULL; 336 mp = ⊤ 337 338 while (error == 0 && uio->uio_resid > 0) { 339 m->m_len = ulmin(mlen, uio->uio_resid); 340 error = uiomove(mtod (m, caddr_t), m->m_len, uio); 341 *mp = m; 342 mp = &m->m_next; 343 if (error == 0 && uio->uio_resid > 0) { 344 MGET(m, M_DONTWAIT, MT_DATA); 345 if (m == NULL) { 346 error = ENOBUFS; 347 break; 348 } 349 mlen = MLEN; 350 if (uio->uio_resid >= MINCLSIZE) { 351 MCLGET(m, M_DONTWAIT); 352 if (!(m->m_flags & M_EXT)) { 353 error = ENOBUFS; 354 m_free(m); 355 break; 356 } 357 mlen = MCLBYTES; 358 } 359 } 360 } 361 362 if (error) { 363 m_freem(top); 364 return (error); 365 } 366 367 top->m_pkthdr.len = tlen; 368 369 /* Find the interface */ 370 th = mtod(top, struct pppx_hdr *); 371 m_adj(top, sizeof(struct pppx_hdr)); 372 373 NET_LOCK(); 374 375 pxi = pppx_if_find(pxd, th->pppx_id, th->pppx_proto); 376 if (pxi == NULL) { 377 NET_UNLOCK(); 378 m_freem(top); 379 return (EINVAL); 380 } 381 top->m_pkthdr.ph_ifidx = pxi->pxi_if.if_index; 382 383 #if NBPFILTER > 0 384 if (pxi->pxi_if.if_bpf) 385 bpf_mtap(pxi->pxi_if.if_bpf, top, BPF_DIRECTION_IN); 386 #endif 387 /* strip the tunnel header */ 388 proto = ntohl(*(uint32_t *)(th + 1)); 389 m_adj(top, sizeof(uint32_t)); 390 391 switch (proto) { 392 case AF_INET: 393 ipv4_input(&pxi->pxi_if, top); 394 break; 395 #ifdef INET6 396 case AF_INET6: 397 ipv6_input(&pxi->pxi_if, top); 398 break; 399 #endif 400 default: 401 m_freem(top); 402 error = EAFNOSUPPORT; 403 break; 404 } 405 406 NET_UNLOCK(); 407 408 return (error); 409 } 410 411 int 412 pppxioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) 413 { 414 struct pppx_dev *pxd = pppx_dev2pxd(dev); 415 int error = 0; 416 417 NET_LOCK(); 418 switch (cmd) { 419 case PIPEXASESSION: 420 error = pppx_add_session(pxd, 421 (struct pipex_session_req *)addr); 422 break; 423 424 case PIPEXDSESSION: 425 error = pppx_del_session(pxd, 426 (struct pipex_session_close_req *)addr); 427 break; 428 429 case PIPEXSIFDESCR: 430 error = pppx_set_session_descr(pxd, 431 (struct pipex_session_descr_req *)addr); 432 break; 433 434 case FIONBIO: 435 break; 436 case FIONREAD: 437 *(int *)addr = mq_hdatalen(&pxd->pxd_svcq); 438 break; 439 440 default: 441 error = pipex_ioctl(pxd, cmd, addr); 442 break; 443 } 444 NET_UNLOCK(); 445 446 return (error); 447 } 448 449 int 450 pppxkqfilter(dev_t dev, struct knote *kn) 451 { 452 struct pppx_dev *pxd = pppx_dev2pxd(dev); 453 struct mutex *mtx; 454 struct klist *klist; 455 456 switch (kn->kn_filter) { 457 case EVFILT_READ: 458 mtx = &pxd->pxd_rsel_mtx; 459 klist = &pxd->pxd_rsel.si_note; 460 kn->kn_fop = &pppx_rd_filtops; 461 break; 462 case EVFILT_WRITE: 463 mtx = &pxd->pxd_wsel_mtx; 464 klist = &pxd->pxd_wsel.si_note; 465 kn->kn_fop = &pppx_wr_filtops; 466 break; 467 default: 468 return (EINVAL); 469 } 470 471 kn->kn_hook = (caddr_t)pxd; 472 473 mtx_enter(mtx); 474 klist_insert_locked(klist, kn); 475 mtx_leave(mtx); 476 477 return (0); 478 } 479 480 void 481 filt_pppx_rdetach(struct knote *kn) 482 { 483 struct pppx_dev *pxd = (struct pppx_dev *)kn->kn_hook; 484 struct klist *klist = &pxd->pxd_rsel.si_note; 485 486 mtx_enter(&pxd->pxd_rsel_mtx); 487 klist_remove_locked(klist, kn); 488 mtx_leave(&pxd->pxd_rsel_mtx); 489 } 490 491 int 492 filt_pppx_read(struct knote *kn, long hint) 493 { 494 struct pppx_dev *pxd = (struct pppx_dev *)kn->kn_hook; 495 496 kn->kn_data = mq_hdatalen(&pxd->pxd_svcq); 497 498 return (kn->kn_data > 0); 499 } 500 501 void 502 filt_pppx_wdetach(struct knote *kn) 503 { 504 struct pppx_dev *pxd = (struct pppx_dev *)kn->kn_hook; 505 struct klist *klist = &pxd->pxd_wsel.si_note; 506 507 mtx_enter(&pxd->pxd_wsel_mtx); 508 klist_remove_locked(klist, kn); 509 mtx_leave(&pxd->pxd_wsel_mtx); 510 } 511 512 int 513 filt_pppx_write(struct knote *kn, long hint) 514 { 515 /* We're always ready to accept a write. */ 516 return (1); 517 } 518 519 int 520 pppxclose(dev_t dev, int flags, int mode, struct proc *p) 521 { 522 struct pppx_dev *pxd; 523 struct pppx_if *pxi; 524 525 pxd = pppx_dev_lookup(dev); 526 527 /* XXX */ 528 NET_LOCK(); 529 while ((pxi = LIST_FIRST(&pxd->pxd_pxis))) 530 pppx_if_destroy(pxd, pxi); 531 NET_UNLOCK(); 532 533 LIST_REMOVE(pxd, pxd_entry); 534 535 mq_purge(&pxd->pxd_svcq); 536 537 free(pxd, M_DEVBUF, sizeof(*pxd)); 538 539 return (0); 540 } 541 542 int 543 pppx_if_next_unit(void) 544 { 545 struct pppx_if *pxi; 546 int unit = 0; 547 548 /* this is safe without splnet since we're not modifying it */ 549 do { 550 int found = 0; 551 RBT_FOREACH(pxi, pppx_ifs, &pppx_ifs) { 552 if (pxi->pxi_unit == unit) { 553 found = 1; 554 break; 555 } 556 } 557 558 if (found == 0) 559 break; 560 unit++; 561 } while (unit > 0); 562 563 return (unit); 564 } 565 566 struct pppx_if * 567 pppx_if_find(struct pppx_dev *pxd, int session_id, int protocol) 568 { 569 struct pppx_if_key key; 570 struct pppx_if *pxi; 571 572 memset(&key, 0, sizeof(key)); 573 key.pxik_session_id = session_id; 574 key.pxik_protocol = protocol; 575 576 pxi = RBT_FIND(pppx_ifs, &pppx_ifs, (struct pppx_if *)&key); 577 if (pxi && pxi->pxi_ready == 0) 578 pxi = NULL; 579 580 return pxi; 581 } 582 583 int 584 pppx_add_session(struct pppx_dev *pxd, struct pipex_session_req *req) 585 { 586 struct pppx_if *pxi; 587 struct pipex_session *session; 588 struct ifnet *ifp; 589 int unit, error = 0; 590 struct in_ifaddr *ia; 591 struct sockaddr_in ifaddr; 592 593 /* 594 * XXX: As long as `session' is allocated as part of a `pxi' 595 * it isn't possible to free it separately. So disallow 596 * the timeout feature until this is fixed. 597 */ 598 if (req->pr_timeout_sec != 0) 599 return (EINVAL); 600 601 error = pipex_init_session(&session, req); 602 if (error) 603 return (error); 604 605 pxi = pool_get(&pppx_if_pl, PR_WAITOK | PR_ZERO); 606 ifp = &pxi->pxi_if; 607 608 pxi->pxi_session = session; 609 610 /* try to set the interface up */ 611 unit = pppx_if_next_unit(); 612 if (unit < 0) { 613 error = ENOMEM; 614 goto out; 615 } 616 617 pxi->pxi_unit = unit; 618 pxi->pxi_key.pxik_session_id = req->pr_session_id; 619 pxi->pxi_key.pxik_protocol = req->pr_protocol; 620 pxi->pxi_dev = pxd; 621 622 if (RBT_INSERT(pppx_ifs, &pppx_ifs, pxi) != NULL) { 623 error = EADDRINUSE; 624 goto out; 625 } 626 LIST_INSERT_HEAD(&pxd->pxd_pxis, pxi, pxi_list); 627 628 snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d", "pppx", unit); 629 ifp->if_mtu = req->pr_peer_mru; /* XXX */ 630 ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST | IFF_UP; 631 ifp->if_xflags = IFXF_CLONED | IFXF_MPSAFE; 632 ifp->if_qstart = pppx_if_qstart; 633 ifp->if_output = pppx_if_output; 634 ifp->if_ioctl = pppx_if_ioctl; 635 ifp->if_rtrequest = p2p_rtrequest; 636 ifp->if_type = IFT_PPP; 637 ifp->if_softc = pxi; 638 /* ifp->if_rdomain = req->pr_rdomain; */ 639 if_counters_alloc(ifp); 640 641 /* XXXSMP breaks atomicity */ 642 NET_UNLOCK(); 643 if_attach(ifp); 644 NET_LOCK(); 645 646 if_addgroup(ifp, "pppx"); 647 if_alloc_sadl(ifp); 648 649 #if NBPFILTER > 0 650 bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(u_int32_t)); 651 #endif 652 653 /* XXX ipv6 support? how does the caller indicate it wants ipv6 654 * instead of ipv4? 655 */ 656 memset(&ifaddr, 0, sizeof(ifaddr)); 657 ifaddr.sin_family = AF_INET; 658 ifaddr.sin_len = sizeof(ifaddr); 659 ifaddr.sin_addr = req->pr_ip_srcaddr; 660 661 ia = malloc(sizeof (*ia), M_IFADDR, M_WAITOK | M_ZERO); 662 663 ia->ia_addr.sin_family = AF_INET; 664 ia->ia_addr.sin_len = sizeof(struct sockaddr_in); 665 ia->ia_addr.sin_addr = req->pr_ip_srcaddr; 666 667 ia->ia_dstaddr.sin_family = AF_INET; 668 ia->ia_dstaddr.sin_len = sizeof(struct sockaddr_in); 669 ia->ia_dstaddr.sin_addr = req->pr_ip_address; 670 671 ia->ia_sockmask.sin_family = AF_INET; 672 ia->ia_sockmask.sin_len = sizeof(struct sockaddr_in); 673 ia->ia_sockmask.sin_addr = req->pr_ip_netmask; 674 675 ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr); 676 ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr); 677 ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask); 678 ia->ia_ifa.ifa_ifp = ifp; 679 680 ia->ia_netmask = ia->ia_sockmask.sin_addr.s_addr; 681 682 error = in_ifinit(ifp, ia, &ifaddr, 1); 683 if (error) { 684 printf("pppx: unable to set addresses for %s, error=%d\n", 685 ifp->if_xname, error); 686 } else { 687 if_addrhooks_run(ifp); 688 } 689 690 error = pipex_link_session(session, ifp, pxd); 691 if (error) 692 goto detach; 693 694 SET(ifp->if_flags, IFF_RUNNING); 695 pxi->pxi_ready = 1; 696 697 return (error); 698 699 detach: 700 /* XXXSMP breaks atomicity */ 701 NET_UNLOCK(); 702 if_detach(ifp); 703 NET_LOCK(); 704 705 if (RBT_REMOVE(pppx_ifs, &pppx_ifs, pxi) == NULL) 706 panic("%s: inconsistent RB tree", __func__); 707 LIST_REMOVE(pxi, pxi_list); 708 out: 709 pool_put(&pppx_if_pl, pxi); 710 pipex_rele_session(session); 711 712 return (error); 713 } 714 715 int 716 pppx_del_session(struct pppx_dev *pxd, struct pipex_session_close_req *req) 717 { 718 struct pppx_if *pxi; 719 720 pxi = pppx_if_find(pxd, req->pcr_session_id, req->pcr_protocol); 721 if (pxi == NULL) 722 return (EINVAL); 723 724 pipex_export_session_stats(pxi->pxi_session, &req->pcr_stat); 725 pppx_if_destroy(pxd, pxi); 726 return (0); 727 } 728 729 int 730 pppx_set_session_descr(struct pppx_dev *pxd, 731 struct pipex_session_descr_req *req) 732 { 733 struct pppx_if *pxi; 734 735 pxi = pppx_if_find(pxd, req->pdr_session_id, req->pdr_protocol); 736 if (pxi == NULL) 737 return (EINVAL); 738 739 (void)memset(pxi->pxi_if.if_description, 0, IFDESCRSIZE); 740 strlcpy(pxi->pxi_if.if_description, req->pdr_descr, IFDESCRSIZE); 741 742 return (0); 743 } 744 745 void 746 pppx_if_destroy(struct pppx_dev *pxd, struct pppx_if *pxi) 747 { 748 struct ifnet *ifp; 749 struct pipex_session *session; 750 751 NET_ASSERT_LOCKED(); 752 session = pxi->pxi_session; 753 ifp = &pxi->pxi_if; 754 pxi->pxi_ready = 0; 755 CLR(ifp->if_flags, IFF_RUNNING); 756 757 pipex_unlink_session(session); 758 759 /* XXXSMP breaks atomicity */ 760 NET_UNLOCK(); 761 if_detach(ifp); 762 NET_LOCK(); 763 764 pipex_rele_session(session); 765 if (RBT_REMOVE(pppx_ifs, &pppx_ifs, pxi) == NULL) 766 panic("%s: inconsistent RB tree", __func__); 767 LIST_REMOVE(pxi, pxi_list); 768 769 pool_put(&pppx_if_pl, pxi); 770 } 771 772 void 773 pppx_if_qstart(struct ifqueue *ifq) 774 { 775 struct ifnet *ifp = ifq->ifq_if; 776 struct pppx_if *pxi = (struct pppx_if *)ifp->if_softc; 777 struct mbuf *m; 778 int proto; 779 780 while ((m = ifq_dequeue(ifq)) != NULL) { 781 proto = *mtod(m, int *); 782 m_adj(m, sizeof(proto)); 783 784 pipex_ppp_output(m, pxi->pxi_session, proto); 785 } 786 } 787 788 int 789 pppx_if_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 790 struct rtentry *rt) 791 { 792 struct pppx_if *pxi = (struct pppx_if *)ifp->if_softc; 793 struct pppx_hdr *th; 794 int error = 0; 795 int pipex_enable_local, proto; 796 797 pipex_enable_local = atomic_load_int(&pipex_enable); 798 799 NET_ASSERT_LOCKED(); 800 801 if (!ISSET(ifp->if_flags, IFF_RUNNING)) { 802 m_freem(m); 803 error = ENETDOWN; 804 goto out; 805 } 806 807 #if NBPFILTER > 0 808 if (ifp->if_bpf) 809 bpf_mtap_af(ifp->if_bpf, dst->sa_family, m, BPF_DIRECTION_OUT); 810 #endif 811 if (pipex_enable_local) { 812 switch (dst->sa_family) { 813 #ifdef INET6 814 case AF_INET6: 815 proto = PPP_IPV6; 816 break; 817 #endif 818 case AF_INET: 819 proto = PPP_IP; 820 break; 821 default: 822 m_freem(m); 823 error = EPFNOSUPPORT; 824 goto out; 825 } 826 } else 827 proto = htonl(dst->sa_family); 828 829 M_PREPEND(m, sizeof(int), M_DONTWAIT); 830 if (m == NULL) { 831 error = ENOBUFS; 832 goto out; 833 } 834 *mtod(m, int *) = proto; 835 836 if (pipex_enable_local) 837 error = if_enqueue(ifp, m); 838 else { 839 M_PREPEND(m, sizeof(struct pppx_hdr), M_DONTWAIT); 840 if (m == NULL) { 841 error = ENOBUFS; 842 goto out; 843 } 844 th = mtod(m, struct pppx_hdr *); 845 th->pppx_proto = 0; /* not used */ 846 th->pppx_id = pxi->pxi_session->ppp_id; 847 error = mq_enqueue(&pxi->pxi_dev->pxd_svcq, m); 848 if (error == 0) { 849 if (pxi->pxi_dev->pxd_waiting) { 850 wakeup((caddr_t)pxi->pxi_dev); 851 pxi->pxi_dev->pxd_waiting = 0; 852 } 853 selwakeup(&pxi->pxi_dev->pxd_rsel); 854 } 855 } 856 857 out: 858 if (error) 859 counters_inc(ifp->if_counters, ifc_oerrors); 860 return (error); 861 } 862 863 int 864 pppx_if_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr) 865 { 866 struct pppx_if *pxi = (struct pppx_if *)ifp->if_softc; 867 struct ifreq *ifr = (struct ifreq *)addr; 868 int error = 0; 869 870 switch (cmd) { 871 case SIOCSIFADDR: 872 break; 873 874 case SIOCSIFFLAGS: 875 break; 876 877 case SIOCADDMULTI: 878 case SIOCDELMULTI: 879 break; 880 881 case SIOCSIFMTU: 882 if (ifr->ifr_mtu < 512 || 883 ifr->ifr_mtu > pxi->pxi_session->peer_mru) 884 error = EINVAL; 885 else 886 ifp->if_mtu = ifr->ifr_mtu; 887 break; 888 889 default: 890 error = ENOTTY; 891 break; 892 } 893 894 return (error); 895 } 896 897 RBT_GENERATE(pppx_ifs, pppx_if, pxi_entry, pppx_if_cmp); 898 899 struct pppac_softc { 900 struct ifnet sc_if; 901 dev_t sc_dev; /* [I] */ 902 int sc_ready; /* [K] */ 903 LIST_ENTRY(pppac_softc) 904 sc_entry; /* [K] */ 905 906 struct mutex sc_rsel_mtx; 907 struct selinfo sc_rsel; 908 struct mutex sc_wsel_mtx; 909 struct selinfo sc_wsel; 910 911 struct pipex_session 912 *sc_multicast_session; 913 914 struct mbuf_queue 915 sc_mq; 916 }; 917 918 LIST_HEAD(pppac_list, pppac_softc); /* [K] */ 919 920 static void filt_pppac_rdetach(struct knote *); 921 static int filt_pppac_read(struct knote *, long); 922 923 static const struct filterops pppac_rd_filtops = { 924 .f_flags = FILTEROP_ISFD, 925 .f_attach = NULL, 926 .f_detach = filt_pppac_rdetach, 927 .f_event = filt_pppac_read 928 }; 929 930 static void filt_pppac_wdetach(struct knote *); 931 static int filt_pppac_write(struct knote *, long); 932 933 static const struct filterops pppac_wr_filtops = { 934 .f_flags = FILTEROP_ISFD, 935 .f_attach = NULL, 936 .f_detach = filt_pppac_wdetach, 937 .f_event = filt_pppac_write 938 }; 939 940 static struct pppac_list pppac_devs = LIST_HEAD_INITIALIZER(pppac_devs); 941 942 static int pppac_ioctl(struct ifnet *, u_long, caddr_t); 943 944 static int pppac_add_session(struct pppac_softc *, 945 struct pipex_session_req *); 946 static int pppac_del_session(struct pppac_softc *, 947 struct pipex_session_close_req *); 948 static int pppac_output(struct ifnet *, struct mbuf *, struct sockaddr *, 949 struct rtentry *); 950 static void pppac_qstart(struct ifqueue *); 951 952 static inline struct pppac_softc * 953 pppac_lookup(dev_t dev) 954 { 955 struct pppac_softc *sc; 956 957 LIST_FOREACH(sc, &pppac_devs, sc_entry) { 958 if (sc->sc_dev == dev) { 959 if (sc->sc_ready == 0) 960 break; 961 962 return (sc); 963 } 964 } 965 966 return (NULL); 967 } 968 969 void 970 pppacattach(int n) 971 { 972 pipex_init(); /* to be sure, to be sure */ 973 } 974 975 int 976 pppacopen(dev_t dev, int flags, int mode, struct proc *p) 977 { 978 struct pppac_softc *sc, *tmp; 979 struct ifnet *ifp; 980 struct pipex_session *session; 981 982 sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); 983 sc->sc_dev = dev; 984 LIST_FOREACH(tmp, &pppac_devs, sc_entry) { 985 if (tmp->sc_dev == dev) { 986 free(sc, M_DEVBUF, sizeof(*sc)); 987 return (EBUSY); 988 } 989 } 990 LIST_INSERT_HEAD(&pppac_devs, sc, sc_entry); 991 992 /* virtual pipex_session entry for multicast */ 993 session = pool_get(&pipex_session_pool, PR_WAITOK | PR_ZERO); 994 session->flags |= PIPEX_SFLAGS_MULTICAST; 995 session->ownersc = sc; 996 sc->sc_multicast_session = session; 997 998 mtx_init(&sc->sc_rsel_mtx, IPL_SOFTNET); 999 mtx_init(&sc->sc_wsel_mtx, IPL_SOFTNET); 1000 mq_init(&sc->sc_mq, IFQ_MAXLEN, IPL_SOFTNET); 1001 1002 ifp = &sc->sc_if; 1003 snprintf(ifp->if_xname, sizeof(ifp->if_xname), "pppac%u", minor(dev)); 1004 1005 ifp->if_softc = sc; 1006 ifp->if_type = IFT_L3IPVLAN; 1007 ifp->if_hdrlen = sizeof(uint32_t); /* for BPF */; 1008 ifp->if_mtu = MAXMCLBYTES - sizeof(uint32_t); 1009 ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST; 1010 ifp->if_xflags = IFXF_CLONED | IFXF_MPSAFE; 1011 ifp->if_rtrequest = p2p_rtrequest; /* XXX */ 1012 ifp->if_output = pppac_output; 1013 ifp->if_qstart = pppac_qstart; 1014 ifp->if_ioctl = pppac_ioctl; 1015 1016 if_counters_alloc(ifp); 1017 if_attach(ifp); 1018 if_alloc_sadl(ifp); 1019 1020 #if NBPFILTER > 0 1021 bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(uint32_t)); 1022 #endif 1023 1024 sc->sc_ready = 1; 1025 1026 return (0); 1027 } 1028 1029 int 1030 pppacread(dev_t dev, struct uio *uio, int ioflag) 1031 { 1032 struct pppac_softc *sc = pppac_lookup(dev); 1033 struct ifnet *ifp = &sc->sc_if; 1034 struct mbuf *m0, *m; 1035 int error = 0; 1036 size_t len; 1037 1038 if (!ISSET(ifp->if_flags, IFF_RUNNING)) 1039 return (EHOSTDOWN); 1040 1041 m0 = mq_dequeue(&sc->sc_mq); 1042 if (m0 == NULL) { 1043 if (ISSET(ioflag, IO_NDELAY)) 1044 return (EWOULDBLOCK); 1045 1046 do { 1047 error = tsleep_nsec(sc, (PZERO + 1)|PCATCH, 1048 "pppacrd", INFSLP); 1049 if (error != 0) 1050 return (error); 1051 1052 m0 = mq_dequeue(&sc->sc_mq); 1053 } while (m0 == NULL); 1054 } 1055 1056 m = m0; 1057 while (uio->uio_resid > 0) { 1058 len = ulmin(uio->uio_resid, m->m_len); 1059 if (len != 0) { 1060 error = uiomove(mtod(m, caddr_t), len, uio); 1061 if (error != 0) 1062 break; 1063 } 1064 1065 m = m->m_next; 1066 if (m == NULL) 1067 break; 1068 } 1069 m_freem(m0); 1070 1071 return (error); 1072 } 1073 1074 int 1075 pppacwrite(dev_t dev, struct uio *uio, int ioflag) 1076 { 1077 struct pppac_softc *sc = pppac_lookup(dev); 1078 struct ifnet *ifp = &sc->sc_if; 1079 uint32_t proto; 1080 int error; 1081 struct mbuf *m; 1082 1083 if (!ISSET(ifp->if_flags, IFF_RUNNING)) 1084 return (EHOSTDOWN); 1085 1086 if (uio->uio_resid < ifp->if_hdrlen || uio->uio_resid > MAXMCLBYTES) 1087 return (EMSGSIZE); 1088 1089 m = m_gethdr(M_DONTWAIT, MT_DATA); 1090 if (m == NULL) 1091 return (ENOMEM); 1092 1093 if (uio->uio_resid > MHLEN) { 1094 m_clget(m, M_WAITOK, uio->uio_resid); 1095 if (!ISSET(m->m_flags, M_EXT)) { 1096 m_free(m); 1097 return (ENOMEM); 1098 } 1099 } 1100 1101 m->m_pkthdr.len = m->m_len = uio->uio_resid; 1102 1103 error = uiomove(mtod(m, void *), m->m_len, uio); 1104 if (error != 0) { 1105 m_freem(m); 1106 return (error); 1107 } 1108 1109 #if NBPFILTER > 0 1110 if (ifp->if_bpf) 1111 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN); 1112 #endif 1113 1114 /* strip the tunnel header */ 1115 proto = ntohl(*mtod(m, uint32_t *)); 1116 m_adj(m, sizeof(uint32_t)); 1117 1118 m->m_flags &= ~(M_MCAST|M_BCAST); 1119 m->m_pkthdr.ph_ifidx = ifp->if_index; 1120 m->m_pkthdr.ph_rtableid = ifp->if_rdomain; 1121 1122 #if NPF > 0 1123 pf_pkt_addr_changed(m); 1124 #endif 1125 1126 counters_pkt(ifp->if_counters, 1127 ifc_ipackets, ifc_ibytes, m->m_pkthdr.len); 1128 1129 NET_LOCK(); 1130 1131 switch (proto) { 1132 case AF_INET: 1133 ipv4_input(ifp, m); 1134 break; 1135 #ifdef INET6 1136 case AF_INET6: 1137 ipv6_input(ifp, m); 1138 break; 1139 #endif 1140 default: 1141 m_freem(m); 1142 error = EAFNOSUPPORT; 1143 break; 1144 } 1145 1146 NET_UNLOCK(); 1147 1148 return (error); 1149 } 1150 1151 int 1152 pppacioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) 1153 { 1154 struct pppac_softc *sc = pppac_lookup(dev); 1155 int error = 0; 1156 1157 NET_LOCK(); 1158 switch (cmd) { 1159 case FIONBIO: 1160 break; 1161 case FIONREAD: 1162 *(int *)data = mq_hdatalen(&sc->sc_mq); 1163 break; 1164 1165 case PIPEXASESSION: 1166 error = pppac_add_session(sc, (struct pipex_session_req *)data); 1167 break; 1168 case PIPEXDSESSION: 1169 error = pppac_del_session(sc, 1170 (struct pipex_session_close_req *)data); 1171 break; 1172 default: 1173 error = pipex_ioctl(sc, cmd, data); 1174 break; 1175 } 1176 NET_UNLOCK(); 1177 1178 return (error); 1179 } 1180 1181 int 1182 pppackqfilter(dev_t dev, struct knote *kn) 1183 { 1184 struct pppac_softc *sc = pppac_lookup(dev); 1185 struct mutex *mtx; 1186 struct klist *klist; 1187 1188 switch (kn->kn_filter) { 1189 case EVFILT_READ: 1190 mtx = &sc->sc_rsel_mtx; 1191 klist = &sc->sc_rsel.si_note; 1192 kn->kn_fop = &pppac_rd_filtops; 1193 break; 1194 case EVFILT_WRITE: 1195 mtx = &sc->sc_wsel_mtx; 1196 klist = &sc->sc_wsel.si_note; 1197 kn->kn_fop = &pppac_wr_filtops; 1198 break; 1199 default: 1200 return (EINVAL); 1201 } 1202 1203 kn->kn_hook = sc; 1204 1205 mtx_enter(mtx); 1206 klist_insert_locked(klist, kn); 1207 mtx_leave(mtx); 1208 1209 return (0); 1210 } 1211 1212 static void 1213 filt_pppac_rdetach(struct knote *kn) 1214 { 1215 struct pppac_softc *sc = kn->kn_hook; 1216 struct klist *klist = &sc->sc_rsel.si_note; 1217 1218 mtx_enter(&sc->sc_rsel_mtx); 1219 klist_remove_locked(klist, kn); 1220 mtx_leave(&sc->sc_rsel_mtx); 1221 } 1222 1223 static int 1224 filt_pppac_read(struct knote *kn, long hint) 1225 { 1226 struct pppac_softc *sc = kn->kn_hook; 1227 1228 kn->kn_data = mq_hdatalen(&sc->sc_mq); 1229 1230 return (kn->kn_data > 0); 1231 } 1232 1233 static void 1234 filt_pppac_wdetach(struct knote *kn) 1235 { 1236 struct pppac_softc *sc = kn->kn_hook; 1237 struct klist *klist = &sc->sc_wsel.si_note; 1238 1239 mtx_enter(&sc->sc_wsel_mtx); 1240 klist_remove_locked(klist, kn); 1241 mtx_leave(&sc->sc_wsel_mtx); 1242 } 1243 1244 static int 1245 filt_pppac_write(struct knote *kn, long hint) 1246 { 1247 /* We're always ready to accept a write. */ 1248 return (1); 1249 } 1250 1251 int 1252 pppacclose(dev_t dev, int flags, int mode, struct proc *p) 1253 { 1254 struct pppac_softc *sc = pppac_lookup(dev); 1255 struct ifnet *ifp = &sc->sc_if; 1256 int s; 1257 1258 sc->sc_ready = 0; 1259 1260 NET_LOCK(); 1261 CLR(ifp->if_flags, IFF_RUNNING); 1262 NET_UNLOCK(); 1263 1264 if_detach(ifp); 1265 1266 s = splhigh(); 1267 klist_invalidate(&sc->sc_rsel.si_note); 1268 klist_invalidate(&sc->sc_wsel.si_note); 1269 splx(s); 1270 1271 pool_put(&pipex_session_pool, sc->sc_multicast_session); 1272 pipex_destroy_all_sessions(sc); 1273 1274 LIST_REMOVE(sc, sc_entry); 1275 free(sc, M_DEVBUF, sizeof(*sc)); 1276 1277 return (0); 1278 } 1279 1280 static int 1281 pppac_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 1282 { 1283 /* struct ifreq *ifr = (struct ifreq *)data; */ 1284 int error = 0; 1285 1286 switch (cmd) { 1287 case SIOCSIFADDR: 1288 SET(ifp->if_flags, IFF_UP); /* XXX cry cry */ 1289 /* FALLTHROUGH */ 1290 case SIOCSIFFLAGS: 1291 if (ISSET(ifp->if_flags, IFF_UP)) 1292 SET(ifp->if_flags, IFF_RUNNING); 1293 else 1294 CLR(ifp->if_flags, IFF_RUNNING); 1295 break; 1296 case SIOCSIFMTU: 1297 break; 1298 case SIOCADDMULTI: 1299 case SIOCDELMULTI: 1300 /* XXX */ 1301 break; 1302 1303 default: 1304 error = ENOTTY; 1305 break; 1306 } 1307 1308 return (error); 1309 } 1310 1311 static int 1312 pppac_add_session(struct pppac_softc *sc, struct pipex_session_req *req) 1313 { 1314 int error; 1315 struct pipex_session *session; 1316 1317 error = pipex_init_session(&session, req); 1318 if (error != 0) 1319 return (error); 1320 error = pipex_link_session(session, &sc->sc_if, sc); 1321 if (error != 0) 1322 pipex_rele_session(session); 1323 1324 return (error); 1325 } 1326 1327 static int 1328 pppac_del_session(struct pppac_softc *sc, struct pipex_session_close_req *req) 1329 { 1330 struct pipex_session *session; 1331 1332 mtx_enter(&pipex_list_mtx); 1333 1334 session = pipex_lookup_by_session_id_locked(req->pcr_protocol, 1335 req->pcr_session_id); 1336 if (session == NULL || session->ownersc != sc) { 1337 mtx_leave(&pipex_list_mtx); 1338 return (EINVAL); 1339 } 1340 pipex_unlink_session_locked(session); 1341 pipex_rele_session(session); 1342 1343 mtx_leave(&pipex_list_mtx); 1344 1345 return (0); 1346 } 1347 1348 static int 1349 pppac_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 1350 struct rtentry *rt) 1351 { 1352 int error; 1353 1354 if (!ISSET(ifp->if_flags, IFF_RUNNING)) { 1355 error = EHOSTDOWN; 1356 goto drop; 1357 } 1358 1359 switch (dst->sa_family) { 1360 case AF_INET: 1361 #ifdef INET6 1362 case AF_INET6: 1363 #endif 1364 break; 1365 default: 1366 error = EAFNOSUPPORT; 1367 goto drop; 1368 } 1369 1370 m->m_pkthdr.ph_family = dst->sa_family; 1371 1372 return (if_enqueue(ifp, m)); 1373 1374 drop: 1375 m_freem(m); 1376 return (error); 1377 } 1378 1379 static void 1380 pppac_qstart(struct ifqueue *ifq) 1381 { 1382 struct ifnet *ifp = ifq->ifq_if; 1383 struct pppac_softc *sc = ifp->if_softc; 1384 struct mbuf *m, *m0; 1385 struct pipex_session *session; 1386 struct ip ip; 1387 int rv; 1388 1389 while ((m = ifq_dequeue(ifq)) != NULL) { 1390 #if NBPFILTER > 0 1391 if (ifp->if_bpf) { 1392 bpf_mtap_af(ifp->if_bpf, m->m_pkthdr.ph_family, m, 1393 BPF_DIRECTION_OUT); 1394 } 1395 #endif 1396 1397 switch (m->m_pkthdr.ph_family) { 1398 case AF_INET: 1399 if (m->m_pkthdr.len < sizeof(struct ip)) 1400 goto bad; 1401 m_copydata(m, 0, sizeof(struct ip), &ip); 1402 if (IN_MULTICAST(ip.ip_dst.s_addr)) { 1403 /* pass a copy to pipex */ 1404 m0 = m_copym(m, 0, M_COPYALL, M_NOWAIT); 1405 if (m0 != NULL) 1406 pipex_ip_output(m0, 1407 sc->sc_multicast_session); 1408 else 1409 goto bad; 1410 } else { 1411 session = pipex_lookup_by_ip_address(ip.ip_dst); 1412 if (session != NULL) { 1413 pipex_ip_output(m, session); 1414 pipex_rele_session(session); 1415 m = NULL; 1416 } 1417 } 1418 break; 1419 } 1420 if (m == NULL) /* handled by pipex */ 1421 continue; 1422 1423 m = m_prepend(m, sizeof(uint32_t), M_DONTWAIT); 1424 if (m == NULL) 1425 goto bad; 1426 *mtod(m, uint32_t *) = htonl(m->m_pkthdr.ph_family); 1427 1428 rv = mq_enqueue(&sc->sc_mq, m); 1429 if (rv == 1) 1430 counters_inc(ifp->if_counters, ifc_collisions); 1431 continue; 1432 bad: 1433 counters_inc(ifp->if_counters, ifc_oerrors); 1434 if (m != NULL) 1435 m_freem(m); 1436 continue; 1437 } 1438 1439 if (!mq_empty(&sc->sc_mq)) { 1440 wakeup(sc); 1441 selwakeup(&sc->sc_rsel); 1442 } 1443 } 1444