1 /* $OpenBSD: if_pppx.c,v 1.56 2016/09/15 02:00:18 dlg 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 <net/ppp_defs.h> 87 #include <net/ppp-comp.h> 88 #include <crypto/arc4.h> 89 90 #ifdef PIPEX 91 #include <net/radix.h> 92 #include <net/pipex.h> 93 #include <net/pipex_local.h> 94 #else 95 #error PIPEX option not enabled 96 #endif 97 98 #ifdef PPPX_DEBUG 99 #define PPPX_D_INIT (1<<0) 100 101 int pppxdebug = 0; 102 103 #define DPRINTF(_m, _p...) do { \ 104 if (ISSET(pppxdebug, (_m))) \ 105 printf(_p); \ 106 } while (0) 107 #else 108 #define DPRINTF(_m, _p...) /* _m, _p */ 109 #endif 110 111 112 struct pppx_if; 113 114 struct pppx_dev { 115 LIST_ENTRY(pppx_dev) pxd_entry; 116 int pxd_unit; 117 118 /* kq shizz */ 119 struct selinfo pxd_rsel; 120 struct mutex pxd_rsel_mtx; 121 struct selinfo pxd_wsel; 122 struct mutex pxd_wsel_mtx; 123 124 /* queue of packets for userland to service - protected by splnet */ 125 struct mbuf_queue pxd_svcq; 126 int pxd_waiting; 127 LIST_HEAD(,pppx_if) pxd_pxis; 128 }; 129 130 struct rwlock pppx_devs_lk = RWLOCK_INITIALIZER("pppxdevs"); 131 LIST_HEAD(, pppx_dev) pppx_devs = LIST_HEAD_INITIALIZER(pppx_devs); 132 struct pool *pppx_if_pl; 133 134 struct pppx_dev *pppx_dev_lookup(dev_t); 135 struct pppx_dev *pppx_dev2pxd(dev_t); 136 137 struct pppx_if_key { 138 int pxik_session_id; 139 int pxik_protocol; 140 }; 141 142 struct pppx_if { 143 struct pppx_if_key pxi_key; /* must be first in the struct */ 144 145 RBT_ENTRY(pppx_if) pxi_entry; 146 LIST_ENTRY(pppx_if) pxi_list; 147 148 int pxi_unit; 149 struct ifnet pxi_if; 150 struct pppx_dev *pxi_dev; 151 struct pipex_session pxi_session; 152 struct pipex_iface_context pxi_ifcontext; 153 }; 154 155 static inline int 156 pppx_if_cmp(const struct pppx_if *a, const struct pppx_if *b) 157 { 158 return memcmp(&a->pxi_key, &b->pxi_key, sizeof(a->pxi_key)); 159 } 160 161 struct rwlock pppx_ifs_lk = RWLOCK_INITIALIZER("pppxifs"); 162 RBT_HEAD(pppx_ifs, pppx_if) pppx_ifs = RBT_INITIALIZER(&pppx_ifs); 163 RBT_PROTOTYPE(pppx_ifs, pppx_if, pxi_entry, pppx_if_cmp); 164 165 int pppx_if_next_unit(void); 166 struct pppx_if *pppx_if_find(struct pppx_dev *, int, int); 167 int pppx_add_session(struct pppx_dev *, 168 struct pipex_session_req *); 169 int pppx_del_session(struct pppx_dev *, 170 struct pipex_session_close_req *); 171 int pppx_set_session_descr(struct pppx_dev *, 172 struct pipex_session_descr_req *); 173 174 void pppx_if_destroy(struct pppx_dev *, struct pppx_if *); 175 void pppx_if_start(struct ifnet *); 176 int pppx_if_output(struct ifnet *, struct mbuf *, 177 struct sockaddr *, struct rtentry *); 178 int pppx_if_ioctl(struct ifnet *, u_long, caddr_t); 179 180 181 void pppxattach(int); 182 183 void filt_pppx_rdetach(struct knote *); 184 int filt_pppx_read(struct knote *, long); 185 186 struct filterops pppx_rd_filtops = { 187 1, 188 NULL, 189 filt_pppx_rdetach, 190 filt_pppx_read 191 }; 192 193 void filt_pppx_wdetach(struct knote *); 194 int filt_pppx_write(struct knote *, long); 195 196 struct filterops pppx_wr_filtops = { 197 1, 198 NULL, 199 filt_pppx_wdetach, 200 filt_pppx_write 201 }; 202 203 struct pppx_dev * 204 pppx_dev_lookup(dev_t dev) 205 { 206 struct pppx_dev *pxd; 207 int unit = minor(dev); 208 209 /* must hold pppx_devs_lk */ 210 211 LIST_FOREACH(pxd, &pppx_devs, pxd_entry) { 212 if (pxd->pxd_unit == unit) 213 return (pxd); 214 } 215 216 return (NULL); 217 } 218 219 struct pppx_dev * 220 pppx_dev2pxd(dev_t dev) 221 { 222 struct pppx_dev *pxd; 223 224 rw_enter_read(&pppx_devs_lk); 225 pxd = pppx_dev_lookup(dev); 226 rw_exit_read(&pppx_devs_lk); 227 228 return (pxd); 229 } 230 231 void 232 pppxattach(int n) 233 { 234 pipex_init(); 235 } 236 237 int 238 pppxopen(dev_t dev, int flags, int mode, struct proc *p) 239 { 240 struct pppx_dev *pxd; 241 int rv = 0; 242 243 rv = rw_enter(&pppx_devs_lk, RW_WRITE | RW_INTR); 244 if (rv != 0) 245 return (rv); 246 247 pxd = pppx_dev_lookup(dev); 248 if (pxd != NULL) { 249 rv = EBUSY; 250 goto out; 251 } 252 253 if (LIST_EMPTY(&pppx_devs) && pppx_if_pl == NULL) { 254 pppx_if_pl = malloc(sizeof(*pppx_if_pl), M_DEVBUF, M_WAITOK); 255 pool_init(pppx_if_pl, sizeof(struct pppx_if), 0, IPL_NONE, 256 PR_WAITOK, "pppxif", NULL); 257 } 258 259 pxd = malloc(sizeof(*pxd), M_DEVBUF, M_WAITOK | M_ZERO); 260 261 pxd->pxd_unit = minor(dev); 262 mtx_init(&pxd->pxd_rsel_mtx, IPL_NET); 263 mtx_init(&pxd->pxd_wsel_mtx, IPL_NET); 264 LIST_INIT(&pxd->pxd_pxis); 265 266 mq_init(&pxd->pxd_svcq, 128, IPL_NET); 267 LIST_INSERT_HEAD(&pppx_devs, pxd, pxd_entry); 268 269 out: 270 rw_exit(&pppx_devs_lk); 271 return (rv); 272 } 273 274 int 275 pppxread(dev_t dev, struct uio *uio, int ioflag) 276 { 277 struct pppx_dev *pxd = pppx_dev2pxd(dev); 278 struct mbuf *m, *m0; 279 int error = 0; 280 int s; 281 size_t len; 282 283 if (!pxd) 284 return (ENXIO); 285 286 while ((m0 = mq_dequeue(&pxd->pxd_svcq)) == NULL) { 287 if (ISSET(ioflag, IO_NDELAY)) 288 return (EWOULDBLOCK); 289 290 s = splnet(); 291 pxd->pxd_waiting = 1; 292 error = tsleep(pxd, (PZERO + 1)|PCATCH, "pppxread", 0); 293 splx(s); 294 if (error != 0) { 295 return (error); 296 } 297 } 298 299 while (m0 != NULL && uio->uio_resid > 0 && error == 0) { 300 len = ulmin(uio->uio_resid, m0->m_len); 301 if (len != 0) 302 error = uiomove(mtod(m0, caddr_t), len, uio); 303 m = m_free(m0); 304 m0 = m; 305 } 306 307 m_freem(m0); 308 309 return (error); 310 } 311 312 int 313 pppxwrite(dev_t dev, struct uio *uio, int ioflag) 314 { 315 struct pppx_dev *pxd = pppx_dev2pxd(dev); 316 struct pppx_hdr *th; 317 struct pppx_if *pxi; 318 uint32_t proto; 319 struct mbuf *top, **mp, *m; 320 struct niqueue *ifq; 321 int tlen; 322 int error = 0; 323 size_t mlen; 324 #if NBPFILTER > 0 325 int s; 326 #endif 327 328 if (uio->uio_resid < sizeof(*th) + sizeof(uint32_t) || 329 uio->uio_resid > MCLBYTES) 330 return (EMSGSIZE); 331 332 tlen = uio->uio_resid; 333 334 MGETHDR(m, M_DONTWAIT, MT_DATA); 335 if (m == NULL) 336 return (ENOBUFS); 337 mlen = MHLEN; 338 if (uio->uio_resid >= MINCLSIZE) { 339 MCLGET(m, M_DONTWAIT); 340 if (!(m->m_flags & M_EXT)) { 341 m_free(m); 342 return (ENOBUFS); 343 } 344 mlen = MCLBYTES; 345 } 346 347 top = NULL; 348 mp = ⊤ 349 350 while (error == 0 && uio->uio_resid > 0) { 351 m->m_len = ulmin(mlen, uio->uio_resid); 352 error = uiomove(mtod (m, caddr_t), m->m_len, uio); 353 *mp = m; 354 mp = &m->m_next; 355 if (error == 0 && uio->uio_resid > 0) { 356 MGET(m, M_DONTWAIT, MT_DATA); 357 if (m == NULL) { 358 error = ENOBUFS; 359 break; 360 } 361 mlen = MLEN; 362 if (uio->uio_resid >= MINCLSIZE) { 363 MCLGET(m, M_DONTWAIT); 364 if (!(m->m_flags & M_EXT)) { 365 error = ENOBUFS; 366 m_free(m); 367 break; 368 } 369 mlen = MCLBYTES; 370 } 371 } 372 } 373 374 if (error) { 375 m_freem(top); 376 return (error); 377 } 378 379 top->m_pkthdr.len = tlen; 380 381 /* Find the interface */ 382 th = mtod(top, struct pppx_hdr *); 383 m_adj(top, sizeof(struct pppx_hdr)); 384 pxi = pppx_if_find(pxd, th->pppx_id, th->pppx_proto); 385 if (pxi == NULL) { 386 m_freem(top); 387 return (EINVAL); 388 } 389 top->m_pkthdr.ph_ifidx = pxi->pxi_if.if_index; 390 391 #if NBPFILTER > 0 392 if (pxi->pxi_if.if_bpf) { 393 s = splnet(); 394 bpf_mtap(pxi->pxi_if.if_bpf, top, BPF_DIRECTION_IN); 395 splx(s); 396 } 397 #endif 398 /* strip the tunnel header */ 399 proto = ntohl(*(uint32_t *)(th + 1)); 400 m_adj(top, sizeof(uint32_t)); 401 402 switch (proto) { 403 case AF_INET: 404 ifq = &ipintrq; 405 break; 406 #ifdef INET6 407 case AF_INET6: 408 ifq = &ip6intrq; 409 break; 410 #endif 411 default: 412 m_freem(top); 413 return (EAFNOSUPPORT); 414 } 415 416 if (niq_enqueue(ifq, top) != 0) 417 return (ENOBUFS); 418 419 return (error); 420 } 421 422 int 423 pppxioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) 424 { 425 struct pppx_dev *pxd = pppx_dev2pxd(dev); 426 int error = 0; 427 428 switch (cmd) { 429 case PIPEXSMODE: 430 /* 431 * npppd always enables on open, and only disables before 432 * closing. we cheat and let open and close do that, so lie 433 * to npppd. 434 */ 435 break; 436 case PIPEXGMODE: 437 *(int *)addr = 1; 438 break; 439 440 case PIPEXASESSION: 441 error = pppx_add_session(pxd, 442 (struct pipex_session_req *)addr); 443 break; 444 445 case PIPEXDSESSION: 446 error = pppx_del_session(pxd, 447 (struct pipex_session_close_req *)addr); 448 break; 449 450 case PIPEXCSESSION: 451 error = pipex_config_session( 452 (struct pipex_session_config_req *)addr); 453 break; 454 455 case PIPEXGSTAT: 456 error = pipex_get_stat((struct pipex_session_stat_req *)addr); 457 break; 458 459 case PIPEXGCLOSED: 460 error = pipex_get_closed((struct pipex_session_list_req *)addr); 461 break; 462 463 case PIPEXSIFDESCR: 464 error = pppx_set_session_descr(pxd, 465 (struct pipex_session_descr_req *)addr); 466 break; 467 468 case FIONBIO: 469 case FIOASYNC: 470 case FIONREAD: 471 return (0); 472 473 default: 474 error = ENOTTY; 475 break; 476 } 477 478 return (error); 479 } 480 481 int 482 pppxpoll(dev_t dev, int events, struct proc *p) 483 { 484 struct pppx_dev *pxd = pppx_dev2pxd(dev); 485 int revents = 0; 486 487 if (events & (POLLIN | POLLRDNORM)) { 488 if (!mq_empty(&pxd->pxd_svcq)) 489 revents |= events & (POLLIN | POLLRDNORM); 490 } 491 if (events & (POLLOUT | POLLWRNORM)) 492 revents |= events & (POLLOUT | POLLWRNORM); 493 494 if (revents == 0) { 495 if (events & (POLLIN | POLLRDNORM)) 496 selrecord(p, &pxd->pxd_rsel); 497 } 498 499 return (revents); 500 } 501 502 int 503 pppxkqfilter(dev_t dev, struct knote *kn) 504 { 505 struct pppx_dev *pxd = pppx_dev2pxd(dev); 506 struct mutex *mtx; 507 struct klist *klist; 508 509 switch (kn->kn_filter) { 510 case EVFILT_READ: 511 mtx = &pxd->pxd_rsel_mtx; 512 klist = &pxd->pxd_rsel.si_note; 513 kn->kn_fop = &pppx_rd_filtops; 514 break; 515 case EVFILT_WRITE: 516 mtx = &pxd->pxd_wsel_mtx; 517 klist = &pxd->pxd_wsel.si_note; 518 kn->kn_fop = &pppx_wr_filtops; 519 break; 520 default: 521 return (EINVAL); 522 } 523 524 kn->kn_hook = (caddr_t)pxd; 525 526 mtx_enter(mtx); 527 SLIST_INSERT_HEAD(klist, kn, kn_selnext); 528 mtx_leave(mtx); 529 530 return (0); 531 } 532 533 void 534 filt_pppx_rdetach(struct knote *kn) 535 { 536 struct pppx_dev *pxd = (struct pppx_dev *)kn->kn_hook; 537 struct klist *klist = &pxd->pxd_rsel.si_note; 538 539 if (ISSET(kn->kn_status, KN_DETACHED)) 540 return; 541 542 mtx_enter(&pxd->pxd_rsel_mtx); 543 SLIST_REMOVE(klist, kn, knote, kn_selnext); 544 mtx_leave(&pxd->pxd_rsel_mtx); 545 } 546 547 int 548 filt_pppx_read(struct knote *kn, long hint) 549 { 550 struct pppx_dev *pxd = (struct pppx_dev *)kn->kn_hook; 551 552 if (ISSET(kn->kn_status, KN_DETACHED)) { 553 kn->kn_data = 0; 554 return (1); 555 } 556 557 kn->kn_data = mq_len(&pxd->pxd_svcq); 558 559 return (kn->kn_data > 0); 560 } 561 562 void 563 filt_pppx_wdetach(struct knote *kn) 564 { 565 struct pppx_dev *pxd = (struct pppx_dev *)kn->kn_hook; 566 struct klist *klist = &pxd->pxd_wsel.si_note; 567 568 if (ISSET(kn->kn_status, KN_DETACHED)) 569 return; 570 571 mtx_enter(&pxd->pxd_wsel_mtx); 572 SLIST_REMOVE(klist, kn, knote, kn_selnext); 573 mtx_leave(&pxd->pxd_wsel_mtx); 574 } 575 576 int 577 filt_pppx_write(struct knote *kn, long hint) 578 { 579 /* We're always ready to accept a write. */ 580 return (1); 581 } 582 583 int 584 pppxclose(dev_t dev, int flags, int mode, struct proc *p) 585 { 586 struct pppx_dev *pxd; 587 struct pppx_if *pxi; 588 589 rw_enter_write(&pppx_devs_lk); 590 591 pxd = pppx_dev_lookup(dev); 592 593 /* XXX */ 594 while ((pxi = LIST_FIRST(&pxd->pxd_pxis))) 595 pppx_if_destroy(pxd, pxi); 596 597 LIST_REMOVE(pxd, pxd_entry); 598 599 mq_purge(&pxd->pxd_svcq); 600 601 free(pxd, M_DEVBUF, 0); 602 603 if (LIST_EMPTY(&pppx_devs)) { 604 pool_destroy(pppx_if_pl); 605 free(pppx_if_pl, M_DEVBUF, 0); 606 pppx_if_pl = NULL; 607 } 608 609 rw_exit_write(&pppx_devs_lk); 610 return (0); 611 } 612 613 int 614 pppx_if_next_unit(void) 615 { 616 struct pppx_if *pxi; 617 int unit = 0; 618 619 rw_assert_wrlock(&pppx_ifs_lk); 620 621 /* this is safe without splnet since we're not modifying it */ 622 do { 623 int found = 0; 624 RBT_FOREACH(pxi, pppx_ifs, &pppx_ifs) { 625 if (pxi->pxi_unit == unit) { 626 found = 1; 627 break; 628 } 629 } 630 631 if (found == 0) 632 break; 633 unit++; 634 } while (unit > 0); 635 636 return (unit); 637 } 638 639 struct pppx_if * 640 pppx_if_find(struct pppx_dev *pxd, int session_id, int protocol) 641 { 642 struct pppx_if *s, *p; 643 s = malloc(sizeof(*s), M_DEVBUF, M_WAITOK | M_ZERO); 644 645 s->pxi_key.pxik_session_id = session_id; 646 s->pxi_key.pxik_protocol = protocol; 647 648 rw_enter_read(&pppx_ifs_lk); 649 p = RBT_FIND(pppx_ifs, &pppx_ifs, s); 650 rw_exit_read(&pppx_ifs_lk); 651 652 free(s, M_DEVBUF, 0); 653 return (p); 654 } 655 656 int 657 pppx_add_session(struct pppx_dev *pxd, struct pipex_session_req *req) 658 { 659 struct pppx_if *pxi; 660 struct pipex_session *session; 661 struct pipex_hash_head *chain; 662 struct ifnet *ifp; 663 int unit, s, error = 0; 664 struct in_ifaddr *ia; 665 struct sockaddr_in ifaddr; 666 #ifdef PIPEX_PPPOE 667 struct ifnet *over_ifp = NULL; 668 #endif 669 670 switch (req->pr_protocol) { 671 #ifdef PIPEX_PPPOE 672 case PIPEX_PROTO_PPPOE: 673 over_ifp = ifunit(req->pr_proto.pppoe.over_ifname); 674 if (over_ifp == NULL) 675 return (EINVAL); 676 if (req->pr_peer_address.ss_family != AF_UNSPEC) 677 return (EINVAL); 678 break; 679 #endif 680 #ifdef PIPEX_PPTP 681 case PIPEX_PROTO_PPTP: 682 #endif 683 #ifdef PIPEX_L2TP 684 case PIPEX_PROTO_L2TP: 685 #endif 686 switch (req->pr_peer_address.ss_family) { 687 case AF_INET: 688 if (req->pr_peer_address.ss_len != sizeof(struct sockaddr_in)) 689 return (EINVAL); 690 break; 691 #ifdef INET6 692 case AF_INET6: 693 if (req->pr_peer_address.ss_len != sizeof(struct sockaddr_in6)) 694 return (EINVAL); 695 break; 696 #endif 697 default: 698 return (EPROTONOSUPPORT); 699 } 700 if (req->pr_peer_address.ss_family != 701 req->pr_local_address.ss_family || 702 req->pr_peer_address.ss_len != 703 req->pr_local_address.ss_len) 704 return (EINVAL); 705 break; 706 default: 707 return (EPROTONOSUPPORT); 708 } 709 710 pxi = pool_get(pppx_if_pl, PR_WAITOK | PR_ZERO); 711 if (pxi == NULL) 712 return (ENOMEM); 713 714 session = &pxi->pxi_session; 715 ifp = &pxi->pxi_if; 716 717 /* fake a pipex interface context */ 718 session->pipex_iface = &pxi->pxi_ifcontext; 719 session->pipex_iface->ifnet_this = ifp; 720 session->pipex_iface->pipexmode = PIPEX_ENABLED; 721 722 /* setup session */ 723 session->state = PIPEX_STATE_OPENED; 724 session->protocol = req->pr_protocol; 725 session->session_id = req->pr_session_id; 726 session->peer_session_id = req->pr_peer_session_id; 727 session->peer_mru = req->pr_peer_mru; 728 session->timeout_sec = req->pr_timeout_sec; 729 session->ppp_flags = req->pr_ppp_flags; 730 session->ppp_id = req->pr_ppp_id; 731 732 session->ip_forward = 1; 733 734 session->ip_address.sin_family = AF_INET; 735 session->ip_address.sin_len = sizeof(struct sockaddr_in); 736 session->ip_address.sin_addr = req->pr_ip_address; 737 738 session->ip_netmask.sin_family = AF_INET; 739 session->ip_netmask.sin_len = sizeof(struct sockaddr_in); 740 session->ip_netmask.sin_addr = req->pr_ip_netmask; 741 742 if (session->ip_netmask.sin_addr.s_addr == 0L) 743 session->ip_netmask.sin_addr.s_addr = 0xffffffffL; 744 session->ip_address.sin_addr.s_addr &= 745 session->ip_netmask.sin_addr.s_addr; 746 747 if (req->pr_peer_address.ss_len > 0) 748 memcpy(&session->peer, &req->pr_peer_address, 749 MIN(req->pr_peer_address.ss_len, sizeof(session->peer))); 750 if (req->pr_local_address.ss_len > 0) 751 memcpy(&session->local, &req->pr_local_address, 752 MIN(req->pr_local_address.ss_len, sizeof(session->local))); 753 #ifdef PIPEX_PPPOE 754 if (req->pr_protocol == PIPEX_PROTO_PPPOE) 755 session->proto.pppoe.over_ifp = over_ifp; 756 #endif 757 #ifdef PIPEX_PPTP 758 if (req->pr_protocol == PIPEX_PROTO_PPTP) { 759 struct pipex_pptp_session *sess_pptp = &session->proto.pptp; 760 761 sess_pptp->snd_gap = 0; 762 sess_pptp->rcv_gap = 0; 763 sess_pptp->snd_una = req->pr_proto.pptp.snd_una; 764 sess_pptp->snd_nxt = req->pr_proto.pptp.snd_nxt; 765 sess_pptp->rcv_nxt = req->pr_proto.pptp.rcv_nxt; 766 sess_pptp->rcv_acked = req->pr_proto.pptp.rcv_acked; 767 768 sess_pptp->winsz = req->pr_proto.pptp.winsz; 769 sess_pptp->maxwinsz = req->pr_proto.pptp.maxwinsz; 770 sess_pptp->peer_maxwinsz = req->pr_proto.pptp.peer_maxwinsz; 771 /* last ack number */ 772 sess_pptp->ul_snd_una = sess_pptp->snd_una - 1; 773 } 774 #endif 775 #ifdef PIPEX_L2TP 776 if (req->pr_protocol == PIPEX_PROTO_L2TP) { 777 struct pipex_l2tp_session *sess_l2tp = &session->proto.l2tp; 778 779 /* session keys */ 780 sess_l2tp->tunnel_id = req->pr_proto.l2tp.tunnel_id; 781 sess_l2tp->peer_tunnel_id = req->pr_proto.l2tp.peer_tunnel_id; 782 783 /* protocol options */ 784 sess_l2tp->option_flags = req->pr_proto.l2tp.option_flags; 785 786 /* initial state of dynamic context */ 787 sess_l2tp->ns_gap = sess_l2tp->nr_gap = 0; 788 sess_l2tp->ns_nxt = req->pr_proto.l2tp.ns_nxt; 789 sess_l2tp->nr_nxt = req->pr_proto.l2tp.nr_nxt; 790 sess_l2tp->ns_una = req->pr_proto.l2tp.ns_una; 791 sess_l2tp->nr_acked = req->pr_proto.l2tp.nr_acked; 792 /* last ack number */ 793 sess_l2tp->ul_ns_una = sess_l2tp->ns_una - 1; 794 } 795 #endif 796 #ifdef PIPEX_MPPE 797 if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ACCEPTED) != 0) 798 pipex_session_init_mppe_recv(session, 799 req->pr_mppe_recv.stateless, req->pr_mppe_recv.keylenbits, 800 req->pr_mppe_recv.master_key); 801 if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ENABLED) != 0) 802 pipex_session_init_mppe_send(session, 803 req->pr_mppe_send.stateless, req->pr_mppe_send.keylenbits, 804 req->pr_mppe_send.master_key); 805 806 if (pipex_session_is_mppe_required(session)) { 807 if (!pipex_session_is_mppe_enabled(session) || 808 !pipex_session_is_mppe_accepted(session)) { 809 pool_put(pppx_if_pl, pxi); 810 return (EINVAL); 811 } 812 } 813 #endif 814 815 /* try to set the interface up */ 816 rw_enter_write(&pppx_ifs_lk); 817 unit = pppx_if_next_unit(); 818 if (unit < 0) { 819 pool_put(pppx_if_pl, pxi); 820 error = ENOMEM; 821 goto out; 822 } 823 824 pxi->pxi_unit = unit; 825 pxi->pxi_key.pxik_session_id = req->pr_session_id; 826 pxi->pxi_key.pxik_protocol = req->pr_protocol; 827 pxi->pxi_dev = pxd; 828 829 /* this is safe without splnet since we're not modifying it */ 830 if (RBT_FIND(pppx_ifs, &pppx_ifs, pxi) != NULL) { 831 pool_put(pppx_if_pl, pxi); 832 error = EADDRINUSE; 833 goto out; 834 } 835 836 snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d", "pppx", unit); 837 ifp->if_mtu = req->pr_peer_mru; /* XXX */ 838 ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST | IFF_UP; 839 ifp->if_start = pppx_if_start; 840 ifp->if_output = pppx_if_output; 841 ifp->if_ioctl = pppx_if_ioctl; 842 ifp->if_rtrequest = p2p_rtrequest; 843 ifp->if_type = IFT_PPP; 844 IFQ_SET_MAXLEN(&ifp->if_snd, 1); 845 ifp->if_softc = pxi; 846 /* ifp->if_rdomain = req->pr_rdomain; */ 847 848 s = splnet(); 849 850 /* hook up pipex context */ 851 chain = PIPEX_ID_HASHTABLE(session->session_id); 852 LIST_INSERT_HEAD(chain, session, id_chain); 853 LIST_INSERT_HEAD(&pipex_session_list, session, session_list); 854 switch (req->pr_protocol) { 855 case PIPEX_PROTO_PPTP: 856 case PIPEX_PROTO_L2TP: 857 chain = PIPEX_PEER_ADDR_HASHTABLE( 858 pipex_sockaddr_hash_key((struct sockaddr *)&session->peer)); 859 LIST_INSERT_HEAD(chain, session, peer_addr_chain); 860 break; 861 } 862 863 /* if first session is added, start timer */ 864 if (LIST_NEXT(session, session_list) == NULL) 865 pipex_timer_start(); 866 867 if_attach(ifp); 868 if_addgroup(ifp, "pppx"); 869 if_alloc_sadl(ifp); 870 871 #if NBPFILTER > 0 872 bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(u_int32_t)); 873 #endif 874 SET(ifp->if_flags, IFF_RUNNING); 875 876 if (RBT_INSERT(pppx_ifs, &pppx_ifs, pxi) != NULL) 877 panic("pppx_ifs modified while lock was held"); 878 LIST_INSERT_HEAD(&pxd->pxd_pxis, pxi, pxi_list); 879 880 /* XXX ipv6 support? how does the caller indicate it wants ipv6 881 * instead of ipv4? 882 */ 883 memset(&ifaddr, 0, sizeof(ifaddr)); 884 ifaddr.sin_family = AF_INET; 885 ifaddr.sin_len = sizeof(ifaddr); 886 ifaddr.sin_addr = req->pr_ip_srcaddr; 887 888 ia = malloc(sizeof (*ia), M_IFADDR, M_WAITOK | M_ZERO); 889 890 ia->ia_addr.sin_family = AF_INET; 891 ia->ia_addr.sin_len = sizeof(struct sockaddr_in); 892 ia->ia_addr.sin_addr = req->pr_ip_srcaddr; 893 894 ia->ia_dstaddr.sin_family = AF_INET; 895 ia->ia_dstaddr.sin_len = sizeof(struct sockaddr_in); 896 ia->ia_dstaddr.sin_addr = req->pr_ip_address; 897 898 ia->ia_sockmask.sin_family = AF_INET; 899 ia->ia_sockmask.sin_len = sizeof(struct sockaddr_in); 900 ia->ia_sockmask.sin_addr = req->pr_ip_netmask; 901 902 ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr); 903 ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr); 904 ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask); 905 ia->ia_ifa.ifa_ifp = ifp; 906 907 ia->ia_netmask = ia->ia_sockmask.sin_addr.s_addr; 908 909 error = in_ifinit(ifp, ia, &ifaddr, 1); 910 if (error) { 911 printf("pppx: unable to set addresses for %s, error=%d\n", 912 ifp->if_xname, error); 913 } else { 914 dohooks(ifp->if_addrhooks, 0); 915 } 916 splx(s); 917 918 out: 919 rw_exit_write(&pppx_ifs_lk); 920 921 return (error); 922 } 923 924 int 925 pppx_del_session(struct pppx_dev *pxd, struct pipex_session_close_req *req) 926 { 927 struct pppx_if *pxi; 928 929 pxi = pppx_if_find(pxd, req->pcr_session_id, req->pcr_protocol); 930 if (pxi == NULL) 931 return (EINVAL); 932 933 req->pcr_stat = pxi->pxi_session.stat; 934 935 pppx_if_destroy(pxd, pxi); 936 return (0); 937 } 938 939 int 940 pppx_set_session_descr(struct pppx_dev *pxd, 941 struct pipex_session_descr_req *req) 942 { 943 struct pppx_if *pxi; 944 945 pxi = pppx_if_find(pxd, req->pdr_session_id, req->pdr_protocol); 946 if (pxi == NULL) 947 return (EINVAL); 948 949 (void)memset(pxi->pxi_if.if_description, 0, IFDESCRSIZE); 950 strlcpy(pxi->pxi_if.if_description, req->pdr_descr, IFDESCRSIZE); 951 952 return (0); 953 } 954 955 void 956 pppx_if_destroy(struct pppx_dev *pxd, struct pppx_if *pxi) 957 { 958 struct ifnet *ifp; 959 struct pipex_session *session; 960 int s; 961 962 session = &pxi->pxi_session; 963 ifp = &pxi->pxi_if; 964 965 s = splnet(); 966 LIST_REMOVE(session, id_chain); 967 LIST_REMOVE(session, session_list); 968 switch (session->protocol) { 969 case PIPEX_PROTO_PPTP: 970 case PIPEX_PROTO_L2TP: 971 LIST_REMOVE((struct pipex_session *)session, 972 peer_addr_chain); 973 break; 974 } 975 976 /* if final session is destroyed, stop timer */ 977 if (LIST_EMPTY(&pipex_session_list)) 978 pipex_timer_stop(); 979 splx(s); 980 981 if_detach(ifp); 982 983 rw_enter_write(&pppx_ifs_lk); 984 if (RBT_REMOVE(pppx_ifs, &pppx_ifs, pxi) == NULL) 985 panic("pppx_ifs modified while lock was held"); 986 LIST_REMOVE(pxi, pxi_list); 987 rw_exit_write(&pppx_ifs_lk); 988 989 pool_put(pppx_if_pl, pxi); 990 } 991 992 void 993 pppx_if_start(struct ifnet *ifp) 994 { 995 struct pppx_if *pxi = (struct pppx_if *)ifp->if_softc; 996 struct mbuf *m; 997 int proto; 998 999 if (!ISSET(ifp->if_flags, IFF_RUNNING)) 1000 return; 1001 1002 for (;;) { 1003 IFQ_DEQUEUE(&ifp->if_snd, m); 1004 1005 if (m == NULL) 1006 break; 1007 1008 proto = *mtod(m, int *); 1009 m_adj(m, sizeof(proto)); 1010 1011 ifp->if_obytes += m->m_pkthdr.len; 1012 ifp->if_opackets++; 1013 1014 pipex_ppp_output(m, &pxi->pxi_session, proto); 1015 } 1016 } 1017 1018 int 1019 pppx_if_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 1020 struct rtentry *rt) 1021 { 1022 struct pppx_if *pxi = (struct pppx_if *)ifp->if_softc; 1023 struct pppx_hdr *th; 1024 int error = 0; 1025 int proto; 1026 #if NBPFILTER > 0 1027 int s; 1028 #endif 1029 1030 if (!ISSET(ifp->if_flags, IFF_UP)) { 1031 m_freem(m); 1032 error = ENETDOWN; 1033 goto out; 1034 } 1035 1036 #if NBPFILTER > 0 1037 if (ifp->if_bpf) { 1038 s = splnet(); 1039 bpf_mtap_af(ifp->if_bpf, dst->sa_family, m, BPF_DIRECTION_OUT); 1040 splx(s); 1041 } 1042 #endif 1043 if (pipex_enable) { 1044 switch (dst->sa_family) { 1045 case AF_INET: 1046 proto = PPP_IP; 1047 break; 1048 default: 1049 m_freem(m); 1050 error = EPFNOSUPPORT; 1051 goto out; 1052 } 1053 } else 1054 proto = htonl(dst->sa_family); 1055 1056 M_PREPEND(m, sizeof(int), M_DONTWAIT); 1057 if (m == NULL) { 1058 error = ENOBUFS; 1059 goto out; 1060 } 1061 *mtod(m, int *) = proto; 1062 1063 if (pipex_enable) 1064 error = if_enqueue(ifp, m); 1065 else { 1066 M_PREPEND(m, sizeof(struct pppx_hdr), M_DONTWAIT); 1067 if (m == NULL) { 1068 error = ENOBUFS; 1069 goto out; 1070 } 1071 th = mtod(m, struct pppx_hdr *); 1072 th->pppx_proto = 0; /* not used */ 1073 th->pppx_id = pxi->pxi_session.ppp_id; 1074 rw_enter_read(&pppx_devs_lk); 1075 error = mq_enqueue(&pxi->pxi_dev->pxd_svcq, m); 1076 if (error == 0) { 1077 s = splnet(); 1078 if (pxi->pxi_dev->pxd_waiting) { 1079 wakeup((caddr_t)pxi->pxi_dev); 1080 pxi->pxi_dev->pxd_waiting = 0; 1081 } 1082 splx(s); 1083 selwakeup(&pxi->pxi_dev->pxd_rsel); 1084 } 1085 rw_exit_read(&pppx_devs_lk); 1086 } 1087 1088 out: 1089 if (error) 1090 ifp->if_oerrors++; 1091 return (error); 1092 } 1093 1094 int 1095 pppx_if_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr) 1096 { 1097 struct pppx_if *pxi = (struct pppx_if *)ifp->if_softc; 1098 struct ifreq *ifr = (struct ifreq *)addr; 1099 int error = 0; 1100 1101 switch (cmd) { 1102 case SIOCSIFADDR: 1103 break; 1104 1105 case SIOCSIFFLAGS: 1106 break; 1107 1108 case SIOCADDMULTI: 1109 case SIOCDELMULTI: 1110 break; 1111 1112 case SIOCSIFMTU: 1113 if (ifr->ifr_mtu < 512 || 1114 ifr->ifr_mtu > pxi->pxi_session.peer_mru) 1115 error = EINVAL; 1116 else 1117 ifp->if_mtu = ifr->ifr_mtu; 1118 break; 1119 1120 default: 1121 error = ENOTTY; 1122 break; 1123 } 1124 1125 return (error); 1126 } 1127 1128 RBT_GENERATE(pppx_ifs, pppx_if, pxi_entry, pppx_if_cmp); 1129