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