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 #define USE_RADIX 71 72 #include <sys/cdefs.h> 73 __KERNEL_RCSID(0, "$NetBSD: ip_encap.c,v 1.18 2004/04/26 01:31:56 matt Exp $"); 74 75 #include "opt_mrouting.h" 76 #include "opt_inet.h" 77 78 #include <sys/param.h> 79 #include <sys/systm.h> 80 #include <sys/socket.h> 81 #include <sys/sockio.h> 82 #include <sys/mbuf.h> 83 #include <sys/errno.h> 84 #include <sys/protosw.h> 85 #include <sys/queue.h> 86 87 #include <net/if.h> 88 #include <net/route.h> 89 90 #include <netinet/in.h> 91 #include <netinet/in_systm.h> 92 #include <netinet/ip.h> 93 #include <netinet/ip_var.h> 94 #include <netinet/ip_encap.h> 95 #ifdef MROUTING 96 #include <netinet/ip_mroute.h> 97 #endif /* MROUTING */ 98 99 #ifdef INET6 100 #include <netinet/ip6.h> 101 #include <netinet6/ip6_var.h> 102 #include <netinet6/ip6protosw.h> 103 #include <netinet6/in6_var.h> 104 #include <netinet6/in6_pcb.h> 105 #include <netinet/icmp6.h> 106 #endif 107 108 #include <machine/stdarg.h> 109 110 #include <net/net_osdep.h> 111 112 /* to lookup a pair of address using radix tree */ 113 struct sockaddr_pack { 114 u_int8_t sp_len; 115 u_int8_t sp_family; /* not really used */ 116 /* followed by variable-length data */ 117 }; 118 119 struct pack4 { 120 struct sockaddr_pack p; 121 struct sockaddr_in mine; 122 struct sockaddr_in yours; 123 }; 124 struct pack6 { 125 struct sockaddr_pack p; 126 struct sockaddr_in6 mine; 127 struct sockaddr_in6 yours; 128 }; 129 130 enum direction { INBOUND, OUTBOUND }; 131 132 #ifdef INET 133 static struct encaptab *encap4_lookup __P((struct mbuf *, int, int, 134 enum direction)); 135 #endif 136 #ifdef INET6 137 static struct encaptab *encap6_lookup __P((struct mbuf *, int, int, 138 enum direction)); 139 #endif 140 static int encap_add __P((struct encaptab *)); 141 static int encap_remove __P((struct encaptab *)); 142 static int encap_afcheck __P((int, const struct sockaddr *, const struct sockaddr *)); 143 #ifdef USE_RADIX 144 static struct radix_node_head *encap_rnh __P((int)); 145 static int mask_matchlen __P((const struct sockaddr *)); 146 #endif 147 #ifndef USE_RADIX 148 static int mask_match __P((const struct encaptab *, const struct sockaddr *, 149 const struct sockaddr *)); 150 #endif 151 static void encap_fillarg __P((struct mbuf *, const struct encaptab *)); 152 153 LIST_HEAD(, encaptab) encaptab = LIST_HEAD_INITIALIZER(&encaptab); 154 155 #ifdef USE_RADIX 156 extern int max_keylen; /* radix.c */ 157 struct radix_node_head *encap_head[2]; /* 0 for AF_INET, 1 for AF_INET6 */ 158 #endif 159 160 void 161 encap_init() 162 { 163 static int initialized = 0; 164 165 if (initialized) 166 return; 167 initialized++; 168 #if 0 169 /* 170 * we cannot use LIST_INIT() here, since drivers may want to call 171 * encap_attach(), on driver attach. encap_init() will be called 172 * on AF_INET{,6} initialization, which happens after driver 173 * initialization - using LIST_INIT() here can nuke encap_attach() 174 * from drivers. 175 */ 176 LIST_INIT(&encaptab); 177 #endif 178 179 #ifdef USE_RADIX 180 /* 181 * initialize radix lookup table. 182 * max_keylen initialization should happen before the call to rn_init(). 183 */ 184 rn_inithead((void *)&encap_head[0], sizeof(struct sockaddr_pack) << 3); 185 if (sizeof(struct pack4) > max_keylen) 186 max_keylen = sizeof(struct pack4); 187 #ifdef INET6 188 rn_inithead((void *)&encap_head[1], sizeof(struct sockaddr_pack) << 3); 189 if (sizeof(struct pack6) > max_keylen) 190 max_keylen = sizeof(struct pack6); 191 #endif 192 #endif 193 } 194 195 #ifdef INET 196 static struct encaptab * 197 encap4_lookup(m, off, proto, dir) 198 struct mbuf *m; 199 int off; 200 int proto; 201 enum direction dir; 202 { 203 struct ip *ip; 204 struct pack4 pack; 205 struct encaptab *ep, *match; 206 int prio, matchprio; 207 #ifdef USE_RADIX 208 struct radix_node_head *rnh = encap_rnh(AF_INET); 209 struct radix_node *rn; 210 #endif 211 212 #ifdef DIAGNOSTIC 213 if (m->m_len < sizeof(*ip)) 214 panic("encap4_lookup"); 215 #endif 216 ip = mtod(m, struct ip *); 217 218 bzero(&pack, sizeof(pack)); 219 pack.p.sp_len = sizeof(pack); 220 pack.mine.sin_family = pack.yours.sin_family = AF_INET; 221 pack.mine.sin_len = pack.yours.sin_len = sizeof(struct sockaddr_in); 222 if (dir == INBOUND) { 223 pack.mine.sin_addr = ip->ip_dst; 224 pack.yours.sin_addr = ip->ip_src; 225 } else { 226 pack.mine.sin_addr = ip->ip_src; 227 pack.yours.sin_addr = ip->ip_dst; 228 } 229 230 match = NULL; 231 matchprio = 0; 232 233 #ifdef USE_RADIX 234 rn = rnh->rnh_matchaddr((caddr_t)&pack, rnh); 235 if (rn && (rn->rn_flags & RNF_ROOT) == 0) { 236 match = (struct encaptab *)rn; 237 matchprio = mask_matchlen(match->srcmask) + 238 mask_matchlen(match->dstmask); 239 } 240 #endif 241 242 for (ep = LIST_FIRST(&encaptab); ep; ep = LIST_NEXT(ep, chain)) { 243 if (ep->af != AF_INET) 244 continue; 245 if (ep->proto >= 0 && ep->proto != proto) 246 continue; 247 if (ep->func) 248 prio = (*ep->func)(m, off, proto, ep->arg); 249 else { 250 #ifdef USE_RADIX 251 continue; 252 #else 253 prio = mask_match(ep, (struct sockaddr *)&pack.mine, 254 (struct sockaddr *)&pack.yours); 255 #endif 256 } 257 258 /* 259 * We prioritize the matches by using bit length of the 260 * matches. mask_match() and user-supplied matching function 261 * should return the bit length of the matches (for example, 262 * if both src/dst are matched for IPv4, 64 should be returned). 263 * 0 or negative return value means "it did not match". 264 * 265 * The question is, since we have two "mask" portion, we 266 * cannot really define total order between entries. 267 * For example, which of these should be preferred? 268 * mask_match() returns 48 (32 + 16) for both of them. 269 * src=3ffe::/16, dst=3ffe:501::/32 270 * src=3ffe:501::/32, dst=3ffe::/16 271 * 272 * We need to loop through all the possible candidates 273 * to get the best match - the search takes O(n) for 274 * n attachments (i.e. interfaces). 275 * 276 * For radix-based lookup, I guess source takes precedence. 277 * See rn_{refines,lexobetter} for the correct answer. 278 */ 279 if (prio <= 0) 280 continue; 281 if (prio > matchprio) { 282 matchprio = prio; 283 match = ep; 284 } 285 } 286 287 return match; 288 #undef s 289 #undef d 290 } 291 292 void 293 encap4_input(struct mbuf *m, ...) 294 { 295 int off, proto; 296 va_list ap; 297 const struct protosw *psw; 298 struct encaptab *match; 299 300 va_start(ap, m); 301 off = va_arg(ap, int); 302 proto = va_arg(ap, int); 303 va_end(ap); 304 305 match = encap4_lookup(m, off, proto, INBOUND); 306 307 if (match) { 308 /* found a match, "match" has the best one */ 309 psw = match->psw; 310 if (psw && psw->pr_input) { 311 encap_fillarg(m, match); 312 (*psw->pr_input)(m, off, proto); 313 } else 314 m_freem(m); 315 return; 316 } 317 318 /* last resort: inject to raw socket */ 319 rip_input(m, off, proto); 320 } 321 #endif 322 323 #ifdef INET6 324 static struct encaptab * 325 encap6_lookup(m, off, proto, dir) 326 struct mbuf *m; 327 int off; 328 int proto; 329 enum direction dir; 330 { 331 struct ip6_hdr *ip6; 332 struct pack6 pack; 333 int prio, matchprio; 334 struct encaptab *ep, *match; 335 #ifdef USE_RADIX 336 struct radix_node_head *rnh = encap_rnh(AF_INET6); 337 struct radix_node *rn; 338 #endif 339 340 #ifdef DIAGNOSTIC 341 if (m->m_len < sizeof(*ip6)) 342 panic("encap6_lookup"); 343 #endif 344 ip6 = mtod(m, struct ip6_hdr *); 345 346 bzero(&pack, sizeof(pack)); 347 pack.p.sp_len = sizeof(pack); 348 pack.mine.sin6_family = pack.yours.sin6_family = AF_INET6; 349 pack.mine.sin6_len = pack.yours.sin6_len = sizeof(struct sockaddr_in6); 350 if (dir == INBOUND) { 351 pack.mine.sin6_addr = ip6->ip6_dst; 352 pack.yours.sin6_addr = ip6->ip6_src; 353 } else { 354 pack.mine.sin6_addr = ip6->ip6_src; 355 pack.yours.sin6_addr = ip6->ip6_dst; 356 } 357 358 match = NULL; 359 matchprio = 0; 360 361 #ifdef USE_RADIX 362 rn = rnh->rnh_matchaddr((caddr_t)&pack, rnh); 363 if (rn && (rn->rn_flags & RNF_ROOT) == 0) { 364 match = (struct encaptab *)rn; 365 matchprio = mask_matchlen(match->srcmask) + 366 mask_matchlen(match->dstmask); 367 } 368 #endif 369 370 for (ep = LIST_FIRST(&encaptab); ep; ep = LIST_NEXT(ep, chain)) { 371 if (ep->af != AF_INET6) 372 continue; 373 if (ep->proto >= 0 && ep->proto != proto) 374 continue; 375 if (ep->func) 376 prio = (*ep->func)(m, off, proto, ep->arg); 377 else { 378 #ifdef USE_RADIX 379 continue; 380 #else 381 prio = mask_match(ep, (struct sockaddr *)&pack.mine, 382 (struct sockaddr *)&pack.yours); 383 #endif 384 } 385 386 /* see encap4_lookup() for issues here */ 387 if (prio <= 0) 388 continue; 389 if (prio > matchprio) { 390 matchprio = prio; 391 match = ep; 392 } 393 } 394 395 return match; 396 #undef s 397 #undef d 398 } 399 400 int 401 encap6_input(mp, offp, proto) 402 struct mbuf **mp; 403 int *offp; 404 int proto; 405 { 406 struct mbuf *m = *mp; 407 const struct ip6protosw *psw; 408 struct encaptab *match; 409 410 match = encap6_lookup(m, *offp, proto, INBOUND); 411 412 if (match) { 413 /* found a match */ 414 psw = (const struct ip6protosw *)match->psw; 415 if (psw && psw->pr_input) { 416 encap_fillarg(m, match); 417 return (*psw->pr_input)(mp, offp, proto); 418 } else { 419 m_freem(m); 420 return IPPROTO_DONE; 421 } 422 } 423 424 /* last resort: inject to raw socket */ 425 return rip6_input(mp, offp, proto); 426 } 427 #endif 428 429 static int 430 encap_add(ep) 431 struct encaptab *ep; 432 { 433 #ifdef USE_RADIX 434 struct radix_node_head *rnh = encap_rnh(ep->af); 435 #endif 436 int error = 0; 437 438 LIST_INSERT_HEAD(&encaptab, ep, chain); 439 #ifdef USE_RADIX 440 if (!ep->func && rnh) { 441 if (!rnh->rnh_addaddr((caddr_t)ep->addrpack, 442 (caddr_t)ep->maskpack, rnh, ep->nodes)) { 443 error = EEXIST; 444 goto fail; 445 } 446 } 447 #endif 448 return error; 449 450 fail: 451 LIST_REMOVE(ep, chain); 452 return error; 453 } 454 455 static int 456 encap_remove(ep) 457 struct encaptab *ep; 458 { 459 #ifdef USE_RADIX 460 struct radix_node_head *rnh = encap_rnh(ep->af); 461 #endif 462 int error = 0; 463 464 LIST_REMOVE(ep, chain); 465 #ifdef USE_RADIX 466 if (!ep->func && rnh) { 467 if (!rnh->rnh_deladdr((caddr_t)ep->addrpack, 468 (caddr_t)ep->maskpack, rnh)) 469 error = ESRCH; 470 } 471 #endif 472 return error; 473 } 474 475 static int 476 encap_afcheck(af, sp, dp) 477 int af; 478 const struct sockaddr *sp; 479 const struct sockaddr *dp; 480 { 481 if (sp && dp) { 482 if (sp->sa_len != dp->sa_len) 483 return EINVAL; 484 if (af != sp->sa_family || af != dp->sa_family) 485 return EINVAL; 486 } else if (!sp && !dp) 487 ; 488 else 489 return EINVAL; 490 491 switch (af) { 492 case AF_INET: 493 if (sp && sp->sa_len != sizeof(struct sockaddr_in)) 494 return EINVAL; 495 if (dp && dp->sa_len != sizeof(struct sockaddr_in)) 496 return EINVAL; 497 break; 498 #ifdef INET6 499 case AF_INET6: 500 if (sp && sp->sa_len != sizeof(struct sockaddr_in6)) 501 return EINVAL; 502 if (dp && dp->sa_len != sizeof(struct sockaddr_in6)) 503 return EINVAL; 504 break; 505 #endif 506 default: 507 return EAFNOSUPPORT; 508 } 509 510 return 0; 511 } 512 513 /* 514 * sp (src ptr) is always my side, and dp (dst ptr) is always remote side. 515 * length of mask (sm and dm) is assumed to be same as sp/dp. 516 * Return value will be necessary as input (cookie) for encap_detach(). 517 */ 518 const struct encaptab * 519 encap_attach(af, proto, sp, sm, dp, dm, psw, arg) 520 int af; 521 int proto; 522 const struct sockaddr *sp, *sm; 523 const struct sockaddr *dp, *dm; 524 const struct protosw *psw; 525 void *arg; 526 { 527 struct encaptab *ep; 528 int error; 529 int s; 530 size_t l; 531 struct pack4 *pack4; 532 #ifdef INET6 533 struct pack6 *pack6; 534 #endif 535 536 s = splsoftnet(); 537 /* sanity check on args */ 538 error = encap_afcheck(af, sp, dp); 539 if (error) 540 goto fail; 541 542 /* check if anyone have already attached with exactly same config */ 543 for (ep = LIST_FIRST(&encaptab); ep; ep = LIST_NEXT(ep, chain)) { 544 if (ep->af != af) 545 continue; 546 if (ep->proto != proto) 547 continue; 548 if (ep->func) 549 continue; 550 #ifdef DIAGNOSTIC 551 if (!ep->src || !ep->dst || !ep->srcmask || !ep->dstmask) 552 panic("null pointers in encaptab"); 553 #endif 554 if (ep->src->sa_len != sp->sa_len || 555 bcmp(ep->src, sp, sp->sa_len) != 0 || 556 bcmp(ep->srcmask, sm, sp->sa_len) != 0) 557 continue; 558 if (ep->dst->sa_len != dp->sa_len || 559 bcmp(ep->dst, dp, dp->sa_len) != 0 || 560 bcmp(ep->dstmask, dm, dp->sa_len) != 0) 561 continue; 562 563 error = EEXIST; 564 goto fail; 565 } 566 567 switch (af) { 568 case AF_INET: 569 l = sizeof(*pack4); 570 break; 571 #ifdef INET6 572 case AF_INET6: 573 l = sizeof(*pack6); 574 break; 575 #endif 576 default: 577 goto fail; 578 } 579 580 #ifdef DIAGNOSTIC 581 /* if l exceeds the value sa_len can possibly express, it's wrong. */ 582 if (l > (1 << (8 * sizeof(ep->addrpack->sa_len)))) { 583 error = EINVAL; 584 goto fail; 585 } 586 #endif 587 588 ep = malloc(sizeof(*ep), M_NETADDR, M_NOWAIT); /* M_NETADDR ok? */ 589 if (ep == NULL) { 590 error = ENOBUFS; 591 goto fail; 592 } 593 bzero(ep, sizeof(*ep)); 594 ep->addrpack = malloc(l, M_NETADDR, M_NOWAIT); 595 if (ep->addrpack == NULL) { 596 error = ENOBUFS; 597 goto gc; 598 } 599 ep->maskpack = malloc(l, M_NETADDR, M_NOWAIT); 600 if (ep->maskpack == NULL) { 601 error = ENOBUFS; 602 goto gc; 603 } 604 605 ep->af = af; 606 ep->proto = proto; 607 ep->addrpack->sa_len = l & 0xff; 608 ep->maskpack->sa_len = l & 0xff; 609 switch (af) { 610 case AF_INET: 611 pack4 = (struct pack4 *)ep->addrpack; 612 ep->src = (struct sockaddr *)&pack4->mine; 613 ep->dst = (struct sockaddr *)&pack4->yours; 614 pack4 = (struct pack4 *)ep->maskpack; 615 ep->srcmask = (struct sockaddr *)&pack4->mine; 616 ep->dstmask = (struct sockaddr *)&pack4->yours; 617 break; 618 #ifdef INET6 619 case AF_INET6: 620 pack6 = (struct pack6 *)ep->addrpack; 621 ep->src = (struct sockaddr *)&pack6->mine; 622 ep->dst = (struct sockaddr *)&pack6->yours; 623 pack6 = (struct pack6 *)ep->maskpack; 624 ep->srcmask = (struct sockaddr *)&pack6->mine; 625 ep->dstmask = (struct sockaddr *)&pack6->yours; 626 break; 627 #endif 628 } 629 630 bcopy(sp, ep->src, sp->sa_len); 631 bcopy(sm, ep->srcmask, sp->sa_len); 632 bcopy(dp, ep->dst, dp->sa_len); 633 bcopy(dm, ep->dstmask, dp->sa_len); 634 ep->psw = psw; 635 ep->arg = arg; 636 637 error = encap_add(ep); 638 if (error) 639 goto gc; 640 641 error = 0; 642 splx(s); 643 return ep; 644 645 gc: 646 if (ep->addrpack) 647 free(ep->addrpack, M_NETADDR); 648 if (ep->maskpack) 649 free(ep->maskpack, M_NETADDR); 650 if (ep) 651 free(ep, M_NETADDR); 652 fail: 653 splx(s); 654 return NULL; 655 } 656 657 const struct encaptab * 658 encap_attach_func(af, proto, func, psw, arg) 659 int af; 660 int proto; 661 int (*func) __P((const struct mbuf *, int, int, void *)); 662 const struct protosw *psw; 663 void *arg; 664 { 665 struct encaptab *ep; 666 int error; 667 int s; 668 669 s = splsoftnet(); 670 /* sanity check on args */ 671 if (!func) { 672 error = EINVAL; 673 goto fail; 674 } 675 676 error = encap_afcheck(af, NULL, NULL); 677 if (error) 678 goto fail; 679 680 ep = malloc(sizeof(*ep), M_NETADDR, M_NOWAIT); /*XXX*/ 681 if (ep == NULL) { 682 error = ENOBUFS; 683 goto fail; 684 } 685 bzero(ep, sizeof(*ep)); 686 687 ep->af = af; 688 ep->proto = proto; 689 ep->func = func; 690 ep->psw = psw; 691 ep->arg = arg; 692 693 error = encap_add(ep); 694 if (error) 695 goto fail; 696 697 error = 0; 698 splx(s); 699 return ep; 700 701 fail: 702 splx(s); 703 return NULL; 704 } 705 706 /* XXX encap4_ctlinput() is necessary if we set DF=1 on outer IPv4 header */ 707 708 #ifdef INET6 709 void 710 encap6_ctlinput(cmd, sa, d0) 711 int cmd; 712 struct sockaddr *sa; 713 void *d0; 714 { 715 void *d = d0; 716 struct ip6_hdr *ip6; 717 struct mbuf *m; 718 int off; 719 struct ip6ctlparam *ip6cp = NULL; 720 int nxt; 721 struct encaptab *ep; 722 const struct ip6protosw *psw; 723 724 if (sa->sa_family != AF_INET6 || 725 sa->sa_len != sizeof(struct sockaddr_in6)) 726 return; 727 728 if ((unsigned)cmd >= PRC_NCMDS) 729 return; 730 if (cmd == PRC_HOSTDEAD) 731 d = NULL; 732 else if (cmd == PRC_MSGSIZE) 733 ; /* special code is present, see below */ 734 else if (inet6ctlerrmap[cmd] == 0) 735 return; 736 737 /* if the parameter is from icmp6, decode it. */ 738 if (d != NULL) { 739 ip6cp = (struct ip6ctlparam *)d; 740 m = ip6cp->ip6c_m; 741 ip6 = ip6cp->ip6c_ip6; 742 off = ip6cp->ip6c_off; 743 nxt = ip6cp->ip6c_nxt; 744 745 if (ip6 && cmd == PRC_MSGSIZE) { 746 int valid = 0; 747 struct encaptab *match; 748 749 /* 750 * Check to see if we have a valid encap configuration. 751 */ 752 match = encap6_lookup(m, off, nxt, OUTBOUND); 753 if (match) 754 valid++; 755 756 /* 757 * Depending on the value of "valid" and routing table 758 * size (mtudisc_{hi,lo}wat), we will: 759 * - recalcurate the new MTU and create the 760 * corresponding routing entry, or 761 * - ignore the MTU change notification. 762 */ 763 icmp6_mtudisc_update((struct ip6ctlparam *)d, valid); 764 } 765 } else { 766 m = NULL; 767 ip6 = NULL; 768 nxt = -1; 769 } 770 771 /* inform all listeners */ 772 for (ep = LIST_FIRST(&encaptab); ep; ep = LIST_NEXT(ep, chain)) { 773 if (ep->af != AF_INET6) 774 continue; 775 if (ep->proto >= 0 && ep->proto != nxt) 776 continue; 777 778 /* should optimize by looking at address pairs */ 779 780 /* XXX need to pass ep->arg or ep itself to listeners */ 781 psw = (const struct ip6protosw *)ep->psw; 782 if (psw && psw->pr_ctlinput) 783 (*psw->pr_ctlinput)(cmd, sa, d); 784 } 785 786 rip6_ctlinput(cmd, sa, d0); 787 } 788 #endif 789 790 int 791 encap_detach(cookie) 792 const struct encaptab *cookie; 793 { 794 const struct encaptab *ep = cookie; 795 struct encaptab *p; 796 int error; 797 798 for (p = LIST_FIRST(&encaptab); p; p = LIST_NEXT(p, chain)) { 799 if (p == ep) { 800 error = encap_remove(p); 801 if (error) 802 return error; 803 if (!ep->func) { 804 free(p->addrpack, M_NETADDR); 805 free(p->maskpack, M_NETADDR); 806 } 807 free(p, M_NETADDR); /*XXX*/ 808 return 0; 809 } 810 } 811 812 return ENOENT; 813 } 814 815 #ifdef USE_RADIX 816 static struct radix_node_head * 817 encap_rnh(af) 818 int af; 819 { 820 821 switch (af) { 822 case AF_INET: 823 return encap_head[0]; 824 #ifdef INET6 825 case AF_INET6: 826 return encap_head[1]; 827 #endif 828 default: 829 return NULL; 830 } 831 } 832 833 static int 834 mask_matchlen(sa) 835 const struct sockaddr *sa; 836 { 837 const char *p, *ep; 838 int l; 839 840 p = (const char *)sa; 841 ep = p + sa->sa_len; 842 p += 2; /* sa_len + sa_family */ 843 844 l = 0; 845 while (p < ep) { 846 l += (*p ? 8 : 0); /* estimate */ 847 p++; 848 } 849 return l; 850 } 851 #endif 852 853 #ifndef USE_RADIX 854 static int 855 mask_match(ep, sp, dp) 856 const struct encaptab *ep; 857 const struct sockaddr *sp; 858 const struct sockaddr *dp; 859 { 860 struct sockaddr_storage s; 861 struct sockaddr_storage d; 862 int i; 863 const u_int8_t *p, *q; 864 u_int8_t *r; 865 int matchlen; 866 867 #ifdef DIAGNOSTIC 868 if (ep->func) 869 panic("wrong encaptab passed to mask_match"); 870 #endif 871 if (sp->sa_len > sizeof(s) || dp->sa_len > sizeof(d)) 872 return 0; 873 if (sp->sa_family != ep->af || dp->sa_family != ep->af) 874 return 0; 875 if (sp->sa_len != ep->src->sa_len || dp->sa_len != ep->dst->sa_len) 876 return 0; 877 878 matchlen = 0; 879 880 p = (const u_int8_t *)sp; 881 q = (const u_int8_t *)ep->srcmask; 882 r = (u_int8_t *)&s; 883 for (i = 0 ; i < sp->sa_len; i++) { 884 r[i] = p[i] & q[i]; 885 /* XXX estimate */ 886 matchlen += (q[i] ? 8 : 0); 887 } 888 889 p = (const u_int8_t *)dp; 890 q = (const u_int8_t *)ep->dstmask; 891 r = (u_int8_t *)&d; 892 for (i = 0 ; i < dp->sa_len; i++) { 893 r[i] = p[i] & q[i]; 894 /* XXX rough estimate */ 895 matchlen += (q[i] ? 8 : 0); 896 } 897 898 /* need to overwrite len/family portion as we don't compare them */ 899 s.ss_len = sp->sa_len; 900 s.ss_family = sp->sa_family; 901 d.ss_len = dp->sa_len; 902 d.ss_family = dp->sa_family; 903 904 if (bcmp(&s, ep->src, ep->src->sa_len) == 0 && 905 bcmp(&d, ep->dst, ep->dst->sa_len) == 0) { 906 return matchlen; 907 } else 908 return 0; 909 } 910 #endif 911 912 static void 913 encap_fillarg(m, ep) 914 struct mbuf *m; 915 const struct encaptab *ep; 916 { 917 struct m_tag *mtag; 918 919 mtag = m_tag_get(PACKET_TAG_ENCAP, sizeof(void *), M_NOWAIT); 920 if (mtag) { 921 *(void **)(mtag + 1) = ep->arg; 922 m_tag_prepend(m, mtag); 923 } 924 } 925 926 void * 927 encap_getarg(m) 928 struct mbuf *m; 929 { 930 void *p; 931 struct m_tag *mtag; 932 933 p = NULL; 934 mtag = m_tag_find(m, PACKET_TAG_ENCAP, NULL); 935 if (mtag != NULL) { 936 p = *(void **)(mtag + 1); 937 m_tag_delete(m, mtag); 938 } 939 return p; 940 } 941