Annotation of src/sys/netinet6/in6_gif.c, Revision 1.95
1.95 ! knakahar 1: /* $NetBSD: in6_gif.c,v 1.94 2019/09/19 06:07:25 knakahara Exp $ */
1.21 itojun 2: /* $KAME: in6_gif.c,v 1.62 2001/07/29 04:27:25 itojun Exp $ */
1.3 thorpej 3:
1.2 itojun 4: /*
5: * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6: * All rights reserved.
1.14 itojun 7: *
1.2 itojun 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.
1.14 itojun 19: *
1.2 itojun 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: */
1.23 lukem 32:
33: #include <sys/cdefs.h>
1.95 ! knakahar 34: __KERNEL_RCSID(0, "$NetBSD: in6_gif.c,v 1.94 2019/09/19 06:07:25 knakahara Exp $");
1.2 itojun 35:
1.62 pooka 36: #ifdef _KERNEL_OPT
1.2 itojun 37: #include "opt_inet.h"
1.62 pooka 38: #endif
1.2 itojun 39:
40: #include <sys/param.h>
41: #include <sys/systm.h>
42: #include <sys/socket.h>
43: #include <sys/sockio.h>
44: #include <sys/mbuf.h>
45: #include <sys/errno.h>
46: #include <sys/ioctl.h>
1.15 itojun 47: #include <sys/queue.h>
48: #include <sys/syslog.h>
1.43 mlelstv 49: #include <sys/kernel.h>
1.14 itojun 50:
1.2 itojun 51: #include <net/if.h>
52: #include <net/route.h>
53:
54: #include <netinet/in.h>
55: #include <netinet/in_systm.h>
56: #ifdef INET
57: #include <netinet/ip.h>
58: #endif
1.14 itojun 59: #include <netinet/ip_encap.h>
1.11 itojun 60: #ifdef INET6
61: #include <netinet/ip6.h>
1.2 itojun 62: #include <netinet6/ip6_var.h>
1.55 thorpej 63: #include <netinet6/ip6_private.h>
1.2 itojun 64: #include <netinet6/in6_gif.h>
1.14 itojun 65: #include <netinet6/in6_var.h>
1.68 riastrad 66: #endif
1.71 knakahar 67: #include <netinet6/ip6protosw.h> /* for struct ip6ctlparam */
1.2 itojun 68: #include <netinet/ip_ecn.h>
69:
70: #include <net/if_gif.h>
71:
1.88 knakahar 72: static int gif_validate6(const struct ip6_hdr *, struct gif_variant *,
1.58 dsl 73: struct ifnet *);
1.26 itojun 74:
75: int ip6_gif_hlim = GIF_HLIM;
1.95 ! knakahar 76: int ip6_gif_pmtu = 0;
1.21 itojun 77:
1.71 knakahar 78: static const struct encapsw in6_gif_encapsw;
1.27 itojun 79:
1.52 christos 80: /*
81: * family - family of the packet to be encapsulate.
82: */
83:
1.88 knakahar 84: static int
85: in6_gif_output(struct gif_variant *var, int family, struct mbuf *m)
1.2 itojun 86: {
1.53 dyoung 87: struct rtentry *rt;
1.88 knakahar 88: struct gif_softc *sc;
89: struct sockaddr_in6 *sin6_src;
90: struct sockaddr_in6 *sin6_dst;
91: struct ifnet *ifp;
1.2 itojun 92: struct ip6_hdr *ip6;
1.94 knakahar 93: struct route *ro_pc;
94: kmutex_t *lock_pc;
1.24 itojun 95: int proto, error;
1.2 itojun 96: u_int8_t itos, otos;
97:
1.88 knakahar 98: KASSERT(gif_heldref_variant(var));
99:
100: sin6_src = satosin6(var->gv_psrc);
101: sin6_dst = satosin6(var->gv_pdst);
102: ifp = &var->gv_softc->gif_if;
103:
1.2 itojun 104: if (sin6_src == NULL || sin6_dst == NULL ||
105: sin6_src->sin6_family != AF_INET6 ||
106: sin6_dst->sin6_family != AF_INET6) {
107: m_freem(m);
108: return EAFNOSUPPORT;
109: }
110:
111: switch (family) {
112: #ifdef INET
113: case AF_INET:
114: {
115: struct ip *ip;
116:
117: proto = IPPROTO_IPV4;
118: if (m->m_len < sizeof(*ip)) {
119: m = m_pullup(m, sizeof(*ip));
120: if (!m)
121: return ENOBUFS;
122: }
123: ip = mtod(m, struct ip *);
124: itos = ip->ip_tos;
125: break;
126: }
127: #endif
128: #ifdef INET6
129: case AF_INET6:
130: {
131: proto = IPPROTO_IPV6;
132: if (m->m_len < sizeof(*ip6)) {
133: m = m_pullup(m, sizeof(*ip6));
134: if (!m)
135: return ENOBUFS;
136: }
137: ip6 = mtod(m, struct ip6_hdr *);
138: itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
139: break;
140: }
1.18 itojun 141: #endif
1.2 itojun 142: default:
1.12 itojun 143: #ifdef DEBUG
1.2 itojun 144: printf("in6_gif_output: warning: unknown family %d passed\n",
145: family);
146: #endif
147: m_freem(m);
148: return EAFNOSUPPORT;
149: }
1.29 itojun 150:
1.2 itojun 151: /* prepend new IP header */
152: M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT);
153: if (m && m->m_len < sizeof(struct ip6_hdr))
154: m = m_pullup(m, sizeof(struct ip6_hdr));
1.21 itojun 155: if (m == NULL)
1.2 itojun 156: return ENOBUFS;
157:
158: ip6 = mtod(m, struct ip6_hdr *);
159: ip6->ip6_flow = 0;
1.9 itojun 160: ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
161: ip6->ip6_vfc |= IPV6_VERSION;
1.36 itojun 162: #if 0 /* ip6->ip6_plen will be filled by ip6_output */
163: ip6->ip6_plen = htons((u_int16_t)m->m_pkthdr.len);
164: #endif
1.2 itojun 165: ip6->ip6_nxt = proto;
166: ip6->ip6_hlim = ip6_gif_hlim;
167: ip6->ip6_src = sin6_src->sin6_addr;
1.20 itojun 168: /* bidirectional configured tunnel mode */
169: if (!IN6_IS_ADDR_UNSPECIFIED(&sin6_dst->sin6_addr))
170: ip6->ip6_dst = sin6_dst->sin6_addr;
171: else {
172: m_freem(m);
173: return ENETUNREACH;
1.2 itojun 174: }
1.19 itojun 175: if (ifp->if_flags & IFF_LINK1)
1.2 itojun 176: ip_ecn_ingress(ECN_ALLOWED, &otos, &itos);
1.19 itojun 177: else
178: ip_ecn_ingress(ECN_NOCARE, &otos, &itos);
179: ip6->ip6_flow &= ~ntohl(0xff00000);
180: ip6->ip6_flow |= htonl((u_int32_t)otos << 20);
1.2 itojun 181:
1.88 knakahar 182: sc = ifp->if_softc;
1.94 knakahar 183: if_tunnel_get_ro(sc->gif_ro_percpu, &ro_pc, &lock_pc);
184: rt = rtcache_lookup(ro_pc, var->gv_pdst);
1.80 ozaki-r 185: if (rt == NULL) {
1.94 knakahar 186: if_tunnel_put_ro(sc->gif_ro_percpu, lock_pc);
1.51 dyoung 187: m_freem(m);
188: return ENETUNREACH;
1.47 joerg 189: }
1.14 itojun 190:
1.47 joerg 191: /* If the route constitutes infinite encapsulation, punt. */
1.53 dyoung 192: if (rt->rt_ifp == ifp) {
1.94 knakahar 193: rtcache_unref(rt, ro_pc);
194: rtcache_free(ro_pc);
195: if_tunnel_put_ro(sc->gif_ro_percpu, lock_pc);
1.47 joerg 196: m_freem(m);
197: return ENETUNREACH; /* XXX */
1.2 itojun 198: }
1.94 knakahar 199: rtcache_unref(rt, ro_pc);
1.29 itojun 200:
1.14 itojun 201: #ifdef IPV6_MINMTU
1.95 ! knakahar 202: int flags;
! 203:
1.14 itojun 204: /*
1.95 ! knakahar 205: * - GIF_PMTU_MINMTU
! 206: * Force fragmentation to minimum MTU to avoid path MTU discovery
! 207: * - GIF_PMTU_OUTERMTU
! 208: * Trust outer MTU is large enough to send all packets
! 209: *
! 210: * It is too painful to ask for resend of inner packet, to achieve
1.14 itojun 211: * path MTU discovery for encapsulated packets.
1.95 ! knakahar 212: *
! 213: * See RFC4459.
1.14 itojun 214: */
1.95 ! knakahar 215: if (sc->gif_pmtu == GIF_PMTU_SYSDEFAULT) {
! 216: switch (ip6_gif_pmtu) {
! 217: case GIF_PMTU_MINMTU:
! 218: flags = IPV6_MINMTU;
! 219: break;
! 220: case GIF_PMTU_OUTERMTU:
! 221: flags = 0;
! 222: break;
! 223: default:
! 224: #ifdef DEBUG
! 225: log(LOG_DEBUG, "%s: ignore unexpected ip6_gif_pmtu %d\n",
! 226: __func__, ip6_gif_pmtu);
! 227: #endif
! 228: flags = IPV6_MINMTU;
! 229: break;
! 230: }
! 231: } else {
! 232: switch (sc->gif_pmtu) {
! 233: case GIF_PMTU_MINMTU:
! 234: flags = IPV6_MINMTU;
! 235: break;
! 236: case GIF_PMTU_OUTERMTU:
! 237: flags = 0;
! 238: break;
! 239: default:
! 240: #ifdef DEBUG
! 241: log(LOG_DEBUG, "%s: ignore unexpected gif_pmtu of %s %d\n",
! 242: __func__, ifp->if_xname, sc->gif_pmtu);
! 243: #endif
! 244: flags = IPV6_MINMTU;
! 245: break;
! 246: }
! 247: }
! 248:
! 249: error = ip6_output(m, 0, ro_pc, flags, NULL, NULL, NULL);
1.14 itojun 250: #else
1.94 knakahar 251: error = ip6_output(m, 0, ro_pc, 0, NULL, NULL, NULL);
1.14 itojun 252: #endif
1.94 knakahar 253: if_tunnel_put_ro(sc->gif_ro_percpu, lock_pc);
1.30 itojun 254: return (error);
1.2 itojun 255: }
256:
1.57 dyoung 257: int
1.87 knakahar 258: in6_gif_input(struct mbuf **mp, int *offp, int proto, void *eparg)
1.2 itojun 259: {
260: struct mbuf *m = *mp;
1.88 knakahar 261: struct gif_softc *sc = eparg;
262: struct ifnet *gifp;
1.2 itojun 263: struct ip6_hdr *ip6;
264: int af = 0;
265: u_int32_t otos;
266:
1.88 knakahar 267: KASSERT(sc != NULL);
1.87 knakahar 268:
1.2 itojun 269: ip6 = mtod(m, struct ip6_hdr *);
270:
1.88 knakahar 271: gifp = &sc->gif_if;
1.89 knakahar 272: if ((gifp->if_flags & IFF_UP) == 0) {
1.2 itojun 273: m_freem(m);
1.55 thorpej 274: IP6_STATINC(IP6_STAT_NOGIF);
1.2 itojun 275: return IPPROTO_DONE;
276: }
1.32 itojun 277: #ifndef GIF_ENCAPCHECK
1.88 knakahar 278: struct psref psref_var;
279: struct gif_variant *var = gif_getref_variant(sc, &psref_var);
1.63 knakahar 280: /* other CPU do delete_tunnel */
1.88 knakahar 281: if (var->gv_psrc == NULL || var->gv_pdst == NULL) {
282: gif_putref_variant(var, &psref_var);
1.63 knakahar 283: m_freem(m);
284: IP6_STATINC(IP6_STAT_NOGIF);
285: return IPPROTO_DONE;
286: }
287:
1.74 ozaki-r 288: struct psref psref;
289: struct ifnet *rcvif = m_get_rcvif_psref(m, &psref);
1.88 knakahar 290: if (rcvif == NULL || !gif_validate6(ip6, var, rcvif)) {
1.74 ozaki-r 291: m_put_rcvif_psref(rcvif, &psref);
1.88 knakahar 292: gif_putref_variant(var, &psref_var);
1.21 itojun 293: m_freem(m);
1.55 thorpej 294: IP6_STATINC(IP6_STAT_NOGIF);
1.21 itojun 295: return IPPROTO_DONE;
296: }
1.74 ozaki-r 297: m_put_rcvif_psref(rcvif, &psref);
1.88 knakahar 298: gif_putref_variant(var, &psref_var);
1.21 itojun 299: #endif
1.14 itojun 300:
1.2 itojun 301: otos = ip6->ip6_flow;
302: m_adj(m, *offp);
303:
304: switch (proto) {
305: #ifdef INET
306: case IPPROTO_IPV4:
307: {
308: struct ip *ip;
309: u_int8_t otos8;
310: af = AF_INET;
311: otos8 = (ntohl(otos) >> 20) & 0xff;
312: if (m->m_len < sizeof(*ip)) {
313: m = m_pullup(m, sizeof(*ip));
314: if (!m)
315: return IPPROTO_DONE;
316: }
317: ip = mtod(m, struct ip *);
318: if (gifp->if_flags & IFF_LINK1)
319: ip_ecn_egress(ECN_ALLOWED, &otos8, &ip->ip_tos);
1.19 itojun 320: else
321: ip_ecn_egress(ECN_NOCARE, &otos8, &ip->ip_tos);
1.2 itojun 322: break;
323: }
324: #endif /* INET */
325: #ifdef INET6
326: case IPPROTO_IPV6:
327: {
1.40 christos 328: struct ip6_hdr *ip6x;
1.2 itojun 329: af = AF_INET6;
1.40 christos 330: if (m->m_len < sizeof(*ip6x)) {
331: m = m_pullup(m, sizeof(*ip6x));
1.2 itojun 332: if (!m)
333: return IPPROTO_DONE;
334: }
1.40 christos 335: ip6x = mtod(m, struct ip6_hdr *);
1.2 itojun 336: if (gifp->if_flags & IFF_LINK1)
1.40 christos 337: ip6_ecn_egress(ECN_ALLOWED, &otos, &ip6x->ip6_flow);
1.19 itojun 338: else
1.40 christos 339: ip6_ecn_egress(ECN_NOCARE, &otos, &ip6x->ip6_flow);
1.2 itojun 340: break;
341: }
1.17 itojun 342: #endif
1.2 itojun 343: default:
1.55 thorpej 344: IP6_STATINC(IP6_STAT_NOGIF);
1.2 itojun 345: m_freem(m);
346: return IPPROTO_DONE;
347: }
1.29 itojun 348:
1.2 itojun 349: gif_input(m, af, gifp);
350: return IPPROTO_DONE;
1.14 itojun 351: }
352:
353: /*
1.21 itojun 354: * validate outer address.
1.14 itojun 355: */
1.21 itojun 356: static int
1.88 knakahar 357: gif_validate6(const struct ip6_hdr *ip6, struct gif_variant *var,
1.52 christos 358: struct ifnet *ifp)
1.14 itojun 359: {
1.49 dyoung 360: const struct sockaddr_in6 *src, *dst;
1.90 knakahar 361: int ret;
1.14 itojun 362:
1.88 knakahar 363: src = satosin6(var->gv_psrc);
364: dst = satosin6(var->gv_pdst);
1.14 itojun 365:
1.90 knakahar 366: ret = in6_tunnel_validate(ip6, &src->sin6_addr, &dst->sin6_addr);
367: if (ret == 0)
1.14 itojun 368: return 0;
369:
370: /* ingress filters on outer source */
1.88 knakahar 371: if ((var->gv_softc->gif_if.if_flags & IFF_LINK2) == 0 && ifp) {
1.57 dyoung 372: union {
373: struct sockaddr sa;
374: struct sockaddr_in6 sin6;
375: } u;
1.14 itojun 376: struct rtentry *rt;
377:
378: /* XXX scopeid */
1.57 dyoung 379: sockaddr_in6_init(&u.sin6, &ip6->ip6_src, 0, 0, 0);
380: rt = rtalloc1(&u.sa, 0);
381: if (rt == NULL || rt->rt_ifp != ifp) {
1.15 itojun 382: #if 0
1.84 ryo 383: char ip6buf[INET6_ADDRSTRLEN];
1.15 itojun 384: log(LOG_WARNING, "%s: packet from %s dropped "
1.88 knakahar 385: "due to ingress filter\n",
386: if_name(&var->gv_softc->gif_if),
1.85 christos 387: IN6_PRINT(ip6buf, &u.sin6.sin6_addr));
1.15 itojun 388: #endif
1.57 dyoung 389: if (rt != NULL)
1.81 ozaki-r 390: rt_unref(rt);
1.14 itojun 391: return 0;
392: }
1.81 ozaki-r 393: rt_unref(rt);
1.14 itojun 394: }
395:
1.90 knakahar 396: return ret;
1.21 itojun 397: }
398:
1.32 itojun 399: #ifdef GIF_ENCAPCHECK
1.21 itojun 400: /*
401: * we know that we are in IFF_UP, outer address available, and outer family
402: * matched the physical addr family. see gif_encapcheck().
403: */
404: int
1.88 knakahar 405: gif_encapcheck6(struct mbuf *m, int off, int proto, struct gif_variant *var)
1.21 itojun 406: {
407: struct ip6_hdr ip6;
1.78 ozaki-r 408: struct ifnet *ifp = NULL;
409: int r;
410: struct psref psref;
1.21 itojun 411:
1.50 christos 412: m_copydata(m, 0, sizeof(ip6), (void *)&ip6);
1.78 ozaki-r 413: if ((m->m_flags & M_PKTHDR) != 0)
414: ifp = m_get_rcvif_psref(m, &psref);
415:
1.88 knakahar 416: r = gif_validate6(&ip6, var, ifp);
1.21 itojun 417:
1.78 ozaki-r 418: m_put_rcvif_psref(ifp, &psref);
419: return r;
1.21 itojun 420: }
1.32 itojun 421: #endif
1.21 itojun 422:
423: int
1.88 knakahar 424: in6_gif_attach(struct gif_variant *var)
1.21 itojun 425: {
1.32 itojun 426: #ifndef GIF_ENCAPCHECK
1.21 itojun 427: struct sockaddr_in6 mask6;
428:
1.57 dyoung 429: memset(&mask6, 0, sizeof(mask6));
1.21 itojun 430: mask6.sin6_len = sizeof(struct sockaddr_in6);
1.28 itojun 431: mask6.sin6_addr.s6_addr32[0] = mask6.sin6_addr.s6_addr32[1] =
1.21 itojun 432: mask6.sin6_addr.s6_addr32[2] = mask6.sin6_addr.s6_addr32[3] = ~0;
433:
1.88 knakahar 434: if (!var->gv_psrc || !var->gv_pdst)
1.21 itojun 435: return EINVAL;
1.88 knakahar 436: var->gv_encap_cookie6 = encap_attach(AF_INET6, -1, var->gv_psrc,
437: sin6tosa(&mask6), var->gv_pdst, sin6tosa(&mask6),
438: (const void *)&in6_gif_encapsw, var->gv_softc);
1.21 itojun 439: #else
1.88 knakahar 440: var->gv_encap_cookie6 = encap_attach_func(AF_INET6, -1, gif_encapcheck,
441: &in6_gif_encapsw, var->gv_softc);
1.21 itojun 442: #endif
1.88 knakahar 443: if (var->gv_encap_cookie6 == NULL)
1.21 itojun 444: return EEXIST;
1.88 knakahar 445:
446: var->gv_output = in6_gif_output;
1.21 itojun 447: return 0;
448: }
449:
450: int
1.88 knakahar 451: in6_gif_detach(struct gif_variant *var)
1.21 itojun 452: {
453: int error;
1.88 knakahar 454: struct gif_softc *sc = var->gv_softc;
1.21 itojun 455:
1.88 knakahar 456: error = encap_detach(var->gv_encap_cookie6);
457: if (error == 0)
458: var->gv_encap_cookie6 = NULL;
1.77 knakahar 459:
1.94 knakahar 460: if_tunnel_ro_percpu_rtcache_free(sc->gif_ro_percpu);
1.77 knakahar 461:
462: return error;
463: }
464:
1.56 ad 465: void *
1.72 knakahar 466: in6_gif_ctlinput(int cmd, const struct sockaddr *sa, void *d, void *eparg)
1.27 itojun 467: {
1.73 knakahar 468: struct gif_softc *sc = eparg;
1.88 knakahar 469: struct gif_variant *var;
1.27 itojun 470: struct ip6ctlparam *ip6cp = NULL;
471: struct ip6_hdr *ip6;
1.49 dyoung 472: const struct sockaddr_in6 *dst6;
1.94 knakahar 473: struct route *ro_pc;
474: kmutex_t *lock_pc;
1.88 knakahar 475: struct psref psref;
1.27 itojun 476:
477: if (sa->sa_family != AF_INET6 ||
478: sa->sa_len != sizeof(struct sockaddr_in6))
1.56 ad 479: return NULL;
1.27 itojun 480:
481: if ((unsigned)cmd >= PRC_NCMDS)
1.56 ad 482: return NULL;
1.27 itojun 483: if (cmd == PRC_HOSTDEAD)
484: d = NULL;
485: else if (inet6ctlerrmap[cmd] == 0)
1.56 ad 486: return NULL;
1.27 itojun 487:
488: /* if the parameter is from icmp6, decode it. */
489: if (d != NULL) {
490: ip6cp = (struct ip6ctlparam *)d;
491: ip6 = ip6cp->ip6c_ip6;
492: } else {
493: ip6 = NULL;
494: }
495:
496: if (!ip6)
1.56 ad 497: return NULL;
1.27 itojun 498:
1.91 knakahar 499: var = gif_getref_variant(sc, &psref);
500: if (var->gv_psrc == NULL || var->gv_pdst == NULL) {
501: gif_putref_variant(var, &psref);
1.72 knakahar 502: return NULL;
1.91 knakahar 503: }
1.88 knakahar 504: if (var->gv_psrc->sa_family != AF_INET6) {
505: gif_putref_variant(var, &psref);
1.72 knakahar 506: return NULL;
1.88 knakahar 507: }
508: gif_putref_variant(var, &psref);
1.72 knakahar 509:
1.94 knakahar 510: if_tunnel_get_ro(sc->gif_ro_percpu, &ro_pc, &lock_pc);
511: dst6 = satocsin6(rtcache_getdst(ro_pc));
1.72 knakahar 512: /* XXX scope */
513: if (dst6 == NULL)
514: ;
515: else if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &dst6->sin6_addr))
1.94 knakahar 516: rtcache_free(ro_pc);
1.56 ad 517:
1.94 knakahar 518: if_tunnel_put_ro(sc->gif_ro_percpu, lock_pc);
1.56 ad 519: return NULL;
1.2 itojun 520: }
1.56 ad 521:
1.72 knakahar 522: ENCAP_PR_WRAP_CTLINPUT(in6_gif_ctlinput)
1.56 ad 523: #define in6_gif_ctlinput in6_gif_ctlinput_wrapper
1.68 riastrad 524:
1.71 knakahar 525: static const struct encapsw in6_gif_encapsw = {
526: .encapsw6 = {
527: .pr_input = in6_gif_input,
528: .pr_ctlinput = in6_gif_ctlinput,
529: }
1.56 ad 530: };
CVSweb <webmaster@jp.NetBSD.org>