2/* $OpenBSD: ip_ipip.c,v 1.25 2002/06/10 18:04:55 itojun Exp $ */ 3/*- 4 * The authors of this code are John Ioannidis (ji@tla.org), 5 * Angelos D. Keromytis (kermit@csd.uch.gr) and 6 * Niels Provos (provos@physnet.uni-hamburg.de). 7 * 8 * The original version of this code was written by John Ioannidis 9 * for BSD/OS in Athens, Greece, in November 1995. 10 * 11 * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, 12 * by Angelos D. Keromytis. 13 * 14 * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis 15 * and Niels Provos. 16 * 17 * Additional features in 1999 by Angelos D. Keromytis. 18 * 19 * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, 20 * Angelos D. Keromytis and Niels Provos. 21 * Copyright (c) 2001, Angelos D. Keromytis. 22 * 23 * Permission to use, copy, and modify this software with or without fee 24 * is hereby granted, provided that this entire notice is included in 25 * all copies of any software which is or includes a copy or 26 * modification of this software. 27 * You may use this code under the GNU public license if you so wish. Please 28 * contribute changes back to the authors under this freer than GPL license 29 * so that we may further the use of strong encryption without limitations to 30 * all. 31 * 32 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR 33 * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY 34 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE 35 * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR 36 * PURPOSE. 37 */ 38 39/* 40 * IP-inside-IP processing 41 */ 42#include "opt_inet.h" 43#include "opt_inet6.h" 44#include "opt_enc.h" 45 46#include <sys/param.h> 47#include <sys/systm.h> 48#include <sys/mbuf.h> 49#include <sys/socket.h> 50#include <sys/kernel.h> 51#include <sys/protosw.h> 52#include <sys/sysctl.h> 53#include <sys/vimage.h> 54 55#include <net/if.h> 56#include <net/pfil.h> 57#include <net/route.h> 58#include <net/netisr.h> 59#include <net/vnet.h> 60 61#include <netinet/in.h> 62#include <netinet/in_systm.h> 63#include <netinet/in_var.h> 64#include <netinet/ip.h> 65#include <netinet/ip_ecn.h> 66#include <netinet/ip_var.h> 67#include <netinet/ip_encap.h> 68#ifdef MROUTING 69#include <netinet/ip_mroute.h> 70#endif 71#include <netinet/vinet.h> 72 73#include <netipsec/ipsec.h> 74#include <netipsec/xform.h> 75 76#include <netipsec/ipip_var.h> 77 78#ifdef INET6 79#include <netinet/ip6.h> 80#include <netipsec/ipsec6.h> 81#include <netinet6/ip6_ecn.h> 82#include <netinet6/in6_var.h> 83#include <netinet6/ip6protosw.h> 84#endif 85 86#include <netipsec/key.h> 87#include <netipsec/key_debug.h> 88 89#include <machine/stdarg.h> 90 91/* 92 * We can control the acceptance of IP4 packets by altering the sysctl 93 * net.inet.ipip.allow value. Zero means drop them, all else is acceptance. 94 */ 95#ifdef VIMAGE_GLOBALS 96int ipip_allow; 97struct ipipstat ipipstat; 98#endif 99 100SYSCTL_DECL(_net_inet_ipip); 101SYSCTL_V_INT(V_NET, vnet_ipsec, _net_inet_ipip, OID_AUTO, 102 ipip_allow, CTLFLAG_RW, ipip_allow, 0, ""); 103SYSCTL_V_STRUCT(V_NET, vnet_ipsec, _net_inet_ipip, IPSECCTL_STATS, 104 stats, CTLFLAG_RD, ipipstat, ipipstat, ""); 105 106/* XXX IPCOMP */ 107#define M_IPSEC (M_AUTHIPHDR|M_AUTHIPDGM|M_DECRYPTED) 108 109static void _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp); 110static int ipe4_iattach(const void *); 111 112#ifndef VIMAGE_GLOBALS 113static const vnet_modinfo_t vnet_ipip_modinfo = { 114 .vmi_id = VNET_MOD_IPIP, 115 .vmi_name = "ipsec_ipip", 116 .vmi_dependson = VNET_MOD_IPSEC, 117 .vmi_iattach = ipe4_iattach 118}; 119#endif /* !VIMAGE_GLOBALS */ 120 121#ifdef INET6 122/* 123 * Really only a wrapper for ipip_input(), for use with IPv6. 124 */ 125int 126ip4_input6(struct mbuf **m, int *offp, int proto) 127{ 128#if 0 129 /* If we do not accept IP-in-IP explicitly, drop. */ 130 if (!V_ipip_allow && ((*m)->m_flags & M_IPSEC) == 0) { 131 DPRINTF(("%s: dropped due to policy\n", __func__)); 132 V_ipipstat.ipips_pdrops++; 133 m_freem(*m); 134 return IPPROTO_DONE; 135 } 136#endif 137 _ipip_input(*m, *offp, NULL); 138 return IPPROTO_DONE; 139} 140#endif /* INET6 */ 141 142#ifdef INET 143/* 144 * Really only a wrapper for ipip_input(), for use with IPv4. 145 */ 146void 147ip4_input(struct mbuf *m, int off) 148{ 149#if 0 150 /* If we do not accept IP-in-IP explicitly, drop. */ 151 if (!V_ipip_allow && (m->m_flags & M_IPSEC) == 0) { 152 DPRINTF(("%s: dropped due to policy\n", __func__)); 153 V_ipipstat.ipips_pdrops++; 154 m_freem(m); 155 return; 156 } 157#endif 158 _ipip_input(m, off, NULL); 159} 160#endif /* INET */ 161 162/* 163 * ipip_input gets called when we receive an IP{46} encapsulated packet, 164 * either because we got it at a real interface, or because AH or ESP 165 * were being used in tunnel mode (in which case the rcvif element will 166 * contain the address of the encX interface associated with the tunnel. 167 */ 168 169static void 170_ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp) 171{ 172 INIT_VNET_NET(curvnet); 173 INIT_VNET_IPSEC(curvnet);
| 2/* $OpenBSD: ip_ipip.c,v 1.25 2002/06/10 18:04:55 itojun Exp $ */ 3/*- 4 * The authors of this code are John Ioannidis (ji@tla.org), 5 * Angelos D. Keromytis (kermit@csd.uch.gr) and 6 * Niels Provos (provos@physnet.uni-hamburg.de). 7 * 8 * The original version of this code was written by John Ioannidis 9 * for BSD/OS in Athens, Greece, in November 1995. 10 * 11 * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, 12 * by Angelos D. Keromytis. 13 * 14 * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis 15 * and Niels Provos. 16 * 17 * Additional features in 1999 by Angelos D. Keromytis. 18 * 19 * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, 20 * Angelos D. Keromytis and Niels Provos. 21 * Copyright (c) 2001, Angelos D. Keromytis. 22 * 23 * Permission to use, copy, and modify this software with or without fee 24 * is hereby granted, provided that this entire notice is included in 25 * all copies of any software which is or includes a copy or 26 * modification of this software. 27 * You may use this code under the GNU public license if you so wish. Please 28 * contribute changes back to the authors under this freer than GPL license 29 * so that we may further the use of strong encryption without limitations to 30 * all. 31 * 32 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR 33 * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY 34 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE 35 * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR 36 * PURPOSE. 37 */ 38 39/* 40 * IP-inside-IP processing 41 */ 42#include "opt_inet.h" 43#include "opt_inet6.h" 44#include "opt_enc.h" 45 46#include <sys/param.h> 47#include <sys/systm.h> 48#include <sys/mbuf.h> 49#include <sys/socket.h> 50#include <sys/kernel.h> 51#include <sys/protosw.h> 52#include <sys/sysctl.h> 53#include <sys/vimage.h> 54 55#include <net/if.h> 56#include <net/pfil.h> 57#include <net/route.h> 58#include <net/netisr.h> 59#include <net/vnet.h> 60 61#include <netinet/in.h> 62#include <netinet/in_systm.h> 63#include <netinet/in_var.h> 64#include <netinet/ip.h> 65#include <netinet/ip_ecn.h> 66#include <netinet/ip_var.h> 67#include <netinet/ip_encap.h> 68#ifdef MROUTING 69#include <netinet/ip_mroute.h> 70#endif 71#include <netinet/vinet.h> 72 73#include <netipsec/ipsec.h> 74#include <netipsec/xform.h> 75 76#include <netipsec/ipip_var.h> 77 78#ifdef INET6 79#include <netinet/ip6.h> 80#include <netipsec/ipsec6.h> 81#include <netinet6/ip6_ecn.h> 82#include <netinet6/in6_var.h> 83#include <netinet6/ip6protosw.h> 84#endif 85 86#include <netipsec/key.h> 87#include <netipsec/key_debug.h> 88 89#include <machine/stdarg.h> 90 91/* 92 * We can control the acceptance of IP4 packets by altering the sysctl 93 * net.inet.ipip.allow value. Zero means drop them, all else is acceptance. 94 */ 95#ifdef VIMAGE_GLOBALS 96int ipip_allow; 97struct ipipstat ipipstat; 98#endif 99 100SYSCTL_DECL(_net_inet_ipip); 101SYSCTL_V_INT(V_NET, vnet_ipsec, _net_inet_ipip, OID_AUTO, 102 ipip_allow, CTLFLAG_RW, ipip_allow, 0, ""); 103SYSCTL_V_STRUCT(V_NET, vnet_ipsec, _net_inet_ipip, IPSECCTL_STATS, 104 stats, CTLFLAG_RD, ipipstat, ipipstat, ""); 105 106/* XXX IPCOMP */ 107#define M_IPSEC (M_AUTHIPHDR|M_AUTHIPDGM|M_DECRYPTED) 108 109static void _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp); 110static int ipe4_iattach(const void *); 111 112#ifndef VIMAGE_GLOBALS 113static const vnet_modinfo_t vnet_ipip_modinfo = { 114 .vmi_id = VNET_MOD_IPIP, 115 .vmi_name = "ipsec_ipip", 116 .vmi_dependson = VNET_MOD_IPSEC, 117 .vmi_iattach = ipe4_iattach 118}; 119#endif /* !VIMAGE_GLOBALS */ 120 121#ifdef INET6 122/* 123 * Really only a wrapper for ipip_input(), for use with IPv6. 124 */ 125int 126ip4_input6(struct mbuf **m, int *offp, int proto) 127{ 128#if 0 129 /* If we do not accept IP-in-IP explicitly, drop. */ 130 if (!V_ipip_allow && ((*m)->m_flags & M_IPSEC) == 0) { 131 DPRINTF(("%s: dropped due to policy\n", __func__)); 132 V_ipipstat.ipips_pdrops++; 133 m_freem(*m); 134 return IPPROTO_DONE; 135 } 136#endif 137 _ipip_input(*m, *offp, NULL); 138 return IPPROTO_DONE; 139} 140#endif /* INET6 */ 141 142#ifdef INET 143/* 144 * Really only a wrapper for ipip_input(), for use with IPv4. 145 */ 146void 147ip4_input(struct mbuf *m, int off) 148{ 149#if 0 150 /* If we do not accept IP-in-IP explicitly, drop. */ 151 if (!V_ipip_allow && (m->m_flags & M_IPSEC) == 0) { 152 DPRINTF(("%s: dropped due to policy\n", __func__)); 153 V_ipipstat.ipips_pdrops++; 154 m_freem(m); 155 return; 156 } 157#endif 158 _ipip_input(m, off, NULL); 159} 160#endif /* INET */ 161 162/* 163 * ipip_input gets called when we receive an IP{46} encapsulated packet, 164 * either because we got it at a real interface, or because AH or ESP 165 * were being used in tunnel mode (in which case the rcvif element will 166 * contain the address of the encX interface associated with the tunnel. 167 */ 168 169static void 170_ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp) 171{ 172 INIT_VNET_NET(curvnet); 173 INIT_VNET_IPSEC(curvnet);
|
175 register struct ifnet *ifp; 176 register struct ifaddr *ifa; 177 struct ip *ipo; 178#ifdef INET6 179 register struct sockaddr_in6 *sin6; 180 struct ip6_hdr *ip6 = NULL; 181 u_int8_t itos; 182#endif 183 u_int8_t nxt; 184 int isr; 185 u_int8_t otos; 186 u_int8_t v; 187 int hlen; 188 189 V_ipipstat.ipips_ipackets++; 190 191 m_copydata(m, 0, 1, &v); 192 193 switch (v >> 4) { 194#ifdef INET 195 case 4: 196 hlen = sizeof(struct ip); 197 break; 198#endif /* INET */ 199#ifdef INET6 200 case 6: 201 hlen = sizeof(struct ip6_hdr); 202 break; 203#endif 204 default: 205 V_ipipstat.ipips_family++; 206 m_freem(m); 207 return /* EAFNOSUPPORT */; 208 } 209 210 /* Bring the IP header in the first mbuf, if not there already */ 211 if (m->m_len < hlen) { 212 if ((m = m_pullup(m, hlen)) == NULL) { 213 DPRINTF(("%s: m_pullup (1) failed\n", __func__)); 214 V_ipipstat.ipips_hdrops++; 215 return; 216 } 217 } 218 219 ipo = mtod(m, struct ip *); 220 221#ifdef MROUTING 222 if (ipo->ip_v == IPVERSION && ipo->ip_p == IPPROTO_IPV4) { 223 if (IN_MULTICAST(((struct ip *)((char *) ipo + iphlen))->ip_dst.s_addr)) { 224 ipip_mroute_input (m, iphlen); 225 return; 226 } 227 } 228#endif /* MROUTING */ 229 230 /* Keep outer ecn field. */ 231 switch (v >> 4) { 232#ifdef INET 233 case 4: 234 otos = ipo->ip_tos; 235 break; 236#endif /* INET */ 237#ifdef INET6 238 case 6: 239 otos = (ntohl(mtod(m, struct ip6_hdr *)->ip6_flow) >> 20) & 0xff; 240 break; 241#endif 242 default: 243 panic("ipip_input: unknown ip version %u (outer)", v>>4); 244 } 245 246 /* Remove outer IP header */ 247 m_adj(m, iphlen); 248 249 /* Sanity check */ 250 if (m->m_pkthdr.len < sizeof(struct ip)) { 251 V_ipipstat.ipips_hdrops++; 252 m_freem(m); 253 return; 254 } 255 256 m_copydata(m, 0, 1, &v); 257 258 switch (v >> 4) { 259#ifdef INET 260 case 4: 261 hlen = sizeof(struct ip); 262 break; 263#endif /* INET */ 264 265#ifdef INET6 266 case 6: 267 hlen = sizeof(struct ip6_hdr); 268 break; 269#endif 270 default: 271 V_ipipstat.ipips_family++; 272 m_freem(m); 273 return; /* EAFNOSUPPORT */ 274 } 275 276 /* 277 * Bring the inner IP header in the first mbuf, if not there already. 278 */ 279 if (m->m_len < hlen) { 280 if ((m = m_pullup(m, hlen)) == NULL) { 281 DPRINTF(("%s: m_pullup (2) failed\n", __func__)); 282 V_ipipstat.ipips_hdrops++; 283 return; 284 } 285 } 286 287 /* 288 * RFC 1853 specifies that the inner TTL should not be touched on 289 * decapsulation. There's no reason this comment should be here, but 290 * this is as good as any a position. 291 */ 292 293 /* Some sanity checks in the inner IP header */ 294 switch (v >> 4) { 295#ifdef INET 296 case 4: 297 ipo = mtod(m, struct ip *); 298 nxt = ipo->ip_p; 299 ip_ecn_egress(V_ip4_ipsec_ecn, &otos, &ipo->ip_tos); 300 break; 301#endif /* INET */ 302#ifdef INET6 303 case 6: 304 ip6 = (struct ip6_hdr *) ipo; 305 nxt = ip6->ip6_nxt; 306 itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; 307 ip_ecn_egress(V_ip6_ipsec_ecn, &otos, &itos); 308 ip6->ip6_flow &= ~htonl(0xff << 20); 309 ip6->ip6_flow |= htonl((u_int32_t) itos << 20); 310 break; 311#endif 312 default: 313 panic("ipip_input: unknown ip version %u (inner)", v>>4); 314 } 315 316 /* Check for local address spoofing. */ 317 if ((m->m_pkthdr.rcvif == NULL || 318 !(m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK)) && 319 V_ipip_allow != 2) { 320 IFNET_RLOCK(); 321 TAILQ_FOREACH(ifp, &V_ifnet, if_link) { 322 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 323#ifdef INET 324 if (ipo) { 325 if (ifa->ifa_addr->sa_family != 326 AF_INET) 327 continue; 328 329 sin = (struct sockaddr_in *) ifa->ifa_addr; 330 331 if (sin->sin_addr.s_addr == 332 ipo->ip_src.s_addr) { 333 V_ipipstat.ipips_spoof++; 334 m_freem(m); 335 IFNET_RUNLOCK(); 336 return; 337 } 338 } 339#endif /* INET */ 340 341#ifdef INET6 342 if (ip6) { 343 if (ifa->ifa_addr->sa_family != 344 AF_INET6) 345 continue; 346 347 sin6 = (struct sockaddr_in6 *) ifa->ifa_addr; 348 349 if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ip6->ip6_src)) { 350 V_ipipstat.ipips_spoof++; 351 m_freem(m); 352 IFNET_RUNLOCK(); 353 return; 354 } 355 356 } 357#endif /* INET6 */ 358 } 359 } 360 IFNET_RUNLOCK(); 361 } 362 363 /* Statistics */ 364 V_ipipstat.ipips_ibytes += m->m_pkthdr.len - iphlen; 365 366#ifdef DEV_ENC 367 switch (v >> 4) { 368#ifdef INET 369 case 4: 370 ipsec_bpf(m, NULL, AF_INET, ENC_IN|ENC_AFTER); 371 break; 372#endif 373#ifdef INET6 374 case 6: 375 ipsec_bpf(m, NULL, AF_INET6, ENC_IN|ENC_AFTER); 376 break; 377#endif 378 default: 379 panic("%s: bogus ip version %u", __func__, v>>4); 380 } 381 /* pass the mbuf to enc0 for packet filtering */ 382 if (ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_AFTER) != 0) 383 return; 384#endif 385 386 /* 387 * Interface pointer stays the same; if no IPsec processing has 388 * been done (or will be done), this will point to a normal 389 * interface. Otherwise, it'll point to an enc interface, which 390 * will allow a packet filter to distinguish between secure and 391 * untrusted packets. 392 */ 393 394 switch (v >> 4) { 395#ifdef INET 396 case 4: 397 isr = NETISR_IP; 398 break; 399#endif 400#ifdef INET6 401 case 6: 402 isr = NETISR_IPV6; 403 break; 404#endif 405 default: 406 panic("%s: bogus ip version %u", __func__, v>>4); 407 } 408 409 if (netisr_queue(isr, m)) { /* (0) on success. */ 410 V_ipipstat.ipips_qfull++; 411 DPRINTF(("%s: packet dropped because of full queue\n", 412 __func__)); 413 } 414} 415 416int 417ipip_output( 418 struct mbuf *m, 419 struct ipsecrequest *isr, 420 struct mbuf **mp, 421 int skip, 422 int protoff 423) 424{ 425 INIT_VNET_IPSEC(curvnet); 426#ifdef INET 427 INIT_VNET_INET(curvnet); 428#endif /* INET */ 429 struct secasvar *sav; 430 u_int8_t tp, otos; 431 struct secasindex *saidx; 432 int error; 433#ifdef INET 434 u_int8_t itos; 435 struct ip *ipo; 436#endif /* INET */ 437#ifdef INET6 438 struct ip6_hdr *ip6, *ip6o; 439#endif /* INET6 */ 440 441 sav = isr->sav; 442 IPSEC_ASSERT(sav != NULL, ("null SA")); 443 IPSEC_ASSERT(sav->sah != NULL, ("null SAH")); 444 445 /* XXX Deal with empty TDB source/destination addresses. */ 446 447 m_copydata(m, 0, 1, &tp); 448 tp = (tp >> 4) & 0xff; /* Get the IP version number. */ 449 450 saidx = &sav->sah->saidx; 451 switch (saidx->dst.sa.sa_family) { 452#ifdef INET 453 case AF_INET: 454 if (saidx->src.sa.sa_family != AF_INET || 455 saidx->src.sin.sin_addr.s_addr == INADDR_ANY || 456 saidx->dst.sin.sin_addr.s_addr == INADDR_ANY) { 457 DPRINTF(("%s: unspecified tunnel endpoint " 458 "address in SA %s/%08lx\n", __func__, 459 ipsec_address(&saidx->dst), 460 (u_long) ntohl(sav->spi))); 461 V_ipipstat.ipips_unspec++; 462 error = EINVAL; 463 goto bad; 464 } 465 466 M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); 467 if (m == 0) { 468 DPRINTF(("%s: M_PREPEND failed\n", __func__)); 469 V_ipipstat.ipips_hdrops++; 470 error = ENOBUFS; 471 goto bad; 472 } 473 474 ipo = mtod(m, struct ip *); 475 476 ipo->ip_v = IPVERSION; 477 ipo->ip_hl = 5; 478 ipo->ip_len = htons(m->m_pkthdr.len); 479 ipo->ip_ttl = V_ip_defttl; 480 ipo->ip_sum = 0; 481 ipo->ip_src = saidx->src.sin.sin_addr; 482 ipo->ip_dst = saidx->dst.sin.sin_addr; 483 484 ipo->ip_id = ip_newid(); 485 486 /* If the inner protocol is IP... */ 487 if (tp == IPVERSION) { 488 /* Save ECN notification */ 489 m_copydata(m, sizeof(struct ip) + 490 offsetof(struct ip, ip_tos), 491 sizeof(u_int8_t), (caddr_t) &itos); 492 493 ipo->ip_p = IPPROTO_IPIP; 494 495 /* 496 * We should be keeping tunnel soft-state and 497 * send back ICMPs if needed. 498 */ 499 m_copydata(m, sizeof(struct ip) + 500 offsetof(struct ip, ip_off), 501 sizeof(u_int16_t), (caddr_t) &ipo->ip_off); 502 ipo->ip_off = ntohs(ipo->ip_off); 503 ipo->ip_off &= ~(IP_DF | IP_MF | IP_OFFMASK); 504 ipo->ip_off = htons(ipo->ip_off); 505 } 506#ifdef INET6 507 else if (tp == (IPV6_VERSION >> 4)) { 508 u_int32_t itos32; 509 510 /* Save ECN notification. */ 511 m_copydata(m, sizeof(struct ip) + 512 offsetof(struct ip6_hdr, ip6_flow), 513 sizeof(u_int32_t), (caddr_t) &itos32); 514 itos = ntohl(itos32) >> 20; 515 ipo->ip_p = IPPROTO_IPV6; 516 ipo->ip_off = 0; 517 } 518#endif /* INET6 */ 519 else { 520 goto nofamily; 521 } 522 523 otos = 0; 524 ip_ecn_ingress(ECN_ALLOWED, &otos, &itos); 525 ipo->ip_tos = otos; 526 break; 527#endif /* INET */ 528 529#ifdef INET6 530 case AF_INET6: 531 if (IN6_IS_ADDR_UNSPECIFIED(&saidx->dst.sin6.sin6_addr) || 532 saidx->src.sa.sa_family != AF_INET6 || 533 IN6_IS_ADDR_UNSPECIFIED(&saidx->src.sin6.sin6_addr)) { 534 DPRINTF(("%s: unspecified tunnel endpoint " 535 "address in SA %s/%08lx\n", __func__, 536 ipsec_address(&saidx->dst), 537 (u_long) ntohl(sav->spi))); 538 V_ipipstat.ipips_unspec++; 539 error = ENOBUFS; 540 goto bad; 541 } 542 543 /* scoped address handling */ 544 ip6 = mtod(m, struct ip6_hdr *); 545 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) 546 ip6->ip6_src.s6_addr16[1] = 0; 547 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) 548 ip6->ip6_dst.s6_addr16[1] = 0; 549 550 M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT); 551 if (m == 0) { 552 DPRINTF(("%s: M_PREPEND failed\n", __func__)); 553 V_ipipstat.ipips_hdrops++; 554 error = ENOBUFS; 555 goto bad; 556 } 557 558 /* Initialize IPv6 header */ 559 ip6o = mtod(m, struct ip6_hdr *); 560 ip6o->ip6_flow = 0; 561 ip6o->ip6_vfc &= ~IPV6_VERSION_MASK; 562 ip6o->ip6_vfc |= IPV6_VERSION; 563 ip6o->ip6_plen = htons(m->m_pkthdr.len); 564 ip6o->ip6_hlim = V_ip_defttl; 565 ip6o->ip6_dst = saidx->dst.sin6.sin6_addr; 566 ip6o->ip6_src = saidx->src.sin6.sin6_addr; 567 568#ifdef INET 569 if (tp == IPVERSION) { 570 /* Save ECN notification */ 571 m_copydata(m, sizeof(struct ip6_hdr) + 572 offsetof(struct ip, ip_tos), sizeof(u_int8_t), 573 (caddr_t) &itos); 574 575 /* This is really IPVERSION. */ 576 ip6o->ip6_nxt = IPPROTO_IPIP; 577 } else 578#endif /* INET */ 579 if (tp == (IPV6_VERSION >> 4)) { 580 u_int32_t itos32; 581 582 /* Save ECN notification. */ 583 m_copydata(m, sizeof(struct ip6_hdr) + 584 offsetof(struct ip6_hdr, ip6_flow), 585 sizeof(u_int32_t), (caddr_t) &itos32); 586 itos = ntohl(itos32) >> 20; 587 588 ip6o->ip6_nxt = IPPROTO_IPV6; 589 } else { 590 goto nofamily; 591 } 592 593 otos = 0; 594 ip_ecn_ingress(ECN_ALLOWED, &otos, &itos); 595 ip6o->ip6_flow |= htonl((u_int32_t) otos << 20); 596 break; 597#endif /* INET6 */ 598 599 default: 600nofamily: 601 DPRINTF(("%s: unsupported protocol family %u\n", __func__, 602 saidx->dst.sa.sa_family)); 603 V_ipipstat.ipips_family++; 604 error = EAFNOSUPPORT; /* XXX diffs from openbsd */ 605 goto bad; 606 } 607 608 V_ipipstat.ipips_opackets++; 609 *mp = m; 610 611#ifdef INET 612 if (saidx->dst.sa.sa_family == AF_INET) { 613#if 0 614 if (sav->tdb_xform->xf_type == XF_IP4) 615 tdb->tdb_cur_bytes += 616 m->m_pkthdr.len - sizeof(struct ip); 617#endif 618 V_ipipstat.ipips_obytes += m->m_pkthdr.len - sizeof(struct ip); 619 } 620#endif /* INET */ 621 622#ifdef INET6 623 if (saidx->dst.sa.sa_family == AF_INET6) { 624#if 0 625 if (sav->tdb_xform->xf_type == XF_IP4) 626 tdb->tdb_cur_bytes += 627 m->m_pkthdr.len - sizeof(struct ip6_hdr); 628#endif 629 V_ipipstat.ipips_obytes += 630 m->m_pkthdr.len - sizeof(struct ip6_hdr); 631 } 632#endif /* INET6 */ 633 634 return 0; 635bad: 636 if (m) 637 m_freem(m); 638 *mp = NULL; 639 return (error); 640} 641 642#ifdef IPSEC 643static int 644ipe4_init(struct secasvar *sav, struct xformsw *xsp) 645{ 646 sav->tdb_xform = xsp; 647 return 0; 648} 649 650static int 651ipe4_zeroize(struct secasvar *sav) 652{ 653 sav->tdb_xform = NULL; 654 return 0; 655} 656 657static int 658ipe4_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff) 659{ 660 /* This is a rather serious mistake, so no conditional printing. */ 661 printf("%s: should never be called\n", __func__); 662 if (m) 663 m_freem(m); 664 return EOPNOTSUPP; 665} 666 667static struct xformsw ipe4_xformsw = { 668 XF_IP4, 0, "IPv4 Simple Encapsulation", 669 ipe4_init, ipe4_zeroize, ipe4_input, ipip_output, 670}; 671 672extern struct domain inetdomain; 673static struct protosw ipe4_protosw = { 674 .pr_type = SOCK_RAW, 675 .pr_domain = &inetdomain, 676 .pr_protocol = IPPROTO_IPV4, 677 .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, 678 .pr_input = ip4_input, 679 .pr_ctloutput = rip_ctloutput, 680 .pr_usrreqs = &rip_usrreqs 681}; 682#ifdef INET6 683static struct ip6protosw ipe6_protosw = { 684 .pr_type = SOCK_RAW, 685 .pr_domain = &inetdomain, 686 .pr_protocol = IPPROTO_IPV6, 687 .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, 688 .pr_input = ip4_input6, 689 .pr_ctloutput = rip_ctloutput, 690 .pr_usrreqs = &rip_usrreqs 691}; 692#endif 693 694/* 695 * Check the encapsulated packet to see if we want it 696 */ 697static int 698ipe4_encapcheck(const struct mbuf *m, int off, int proto, void *arg) 699{ 700 /* 701 * Only take packets coming from IPSEC tunnels; the rest 702 * must be handled by the gif tunnel code. Note that we 703 * also return a minimum priority when we want the packet 704 * so any explicit gif tunnels take precedence. 705 */ 706 return ((m->m_flags & M_IPSEC) != 0 ? 1 : 0); 707} 708 709static int 710ipe4_iattach(const void *unused __unused) 711{ 712 INIT_VNET_IPSEC(curvnet); 713 714 V_ipip_allow = 0; 715 return (0); 716} 717 718static void 719ipe4_attach(void) 720{ 721 722 xform_register(&ipe4_xformsw); 723 /* attach to encapsulation framework */ 724 /* XXX save return cookie for detach on module remove */ 725 (void) encap_attach_func(AF_INET, -1, 726 ipe4_encapcheck, &ipe4_protosw, NULL); 727#ifdef INET6 728 (void) encap_attach_func(AF_INET6, -1, 729 ipe4_encapcheck, (struct protosw *)&ipe6_protosw, NULL); 730#endif 731#ifndef VIMAGE_GLOBALS 732 vnet_mod_register(&vnet_ipip_modinfo); 733#else 734 ipe4_iattach(NULL); 735#endif 736} 737SYSINIT(ipe4_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ipe4_attach, NULL); 738#endif /* IPSEC */
| 177 register struct ifnet *ifp; 178 register struct ifaddr *ifa; 179 struct ip *ipo; 180#ifdef INET6 181 register struct sockaddr_in6 *sin6; 182 struct ip6_hdr *ip6 = NULL; 183 u_int8_t itos; 184#endif 185 u_int8_t nxt; 186 int isr; 187 u_int8_t otos; 188 u_int8_t v; 189 int hlen; 190 191 V_ipipstat.ipips_ipackets++; 192 193 m_copydata(m, 0, 1, &v); 194 195 switch (v >> 4) { 196#ifdef INET 197 case 4: 198 hlen = sizeof(struct ip); 199 break; 200#endif /* INET */ 201#ifdef INET6 202 case 6: 203 hlen = sizeof(struct ip6_hdr); 204 break; 205#endif 206 default: 207 V_ipipstat.ipips_family++; 208 m_freem(m); 209 return /* EAFNOSUPPORT */; 210 } 211 212 /* Bring the IP header in the first mbuf, if not there already */ 213 if (m->m_len < hlen) { 214 if ((m = m_pullup(m, hlen)) == NULL) { 215 DPRINTF(("%s: m_pullup (1) failed\n", __func__)); 216 V_ipipstat.ipips_hdrops++; 217 return; 218 } 219 } 220 221 ipo = mtod(m, struct ip *); 222 223#ifdef MROUTING 224 if (ipo->ip_v == IPVERSION && ipo->ip_p == IPPROTO_IPV4) { 225 if (IN_MULTICAST(((struct ip *)((char *) ipo + iphlen))->ip_dst.s_addr)) { 226 ipip_mroute_input (m, iphlen); 227 return; 228 } 229 } 230#endif /* MROUTING */ 231 232 /* Keep outer ecn field. */ 233 switch (v >> 4) { 234#ifdef INET 235 case 4: 236 otos = ipo->ip_tos; 237 break; 238#endif /* INET */ 239#ifdef INET6 240 case 6: 241 otos = (ntohl(mtod(m, struct ip6_hdr *)->ip6_flow) >> 20) & 0xff; 242 break; 243#endif 244 default: 245 panic("ipip_input: unknown ip version %u (outer)", v>>4); 246 } 247 248 /* Remove outer IP header */ 249 m_adj(m, iphlen); 250 251 /* Sanity check */ 252 if (m->m_pkthdr.len < sizeof(struct ip)) { 253 V_ipipstat.ipips_hdrops++; 254 m_freem(m); 255 return; 256 } 257 258 m_copydata(m, 0, 1, &v); 259 260 switch (v >> 4) { 261#ifdef INET 262 case 4: 263 hlen = sizeof(struct ip); 264 break; 265#endif /* INET */ 266 267#ifdef INET6 268 case 6: 269 hlen = sizeof(struct ip6_hdr); 270 break; 271#endif 272 default: 273 V_ipipstat.ipips_family++; 274 m_freem(m); 275 return; /* EAFNOSUPPORT */ 276 } 277 278 /* 279 * Bring the inner IP header in the first mbuf, if not there already. 280 */ 281 if (m->m_len < hlen) { 282 if ((m = m_pullup(m, hlen)) == NULL) { 283 DPRINTF(("%s: m_pullup (2) failed\n", __func__)); 284 V_ipipstat.ipips_hdrops++; 285 return; 286 } 287 } 288 289 /* 290 * RFC 1853 specifies that the inner TTL should not be touched on 291 * decapsulation. There's no reason this comment should be here, but 292 * this is as good as any a position. 293 */ 294 295 /* Some sanity checks in the inner IP header */ 296 switch (v >> 4) { 297#ifdef INET 298 case 4: 299 ipo = mtod(m, struct ip *); 300 nxt = ipo->ip_p; 301 ip_ecn_egress(V_ip4_ipsec_ecn, &otos, &ipo->ip_tos); 302 break; 303#endif /* INET */ 304#ifdef INET6 305 case 6: 306 ip6 = (struct ip6_hdr *) ipo; 307 nxt = ip6->ip6_nxt; 308 itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; 309 ip_ecn_egress(V_ip6_ipsec_ecn, &otos, &itos); 310 ip6->ip6_flow &= ~htonl(0xff << 20); 311 ip6->ip6_flow |= htonl((u_int32_t) itos << 20); 312 break; 313#endif 314 default: 315 panic("ipip_input: unknown ip version %u (inner)", v>>4); 316 } 317 318 /* Check for local address spoofing. */ 319 if ((m->m_pkthdr.rcvif == NULL || 320 !(m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK)) && 321 V_ipip_allow != 2) { 322 IFNET_RLOCK(); 323 TAILQ_FOREACH(ifp, &V_ifnet, if_link) { 324 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 325#ifdef INET 326 if (ipo) { 327 if (ifa->ifa_addr->sa_family != 328 AF_INET) 329 continue; 330 331 sin = (struct sockaddr_in *) ifa->ifa_addr; 332 333 if (sin->sin_addr.s_addr == 334 ipo->ip_src.s_addr) { 335 V_ipipstat.ipips_spoof++; 336 m_freem(m); 337 IFNET_RUNLOCK(); 338 return; 339 } 340 } 341#endif /* INET */ 342 343#ifdef INET6 344 if (ip6) { 345 if (ifa->ifa_addr->sa_family != 346 AF_INET6) 347 continue; 348 349 sin6 = (struct sockaddr_in6 *) ifa->ifa_addr; 350 351 if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ip6->ip6_src)) { 352 V_ipipstat.ipips_spoof++; 353 m_freem(m); 354 IFNET_RUNLOCK(); 355 return; 356 } 357 358 } 359#endif /* INET6 */ 360 } 361 } 362 IFNET_RUNLOCK(); 363 } 364 365 /* Statistics */ 366 V_ipipstat.ipips_ibytes += m->m_pkthdr.len - iphlen; 367 368#ifdef DEV_ENC 369 switch (v >> 4) { 370#ifdef INET 371 case 4: 372 ipsec_bpf(m, NULL, AF_INET, ENC_IN|ENC_AFTER); 373 break; 374#endif 375#ifdef INET6 376 case 6: 377 ipsec_bpf(m, NULL, AF_INET6, ENC_IN|ENC_AFTER); 378 break; 379#endif 380 default: 381 panic("%s: bogus ip version %u", __func__, v>>4); 382 } 383 /* pass the mbuf to enc0 for packet filtering */ 384 if (ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_AFTER) != 0) 385 return; 386#endif 387 388 /* 389 * Interface pointer stays the same; if no IPsec processing has 390 * been done (or will be done), this will point to a normal 391 * interface. Otherwise, it'll point to an enc interface, which 392 * will allow a packet filter to distinguish between secure and 393 * untrusted packets. 394 */ 395 396 switch (v >> 4) { 397#ifdef INET 398 case 4: 399 isr = NETISR_IP; 400 break; 401#endif 402#ifdef INET6 403 case 6: 404 isr = NETISR_IPV6; 405 break; 406#endif 407 default: 408 panic("%s: bogus ip version %u", __func__, v>>4); 409 } 410 411 if (netisr_queue(isr, m)) { /* (0) on success. */ 412 V_ipipstat.ipips_qfull++; 413 DPRINTF(("%s: packet dropped because of full queue\n", 414 __func__)); 415 } 416} 417 418int 419ipip_output( 420 struct mbuf *m, 421 struct ipsecrequest *isr, 422 struct mbuf **mp, 423 int skip, 424 int protoff 425) 426{ 427 INIT_VNET_IPSEC(curvnet); 428#ifdef INET 429 INIT_VNET_INET(curvnet); 430#endif /* INET */ 431 struct secasvar *sav; 432 u_int8_t tp, otos; 433 struct secasindex *saidx; 434 int error; 435#ifdef INET 436 u_int8_t itos; 437 struct ip *ipo; 438#endif /* INET */ 439#ifdef INET6 440 struct ip6_hdr *ip6, *ip6o; 441#endif /* INET6 */ 442 443 sav = isr->sav; 444 IPSEC_ASSERT(sav != NULL, ("null SA")); 445 IPSEC_ASSERT(sav->sah != NULL, ("null SAH")); 446 447 /* XXX Deal with empty TDB source/destination addresses. */ 448 449 m_copydata(m, 0, 1, &tp); 450 tp = (tp >> 4) & 0xff; /* Get the IP version number. */ 451 452 saidx = &sav->sah->saidx; 453 switch (saidx->dst.sa.sa_family) { 454#ifdef INET 455 case AF_INET: 456 if (saidx->src.sa.sa_family != AF_INET || 457 saidx->src.sin.sin_addr.s_addr == INADDR_ANY || 458 saidx->dst.sin.sin_addr.s_addr == INADDR_ANY) { 459 DPRINTF(("%s: unspecified tunnel endpoint " 460 "address in SA %s/%08lx\n", __func__, 461 ipsec_address(&saidx->dst), 462 (u_long) ntohl(sav->spi))); 463 V_ipipstat.ipips_unspec++; 464 error = EINVAL; 465 goto bad; 466 } 467 468 M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); 469 if (m == 0) { 470 DPRINTF(("%s: M_PREPEND failed\n", __func__)); 471 V_ipipstat.ipips_hdrops++; 472 error = ENOBUFS; 473 goto bad; 474 } 475 476 ipo = mtod(m, struct ip *); 477 478 ipo->ip_v = IPVERSION; 479 ipo->ip_hl = 5; 480 ipo->ip_len = htons(m->m_pkthdr.len); 481 ipo->ip_ttl = V_ip_defttl; 482 ipo->ip_sum = 0; 483 ipo->ip_src = saidx->src.sin.sin_addr; 484 ipo->ip_dst = saidx->dst.sin.sin_addr; 485 486 ipo->ip_id = ip_newid(); 487 488 /* If the inner protocol is IP... */ 489 if (tp == IPVERSION) { 490 /* Save ECN notification */ 491 m_copydata(m, sizeof(struct ip) + 492 offsetof(struct ip, ip_tos), 493 sizeof(u_int8_t), (caddr_t) &itos); 494 495 ipo->ip_p = IPPROTO_IPIP; 496 497 /* 498 * We should be keeping tunnel soft-state and 499 * send back ICMPs if needed. 500 */ 501 m_copydata(m, sizeof(struct ip) + 502 offsetof(struct ip, ip_off), 503 sizeof(u_int16_t), (caddr_t) &ipo->ip_off); 504 ipo->ip_off = ntohs(ipo->ip_off); 505 ipo->ip_off &= ~(IP_DF | IP_MF | IP_OFFMASK); 506 ipo->ip_off = htons(ipo->ip_off); 507 } 508#ifdef INET6 509 else if (tp == (IPV6_VERSION >> 4)) { 510 u_int32_t itos32; 511 512 /* Save ECN notification. */ 513 m_copydata(m, sizeof(struct ip) + 514 offsetof(struct ip6_hdr, ip6_flow), 515 sizeof(u_int32_t), (caddr_t) &itos32); 516 itos = ntohl(itos32) >> 20; 517 ipo->ip_p = IPPROTO_IPV6; 518 ipo->ip_off = 0; 519 } 520#endif /* INET6 */ 521 else { 522 goto nofamily; 523 } 524 525 otos = 0; 526 ip_ecn_ingress(ECN_ALLOWED, &otos, &itos); 527 ipo->ip_tos = otos; 528 break; 529#endif /* INET */ 530 531#ifdef INET6 532 case AF_INET6: 533 if (IN6_IS_ADDR_UNSPECIFIED(&saidx->dst.sin6.sin6_addr) || 534 saidx->src.sa.sa_family != AF_INET6 || 535 IN6_IS_ADDR_UNSPECIFIED(&saidx->src.sin6.sin6_addr)) { 536 DPRINTF(("%s: unspecified tunnel endpoint " 537 "address in SA %s/%08lx\n", __func__, 538 ipsec_address(&saidx->dst), 539 (u_long) ntohl(sav->spi))); 540 V_ipipstat.ipips_unspec++; 541 error = ENOBUFS; 542 goto bad; 543 } 544 545 /* scoped address handling */ 546 ip6 = mtod(m, struct ip6_hdr *); 547 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) 548 ip6->ip6_src.s6_addr16[1] = 0; 549 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) 550 ip6->ip6_dst.s6_addr16[1] = 0; 551 552 M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT); 553 if (m == 0) { 554 DPRINTF(("%s: M_PREPEND failed\n", __func__)); 555 V_ipipstat.ipips_hdrops++; 556 error = ENOBUFS; 557 goto bad; 558 } 559 560 /* Initialize IPv6 header */ 561 ip6o = mtod(m, struct ip6_hdr *); 562 ip6o->ip6_flow = 0; 563 ip6o->ip6_vfc &= ~IPV6_VERSION_MASK; 564 ip6o->ip6_vfc |= IPV6_VERSION; 565 ip6o->ip6_plen = htons(m->m_pkthdr.len); 566 ip6o->ip6_hlim = V_ip_defttl; 567 ip6o->ip6_dst = saidx->dst.sin6.sin6_addr; 568 ip6o->ip6_src = saidx->src.sin6.sin6_addr; 569 570#ifdef INET 571 if (tp == IPVERSION) { 572 /* Save ECN notification */ 573 m_copydata(m, sizeof(struct ip6_hdr) + 574 offsetof(struct ip, ip_tos), sizeof(u_int8_t), 575 (caddr_t) &itos); 576 577 /* This is really IPVERSION. */ 578 ip6o->ip6_nxt = IPPROTO_IPIP; 579 } else 580#endif /* INET */ 581 if (tp == (IPV6_VERSION >> 4)) { 582 u_int32_t itos32; 583 584 /* Save ECN notification. */ 585 m_copydata(m, sizeof(struct ip6_hdr) + 586 offsetof(struct ip6_hdr, ip6_flow), 587 sizeof(u_int32_t), (caddr_t) &itos32); 588 itos = ntohl(itos32) >> 20; 589 590 ip6o->ip6_nxt = IPPROTO_IPV6; 591 } else { 592 goto nofamily; 593 } 594 595 otos = 0; 596 ip_ecn_ingress(ECN_ALLOWED, &otos, &itos); 597 ip6o->ip6_flow |= htonl((u_int32_t) otos << 20); 598 break; 599#endif /* INET6 */ 600 601 default: 602nofamily: 603 DPRINTF(("%s: unsupported protocol family %u\n", __func__, 604 saidx->dst.sa.sa_family)); 605 V_ipipstat.ipips_family++; 606 error = EAFNOSUPPORT; /* XXX diffs from openbsd */ 607 goto bad; 608 } 609 610 V_ipipstat.ipips_opackets++; 611 *mp = m; 612 613#ifdef INET 614 if (saidx->dst.sa.sa_family == AF_INET) { 615#if 0 616 if (sav->tdb_xform->xf_type == XF_IP4) 617 tdb->tdb_cur_bytes += 618 m->m_pkthdr.len - sizeof(struct ip); 619#endif 620 V_ipipstat.ipips_obytes += m->m_pkthdr.len - sizeof(struct ip); 621 } 622#endif /* INET */ 623 624#ifdef INET6 625 if (saidx->dst.sa.sa_family == AF_INET6) { 626#if 0 627 if (sav->tdb_xform->xf_type == XF_IP4) 628 tdb->tdb_cur_bytes += 629 m->m_pkthdr.len - sizeof(struct ip6_hdr); 630#endif 631 V_ipipstat.ipips_obytes += 632 m->m_pkthdr.len - sizeof(struct ip6_hdr); 633 } 634#endif /* INET6 */ 635 636 return 0; 637bad: 638 if (m) 639 m_freem(m); 640 *mp = NULL; 641 return (error); 642} 643 644#ifdef IPSEC 645static int 646ipe4_init(struct secasvar *sav, struct xformsw *xsp) 647{ 648 sav->tdb_xform = xsp; 649 return 0; 650} 651 652static int 653ipe4_zeroize(struct secasvar *sav) 654{ 655 sav->tdb_xform = NULL; 656 return 0; 657} 658 659static int 660ipe4_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff) 661{ 662 /* This is a rather serious mistake, so no conditional printing. */ 663 printf("%s: should never be called\n", __func__); 664 if (m) 665 m_freem(m); 666 return EOPNOTSUPP; 667} 668 669static struct xformsw ipe4_xformsw = { 670 XF_IP4, 0, "IPv4 Simple Encapsulation", 671 ipe4_init, ipe4_zeroize, ipe4_input, ipip_output, 672}; 673 674extern struct domain inetdomain; 675static struct protosw ipe4_protosw = { 676 .pr_type = SOCK_RAW, 677 .pr_domain = &inetdomain, 678 .pr_protocol = IPPROTO_IPV4, 679 .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, 680 .pr_input = ip4_input, 681 .pr_ctloutput = rip_ctloutput, 682 .pr_usrreqs = &rip_usrreqs 683}; 684#ifdef INET6 685static struct ip6protosw ipe6_protosw = { 686 .pr_type = SOCK_RAW, 687 .pr_domain = &inetdomain, 688 .pr_protocol = IPPROTO_IPV6, 689 .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, 690 .pr_input = ip4_input6, 691 .pr_ctloutput = rip_ctloutput, 692 .pr_usrreqs = &rip_usrreqs 693}; 694#endif 695 696/* 697 * Check the encapsulated packet to see if we want it 698 */ 699static int 700ipe4_encapcheck(const struct mbuf *m, int off, int proto, void *arg) 701{ 702 /* 703 * Only take packets coming from IPSEC tunnels; the rest 704 * must be handled by the gif tunnel code. Note that we 705 * also return a minimum priority when we want the packet 706 * so any explicit gif tunnels take precedence. 707 */ 708 return ((m->m_flags & M_IPSEC) != 0 ? 1 : 0); 709} 710 711static int 712ipe4_iattach(const void *unused __unused) 713{ 714 INIT_VNET_IPSEC(curvnet); 715 716 V_ipip_allow = 0; 717 return (0); 718} 719 720static void 721ipe4_attach(void) 722{ 723 724 xform_register(&ipe4_xformsw); 725 /* attach to encapsulation framework */ 726 /* XXX save return cookie for detach on module remove */ 727 (void) encap_attach_func(AF_INET, -1, 728 ipe4_encapcheck, &ipe4_protosw, NULL); 729#ifdef INET6 730 (void) encap_attach_func(AF_INET6, -1, 731 ipe4_encapcheck, (struct protosw *)&ipe6_protosw, NULL); 732#endif 733#ifndef VIMAGE_GLOBALS 734 vnet_mod_register(&vnet_ipip_modinfo); 735#else 736 ipe4_iattach(NULL); 737#endif 738} 739SYSINIT(ipe4_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ipe4_attach, NULL); 740#endif /* IPSEC */
|