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