1 1.24 ozaki /* $NetBSD: ipsecif.c,v 1.24 2025/06/11 02:44:13 ozaki-r Exp $ */ 2 1.1 knakahar 3 1.1 knakahar /* 4 1.1 knakahar * Copyright (c) 2017 Internet Initiative Japan Inc. 5 1.1 knakahar * All rights reserved. 6 1.1 knakahar * 7 1.1 knakahar * Redistribution and use in source and binary forms, with or without 8 1.1 knakahar * modification, are permitted provided that the following conditions 9 1.1 knakahar * are met: 10 1.1 knakahar * 1. Redistributions of source code must retain the above copyright 11 1.1 knakahar * notice, this list of conditions and the following disclaimer. 12 1.1 knakahar * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 knakahar * notice, this list of conditions and the following disclaimer in the 14 1.1 knakahar * documentation and/or other materials provided with the distribution. 15 1.1 knakahar * 16 1.1 knakahar * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 1.1 knakahar * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 1.1 knakahar * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 1.1 knakahar * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 1.1 knakahar * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 1.1 knakahar * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 1.1 knakahar * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 1.1 knakahar * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 1.1 knakahar * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 1.1 knakahar * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 1.1 knakahar * POSSIBILITY OF SUCH DAMAGE. 27 1.1 knakahar */ 28 1.1 knakahar 29 1.1 knakahar #include <sys/cdefs.h> 30 1.24 ozaki __KERNEL_RCSID(0, "$NetBSD: ipsecif.c,v 1.24 2025/06/11 02:44:13 ozaki-r Exp $"); 31 1.1 knakahar 32 1.1 knakahar #ifdef _KERNEL_OPT 33 1.1 knakahar #include "opt_inet.h" 34 1.1 knakahar #include "opt_ipsec.h" 35 1.1 knakahar #endif 36 1.1 knakahar 37 1.1 knakahar #include <sys/param.h> 38 1.1 knakahar #include <sys/systm.h> 39 1.1 knakahar #include <sys/socket.h> 40 1.1 knakahar #include <sys/sockio.h> 41 1.1 knakahar #include <sys/mbuf.h> 42 1.1 knakahar #include <sys/errno.h> 43 1.1 knakahar #include <sys/ioctl.h> 44 1.1 knakahar #include <sys/syslog.h> 45 1.1 knakahar #include <sys/kernel.h> 46 1.1 knakahar 47 1.1 knakahar #include <net/if.h> 48 1.1 knakahar #include <net/route.h> 49 1.1 knakahar 50 1.1 knakahar #include <netinet/in.h> 51 1.1 knakahar #include <netinet/in_systm.h> 52 1.1 knakahar #include <netinet/ip.h> 53 1.1 knakahar #include <netinet/ip_var.h> 54 1.1 knakahar #include <netinet/in_var.h> 55 1.1 knakahar #include <netinet/ip_encap.h> 56 1.1 knakahar #include <netinet/ip_ecn.h> 57 1.1 knakahar #include <netinet/ip_private.h> 58 1.1 knakahar #include <netinet/udp.h> 59 1.1 knakahar 60 1.1 knakahar #ifdef INET6 61 1.1 knakahar #include <netinet/ip6.h> 62 1.1 knakahar #include <netinet6/ip6_var.h> 63 1.1 knakahar #include <netinet6/ip6_private.h> 64 1.1 knakahar #include <netinet6/in6_var.h> 65 1.1 knakahar #include <netinet6/ip6protosw.h> /* for struct ip6ctlparam */ 66 1.1 knakahar #include <netinet/ip_ecn.h> 67 1.1 knakahar #endif 68 1.1 knakahar 69 1.1 knakahar #include <netipsec/key.h> 70 1.1 knakahar #include <netipsec/ipsecif.h> 71 1.1 knakahar 72 1.1 knakahar #include <net/if_ipsec.h> 73 1.1 knakahar 74 1.13 knakahar static int ipsecif_set_natt_ports(struct ipsec_variant *, struct mbuf *); 75 1.1 knakahar static void ipsecif4_input(struct mbuf *, int, int, void *); 76 1.1 knakahar static int ipsecif4_output(struct ipsec_variant *, int, struct mbuf *); 77 1.1 knakahar static int ipsecif4_filter4(const struct ip *, struct ipsec_variant *, 78 1.1 knakahar struct ifnet *); 79 1.1 knakahar 80 1.1 knakahar #ifdef INET6 81 1.1 knakahar static int ipsecif6_input(struct mbuf **, int *, int, void *); 82 1.1 knakahar static int ipsecif6_output(struct ipsec_variant *, int, struct mbuf *); 83 1.1 knakahar static int ipsecif6_filter6(const struct ip6_hdr *, struct ipsec_variant *, 84 1.1 knakahar struct ifnet *); 85 1.1 knakahar #endif 86 1.1 knakahar 87 1.1 knakahar static int ip_ipsec_ttl = IPSEC_TTL; 88 1.1 knakahar static int ip_ipsec_copy_tos = 0; 89 1.1 knakahar #ifdef INET6 90 1.18 knakahar int ip6_ipsec_hlim = IPSEC_HLIM; 91 1.18 knakahar int ip6_ipsec_pmtu = 0; 92 1.1 knakahar static int ip6_ipsec_copy_tos = 0; 93 1.1 knakahar #endif 94 1.1 knakahar 95 1.9 maxv static const struct encapsw ipsecif4_encapsw = { 96 1.1 knakahar .encapsw4 = { 97 1.1 knakahar .pr_input = ipsecif4_input, 98 1.1 knakahar .pr_ctlinput = NULL, 99 1.1 knakahar } 100 1.1 knakahar }; 101 1.1 knakahar 102 1.1 knakahar #ifdef INET6 103 1.1 knakahar static const struct encapsw ipsecif6_encapsw; 104 1.1 knakahar #endif 105 1.1 knakahar 106 1.13 knakahar static int 107 1.13 knakahar ipsecif_set_natt_ports(struct ipsec_variant *var, struct mbuf *m) 108 1.13 knakahar { 109 1.13 knakahar 110 1.13 knakahar KASSERT(if_ipsec_heldref_variant(var)); 111 1.13 knakahar 112 1.13 knakahar if (var->iv_sport || var->iv_dport) { 113 1.13 knakahar struct m_tag *mtag; 114 1.13 knakahar 115 1.13 knakahar mtag = m_tag_get(PACKET_TAG_IPSEC_NAT_T_PORTS, 116 1.13 knakahar sizeof(uint16_t) + sizeof(uint16_t), M_DONTWAIT); 117 1.13 knakahar if (mtag) { 118 1.13 knakahar uint16_t *natt_port; 119 1.13 knakahar 120 1.13 knakahar natt_port = (uint16_t *)(mtag + 1); 121 1.13 knakahar natt_port[0] = var->iv_dport; 122 1.13 knakahar natt_port[1] = var->iv_sport; 123 1.13 knakahar m_tag_prepend(m, mtag); 124 1.13 knakahar } else { 125 1.13 knakahar return ENOBUFS; 126 1.13 knakahar } 127 1.13 knakahar } 128 1.13 knakahar 129 1.13 knakahar return 0; 130 1.13 knakahar } 131 1.13 knakahar 132 1.1 knakahar static struct mbuf * 133 1.1 knakahar ipsecif4_prepend_hdr(struct ipsec_variant *var, struct mbuf *m, 134 1.1 knakahar uint8_t proto, uint8_t tos) 135 1.1 knakahar { 136 1.1 knakahar struct ip *ip; 137 1.1 knakahar struct sockaddr_in *src, *dst; 138 1.1 knakahar 139 1.1 knakahar src = satosin(var->iv_psrc); 140 1.1 knakahar dst = satosin(var->iv_pdst); 141 1.1 knakahar 142 1.1 knakahar if (in_nullhost(src->sin_addr) || in_nullhost(src->sin_addr) || 143 1.1 knakahar src->sin_addr.s_addr == INADDR_BROADCAST || 144 1.1 knakahar dst->sin_addr.s_addr == INADDR_BROADCAST) { 145 1.1 knakahar m_freem(m); 146 1.1 knakahar return NULL; 147 1.1 knakahar } 148 1.1 knakahar m->m_flags &= ~M_BCAST; 149 1.1 knakahar 150 1.1 knakahar if (IN_MULTICAST(src->sin_addr.s_addr) || 151 1.2 maxv IN_MULTICAST(dst->sin_addr.s_addr)) { 152 1.1 knakahar m_freem(m); 153 1.1 knakahar return NULL; 154 1.1 knakahar } 155 1.1 knakahar 156 1.1 knakahar M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); 157 1.1 knakahar if (m && M_UNWRITABLE(m, sizeof(struct ip))) 158 1.1 knakahar m = m_pullup(m, sizeof(struct ip)); 159 1.1 knakahar if (m == NULL) 160 1.1 knakahar return NULL; 161 1.1 knakahar 162 1.1 knakahar ip = mtod(m, struct ip *); 163 1.1 knakahar ip->ip_v = IPVERSION; 164 1.1 knakahar ip->ip_off = htons(0); 165 1.6 knakahar if (m->m_pkthdr.len < IP_MINFRAGSIZE) 166 1.6 knakahar ip->ip_id = 0; 167 1.6 knakahar else 168 1.24 ozaki ip->ip_id = ip_newid(); 169 1.1 knakahar ip->ip_hl = sizeof(*ip) >> 2; 170 1.1 knakahar if (ip_ipsec_copy_tos) 171 1.1 knakahar ip->ip_tos = tos; 172 1.1 knakahar else 173 1.1 knakahar ip->ip_tos = 0; 174 1.1 knakahar ip->ip_sum = 0; 175 1.1 knakahar ip->ip_src = src->sin_addr; 176 1.1 knakahar ip->ip_dst = dst->sin_addr; 177 1.1 knakahar ip->ip_p = proto; 178 1.1 knakahar ip->ip_ttl = ip_ipsec_ttl; 179 1.1 knakahar ip->ip_len = htons(m->m_pkthdr.len); 180 1.1 knakahar #ifndef IPSEC_TX_TOS_CLEAR 181 1.1 knakahar struct ifnet *ifp = &var->iv_softc->ipsec_if; 182 1.1 knakahar if (ifp->if_flags & IFF_ECN) 183 1.1 knakahar ip_ecn_ingress(ECN_ALLOWED, &ip->ip_tos, &tos); 184 1.1 knakahar else 185 1.1 knakahar ip_ecn_ingress(ECN_NOCARE, &ip->ip_tos, &tos); 186 1.1 knakahar #endif 187 1.1 knakahar 188 1.1 knakahar return m; 189 1.1 knakahar } 190 1.1 knakahar 191 1.1 knakahar static int 192 1.1 knakahar ipsecif4_needfrag(struct mbuf *m, struct ipsecrequest *isr) 193 1.1 knakahar { 194 1.1 knakahar struct ip ip0; 195 1.1 knakahar struct ip *ip; 196 1.1 knakahar int mtu; 197 1.1 knakahar struct secasvar *sav; 198 1.1 knakahar 199 1.1 knakahar sav = key_lookup_sa_bysaidx(&isr->saidx); 200 1.1 knakahar if (sav == NULL) 201 1.1 knakahar return 0; 202 1.1 knakahar 203 1.10 maxv if (!(sav->natt_type & UDP_ENCAP_ESPINUDP)) { 204 1.1 knakahar mtu = 0; 205 1.1 knakahar goto out; 206 1.1 knakahar } 207 1.1 knakahar 208 1.1 knakahar if (m->m_len < sizeof(struct ip)) { 209 1.1 knakahar m_copydata(m, 0, sizeof(ip0), &ip0); 210 1.1 knakahar ip = &ip0; 211 1.1 knakahar } else { 212 1.1 knakahar ip = mtod(m, struct ip *); 213 1.1 knakahar } 214 1.1 knakahar mtu = sav->esp_frag; 215 1.1 knakahar if (ntohs(ip->ip_len) <= mtu) 216 1.1 knakahar mtu = 0; 217 1.1 knakahar 218 1.1 knakahar out: 219 1.1 knakahar KEY_SA_UNREF(&sav); 220 1.1 knakahar return mtu; 221 1.1 knakahar } 222 1.1 knakahar 223 1.1 knakahar static struct mbuf * 224 1.1 knakahar ipsecif4_flowinfo(struct mbuf *m, int family, int *proto0, u_int8_t *tos0) 225 1.1 knakahar { 226 1.1 knakahar const struct ip *ip; 227 1.1 knakahar int proto; 228 1.1 knakahar int tos; 229 1.1 knakahar 230 1.1 knakahar KASSERT(proto0 != NULL); 231 1.1 knakahar KASSERT(tos0 != NULL); 232 1.1 knakahar 233 1.1 knakahar switch (family) { 234 1.1 knakahar case AF_INET: 235 1.1 knakahar proto = IPPROTO_IPV4; 236 1.1 knakahar if (m->m_len < sizeof(*ip)) { 237 1.1 knakahar m = m_pullup(m, sizeof(*ip)); 238 1.2 maxv if (m == NULL) { 239 1.1 knakahar *tos0 = 0; 240 1.1 knakahar *proto0 = 0; 241 1.2 maxv return NULL; 242 1.1 knakahar } 243 1.1 knakahar } 244 1.1 knakahar ip = mtod(m, const struct ip *); 245 1.1 knakahar tos = ip->ip_tos; 246 1.22 andvar /* TODO: support ALTQ for inner packet */ 247 1.1 knakahar break; 248 1.1 knakahar #ifdef INET6 249 1.1 knakahar case AF_INET6: { 250 1.1 knakahar const struct ip6_hdr *ip6; 251 1.1 knakahar proto = IPPROTO_IPV6; 252 1.1 knakahar if (m->m_len < sizeof(*ip6)) { 253 1.1 knakahar m = m_pullup(m, sizeof(*ip6)); 254 1.2 maxv if (m == NULL) { 255 1.1 knakahar *tos0 = 0; 256 1.1 knakahar *proto0 = 0; 257 1.1 knakahar return NULL; 258 1.1 knakahar } 259 1.1 knakahar } 260 1.1 knakahar ip6 = mtod(m, const struct ip6_hdr *); 261 1.1 knakahar tos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; 262 1.22 andvar /* TODO: support ALTQ for inner packet */ 263 1.1 knakahar break; 264 1.1 knakahar } 265 1.1 knakahar #endif /* INET6 */ 266 1.1 knakahar default: 267 1.1 knakahar *tos0 = 0; 268 1.1 knakahar *proto0 = 0; 269 1.1 knakahar return NULL; 270 1.1 knakahar } 271 1.1 knakahar 272 1.1 knakahar *proto0 = proto; 273 1.1 knakahar *tos0 = tos; 274 1.1 knakahar return m; 275 1.1 knakahar } 276 1.1 knakahar 277 1.1 knakahar static int 278 1.1 knakahar ipsecif4_fragout(struct ipsec_variant *var, int family, struct mbuf *m, int mtu) 279 1.1 knakahar { 280 1.1 knakahar struct ifnet *ifp = &var->iv_softc->ipsec_if; 281 1.1 knakahar struct mbuf *next; 282 1.1 knakahar struct m_tag *mtag; 283 1.1 knakahar int error; 284 1.1 knakahar 285 1.1 knakahar KASSERT(if_ipsec_heldref_variant(var)); 286 1.1 knakahar 287 1.11 maxv mtag = m_tag_find(m, PACKET_TAG_IPSEC_NAT_T_PORTS); 288 1.1 knakahar if (mtag) 289 1.1 knakahar m_tag_delete(m, mtag); 290 1.1 knakahar 291 1.4 knakahar /* consider new IP header prepended in ipsecif4_output() */ 292 1.4 knakahar if (mtu <= sizeof(struct ip)) { 293 1.4 knakahar m_freem(m); 294 1.4 knakahar return ENETUNREACH; 295 1.4 knakahar } 296 1.4 knakahar m->m_pkthdr.csum_flags |= M_CSUM_IPv4; 297 1.4 knakahar error = ip_fragment(m, ifp, mtu - sizeof(struct ip)); 298 1.1 knakahar if (error) 299 1.1 knakahar return error; 300 1.1 knakahar 301 1.1 knakahar for (error = 0; m; m = next) { 302 1.1 knakahar next = m->m_nextpkt; 303 1.3 knakahar m->m_nextpkt = NULL; 304 1.1 knakahar if (error) { 305 1.1 knakahar m_freem(m); 306 1.1 knakahar continue; 307 1.1 knakahar } 308 1.1 knakahar 309 1.1 knakahar error = ipsecif4_output(var, family, m); 310 1.1 knakahar } 311 1.1 knakahar if (error == 0) 312 1.1 knakahar IP_STATINC(IP_STAT_FRAGMENTED); 313 1.1 knakahar 314 1.1 knakahar return error; 315 1.1 knakahar } 316 1.1 knakahar 317 1.1 knakahar int 318 1.1 knakahar ipsecif4_encap_func(struct mbuf *m, struct ip *ip, struct ipsec_variant *var) 319 1.1 knakahar { 320 1.1 knakahar struct m_tag *mtag; 321 1.1 knakahar struct sockaddr_in *src, *dst; 322 1.1 knakahar u_int16_t src_port = 0; 323 1.1 knakahar u_int16_t dst_port = 0; 324 1.1 knakahar 325 1.1 knakahar KASSERT(var != NULL); 326 1.1 knakahar 327 1.1 knakahar src = satosin(var->iv_psrc); 328 1.1 knakahar dst = satosin(var->iv_pdst); 329 1.11 maxv mtag = m_tag_find(m, PACKET_TAG_IPSEC_NAT_T_PORTS); 330 1.1 knakahar if (mtag) { 331 1.1 knakahar u_int16_t *ports; 332 1.1 knakahar 333 1.1 knakahar ports = (u_int16_t *)(mtag + 1); 334 1.1 knakahar src_port = ports[0]; 335 1.1 knakahar dst_port = ports[1]; 336 1.1 knakahar } 337 1.1 knakahar 338 1.1 knakahar /* address match */ 339 1.1 knakahar if (src->sin_addr.s_addr != ip->ip_dst.s_addr || 340 1.1 knakahar dst->sin_addr.s_addr != ip->ip_src.s_addr) 341 1.1 knakahar return 0; 342 1.1 knakahar 343 1.1 knakahar /* UDP encap? */ 344 1.1 knakahar if (mtag == NULL && var->iv_sport == 0 && var->iv_dport == 0) 345 1.1 knakahar goto match; 346 1.1 knakahar 347 1.1 knakahar /* port match */ 348 1.1 knakahar if (src_port != var->iv_dport || 349 1.1 knakahar dst_port != var->iv_sport) { 350 1.1 knakahar #ifdef DEBUG 351 1.1 knakahar printf("%s: port mismatch: pkt(%u, %u), if(%u, %u)\n", 352 1.1 knakahar __func__, ntohs(src_port), ntohs(dst_port), 353 1.1 knakahar ntohs(var->iv_sport), ntohs(var->iv_dport)); 354 1.1 knakahar #endif 355 1.1 knakahar return 0; 356 1.1 knakahar } 357 1.1 knakahar 358 1.1 knakahar match: 359 1.1 knakahar /* 360 1.1 knakahar * hide NAT-T information from encapsulated traffics. 361 1.1 knakahar * they don't know about IPsec. 362 1.1 knakahar */ 363 1.1 knakahar if (mtag) 364 1.1 knakahar m_tag_delete(m, mtag); 365 1.1 knakahar return sizeof(src->sin_addr) + sizeof(dst->sin_addr); 366 1.1 knakahar } 367 1.1 knakahar 368 1.1 knakahar static int 369 1.1 knakahar ipsecif4_output(struct ipsec_variant *var, int family, struct mbuf *m) 370 1.1 knakahar { 371 1.1 knakahar struct secpolicy *sp = NULL; 372 1.1 knakahar u_int8_t tos; 373 1.1 knakahar int proto; 374 1.1 knakahar int error; 375 1.1 knakahar int mtu; 376 1.1 knakahar u_long sa_mtu = 0; 377 1.1 knakahar 378 1.1 knakahar KASSERT(if_ipsec_heldref_variant(var)); 379 1.1 knakahar KASSERT(if_ipsec_variant_is_configured(var)); 380 1.1 knakahar KASSERT(var->iv_psrc->sa_family == AF_INET); 381 1.1 knakahar KASSERT(var->iv_pdst->sa_family == AF_INET); 382 1.1 knakahar 383 1.19 knakahar switch (family) { 384 1.19 knakahar case AF_INET: 385 1.19 knakahar sp = IV_SP_OUT(var); 386 1.19 knakahar break; 387 1.19 knakahar case AF_INET6: 388 1.19 knakahar sp = IV_SP_OUT6(var); 389 1.19 knakahar break; 390 1.19 knakahar default: 391 1.19 knakahar m_freem(m); 392 1.19 knakahar return EAFNOSUPPORT; 393 1.19 knakahar } 394 1.1 knakahar KASSERT(sp != NULL); 395 1.1 knakahar /* 396 1.1 knakahar * The SPs in ipsec_variant are prevented from freed by 397 1.1 knakahar * ipsec_variant->iv_psref. So, KEY_SP_REF() is unnecessary here. 398 1.21 knakahar * 399 1.21 knakahar * However, lastused should be updated. 400 1.1 knakahar */ 401 1.21 knakahar key_sp_touch(sp); 402 1.1 knakahar 403 1.1 knakahar KASSERT(sp->policy != IPSEC_POLICY_NONE); 404 1.1 knakahar KASSERT(sp->policy != IPSEC_POLICY_ENTRUST); 405 1.1 knakahar KASSERT(sp->policy != IPSEC_POLICY_BYPASS); 406 1.2 maxv if (sp->policy != IPSEC_POLICY_IPSEC) { 407 1.1 knakahar m_freem(m); 408 1.12 knakahar error = ENETUNREACH; 409 1.12 knakahar goto done; 410 1.1 knakahar } 411 1.1 knakahar 412 1.1 knakahar /* get flowinfo */ 413 1.1 knakahar m = ipsecif4_flowinfo(m, family, &proto, &tos); 414 1.1 knakahar if (m == NULL) { 415 1.1 knakahar error = ENETUNREACH; 416 1.1 knakahar goto done; 417 1.1 knakahar } 418 1.1 knakahar 419 1.1 knakahar /* prepend new IP header */ 420 1.1 knakahar m = ipsecif4_prepend_hdr(var, m, proto, tos); 421 1.1 knakahar if (m == NULL) { 422 1.1 knakahar error = ENETUNREACH; 423 1.1 knakahar goto done; 424 1.1 knakahar } 425 1.1 knakahar 426 1.1 knakahar /* 427 1.1 knakahar * Normal netipsec's NAT-T fragmentation is done in ip_output(). 428 1.1 knakahar * See "natt_frag" processing. 429 1.1 knakahar * However, ipsec(4) interface's one is not done in the same way, 430 1.1 knakahar * so we must do NAT-T fragmentation by own code. 431 1.1 knakahar */ 432 1.1 knakahar /* NAT-T ESP fragmentation */ 433 1.1 knakahar mtu = ipsecif4_needfrag(m, sp->req); 434 1.1 knakahar if (mtu > 0) 435 1.1 knakahar return ipsecif4_fragout(var, family, m, mtu); 436 1.1 knakahar 437 1.13 knakahar /* set NAT-T ports */ 438 1.13 knakahar error = ipsecif_set_natt_ports(var, m); 439 1.13 knakahar if (error) { 440 1.13 knakahar m_freem(m); 441 1.13 knakahar goto done; 442 1.13 knakahar } 443 1.13 knakahar 444 1.1 knakahar /* IPsec output */ 445 1.1 knakahar IP_STATINC(IP_STAT_LOCALOUT); 446 1.1 knakahar error = ipsec4_process_packet(m, sp->req, &sa_mtu); 447 1.1 knakahar if (error == ENOENT) 448 1.1 knakahar error = 0; 449 1.1 knakahar /* 450 1.23 andvar * fragmentation is already done in ipsecif4_fragout(), 451 1.1 knakahar * so ipsec4_process_packet() must not do fragmentation here. 452 1.1 knakahar */ 453 1.4 knakahar KASSERT(sa_mtu == 0); 454 1.1 knakahar 455 1.1 knakahar done: 456 1.1 knakahar return error; 457 1.1 knakahar } 458 1.1 knakahar 459 1.1 knakahar #ifdef INET6 460 1.7 knakahar int 461 1.7 knakahar ipsecif6_encap_func(struct mbuf *m, struct ip6_hdr *ip6, struct ipsec_variant *var) 462 1.7 knakahar { 463 1.7 knakahar struct m_tag *mtag; 464 1.7 knakahar struct sockaddr_in6 *src, *dst; 465 1.7 knakahar u_int16_t src_port = 0; 466 1.7 knakahar u_int16_t dst_port = 0; 467 1.7 knakahar 468 1.7 knakahar KASSERT(var != NULL); 469 1.7 knakahar 470 1.7 knakahar src = satosin6(var->iv_psrc); 471 1.7 knakahar dst = satosin6(var->iv_pdst); 472 1.11 maxv mtag = m_tag_find(m, PACKET_TAG_IPSEC_NAT_T_PORTS); 473 1.7 knakahar if (mtag) { 474 1.7 knakahar u_int16_t *ports; 475 1.7 knakahar 476 1.7 knakahar ports = (u_int16_t *)(mtag + 1); 477 1.7 knakahar src_port = ports[0]; 478 1.7 knakahar dst_port = ports[1]; 479 1.7 knakahar } 480 1.7 knakahar 481 1.7 knakahar /* address match */ 482 1.7 knakahar if (!IN6_ARE_ADDR_EQUAL(&src->sin6_addr, &ip6->ip6_dst) || 483 1.7 knakahar !IN6_ARE_ADDR_EQUAL(&dst->sin6_addr, &ip6->ip6_src)) 484 1.7 knakahar return 0; 485 1.7 knakahar 486 1.7 knakahar /* UDP encap? */ 487 1.7 knakahar if (mtag == NULL && var->iv_sport == 0 && var->iv_dport == 0) 488 1.7 knakahar goto match; 489 1.7 knakahar 490 1.7 knakahar /* port match */ 491 1.7 knakahar if (src_port != var->iv_dport || 492 1.7 knakahar dst_port != var->iv_sport) { 493 1.7 knakahar #ifdef DEBUG 494 1.7 knakahar printf("%s: port mismatch: pkt(%u, %u), if(%u, %u)\n", 495 1.7 knakahar __func__, ntohs(src_port), ntohs(dst_port), 496 1.7 knakahar ntohs(var->iv_sport), ntohs(var->iv_dport)); 497 1.7 knakahar #endif 498 1.7 knakahar return 0; 499 1.7 knakahar } 500 1.7 knakahar 501 1.7 knakahar match: 502 1.7 knakahar /* 503 1.7 knakahar * hide NAT-T information from encapsulated traffics. 504 1.7 knakahar * they don't know about IPsec. 505 1.7 knakahar */ 506 1.7 knakahar if (mtag) 507 1.7 knakahar m_tag_delete(m, mtag); 508 1.7 knakahar return sizeof(src->sin6_addr) + sizeof(dst->sin6_addr); 509 1.7 knakahar } 510 1.7 knakahar 511 1.1 knakahar static int 512 1.1 knakahar ipsecif6_output(struct ipsec_variant *var, int family, struct mbuf *m) 513 1.1 knakahar { 514 1.1 knakahar struct ifnet *ifp = &var->iv_softc->ipsec_if; 515 1.1 knakahar struct ipsec_softc *sc = ifp->if_softc; 516 1.17 knakahar struct route *ro_pc; 517 1.17 knakahar kmutex_t *lock_pc; 518 1.1 knakahar struct rtentry *rt; 519 1.1 knakahar struct sockaddr_in6 *sin6_src; 520 1.1 knakahar struct sockaddr_in6 *sin6_dst; 521 1.1 knakahar struct ip6_hdr *ip6; 522 1.18 knakahar int proto, error, flags; 523 1.1 knakahar u_int8_t itos, otos; 524 1.1 knakahar union { 525 1.1 knakahar struct sockaddr dst; 526 1.1 knakahar struct sockaddr_in6 dst6; 527 1.1 knakahar } u; 528 1.1 knakahar 529 1.1 knakahar KASSERT(if_ipsec_heldref_variant(var)); 530 1.1 knakahar KASSERT(if_ipsec_variant_is_configured(var)); 531 1.1 knakahar 532 1.1 knakahar sin6_src = satosin6(var->iv_psrc); 533 1.1 knakahar sin6_dst = satosin6(var->iv_pdst); 534 1.1 knakahar 535 1.1 knakahar KASSERT(sin6_src->sin6_family == AF_INET6); 536 1.1 knakahar KASSERT(sin6_dst->sin6_family == AF_INET6); 537 1.1 knakahar 538 1.1 knakahar switch (family) { 539 1.1 knakahar #ifdef INET 540 1.1 knakahar case AF_INET: 541 1.1 knakahar { 542 1.1 knakahar struct ip *ip; 543 1.1 knakahar 544 1.1 knakahar proto = IPPROTO_IPV4; 545 1.1 knakahar if (m->m_len < sizeof(*ip)) { 546 1.1 knakahar m = m_pullup(m, sizeof(*ip)); 547 1.2 maxv if (m == NULL) 548 1.1 knakahar return ENOBUFS; 549 1.1 knakahar } 550 1.1 knakahar ip = mtod(m, struct ip *); 551 1.1 knakahar itos = ip->ip_tos; 552 1.22 andvar /* TODO: support ALTQ for inner packet */ 553 1.1 knakahar break; 554 1.1 knakahar } 555 1.1 knakahar #endif /* INET */ 556 1.1 knakahar case AF_INET6: 557 1.1 knakahar { 558 1.1 knakahar struct ip6_hdr *xip6; 559 1.1 knakahar proto = IPPROTO_IPV6; 560 1.1 knakahar if (m->m_len < sizeof(*xip6)) { 561 1.1 knakahar m = m_pullup(m, sizeof(*xip6)); 562 1.2 maxv if (m == NULL) 563 1.1 knakahar return ENOBUFS; 564 1.1 knakahar } 565 1.1 knakahar xip6 = mtod(m, struct ip6_hdr *); 566 1.1 knakahar itos = (ntohl(xip6->ip6_flow) >> 20) & 0xff; 567 1.22 andvar /* TODO: support ALTQ for inner packet */ 568 1.1 knakahar break; 569 1.1 knakahar } 570 1.1 knakahar default: 571 1.1 knakahar m_freem(m); 572 1.1 knakahar return EAFNOSUPPORT; 573 1.1 knakahar } 574 1.1 knakahar 575 1.1 knakahar /* prepend new IP header */ 576 1.1 knakahar M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT); 577 1.1 knakahar if (m && M_UNWRITABLE(m, sizeof(struct ip6_hdr))) 578 1.1 knakahar m = m_pullup(m, sizeof(struct ip6_hdr)); 579 1.1 knakahar if (m == NULL) 580 1.1 knakahar return ENOBUFS; 581 1.1 knakahar 582 1.1 knakahar ip6 = mtod(m, struct ip6_hdr *); 583 1.1 knakahar ip6->ip6_flow = 0; 584 1.1 knakahar ip6->ip6_vfc &= ~IPV6_VERSION_MASK; 585 1.1 knakahar ip6->ip6_vfc |= IPV6_VERSION; 586 1.5 knakahar #if 0 /* ip6->ip6_plen will be filled by ip6_output */ 587 1.5 knakahar ip6->ip6_plen = htons((u_short)m->m_pkthdr.len - sizeof(*ip6)); 588 1.5 knakahar #endif 589 1.1 knakahar ip6->ip6_nxt = proto; 590 1.1 knakahar ip6->ip6_hlim = ip6_ipsec_hlim; 591 1.1 knakahar ip6->ip6_src = sin6_src->sin6_addr; 592 1.1 knakahar /* bidirectional configured tunnel mode */ 593 1.1 knakahar if (!IN6_IS_ADDR_UNSPECIFIED(&sin6_dst->sin6_addr)) { 594 1.1 knakahar ip6->ip6_dst = sin6_dst->sin6_addr; 595 1.1 knakahar } else { 596 1.1 knakahar m_freem(m); 597 1.1 knakahar return ENETUNREACH; 598 1.1 knakahar } 599 1.1 knakahar #ifndef IPSEC_TX_TOS_CLEAR 600 1.16 knakahar if (!ip6_ipsec_copy_tos) 601 1.16 knakahar otos = 0; 602 1.16 knakahar 603 1.1 knakahar if (ifp->if_flags & IFF_ECN) 604 1.1 knakahar ip_ecn_ingress(ECN_ALLOWED, &otos, &itos); 605 1.1 knakahar else 606 1.1 knakahar ip_ecn_ingress(ECN_NOCARE, &otos, &itos); 607 1.1 knakahar #else 608 1.1 knakahar if (ip6_ipsec_copy_tos) 609 1.1 knakahar otos = itos; 610 1.1 knakahar else 611 1.1 knakahar otos = 0; 612 1.1 knakahar #endif 613 1.1 knakahar ip6->ip6_flow &= ~ntohl(0xff00000); 614 1.1 knakahar ip6->ip6_flow |= htonl((u_int32_t)otos << 20); 615 1.1 knakahar 616 1.1 knakahar sockaddr_in6_init(&u.dst6, &sin6_dst->sin6_addr, 0, 0, 0); 617 1.1 knakahar 618 1.17 knakahar if_tunnel_get_ro(sc->ipsec_ro_percpu, &ro_pc, &lock_pc); 619 1.17 knakahar if ((rt = rtcache_lookup(ro_pc, &u.dst)) == NULL) { 620 1.17 knakahar if_tunnel_put_ro(sc->ipsec_ro_percpu, lock_pc); 621 1.1 knakahar m_freem(m); 622 1.1 knakahar return ENETUNREACH; 623 1.1 knakahar } 624 1.1 knakahar 625 1.1 knakahar if (rt->rt_ifp == ifp) { 626 1.17 knakahar rtcache_unref(rt, ro_pc); 627 1.17 knakahar rtcache_free(ro_pc); 628 1.17 knakahar if_tunnel_put_ro(sc->ipsec_ro_percpu, lock_pc); 629 1.1 knakahar m_freem(m); 630 1.1 knakahar return ENETUNREACH; 631 1.1 knakahar } 632 1.17 knakahar rtcache_unref(rt, ro_pc); 633 1.1 knakahar 634 1.13 knakahar /* set NAT-T ports */ 635 1.13 knakahar error = ipsecif_set_natt_ports(var, m); 636 1.13 knakahar if (error) { 637 1.13 knakahar m_freem(m); 638 1.13 knakahar goto out; 639 1.13 knakahar } 640 1.13 knakahar 641 1.1 knakahar /* 642 1.18 knakahar * - IPSEC_PMTU_MINMTU 643 1.18 knakahar * Force fragmentation to minimum MTU to avoid path MTU discovery 644 1.18 knakahar * - IPSEC_PMTU_OUTERMTU 645 1.18 knakahar * Trust outer MTU is large enough to send all packets 646 1.18 knakahar * 647 1.18 knakahar * It is too painful to ask for resend of inner packet, to achieve 648 1.1 knakahar * path MTU discovery for encapsulated packets. 649 1.18 knakahar * 650 1.18 knakahar * See RFC4459. 651 1.1 knakahar */ 652 1.18 knakahar if (sc->ipsec_pmtu == IPSEC_PMTU_SYSDEFAULT) { 653 1.18 knakahar switch (ip6_ipsec_pmtu) { 654 1.18 knakahar case IPSEC_PMTU_MINMTU: 655 1.18 knakahar flags = IPV6_MINMTU; 656 1.18 knakahar break; 657 1.18 knakahar case IPSEC_PMTU_OUTERMTU: 658 1.18 knakahar flags = 0; 659 1.18 knakahar break; 660 1.18 knakahar default: 661 1.18 knakahar #ifdef DEBUG 662 1.18 knakahar log(LOG_DEBUG, "%s: ignore unexpected ip6_ipsec_pmtu %d\n", 663 1.18 knakahar __func__, ip6_ipsec_pmtu); 664 1.18 knakahar #endif 665 1.18 knakahar flags = IPV6_MINMTU; 666 1.18 knakahar break; 667 1.18 knakahar } 668 1.18 knakahar } else { 669 1.18 knakahar switch (sc->ipsec_pmtu) { 670 1.18 knakahar case IPSEC_PMTU_MINMTU: 671 1.18 knakahar flags = IPV6_MINMTU; 672 1.18 knakahar break; 673 1.18 knakahar case IPSEC_PMTU_OUTERMTU: 674 1.18 knakahar flags = 0; 675 1.18 knakahar break; 676 1.18 knakahar default: 677 1.18 knakahar #ifdef DEBUG 678 1.18 knakahar log(LOG_DEBUG, "%s: ignore unexpected ipsec_pmtu of %s %d\n", 679 1.18 knakahar __func__, ifp->if_xname, sc->ipsec_pmtu); 680 1.18 knakahar #endif 681 1.18 knakahar flags = IPV6_MINMTU; 682 1.18 knakahar break; 683 1.18 knakahar } 684 1.18 knakahar } 685 1.18 knakahar error = ip6_output(m, 0, ro_pc, flags, 0, NULL, NULL); 686 1.13 knakahar 687 1.13 knakahar out: 688 1.1 knakahar if (error) 689 1.17 knakahar rtcache_free(ro_pc); 690 1.17 knakahar if_tunnel_put_ro(sc->ipsec_ro_percpu, lock_pc); 691 1.1 knakahar 692 1.1 knakahar return error; 693 1.1 knakahar } 694 1.1 knakahar #endif /* INET6 */ 695 1.1 knakahar 696 1.1 knakahar static void 697 1.1 knakahar ipsecif4_input(struct mbuf *m, int off, int proto, void *eparg) 698 1.1 knakahar { 699 1.1 knakahar struct ifnet *ipsecp; 700 1.1 knakahar struct ipsec_softc *sc = eparg; 701 1.1 knakahar struct ipsec_variant *var; 702 1.1 knakahar const struct ip *ip; 703 1.1 knakahar int af; 704 1.1 knakahar #ifndef IPSEC_TX_TOS_CLEAR 705 1.1 knakahar u_int8_t otos; 706 1.1 knakahar #endif 707 1.1 knakahar struct psref psref_rcvif; 708 1.1 knakahar struct psref psref_var; 709 1.1 knakahar struct ifnet *rcvif; 710 1.1 knakahar 711 1.1 knakahar KASSERT(sc != NULL); 712 1.1 knakahar 713 1.1 knakahar ipsecp = &sc->ipsec_if; 714 1.1 knakahar if ((ipsecp->if_flags & IFF_UP) == 0) { 715 1.1 knakahar m_freem(m); 716 1.1 knakahar ip_statinc(IP_STAT_NOIPSEC); 717 1.1 knakahar return; 718 1.1 knakahar } 719 1.1 knakahar 720 1.1 knakahar var = if_ipsec_getref_variant(sc, &psref_var); 721 1.1 knakahar if (if_ipsec_variant_is_unconfigured(var)) { 722 1.1 knakahar if_ipsec_putref_variant(var, &psref_var); 723 1.1 knakahar m_freem(m); 724 1.1 knakahar ip_statinc(IP_STAT_NOIPSEC); 725 1.1 knakahar return; 726 1.1 knakahar } 727 1.1 knakahar 728 1.1 knakahar ip = mtod(m, const struct ip *); 729 1.1 knakahar 730 1.1 knakahar rcvif = m_get_rcvif_psref(m, &psref_rcvif); 731 1.1 knakahar if (rcvif == NULL || !ipsecif4_filter4(ip, var, rcvif)) { 732 1.1 knakahar m_put_rcvif_psref(rcvif, &psref_rcvif); 733 1.1 knakahar if_ipsec_putref_variant(var, &psref_var); 734 1.1 knakahar m_freem(m); 735 1.1 knakahar ip_statinc(IP_STAT_NOIPSEC); 736 1.1 knakahar return; 737 1.1 knakahar } 738 1.1 knakahar m_put_rcvif_psref(rcvif, &psref_rcvif); 739 1.1 knakahar if_ipsec_putref_variant(var, &psref_var); 740 1.1 knakahar #ifndef IPSEC_TX_TOS_CLEAR 741 1.1 knakahar otos = ip->ip_tos; 742 1.1 knakahar #endif 743 1.1 knakahar m_adj(m, off); 744 1.1 knakahar 745 1.1 knakahar switch (proto) { 746 1.1 knakahar case IPPROTO_IPV4: 747 1.1 knakahar { 748 1.1 knakahar struct ip *xip; 749 1.1 knakahar af = AF_INET; 750 1.1 knakahar if (M_UNWRITABLE(m, sizeof(*xip))) { 751 1.1 knakahar m = m_pullup(m, sizeof(*xip)); 752 1.2 maxv if (m == NULL) 753 1.1 knakahar return; 754 1.1 knakahar } 755 1.1 knakahar xip = mtod(m, struct ip *); 756 1.1 knakahar #ifndef IPSEC_TX_TOS_CLEAR 757 1.1 knakahar if (ipsecp->if_flags & IFF_ECN) 758 1.1 knakahar ip_ecn_egress(ECN_ALLOWED, &otos, &xip->ip_tos); 759 1.1 knakahar else 760 1.1 knakahar ip_ecn_egress(ECN_NOCARE, &otos, &xip->ip_tos); 761 1.1 knakahar #endif 762 1.1 knakahar break; 763 1.1 knakahar } 764 1.1 knakahar #ifdef INET6 765 1.1 knakahar case IPPROTO_IPV6: 766 1.1 knakahar { 767 1.1 knakahar struct ip6_hdr *ip6; 768 1.1 knakahar u_int8_t itos; 769 1.1 knakahar af = AF_INET6; 770 1.1 knakahar if (M_UNWRITABLE(m, sizeof(*ip6))) { 771 1.1 knakahar m = m_pullup(m, sizeof(*ip6)); 772 1.2 maxv if (m == NULL) 773 1.1 knakahar return; 774 1.1 knakahar } 775 1.1 knakahar ip6 = mtod(m, struct ip6_hdr *); 776 1.1 knakahar itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; 777 1.1 knakahar #ifndef IPSEC_TX_TOS_CLEAR 778 1.1 knakahar if (ipsecp->if_flags & IFF_ECN) 779 1.1 knakahar ip_ecn_egress(ECN_ALLOWED, &otos, &itos); 780 1.1 knakahar else 781 1.1 knakahar ip_ecn_egress(ECN_NOCARE, &otos, &itos); 782 1.1 knakahar #endif 783 1.1 knakahar ip6->ip6_flow &= ~htonl(0xff << 20); 784 1.1 knakahar ip6->ip6_flow |= htonl((u_int32_t)itos << 20); 785 1.1 knakahar break; 786 1.1 knakahar } 787 1.1 knakahar #endif /* INET6 */ 788 1.1 knakahar default: 789 1.1 knakahar ip_statinc(IP_STAT_NOIPSEC); 790 1.1 knakahar m_freem(m); 791 1.1 knakahar return; 792 1.1 knakahar } 793 1.1 knakahar if_ipsec_input(m, af, ipsecp); 794 1.1 knakahar 795 1.1 knakahar return; 796 1.1 knakahar } 797 1.1 knakahar 798 1.1 knakahar /* 799 1.14 msaitoh * validate and filter the packet 800 1.1 knakahar */ 801 1.1 knakahar static int 802 1.1 knakahar ipsecif4_filter4(const struct ip *ip, struct ipsec_variant *var, 803 1.1 knakahar struct ifnet *ifp) 804 1.1 knakahar { 805 1.1 knakahar struct sockaddr_in *src, *dst; 806 1.1 knakahar 807 1.1 knakahar src = satosin(var->iv_psrc); 808 1.1 knakahar dst = satosin(var->iv_pdst); 809 1.1 knakahar 810 1.1 knakahar return in_tunnel_validate(ip, src->sin_addr, dst->sin_addr); 811 1.1 knakahar } 812 1.1 knakahar 813 1.1 knakahar #ifdef INET6 814 1.1 knakahar static int 815 1.1 knakahar ipsecif6_input(struct mbuf **mp, int *offp, int proto, void *eparg) 816 1.1 knakahar { 817 1.1 knakahar struct mbuf *m = *mp; 818 1.1 knakahar struct ifnet *ipsecp; 819 1.1 knakahar struct ipsec_softc *sc = eparg; 820 1.1 knakahar struct ipsec_variant *var; 821 1.1 knakahar struct ip6_hdr *ip6; 822 1.1 knakahar int af = 0; 823 1.1 knakahar #ifndef IPSEC_TX_TOS_CLEAR 824 1.1 knakahar u_int32_t otos; 825 1.1 knakahar #endif 826 1.1 knakahar struct psref psref_rcvif; 827 1.1 knakahar struct psref psref_var; 828 1.1 knakahar struct ifnet *rcvif; 829 1.1 knakahar 830 1.1 knakahar KASSERT(eparg != NULL); 831 1.1 knakahar 832 1.1 knakahar ipsecp = &sc->ipsec_if; 833 1.1 knakahar if ((ipsecp->if_flags & IFF_UP) == 0) { 834 1.1 knakahar m_freem(m); 835 1.1 knakahar IP6_STATINC(IP6_STAT_NOIPSEC); 836 1.1 knakahar return IPPROTO_DONE; 837 1.1 knakahar } 838 1.1 knakahar 839 1.1 knakahar var = if_ipsec_getref_variant(sc, &psref_var); 840 1.1 knakahar if (if_ipsec_variant_is_unconfigured(var)) { 841 1.1 knakahar if_ipsec_putref_variant(var, &psref_var); 842 1.1 knakahar m_freem(m); 843 1.1 knakahar IP6_STATINC(IP6_STAT_NOIPSEC); 844 1.1 knakahar return IPPROTO_DONE; 845 1.1 knakahar } 846 1.1 knakahar 847 1.1 knakahar ip6 = mtod(m, struct ip6_hdr *); 848 1.1 knakahar 849 1.1 knakahar rcvif = m_get_rcvif_psref(m, &psref_rcvif); 850 1.1 knakahar if (rcvif == NULL || !ipsecif6_filter6(ip6, var, rcvif)) { 851 1.1 knakahar m_put_rcvif_psref(rcvif, &psref_rcvif); 852 1.1 knakahar if_ipsec_putref_variant(var, &psref_var); 853 1.1 knakahar m_freem(m); 854 1.1 knakahar IP6_STATINC(IP6_STAT_NOIPSEC); 855 1.1 knakahar return IPPROTO_DONE; 856 1.1 knakahar } 857 1.1 knakahar m_put_rcvif_psref(rcvif, &psref_rcvif); 858 1.1 knakahar if_ipsec_putref_variant(var, &psref_var); 859 1.1 knakahar 860 1.1 knakahar #ifndef IPSEC_TX_TOS_CLEAR 861 1.1 knakahar otos = ip6->ip6_flow; 862 1.1 knakahar #endif 863 1.1 knakahar m_adj(m, *offp); 864 1.1 knakahar 865 1.1 knakahar switch (proto) { 866 1.1 knakahar #ifdef INET 867 1.1 knakahar case IPPROTO_IPV4: 868 1.1 knakahar { 869 1.1 knakahar af = AF_INET; 870 1.1 knakahar #ifndef IPSEC_TX_TOS_CLEAR 871 1.1 knakahar struct ip *ip; 872 1.1 knakahar u_int8_t otos8; 873 1.1 knakahar otos8 = (ntohl(otos) >> 20) & 0xff; 874 1.1 knakahar 875 1.1 knakahar if (M_UNWRITABLE(m, sizeof(*ip))) { 876 1.1 knakahar m = m_pullup(m, sizeof(*ip)); 877 1.2 maxv if (m == NULL) 878 1.1 knakahar return IPPROTO_DONE; 879 1.1 knakahar } 880 1.1 knakahar ip = mtod(m, struct ip *); 881 1.1 knakahar if (ipsecp->if_flags & IFF_ECN) 882 1.1 knakahar ip_ecn_egress(ECN_ALLOWED, &otos8, &ip->ip_tos); 883 1.1 knakahar else 884 1.1 knakahar ip_ecn_egress(ECN_NOCARE, &otos8, &ip->ip_tos); 885 1.1 knakahar #endif 886 1.1 knakahar break; 887 1.1 knakahar } 888 1.1 knakahar #endif /* INET */ 889 1.1 knakahar case IPPROTO_IPV6: 890 1.1 knakahar { 891 1.1 knakahar af = AF_INET6; 892 1.1 knakahar #ifndef IPSEC_TX_TOS_CLEAR 893 1.1 knakahar struct ip6_hdr *xip6; 894 1.1 knakahar 895 1.1 knakahar if (M_UNWRITABLE(m, sizeof(*xip6))) { 896 1.1 knakahar m = m_pullup(m, sizeof(*xip6)); 897 1.2 maxv if (m == NULL) 898 1.1 knakahar return IPPROTO_DONE; 899 1.1 knakahar } 900 1.1 knakahar xip6 = mtod(m, struct ip6_hdr *); 901 1.1 knakahar if (ipsecp->if_flags & IFF_ECN) 902 1.1 knakahar ip6_ecn_egress(ECN_ALLOWED, &otos, &xip6->ip6_flow); 903 1.1 knakahar else 904 1.1 knakahar ip6_ecn_egress(ECN_NOCARE, &otos, &xip6->ip6_flow); 905 1.1 knakahar break; 906 1.1 knakahar #endif 907 1.1 knakahar } 908 1.1 knakahar default: 909 1.1 knakahar IP6_STATINC(IP6_STAT_NOIPSEC); 910 1.1 knakahar m_freem(m); 911 1.1 knakahar return IPPROTO_DONE; 912 1.1 knakahar } 913 1.1 knakahar 914 1.1 knakahar if_ipsec_input(m, af, ipsecp); 915 1.1 knakahar return IPPROTO_DONE; 916 1.1 knakahar } 917 1.1 knakahar 918 1.1 knakahar /* 919 1.1 knakahar * validate and filter the packet. 920 1.1 knakahar */ 921 1.1 knakahar static int 922 1.1 knakahar ipsecif6_filter6(const struct ip6_hdr *ip6, struct ipsec_variant *var, 923 1.1 knakahar struct ifnet *ifp) 924 1.1 knakahar { 925 1.1 knakahar struct sockaddr_in6 *src, *dst; 926 1.1 knakahar 927 1.1 knakahar src = satosin6(var->iv_psrc); 928 1.1 knakahar dst = satosin6(var->iv_pdst); 929 1.1 knakahar 930 1.1 knakahar return in6_tunnel_validate(ip6, &src->sin6_addr, &dst->sin6_addr); 931 1.1 knakahar } 932 1.1 knakahar #endif /* INET6 */ 933 1.1 knakahar 934 1.1 knakahar int 935 1.1 knakahar ipsecif4_attach(struct ipsec_variant *var) 936 1.1 knakahar { 937 1.1 knakahar struct ipsec_softc *sc = var->iv_softc; 938 1.1 knakahar 939 1.1 knakahar KASSERT(if_ipsec_variant_is_configured(var)); 940 1.1 knakahar 941 1.1 knakahar if (var->iv_encap_cookie4 != NULL) 942 1.1 knakahar return EALREADY; 943 1.20 knakahar 944 1.20 knakahar var->iv_encap_cookie4 = encap_attach_addr(AF_INET, -1, 945 1.20 knakahar var->iv_psrc, var->iv_pdst, if_ipsec_encap_func, &ipsecif4_encapsw, 946 1.20 knakahar sc); 947 1.1 knakahar if (var->iv_encap_cookie4 == NULL) 948 1.1 knakahar return EEXIST; 949 1.1 knakahar 950 1.1 knakahar var->iv_output = ipsecif4_output; 951 1.1 knakahar return 0; 952 1.1 knakahar } 953 1.1 knakahar 954 1.1 knakahar int 955 1.1 knakahar ipsecif4_detach(struct ipsec_variant *var) 956 1.1 knakahar { 957 1.1 knakahar int error; 958 1.1 knakahar 959 1.1 knakahar if (var->iv_encap_cookie4 == NULL) 960 1.1 knakahar return 0; 961 1.1 knakahar 962 1.1 knakahar var->iv_output = NULL; 963 1.1 knakahar error = encap_detach(var->iv_encap_cookie4); 964 1.1 knakahar if (error == 0) 965 1.1 knakahar var->iv_encap_cookie4 = NULL; 966 1.1 knakahar 967 1.1 knakahar return error; 968 1.1 knakahar } 969 1.1 knakahar 970 1.1 knakahar #ifdef INET6 971 1.1 knakahar int 972 1.1 knakahar ipsecif6_attach(struct ipsec_variant *var) 973 1.1 knakahar { 974 1.1 knakahar struct ipsec_softc *sc = var->iv_softc; 975 1.1 knakahar 976 1.1 knakahar KASSERT(if_ipsec_variant_is_configured(var)); 977 1.1 knakahar KASSERT(var->iv_encap_cookie6 == NULL); 978 1.1 knakahar 979 1.20 knakahar var->iv_encap_cookie6 = encap_attach_addr(AF_INET6, -1, 980 1.20 knakahar var->iv_psrc, var->iv_pdst, if_ipsec_encap_func, &ipsecif6_encapsw, 981 1.20 knakahar sc); 982 1.1 knakahar if (var->iv_encap_cookie6 == NULL) 983 1.1 knakahar return EEXIST; 984 1.1 knakahar 985 1.1 knakahar var->iv_output = ipsecif6_output; 986 1.1 knakahar return 0; 987 1.1 knakahar } 988 1.1 knakahar 989 1.1 knakahar int 990 1.1 knakahar ipsecif6_detach(struct ipsec_variant *var) 991 1.1 knakahar { 992 1.1 knakahar struct ipsec_softc *sc = var->iv_softc; 993 1.1 knakahar int error; 994 1.1 knakahar 995 1.1 knakahar KASSERT(var->iv_encap_cookie6 != NULL); 996 1.1 knakahar 997 1.17 knakahar if_tunnel_ro_percpu_rtcache_free(sc->ipsec_ro_percpu); 998 1.1 knakahar 999 1.1 knakahar var->iv_output = NULL; 1000 1.1 knakahar error = encap_detach(var->iv_encap_cookie6); 1001 1.1 knakahar if (error == 0) 1002 1.1 knakahar var->iv_encap_cookie6 = NULL; 1003 1.1 knakahar return error; 1004 1.1 knakahar } 1005 1.1 knakahar 1006 1.1 knakahar void * 1007 1.1 knakahar ipsecif6_ctlinput(int cmd, const struct sockaddr *sa, void *d, void *eparg) 1008 1.1 knakahar { 1009 1.1 knakahar struct ipsec_softc *sc = eparg; 1010 1.1 knakahar struct ip6ctlparam *ip6cp = NULL; 1011 1.1 knakahar struct ip6_hdr *ip6; 1012 1.1 knakahar const struct sockaddr_in6 *dst6; 1013 1.17 knakahar struct route *ro_pc; 1014 1.17 knakahar kmutex_t *lock_pc; 1015 1.1 knakahar 1016 1.1 knakahar if (sa->sa_family != AF_INET6 || 1017 1.1 knakahar sa->sa_len != sizeof(struct sockaddr_in6)) 1018 1.1 knakahar return NULL; 1019 1.1 knakahar 1020 1.1 knakahar if ((unsigned)cmd >= PRC_NCMDS) 1021 1.1 knakahar return NULL; 1022 1.1 knakahar if (cmd == PRC_HOSTDEAD) 1023 1.1 knakahar d = NULL; 1024 1.1 knakahar else if (inet6ctlerrmap[cmd] == 0) 1025 1.1 knakahar return NULL; 1026 1.1 knakahar 1027 1.1 knakahar /* if the parameter is from icmp6, decode it. */ 1028 1.1 knakahar if (d != NULL) { 1029 1.1 knakahar ip6cp = (struct ip6ctlparam *)d; 1030 1.1 knakahar ip6 = ip6cp->ip6c_ip6; 1031 1.1 knakahar } else { 1032 1.1 knakahar ip6 = NULL; 1033 1.1 knakahar } 1034 1.1 knakahar 1035 1.1 knakahar if (!ip6) 1036 1.1 knakahar return NULL; 1037 1.1 knakahar 1038 1.17 knakahar if_tunnel_get_ro(sc->ipsec_ro_percpu, &ro_pc, &lock_pc); 1039 1.17 knakahar dst6 = satocsin6(rtcache_getdst(ro_pc)); 1040 1.1 knakahar /* XXX scope */ 1041 1.1 knakahar if (dst6 == NULL) 1042 1.1 knakahar ; 1043 1.1 knakahar else if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &dst6->sin6_addr)) 1044 1.1 knakahar /* flush route cache */ 1045 1.17 knakahar rtcache_free(ro_pc); 1046 1.1 knakahar 1047 1.17 knakahar if_tunnel_put_ro(sc->ipsec_ro_percpu, lock_pc); 1048 1.1 knakahar 1049 1.1 knakahar return NULL; 1050 1.1 knakahar } 1051 1.1 knakahar 1052 1.1 knakahar ENCAP_PR_WRAP_CTLINPUT(ipsecif6_ctlinput) 1053 1.1 knakahar #define ipsecif6_ctlinput ipsecif6_ctlinput_wrapper 1054 1.1 knakahar 1055 1.1 knakahar static const struct encapsw ipsecif6_encapsw = { 1056 1.1 knakahar .encapsw6 = { 1057 1.1 knakahar .pr_input = ipsecif6_input, 1058 1.1 knakahar .pr_ctlinput = ipsecif6_ctlinput, 1059 1.1 knakahar } 1060 1.1 knakahar }; 1061 1.1 knakahar #endif /* INET6 */ 1062