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