1 /* $KAME: ip_encap.c,v 1.73 2001/10/02 08:30:58 itojun Exp $ */ 2 3 /* 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 /* 32 * My grandfather said that there's a devil inside tunnelling technology... 33 * 34 * We have surprisingly many protocols that want packets with IP protocol 35 * #4 or #41. Here's a list of protocols that want protocol #41: 36 * RFC1933 configured tunnel 37 * RFC1933 automatic tunnel 38 * RFC2401 IPsec tunnel 39 * RFC2473 IPv6 generic packet tunnelling 40 * RFC2529 6over4 tunnel 41 * RFC3056 6to4 tunnel 42 * isatap tunnel 43 * mobile-ip6 (uses RFC2473) 44 * Here's a list of protocol that want protocol #4: 45 * RFC1853 IPv4-in-IPv4 tunnelling 46 * RFC2003 IPv4 encapsulation within IPv4 47 * RFC2344 reverse tunnelling for mobile-ip4 48 * RFC2401 IPsec tunnel 49 * Well, what can I say. They impose different en/decapsulation mechanism 50 * from each other, so they need separate protocol handler. The only one 51 * we can easily determine by protocol # is IPsec, which always has 52 * AH/ESP/IPComp header right after outer IP header. 53 * 54 * So, clearly good old protosw does not work for protocol #4 and #41. 55 * The code will let you match protocol via src/dst address pair. 56 */ 57 /* XXX is M_NETADDR correct? */ 58 59 /* 60 * With USE_RADIX the code will use radix table for tunnel lookup, for 61 * tunnels registered with encap_attach() with a addr/mask pair. 62 * Faster on machines with thousands of tunnel registerations (= interfaces). 63 * 64 * The code assumes that radix table code can handle non-continuous netmask, 65 * as it will pass radix table memory region with (src + dst) sockaddr pair. 66 * 67 * FreeBSD is excluded here as they make max_keylen a static variable, and 68 * thus forbid definition of radix table other than proper domains. 69 * 70 * !!!!!!! 71 * !!NOTE: dom_maxrtkey assumes USE_RADIX is defined. 72 * !!!!!!! 73 */ 74 #define USE_RADIX 75 76 #include <sys/cdefs.h> 77 __KERNEL_RCSID(0, "$NetBSD: ip_encap.c,v 1.33 2008/11/25 18:28:05 pooka Exp $"); 78 79 #include "opt_mrouting.h" 80 #include "opt_inet.h" 81 82 #include <sys/param.h> 83 #include <sys/systm.h> 84 #include <sys/socket.h> 85 #include <sys/sockio.h> 86 #include <sys/mbuf.h> 87 #include <sys/errno.h> 88 #include <sys/protosw.h> 89 #include <sys/queue.h> 90 91 #include <net/if.h> 92 #include <net/route.h> 93 94 #include <netinet/in.h> 95 #include <netinet/in_systm.h> 96 #include <netinet/ip.h> 97 #include <netinet/ip_var.h> 98 #include <netinet/ip_encap.h> 99 #ifdef MROUTING 100 #include <netinet/ip_mroute.h> 101 #endif /* MROUTING */ 102 103 #ifdef INET6 104 #include <netinet/ip6.h> 105 #include <netinet6/ip6_var.h> 106 #include <netinet6/ip6protosw.h> 107 #include <netinet6/in6_var.h> 108 #include <netinet6/in6_pcb.h> 109 #include <netinet/icmp6.h> 110 #endif 111 112 #include <machine/stdarg.h> 113 114 #include <net/net_osdep.h> 115 116 enum direction { INBOUND, OUTBOUND }; 117 118 #ifdef INET 119 static struct encaptab *encap4_lookup(struct mbuf *, int, int, enum direction); 120 #endif 121 #ifdef INET6 122 static struct encaptab *encap6_lookup(struct mbuf *, int, int, enum direction); 123 #endif 124 static int encap_add(struct encaptab *); 125 static int encap_remove(struct encaptab *); 126 static int encap_afcheck(int, const struct sockaddr *, const struct sockaddr *); 127 #ifdef USE_RADIX 128 static struct radix_node_head *encap_rnh(int); 129 static int mask_matchlen(const struct sockaddr *); 130 #endif 131 #ifndef USE_RADIX 132 static int mask_match(const struct encaptab *, const struct sockaddr *, 133 const struct sockaddr *); 134 #endif 135 static void encap_fillarg(struct mbuf *, const struct encaptab *); 136 137 LIST_HEAD(, encaptab) encaptab = LIST_HEAD_INITIALIZER(&encaptab); 138 139 #ifdef USE_RADIX 140 extern int max_keylen; /* radix.c */ 141 struct radix_node_head *encap_head[2]; /* 0 for AF_INET, 1 for AF_INET6 */ 142 #endif 143 144 void 145 encap_init(void) 146 { 147 static int initialized = 0; 148 149 if (initialized) 150 return; 151 initialized++; 152 #if 0 153 /* 154 * we cannot use LIST_INIT() here, since drivers may want to call 155 * encap_attach(), on driver attach. encap_init() will be called 156 * on AF_INET{,6} initialization, which happens after driver 157 * initialization - using LIST_INIT() here can nuke encap_attach() 158 * from drivers. 159 */ 160 LIST_INIT(&encaptab); 161 #endif 162 163 #ifdef USE_RADIX 164 /* 165 * initialize radix lookup table. 166 * max_keylen initialization happen in the rn_init(). 167 */ 168 rn_init(); 169 rn_inithead((void *)&encap_head[0], sizeof(struct sockaddr_pack) << 3); 170 #ifdef INET6 171 rn_inithead((void *)&encap_head[1], sizeof(struct sockaddr_pack) << 3); 172 #endif 173 #endif 174 } 175 176 #ifdef INET 177 static struct encaptab * 178 encap4_lookup(struct mbuf *m, int off, int proto, enum direction dir) 179 { 180 struct ip *ip; 181 struct ip_pack4 pack; 182 struct encaptab *ep, *match; 183 int prio, matchprio; 184 #ifdef USE_RADIX 185 struct radix_node_head *rnh = encap_rnh(AF_INET); 186 struct radix_node *rn; 187 #endif 188 189 #ifdef DIAGNOSTIC 190 if (m->m_len < sizeof(*ip)) 191 panic("encap4_lookup"); 192 #endif 193 ip = mtod(m, struct ip *); 194 195 bzero(&pack, sizeof(pack)); 196 pack.p.sp_len = sizeof(pack); 197 pack.mine.sin_family = pack.yours.sin_family = AF_INET; 198 pack.mine.sin_len = pack.yours.sin_len = sizeof(struct sockaddr_in); 199 if (dir == INBOUND) { 200 pack.mine.sin_addr = ip->ip_dst; 201 pack.yours.sin_addr = ip->ip_src; 202 } else { 203 pack.mine.sin_addr = ip->ip_src; 204 pack.yours.sin_addr = ip->ip_dst; 205 } 206 207 match = NULL; 208 matchprio = 0; 209 210 #ifdef USE_RADIX 211 rn = rnh->rnh_matchaddr((void *)&pack, rnh); 212 if (rn && (rn->rn_flags & RNF_ROOT) == 0) { 213 match = (struct encaptab *)rn; 214 matchprio = mask_matchlen(match->srcmask) + 215 mask_matchlen(match->dstmask); 216 } 217 #endif 218 219 LIST_FOREACH(ep, &encaptab, chain) { 220 if (ep->af != AF_INET) 221 continue; 222 if (ep->proto >= 0 && ep->proto != proto) 223 continue; 224 if (ep->func) 225 prio = (*ep->func)(m, off, proto, ep->arg); 226 else { 227 #ifdef USE_RADIX 228 continue; 229 #else 230 prio = mask_match(ep, (struct sockaddr *)&pack.mine, 231 (struct sockaddr *)&pack.yours); 232 #endif 233 } 234 235 /* 236 * We prioritize the matches by using bit length of the 237 * matches. mask_match() and user-supplied matching function 238 * should return the bit length of the matches (for example, 239 * if both src/dst are matched for IPv4, 64 should be returned). 240 * 0 or negative return value means "it did not match". 241 * 242 * The question is, since we have two "mask" portion, we 243 * cannot really define total order between entries. 244 * For example, which of these should be preferred? 245 * mask_match() returns 48 (32 + 16) for both of them. 246 * src=3ffe::/16, dst=3ffe:501::/32 247 * src=3ffe:501::/32, dst=3ffe::/16 248 * 249 * We need to loop through all the possible candidates 250 * to get the best match - the search takes O(n) for 251 * n attachments (i.e. interfaces). 252 * 253 * For radix-based lookup, I guess source takes precedence. 254 * See rn_{refines,lexobetter} for the correct answer. 255 */ 256 if (prio <= 0) 257 continue; 258 if (prio > matchprio) { 259 matchprio = prio; 260 match = ep; 261 } 262 } 263 264 return match; 265 #undef s 266 #undef d 267 } 268 269 void 270 encap4_input(struct mbuf *m, ...) 271 { 272 int off, proto; 273 va_list ap; 274 const struct protosw *psw; 275 struct encaptab *match; 276 277 va_start(ap, m); 278 off = va_arg(ap, int); 279 proto = va_arg(ap, int); 280 va_end(ap); 281 282 match = encap4_lookup(m, off, proto, INBOUND); 283 284 if (match) { 285 /* found a match, "match" has the best one */ 286 psw = match->psw; 287 if (psw && psw->pr_input) { 288 encap_fillarg(m, match); 289 (*psw->pr_input)(m, off, proto); 290 } else 291 m_freem(m); 292 return; 293 } 294 295 /* last resort: inject to raw socket */ 296 rip_input(m, off, proto); 297 } 298 #endif 299 300 #ifdef INET6 301 static struct encaptab * 302 encap6_lookup(struct mbuf *m, int off, int proto, enum direction dir) 303 { 304 struct ip6_hdr *ip6; 305 struct ip_pack6 pack; 306 int prio, matchprio; 307 struct encaptab *ep, *match; 308 #ifdef USE_RADIX 309 struct radix_node_head *rnh = encap_rnh(AF_INET6); 310 struct radix_node *rn; 311 #endif 312 313 #ifdef DIAGNOSTIC 314 if (m->m_len < sizeof(*ip6)) 315 panic("encap6_lookup"); 316 #endif 317 ip6 = mtod(m, struct ip6_hdr *); 318 319 bzero(&pack, sizeof(pack)); 320 pack.p.sp_len = sizeof(pack); 321 pack.mine.sin6_family = pack.yours.sin6_family = AF_INET6; 322 pack.mine.sin6_len = pack.yours.sin6_len = sizeof(struct sockaddr_in6); 323 if (dir == INBOUND) { 324 pack.mine.sin6_addr = ip6->ip6_dst; 325 pack.yours.sin6_addr = ip6->ip6_src; 326 } else { 327 pack.mine.sin6_addr = ip6->ip6_src; 328 pack.yours.sin6_addr = ip6->ip6_dst; 329 } 330 331 match = NULL; 332 matchprio = 0; 333 334 #ifdef USE_RADIX 335 rn = rnh->rnh_matchaddr((void *)&pack, rnh); 336 if (rn && (rn->rn_flags & RNF_ROOT) == 0) { 337 match = (struct encaptab *)rn; 338 matchprio = mask_matchlen(match->srcmask) + 339 mask_matchlen(match->dstmask); 340 } 341 #endif 342 343 LIST_FOREACH(ep, &encaptab, chain) { 344 if (ep->af != AF_INET6) 345 continue; 346 if (ep->proto >= 0 && ep->proto != proto) 347 continue; 348 if (ep->func) 349 prio = (*ep->func)(m, off, proto, ep->arg); 350 else { 351 #ifdef USE_RADIX 352 continue; 353 #else 354 prio = mask_match(ep, (struct sockaddr *)&pack.mine, 355 (struct sockaddr *)&pack.yours); 356 #endif 357 } 358 359 /* see encap4_lookup() for issues here */ 360 if (prio <= 0) 361 continue; 362 if (prio > matchprio) { 363 matchprio = prio; 364 match = ep; 365 } 366 } 367 368 return match; 369 #undef s 370 #undef d 371 } 372 373 int 374 encap6_input(struct mbuf **mp, int *offp, int proto) 375 { 376 struct mbuf *m = *mp; 377 const struct ip6protosw *psw; 378 struct encaptab *match; 379 380 match = encap6_lookup(m, *offp, proto, INBOUND); 381 382 if (match) { 383 /* found a match */ 384 psw = (const struct ip6protosw *)match->psw; 385 if (psw && psw->pr_input) { 386 encap_fillarg(m, match); 387 return (*psw->pr_input)(mp, offp, proto); 388 } else { 389 m_freem(m); 390 return IPPROTO_DONE; 391 } 392 } 393 394 /* last resort: inject to raw socket */ 395 return rip6_input(mp, offp, proto); 396 } 397 #endif 398 399 static int 400 encap_add(struct encaptab *ep) 401 { 402 #ifdef USE_RADIX 403 struct radix_node_head *rnh = encap_rnh(ep->af); 404 #endif 405 int error = 0; 406 407 LIST_INSERT_HEAD(&encaptab, ep, chain); 408 #ifdef USE_RADIX 409 if (!ep->func && rnh) { 410 if (!rnh->rnh_addaddr((void *)ep->addrpack, 411 (void *)ep->maskpack, rnh, ep->nodes)) { 412 error = EEXIST; 413 goto fail; 414 } 415 } 416 #endif 417 return error; 418 419 fail: 420 LIST_REMOVE(ep, chain); 421 return error; 422 } 423 424 static int 425 encap_remove(struct encaptab *ep) 426 { 427 #ifdef USE_RADIX 428 struct radix_node_head *rnh = encap_rnh(ep->af); 429 #endif 430 int error = 0; 431 432 LIST_REMOVE(ep, chain); 433 #ifdef USE_RADIX 434 if (!ep->func && rnh) { 435 if (!rnh->rnh_deladdr((void *)ep->addrpack, 436 (void *)ep->maskpack, rnh)) 437 error = ESRCH; 438 } 439 #endif 440 return error; 441 } 442 443 static int 444 encap_afcheck(int af, const struct sockaddr *sp, const struct sockaddr *dp) 445 { 446 if (sp && dp) { 447 if (sp->sa_len != dp->sa_len) 448 return EINVAL; 449 if (af != sp->sa_family || af != dp->sa_family) 450 return EINVAL; 451 } else if (!sp && !dp) 452 ; 453 else 454 return EINVAL; 455 456 switch (af) { 457 case AF_INET: 458 if (sp && sp->sa_len != sizeof(struct sockaddr_in)) 459 return EINVAL; 460 if (dp && dp->sa_len != sizeof(struct sockaddr_in)) 461 return EINVAL; 462 break; 463 #ifdef INET6 464 case AF_INET6: 465 if (sp && sp->sa_len != sizeof(struct sockaddr_in6)) 466 return EINVAL; 467 if (dp && dp->sa_len != sizeof(struct sockaddr_in6)) 468 return EINVAL; 469 break; 470 #endif 471 default: 472 return EAFNOSUPPORT; 473 } 474 475 return 0; 476 } 477 478 /* 479 * sp (src ptr) is always my side, and dp (dst ptr) is always remote side. 480 * length of mask (sm and dm) is assumed to be same as sp/dp. 481 * Return value will be necessary as input (cookie) for encap_detach(). 482 */ 483 const struct encaptab * 484 encap_attach(int af, int proto, 485 const struct sockaddr *sp, const struct sockaddr *sm, 486 const struct sockaddr *dp, const struct sockaddr *dm, 487 const struct protosw *psw, void *arg) 488 { 489 struct encaptab *ep; 490 int error; 491 int s; 492 size_t l; 493 struct ip_pack4 *pack4; 494 #ifdef INET6 495 struct ip_pack6 *pack6; 496 #endif 497 498 s = splsoftnet(); 499 /* sanity check on args */ 500 error = encap_afcheck(af, sp, dp); 501 if (error) 502 goto fail; 503 504 /* check if anyone have already attached with exactly same config */ 505 LIST_FOREACH(ep, &encaptab, chain) { 506 if (ep->af != af) 507 continue; 508 if (ep->proto != proto) 509 continue; 510 if (ep->func) 511 continue; 512 #ifdef DIAGNOSTIC 513 if (!ep->src || !ep->dst || !ep->srcmask || !ep->dstmask) 514 panic("null pointers in encaptab"); 515 #endif 516 if (ep->src->sa_len != sp->sa_len || 517 bcmp(ep->src, sp, sp->sa_len) != 0 || 518 bcmp(ep->srcmask, sm, sp->sa_len) != 0) 519 continue; 520 if (ep->dst->sa_len != dp->sa_len || 521 bcmp(ep->dst, dp, dp->sa_len) != 0 || 522 bcmp(ep->dstmask, dm, dp->sa_len) != 0) 523 continue; 524 525 error = EEXIST; 526 goto fail; 527 } 528 529 switch (af) { 530 case AF_INET: 531 l = sizeof(*pack4); 532 break; 533 #ifdef INET6 534 case AF_INET6: 535 l = sizeof(*pack6); 536 break; 537 #endif 538 default: 539 goto fail; 540 } 541 542 /* M_NETADDR ok? */ 543 ep = malloc(sizeof(*ep), M_NETADDR, M_NOWAIT|M_ZERO); 544 if (ep == NULL) { 545 error = ENOBUFS; 546 goto fail; 547 } 548 ep->addrpack = malloc(l, M_NETADDR, M_NOWAIT|M_ZERO); 549 if (ep->addrpack == NULL) { 550 error = ENOBUFS; 551 goto gc; 552 } 553 ep->maskpack = malloc(l, M_NETADDR, M_NOWAIT|M_ZERO); 554 if (ep->maskpack == NULL) { 555 error = ENOBUFS; 556 goto gc; 557 } 558 559 ep->af = af; 560 ep->proto = proto; 561 ep->addrpack->sa_len = l & 0xff; 562 ep->maskpack->sa_len = l & 0xff; 563 switch (af) { 564 case AF_INET: 565 pack4 = (struct ip_pack4 *)ep->addrpack; 566 ep->src = (struct sockaddr *)&pack4->mine; 567 ep->dst = (struct sockaddr *)&pack4->yours; 568 pack4 = (struct ip_pack4 *)ep->maskpack; 569 ep->srcmask = (struct sockaddr *)&pack4->mine; 570 ep->dstmask = (struct sockaddr *)&pack4->yours; 571 break; 572 #ifdef INET6 573 case AF_INET6: 574 pack6 = (struct ip_pack6 *)ep->addrpack; 575 ep->src = (struct sockaddr *)&pack6->mine; 576 ep->dst = (struct sockaddr *)&pack6->yours; 577 pack6 = (struct ip_pack6 *)ep->maskpack; 578 ep->srcmask = (struct sockaddr *)&pack6->mine; 579 ep->dstmask = (struct sockaddr *)&pack6->yours; 580 break; 581 #endif 582 } 583 584 bcopy(sp, ep->src, sp->sa_len); 585 bcopy(sm, ep->srcmask, sp->sa_len); 586 bcopy(dp, ep->dst, dp->sa_len); 587 bcopy(dm, ep->dstmask, dp->sa_len); 588 ep->psw = psw; 589 ep->arg = arg; 590 591 error = encap_add(ep); 592 if (error) 593 goto gc; 594 595 error = 0; 596 splx(s); 597 return ep; 598 599 gc: 600 if (ep->addrpack) 601 free(ep->addrpack, M_NETADDR); 602 if (ep->maskpack) 603 free(ep->maskpack, M_NETADDR); 604 if (ep) 605 free(ep, M_NETADDR); 606 fail: 607 splx(s); 608 return NULL; 609 } 610 611 const struct encaptab * 612 encap_attach_func(int af, int proto, 613 int (*func)(struct mbuf *, int, int, void *), 614 const struct protosw *psw, void *arg) 615 { 616 struct encaptab *ep; 617 int error; 618 int s; 619 620 s = splsoftnet(); 621 /* sanity check on args */ 622 if (!func) { 623 error = EINVAL; 624 goto fail; 625 } 626 627 error = encap_afcheck(af, NULL, NULL); 628 if (error) 629 goto fail; 630 631 ep = malloc(sizeof(*ep), M_NETADDR, M_NOWAIT); /*XXX*/ 632 if (ep == NULL) { 633 error = ENOBUFS; 634 goto fail; 635 } 636 bzero(ep, sizeof(*ep)); 637 638 ep->af = af; 639 ep->proto = proto; 640 ep->func = func; 641 ep->psw = psw; 642 ep->arg = arg; 643 644 error = encap_add(ep); 645 if (error) 646 goto fail; 647 648 error = 0; 649 splx(s); 650 return ep; 651 652 fail: 653 splx(s); 654 return NULL; 655 } 656 657 /* XXX encap4_ctlinput() is necessary if we set DF=1 on outer IPv4 header */ 658 659 #ifdef INET6 660 void * 661 encap6_ctlinput(int cmd, const struct sockaddr *sa, void *d0) 662 { 663 void *d = d0; 664 struct ip6_hdr *ip6; 665 struct mbuf *m; 666 int off; 667 struct ip6ctlparam *ip6cp = NULL; 668 int nxt; 669 struct encaptab *ep; 670 const struct ip6protosw *psw; 671 672 if (sa->sa_family != AF_INET6 || 673 sa->sa_len != sizeof(struct sockaddr_in6)) 674 return NULL; 675 676 if ((unsigned)cmd >= PRC_NCMDS) 677 return NULL; 678 if (cmd == PRC_HOSTDEAD) 679 d = NULL; 680 else if (cmd == PRC_MSGSIZE) 681 ; /* special code is present, see below */ 682 else if (inet6ctlerrmap[cmd] == 0) 683 return NULL; 684 685 /* if the parameter is from icmp6, decode it. */ 686 if (d != NULL) { 687 ip6cp = (struct ip6ctlparam *)d; 688 m = ip6cp->ip6c_m; 689 ip6 = ip6cp->ip6c_ip6; 690 off = ip6cp->ip6c_off; 691 nxt = ip6cp->ip6c_nxt; 692 693 if (ip6 && cmd == PRC_MSGSIZE) { 694 int valid = 0; 695 struct encaptab *match; 696 697 /* 698 * Check to see if we have a valid encap configuration. 699 */ 700 match = encap6_lookup(m, off, nxt, OUTBOUND); 701 if (match) 702 valid++; 703 704 /* 705 * Depending on the value of "valid" and routing table 706 * size (mtudisc_{hi,lo}wat), we will: 707 * - recalcurate the new MTU and create the 708 * corresponding routing entry, or 709 * - ignore the MTU change notification. 710 */ 711 icmp6_mtudisc_update((struct ip6ctlparam *)d, valid); 712 } 713 } else { 714 m = NULL; 715 ip6 = NULL; 716 nxt = -1; 717 } 718 719 /* inform all listeners */ 720 LIST_FOREACH(ep, &encaptab, chain) { 721 if (ep->af != AF_INET6) 722 continue; 723 if (ep->proto >= 0 && ep->proto != nxt) 724 continue; 725 726 /* should optimize by looking at address pairs */ 727 728 /* XXX need to pass ep->arg or ep itself to listeners */ 729 psw = (const struct ip6protosw *)ep->psw; 730 if (psw && psw->pr_ctlinput) 731 (*psw->pr_ctlinput)(cmd, sa, d); 732 } 733 734 rip6_ctlinput(cmd, sa, d0); 735 return NULL; 736 } 737 #endif 738 739 int 740 encap_detach(const struct encaptab *cookie) 741 { 742 const struct encaptab *ep = cookie; 743 struct encaptab *p; 744 int error; 745 746 LIST_FOREACH(p, &encaptab, chain) { 747 if (p == ep) { 748 error = encap_remove(p); 749 if (error) 750 return error; 751 if (!ep->func) { 752 free(p->addrpack, M_NETADDR); 753 free(p->maskpack, M_NETADDR); 754 } 755 free(p, M_NETADDR); /*XXX*/ 756 return 0; 757 } 758 } 759 760 return ENOENT; 761 } 762 763 #ifdef USE_RADIX 764 static struct radix_node_head * 765 encap_rnh(int af) 766 { 767 768 switch (af) { 769 case AF_INET: 770 return encap_head[0]; 771 #ifdef INET6 772 case AF_INET6: 773 return encap_head[1]; 774 #endif 775 default: 776 return NULL; 777 } 778 } 779 780 static int 781 mask_matchlen(const struct sockaddr *sa) 782 { 783 const char *p, *ep; 784 int l; 785 786 p = (const char *)sa; 787 ep = p + sa->sa_len; 788 p += 2; /* sa_len + sa_family */ 789 790 l = 0; 791 while (p < ep) { 792 l += (*p ? 8 : 0); /* estimate */ 793 p++; 794 } 795 return l; 796 } 797 #endif 798 799 #ifndef USE_RADIX 800 static int 801 mask_match(const struct encaptab *ep, 802 const struct sockaddr *sp, 803 const struct sockaddr *dp) 804 { 805 struct sockaddr_storage s; 806 struct sockaddr_storage d; 807 int i; 808 const u_int8_t *p, *q; 809 u_int8_t *r; 810 int matchlen; 811 812 #ifdef DIAGNOSTIC 813 if (ep->func) 814 panic("wrong encaptab passed to mask_match"); 815 #endif 816 if (sp->sa_len > sizeof(s) || dp->sa_len > sizeof(d)) 817 return 0; 818 if (sp->sa_family != ep->af || dp->sa_family != ep->af) 819 return 0; 820 if (sp->sa_len != ep->src->sa_len || dp->sa_len != ep->dst->sa_len) 821 return 0; 822 823 matchlen = 0; 824 825 p = (const u_int8_t *)sp; 826 q = (const u_int8_t *)ep->srcmask; 827 r = (u_int8_t *)&s; 828 for (i = 0 ; i < sp->sa_len; i++) { 829 r[i] = p[i] & q[i]; 830 /* XXX estimate */ 831 matchlen += (q[i] ? 8 : 0); 832 } 833 834 p = (const u_int8_t *)dp; 835 q = (const u_int8_t *)ep->dstmask; 836 r = (u_int8_t *)&d; 837 for (i = 0 ; i < dp->sa_len; i++) { 838 r[i] = p[i] & q[i]; 839 /* XXX rough estimate */ 840 matchlen += (q[i] ? 8 : 0); 841 } 842 843 /* need to overwrite len/family portion as we don't compare them */ 844 s.ss_len = sp->sa_len; 845 s.ss_family = sp->sa_family; 846 d.ss_len = dp->sa_len; 847 d.ss_family = dp->sa_family; 848 849 if (bcmp(&s, ep->src, ep->src->sa_len) == 0 && 850 bcmp(&d, ep->dst, ep->dst->sa_len) == 0) { 851 return matchlen; 852 } else 853 return 0; 854 } 855 #endif 856 857 static void 858 encap_fillarg(struct mbuf *m, const struct encaptab *ep) 859 { 860 struct m_tag *mtag; 861 862 mtag = m_tag_get(PACKET_TAG_ENCAP, sizeof(void *), M_NOWAIT); 863 if (mtag) { 864 *(void **)(mtag + 1) = ep->arg; 865 m_tag_prepend(m, mtag); 866 } 867 } 868 869 void * 870 encap_getarg(struct mbuf *m) 871 { 872 void *p; 873 struct m_tag *mtag; 874 875 p = NULL; 876 mtag = m_tag_find(m, PACKET_TAG_ENCAP, NULL); 877 if (mtag != NULL) { 878 p = *(void **)(mtag + 1); 879 m_tag_delete(m, mtag); 880 } 881 return p; 882 } 883