1/* $KAME: ip_encap.c,v 1.41 2001/03/15 08:35:08 itojun Exp $ */ 2 3/*- 4 * SPDX-License-Identifier: BSD-3-Clause 5 * 6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 7 * Copyright (c) 2018 Andrey V. Elsukov <ae@FreeBSD.org> 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the project nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34/* 35 * My grandfather said that there's a devil inside tunnelling technology... 36 * 37 * We have surprisingly many protocols that want packets with IP protocol 38 * #4 or #41. Here's a list of protocols that want protocol #41: 39 * RFC1933 configured tunnel 40 * RFC1933 automatic tunnel 41 * RFC2401 IPsec tunnel 42 * RFC2473 IPv6 generic packet tunnelling 43 * RFC2529 6over4 tunnel 44 * mobile-ip6 (uses RFC2473) 45 * RFC3056 6to4 tunnel 46 * isatap tunnel 47 * Here's a list of protocol that want protocol #4: 48 * RFC1853 IPv4-in-IPv4 tunnelling 49 * RFC2003 IPv4 encapsulation within IPv4 50 * RFC2344 reverse tunnelling for mobile-ip4 51 * RFC2401 IPsec tunnel 52 * Well, what can I say. They impose different en/decapsulation mechanism 53 * from each other, so they need separate protocol handler. The only one 54 * we can easily determine by protocol # is IPsec, which always has 55 * AH/ESP/IPComp header right after outer IP header. 56 * 57 * So, clearly good old protosw does not work for protocol #4 and #41. 58 * The code will let you match protocol via src/dst address pair. 59 */ 60 61#include <sys/cdefs.h> 62__FBSDID("$FreeBSD$"); 63 64#include "opt_inet.h" 65#include "opt_inet6.h" 66 67#include <sys/param.h> 68#include <sys/systm.h> 69#include <sys/eventhandler.h> 70#include <sys/kernel.h> 71#include <sys/lock.h> 72#include <sys/malloc.h> 73#include <sys/mutex.h> 74#include <sys/mbuf.h> 75#include <sys/errno.h> 76#include <sys/socket.h> 77 78#include <net/if.h> 79#include <net/if_var.h> 80 81#include <netinet/in.h> 82#include <netinet/ip_var.h> 83#include <netinet/ip_encap.h> 84 85#ifdef INET6 86#include <netinet6/ip6_var.h> 87#endif 88 89static MALLOC_DEFINE(M_NETADDR, "encap_export_host", 90 "Export host address structure"); 91 92struct encaptab { 93 CK_LIST_ENTRY(encaptab) chain; 94 int proto; 95 int min_length; 96 int exact_match; 97 void *arg; 98 99 encap_lookup_t lookup; 100 encap_check_t check; 101 encap_input_t input; 102}; 103 104struct srcaddrtab { 105 CK_LIST_ENTRY(srcaddrtab) chain; 106 107 encap_srcaddr_t srcaddr; 108 void *arg; 109}; 110 111CK_LIST_HEAD(encaptab_head, encaptab); 112CK_LIST_HEAD(srcaddrtab_head, srcaddrtab); 113#ifdef INET 114static struct encaptab_head ipv4_encaptab = CK_LIST_HEAD_INITIALIZER(); 115static struct srcaddrtab_head ipv4_srcaddrtab = CK_LIST_HEAD_INITIALIZER(); 116#endif 117#ifdef INET6 118static struct encaptab_head ipv6_encaptab = CK_LIST_HEAD_INITIALIZER(); 119static struct srcaddrtab_head ipv6_srcaddrtab = CK_LIST_HEAD_INITIALIZER(); 120#endif 121 122static struct mtx encapmtx, srcaddrmtx; 123MTX_SYSINIT(encapmtx, &encapmtx, "encapmtx", MTX_DEF); 124MTX_SYSINIT(srcaddrmtx, &srcaddrmtx, "srcaddrmtx", MTX_DEF); 125#define ENCAP_WLOCK() mtx_lock(&encapmtx) 126#define ENCAP_WUNLOCK() mtx_unlock(&encapmtx) 127#define ENCAP_RLOCK_TRACKER struct epoch_tracker encap_et 128#define ENCAP_RLOCK() NET_EPOCH_ENTER(encap_et) 129#define ENCAP_RUNLOCK() NET_EPOCH_EXIT(encap_et) 130#define ENCAP_WAIT() NET_EPOCH_WAIT() 131 132#define SRCADDR_WLOCK() mtx_lock(&srcaddrmtx) 133#define SRCADDR_WUNLOCK() mtx_unlock(&srcaddrmtx) 134#define SRCADDR_RLOCK_TRACKER struct epoch_tracker srcaddr_et 135#define SRCADDR_RLOCK() \ 136 epoch_enter_preempt(net_epoch_preempt, &srcaddr_et) 137#define SRCADDR_RUNLOCK() \ 138 epoch_exit_preempt(net_epoch_preempt, &srcaddr_et) 139#define SRCADDR_WAIT() epoch_wait_preempt(net_epoch_preempt) 140 141/* 142 * ifaddr_event_ext handler. 143 * 144 * Tunnelling interfaces may request the kernel to notify when 145 * some interface addresses appears or disappears. Usually tunnelling 146 * interface must use an address configured on the local machine as 147 * ingress address to be able receive datagramms and do not send 148 * spoofed packets. 149 */ 150static void 151srcaddr_change_event(void *arg __unused, struct ifnet *ifp, 152 struct ifaddr *ifa, int event) 153{ 154 SRCADDR_RLOCK_TRACKER; 155 struct srcaddrtab_head *head; 156 struct srcaddrtab *p; 157 158 /* Support for old ifaddr_event. */ 159 EVENTHANDLER_INVOKE(ifaddr_event, ifp); 160 161 switch (ifa->ifa_addr->sa_family) { 162#ifdef INET 163 case AF_INET: 164 head = &ipv4_srcaddrtab; 165 break; 166#endif 167#ifdef INET6 168 case AF_INET6: 169 head = &ipv6_srcaddrtab; 170 break; 171#endif 172 default: 173 /* ignore event */ 174 return; 175 } 176 177 SRCADDR_RLOCK(); 178 CK_LIST_FOREACH(p, head, chain) { 179 (*p->srcaddr)(p->arg, ifa->ifa_addr, event); 180 } 181 SRCADDR_RUNLOCK(); 182} 183EVENTHANDLER_DEFINE(ifaddr_event_ext, srcaddr_change_event, NULL, 0); 184 185static struct srcaddrtab * 186encap_register_srcaddr(struct srcaddrtab_head *head, encap_srcaddr_t func, 187 void *arg, int mflags) 188{ 189 struct srcaddrtab *p, *tmp; 190 191 if (func == NULL) 192 return (NULL); 193 p = malloc(sizeof(*p), M_NETADDR, mflags); 194 if (p == NULL) 195 return (NULL); 196 p->srcaddr = func; 197 p->arg = arg; 198 199 SRCADDR_WLOCK(); 200 CK_LIST_FOREACH(tmp, head, chain) { 201 if (func == tmp->srcaddr && arg == tmp->arg) 202 break; 203 } 204 if (tmp == NULL) 205 CK_LIST_INSERT_HEAD(head, p, chain); 206 SRCADDR_WUNLOCK(); 207 208 if (tmp != NULL) { 209 free(p, M_NETADDR); 210 p = tmp; 211 } 212 return (p); 213} 214 215static int 216encap_unregister_srcaddr(struct srcaddrtab_head *head, 217 const struct srcaddrtab *cookie) 218{ 219 struct srcaddrtab *p; 220 221 SRCADDR_WLOCK(); 222 CK_LIST_FOREACH(p, head, chain) { 223 if (p == cookie) { 224 CK_LIST_REMOVE(p, chain); 225 SRCADDR_WUNLOCK(); 226 SRCADDR_WAIT(); 227 free(p, M_NETADDR); 228 return (0); 229 } 230 } 231 SRCADDR_WUNLOCK(); 232 return (EINVAL); 233} 234 235static struct encaptab * 236encap_attach(struct encaptab_head *head, const struct encap_config *cfg, 237 void *arg, int mflags) 238{ 239 struct encaptab *ep, *tmp; 240 241 if (cfg == NULL || cfg->input == NULL || 242 (cfg->check == NULL && cfg->lookup == NULL) || 243 (cfg->lookup != NULL && cfg->exact_match != ENCAP_DRV_LOOKUP) || 244 (cfg->exact_match == ENCAP_DRV_LOOKUP && cfg->lookup == NULL)) 245 return (NULL); 246 247 ep = malloc(sizeof(*ep), M_NETADDR, mflags); 248 if (ep == NULL) 249 return (NULL); 250 251 ep->proto = cfg->proto; 252 ep->min_length = cfg->min_length; 253 ep->exact_match = cfg->exact_match; 254 ep->arg = arg; 255 ep->lookup = cfg->exact_match == ENCAP_DRV_LOOKUP ? cfg->lookup: NULL; 256 ep->check = cfg->exact_match != ENCAP_DRV_LOOKUP ? cfg->check: NULL; 257 ep->input = cfg->input; 258 259 ENCAP_WLOCK(); 260 CK_LIST_FOREACH(tmp, head, chain) { 261 if (tmp->exact_match <= ep->exact_match) 262 break; 263 } 264 if (tmp == NULL) 265 CK_LIST_INSERT_HEAD(head, ep, chain); 266 else 267 CK_LIST_INSERT_BEFORE(tmp, ep, chain); 268 ENCAP_WUNLOCK(); 269 return (ep); 270} 271 272static int 273encap_detach(struct encaptab_head *head, const struct encaptab *cookie) 274{ 275 struct encaptab *ep; 276 277 ENCAP_WLOCK(); 278 CK_LIST_FOREACH(ep, head, chain) { 279 if (ep == cookie) { 280 CK_LIST_REMOVE(ep, chain); 281 ENCAP_WUNLOCK(); 282 ENCAP_WAIT(); 283 free(ep, M_NETADDR); 284 return (0); 285 } 286 } 287 ENCAP_WUNLOCK(); 288 return (EINVAL); 289} 290 291static int 292encap_input(struct encaptab_head *head, struct mbuf *m, int off, int proto) 293{ 294 ENCAP_RLOCK_TRACKER; 295 struct encaptab *ep, *match; 296 void *arg; 297 int matchprio, ret; 298 299 match = NULL; 300 matchprio = 0; 301 302 ENCAP_RLOCK(); 303 CK_LIST_FOREACH(ep, head, chain) { 304 if (ep->proto >= 0 && ep->proto != proto) 305 continue; 306 if (ep->min_length > m->m_pkthdr.len) 307 continue; 308 if (ep->exact_match == ENCAP_DRV_LOOKUP) 309 ret = (*ep->lookup)(m, off, proto, &arg); 310 else 311 ret = (*ep->check)(m, off, proto, ep->arg); 312 if (ret <= 0) 313 continue; 314 if (ret > matchprio) { 315 match = ep; 316 if (ep->exact_match != ENCAP_DRV_LOOKUP) 317 arg = ep->arg; 318 /* 319 * No need to continue the search, we got the 320 * exact match. 321 */ 322 if (ret >= ep->exact_match) 323 break; 324 matchprio = ret; 325 } 326 } 327 328 if (match != NULL) { 329 /* found a match, "match" has the best one */ 330 ret = (*match->input)(m, off, proto, arg); 331 ENCAP_RUNLOCK(); 332 MPASS(ret == IPPROTO_DONE); 333 return (IPPROTO_DONE); 334 } 335 ENCAP_RUNLOCK(); 336 return (0); 337} 338 339#ifdef INET 340const struct srcaddrtab * 341ip_encap_register_srcaddr(encap_srcaddr_t func, void *arg, int mflags) 342{ 343 344 return (encap_register_srcaddr(&ipv4_srcaddrtab, func, arg, mflags)); 345} 346 347int 348ip_encap_unregister_srcaddr(const struct srcaddrtab *cookie) 349{ 350 351 return (encap_unregister_srcaddr(&ipv4_srcaddrtab, cookie)); 352} 353 354const struct encaptab * 355ip_encap_attach(const struct encap_config *cfg, void *arg, int mflags) 356{ 357 358 return (encap_attach(&ipv4_encaptab, cfg, arg, mflags)); 359} 360 361int 362ip_encap_detach(const struct encaptab *cookie) 363{ 364 365 return (encap_detach(&ipv4_encaptab, cookie)); 366} 367 368int 369encap4_input(struct mbuf **mp, int *offp, int proto) 370{ 371 372 if (encap_input(&ipv4_encaptab, *mp, *offp, proto) != IPPROTO_DONE) 373 return (rip_input(mp, offp, proto)); 374 return (IPPROTO_DONE); 375} 376#endif /* INET */ 377 378#ifdef INET6 379const struct srcaddrtab * 380ip6_encap_register_srcaddr(encap_srcaddr_t func, void *arg, int mflags) 381{ 382 383 return (encap_register_srcaddr(&ipv6_srcaddrtab, func, arg, mflags)); 384} 385 386int 387ip6_encap_unregister_srcaddr(const struct srcaddrtab *cookie) 388{ 389 390 return (encap_unregister_srcaddr(&ipv6_srcaddrtab, cookie)); 391} 392 393const struct encaptab * 394ip6_encap_attach(const struct encap_config *cfg, void *arg, int mflags) 395{ 396 397 return (encap_attach(&ipv6_encaptab, cfg, arg, mflags)); 398} 399 400int 401ip6_encap_detach(const struct encaptab *cookie) 402{ 403 404 return (encap_detach(&ipv6_encaptab, cookie)); 405} 406 407int 408encap6_input(struct mbuf **mp, int *offp, int proto) 409{ 410 411 if (encap_input(&ipv6_encaptab, *mp, *offp, proto) != IPPROTO_DONE) 412 return (rip6_input(mp, offp, proto)); 413 return (IPPROTO_DONE); 414} 415#endif /* INET6 */ 416