1 /* $NetBSD: ip_encap.c,v 1.5 2001/05/08 10:07:15 itojun Exp $ */ 2 /* $KAME: ip_encap.c,v 1.39 2000/10/01 12:37:18 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 * mobile-ip6 (uses RFC2473) 43 * 6to4 tunnel 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 #include "opt_mrouting.h" 60 #include "opt_inet.h" 61 62 #include <sys/param.h> 63 #include <sys/systm.h> 64 #include <sys/socket.h> 65 #include <sys/sockio.h> 66 #include <sys/mbuf.h> 67 #include <sys/errno.h> 68 #include <sys/protosw.h> 69 #include <sys/queue.h> 70 71 #include <net/if.h> 72 #include <net/route.h> 73 74 #include <netinet/in.h> 75 #include <netinet/in_systm.h> 76 #include <netinet/ip.h> 77 #include <netinet/ip_var.h> 78 #include <netinet/ip_encap.h> 79 #ifdef MROUTING 80 #include <netinet/ip_mroute.h> 81 #endif /* MROUTING */ 82 83 #ifdef INET6 84 #include <netinet/ip6.h> 85 #include <netinet6/ip6_var.h> 86 #include <netinet6/ip6protosw.h> 87 #endif 88 89 #include <machine/stdarg.h> 90 91 #include "ipip.h" 92 #if NIPIP > 0 93 # include <netinet/ip_ipip.h> 94 #else 95 # ifdef MROUTING 96 # include <netinet/ip_mroute.h> 97 # endif 98 #endif 99 100 #include <net/net_osdep.h> 101 102 static void encap_add __P((struct encaptab *)); 103 static int mask_match __P((const struct encaptab *, const struct sockaddr *, 104 const struct sockaddr *)); 105 static void encap_fillarg __P((struct mbuf *, const struct encaptab *)); 106 107 /* rely upon BSS initialization */ 108 LIST_HEAD(, encaptab) encaptab = LIST_HEAD_INITIALIZER(&encaptab); 109 110 void 111 encap_init() 112 { 113 #if 0 114 /* 115 * we cannot use LIST_INIT() here, since drivers may want to call 116 * encap_attach(), on driver attach. encap_init() will be called 117 * on AF_INET{,6} initialization, which happens after driver 118 * initialization - using LIST_INIT() here can nuke encap_attach() 119 * from drivers. 120 */ 121 LIST_INIT(&encaptab); 122 #endif 123 } 124 125 #ifdef INET 126 void 127 #if __STDC__ 128 encap4_input(struct mbuf *m, ...) 129 #else 130 encap4_input(m, va_alist) 131 struct mbuf *m; 132 va_dcl 133 #endif 134 { 135 int off, proto; 136 struct ip *ip; 137 struct sockaddr_in s, d; 138 const struct protosw *psw; 139 struct encaptab *ep, *match; 140 va_list ap; 141 int prio, matchprio; 142 143 va_start(ap, m); 144 off = va_arg(ap, int); 145 proto = va_arg(ap, int); 146 va_end(ap); 147 148 ip = mtod(m, struct ip *); 149 150 bzero(&s, sizeof(s)); 151 s.sin_family = AF_INET; 152 s.sin_len = sizeof(struct sockaddr_in); 153 s.sin_addr = ip->ip_src; 154 bzero(&d, sizeof(d)); 155 d.sin_family = AF_INET; 156 d.sin_len = sizeof(struct sockaddr_in); 157 d.sin_addr = ip->ip_dst; 158 159 match = NULL; 160 matchprio = 0; 161 for (ep = LIST_FIRST(&encaptab); ep; ep = LIST_NEXT(ep, chain)) { 162 if (ep->af != AF_INET) 163 continue; 164 if (ep->proto >= 0 && ep->proto != proto) 165 continue; 166 if (ep->func) 167 prio = (*ep->func)(m, off, proto, ep->arg); 168 else { 169 /* 170 * it's inbound traffic, we need to match in reverse 171 * order 172 */ 173 prio = mask_match(ep, (struct sockaddr *)&d, 174 (struct sockaddr *)&s); 175 } 176 177 /* 178 * We prioritize the matches by using bit length of the 179 * matches. mask_match() and user-supplied matching function 180 * should return the bit length of the matches (for example, 181 * if both src/dst are matched for IPv4, 64 should be returned). 182 * 0 or negative return value means "it did not match". 183 * 184 * The question is, since we have two "mask" portion, we 185 * cannot really define total order between entries. 186 * For example, which of these should be preferred? 187 * mask_match() returns 48 (32 + 16) for both of them. 188 * src=3ffe::/16, dst=3ffe:501::/32 189 * src=3ffe:501::/32, dst=3ffe::/16 190 * 191 * We need to loop through all the possible candidates 192 * to get the best match - the search takes O(n) for 193 * n attachments (i.e. interfaces). 194 */ 195 if (prio <= 0) 196 continue; 197 if (prio > matchprio) { 198 matchprio = prio; 199 match = ep; 200 } 201 } 202 203 if (match) { 204 /* found a match, "match" has the best one */ 205 psw = match->psw; 206 if (psw && psw->pr_input) { 207 encap_fillarg(m, match); 208 (*psw->pr_input)(m, off, proto); 209 } else 210 m_freem(m); 211 return; 212 } 213 214 /* last resort: inject to raw socket */ 215 rip_input(m, off, proto); 216 } 217 #endif 218 219 #ifdef INET6 220 int 221 encap6_input(mp, offp, proto) 222 struct mbuf **mp; 223 int *offp; 224 int proto; 225 { 226 struct mbuf *m = *mp; 227 struct ip6_hdr *ip6; 228 struct sockaddr_in6 s, d; 229 const struct ip6protosw *psw; 230 struct encaptab *ep, *match; 231 int prio, matchprio; 232 233 ip6 = mtod(m, struct ip6_hdr *); 234 235 bzero(&s, sizeof(s)); 236 s.sin6_family = AF_INET6; 237 s.sin6_len = sizeof(struct sockaddr_in6); 238 s.sin6_addr = ip6->ip6_src; 239 bzero(&d, sizeof(d)); 240 d.sin6_family = AF_INET6; 241 d.sin6_len = sizeof(struct sockaddr_in6); 242 d.sin6_addr = ip6->ip6_dst; 243 244 match = NULL; 245 matchprio = 0; 246 for (ep = LIST_FIRST(&encaptab); ep; ep = LIST_NEXT(ep, chain)) { 247 if (ep->af != AF_INET6) 248 continue; 249 if (ep->proto >= 0 && ep->proto != proto) 250 continue; 251 if (ep->func) 252 prio = (*ep->func)(m, *offp, proto, ep->arg); 253 else { 254 /* 255 * it's inbound traffic, we need to match in reverse 256 * order 257 */ 258 prio = mask_match(ep, (struct sockaddr *)&d, 259 (struct sockaddr *)&s); 260 } 261 262 /* see encap4_input() for issues here */ 263 if (prio <= 0) 264 continue; 265 if (prio > matchprio) { 266 matchprio = prio; 267 match = ep; 268 } 269 } 270 271 if (match) { 272 /* found a match */ 273 psw = (const struct ip6protosw *)match->psw; 274 if (psw && psw->pr_input) { 275 encap_fillarg(m, match); 276 return (*psw->pr_input)(mp, offp, proto); 277 } else { 278 m_freem(m); 279 return IPPROTO_DONE; 280 } 281 } 282 283 /* last resort: inject to raw socket */ 284 return rip6_input(mp, offp, proto); 285 } 286 #endif 287 288 static void 289 encap_add(ep) 290 struct encaptab *ep; 291 { 292 293 LIST_INSERT_HEAD(&encaptab, ep, chain); 294 } 295 296 /* 297 * sp (src ptr) is always my side, and dp (dst ptr) is always remote side. 298 * length of mask (sm and dm) is assumed to be same as sp/dp. 299 * Return value will be necessary as input (cookie) for encap_detach(). 300 */ 301 const struct encaptab * 302 encap_attach(af, proto, sp, sm, dp, dm, psw, arg) 303 int af; 304 int proto; 305 const struct sockaddr *sp, *sm; 306 const struct sockaddr *dp, *dm; 307 const struct protosw *psw; 308 void *arg; 309 { 310 struct encaptab *ep; 311 int error; 312 int s; 313 314 s = splsoftnet(); 315 /* sanity check on args */ 316 if (sp->sa_len > sizeof(ep->src) || dp->sa_len > sizeof(ep->dst)) { 317 error = EINVAL; 318 goto fail; 319 } 320 if (sp->sa_len != dp->sa_len) { 321 error = EINVAL; 322 goto fail; 323 } 324 if (af != sp->sa_family || af != dp->sa_family) { 325 error = EINVAL; 326 goto fail; 327 } 328 329 /* check if anyone have already attached with exactly same config */ 330 for (ep = LIST_FIRST(&encaptab); ep; ep = LIST_NEXT(ep, chain)) { 331 if (ep->af != af) 332 continue; 333 if (ep->proto != proto) 334 continue; 335 if (ep->src.ss_len != sp->sa_len || 336 bcmp(&ep->src, sp, sp->sa_len) != 0 || 337 bcmp(&ep->srcmask, sm, sp->sa_len) != 0) 338 continue; 339 if (ep->dst.ss_len != dp->sa_len || 340 bcmp(&ep->dst, dp, dp->sa_len) != 0 || 341 bcmp(&ep->dstmask, dm, dp->sa_len) != 0) 342 continue; 343 344 error = EEXIST; 345 goto fail; 346 } 347 348 /* 349 * XXX NEED TO CHECK viftable IN THE ip_mroute CODE!!! 350 * XXX Actually, that code needs to be replaced with 351 * XXX new code that uses `gif' tunnels. 352 */ 353 354 ep = malloc(sizeof(*ep), M_NETADDR, M_NOWAIT); /*XXX*/ 355 if (ep == NULL) { 356 error = ENOBUFS; 357 goto fail; 358 } 359 bzero(ep, sizeof(*ep)); 360 361 ep->af = af; 362 ep->proto = proto; 363 bcopy(sp, &ep->src, sp->sa_len); 364 bcopy(sm, &ep->srcmask, sp->sa_len); 365 bcopy(dp, &ep->dst, dp->sa_len); 366 bcopy(dm, &ep->dstmask, dp->sa_len); 367 ep->psw = psw; 368 ep->arg = arg; 369 370 encap_add(ep); 371 372 error = 0; 373 splx(s); 374 return ep; 375 376 fail: 377 splx(s); 378 return NULL; 379 } 380 381 const struct encaptab * 382 encap_attach_func(af, proto, func, psw, arg) 383 int af; 384 int proto; 385 int (*func) __P((const struct mbuf *, int, int, void *)); 386 const struct protosw *psw; 387 void *arg; 388 { 389 struct encaptab *ep; 390 int error; 391 int s; 392 393 s = splsoftnet(); 394 /* sanity check on args */ 395 if (!func) { 396 error = EINVAL; 397 goto fail; 398 } 399 400 ep = malloc(sizeof(*ep), M_NETADDR, M_NOWAIT); /*XXX*/ 401 if (ep == NULL) { 402 error = ENOBUFS; 403 goto fail; 404 } 405 bzero(ep, sizeof(*ep)); 406 407 ep->af = af; 408 ep->proto = proto; 409 ep->func = func; 410 ep->psw = psw; 411 ep->arg = arg; 412 413 encap_add(ep); 414 415 error = 0; 416 splx(s); 417 return ep; 418 419 fail: 420 splx(s); 421 return NULL; 422 } 423 424 int 425 encap_detach(cookie) 426 const struct encaptab *cookie; 427 { 428 const struct encaptab *ep = cookie; 429 struct encaptab *p; 430 431 for (p = LIST_FIRST(&encaptab); p; p = LIST_NEXT(p, chain)) { 432 if (p == ep) { 433 LIST_REMOVE(p, chain); 434 free(p, M_NETADDR); /*XXX*/ 435 return 0; 436 } 437 } 438 439 return EINVAL; 440 } 441 442 static int 443 mask_match(ep, sp, dp) 444 const struct encaptab *ep; 445 const struct sockaddr *sp; 446 const struct sockaddr *dp; 447 { 448 struct sockaddr_storage s; 449 struct sockaddr_storage d; 450 int i; 451 const u_int8_t *p, *q; 452 u_int8_t *r; 453 int matchlen; 454 455 if (sp->sa_len > sizeof(s) || dp->sa_len > sizeof(d)) 456 return 0; 457 if (sp->sa_family != ep->af || dp->sa_family != ep->af) 458 return 0; 459 if (sp->sa_len != ep->src.ss_len || dp->sa_len != ep->dst.ss_len) 460 return 0; 461 462 matchlen = 0; 463 464 p = (const u_int8_t *)sp; 465 q = (const u_int8_t *)&ep->srcmask; 466 r = (u_int8_t *)&s; 467 for (i = 0 ; i < sp->sa_len; i++) { 468 r[i] = p[i] & q[i]; 469 /* XXX estimate */ 470 matchlen += (q[i] ? 8 : 0); 471 } 472 473 p = (const u_int8_t *)dp; 474 q = (const u_int8_t *)&ep->dstmask; 475 r = (u_int8_t *)&d; 476 for (i = 0 ; i < dp->sa_len; i++) { 477 r[i] = p[i] & q[i]; 478 /* XXX rough estimate */ 479 matchlen += (q[i] ? 8 : 0); 480 } 481 482 /* need to overwrite len/family portion as we don't compare them */ 483 s.ss_len = sp->sa_len; 484 s.ss_family = sp->sa_family; 485 d.ss_len = dp->sa_len; 486 d.ss_family = dp->sa_family; 487 488 if (bcmp(&s, &ep->src, ep->src.ss_len) == 0 && 489 bcmp(&d, &ep->dst, ep->dst.ss_len) == 0) { 490 return matchlen; 491 } else 492 return 0; 493 } 494 495 static void 496 encap_fillarg(m, ep) 497 struct mbuf *m; 498 const struct encaptab *ep; 499 { 500 #if 0 501 m->m_pkthdr.aux = ep->arg; 502 #else 503 struct mbuf *n; 504 505 n = m_aux_add(m, AF_INET, IPPROTO_IPV4); 506 if (n) { 507 *mtod(n, void **) = ep->arg; 508 n->m_len = sizeof(void *); 509 } 510 #endif 511 } 512 513 void * 514 encap_getarg(m) 515 struct mbuf *m; 516 { 517 void *p; 518 #if 0 519 p = m->m_pkthdr.aux; 520 m->m_pkthdr.aux = NULL; 521 return p; 522 #else 523 struct mbuf *n; 524 525 p = NULL; 526 n = m_aux_find(m, AF_INET, IPPROTO_IPV4); 527 if (n) { 528 if (n->m_len == sizeof(void *)) 529 p = *mtod(n, void **); 530 m_aux_delete(m, n); 531 } 532 return p; 533 #endif 534 } 535