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