| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: ipsec.c,v 1.99 2017/06/02 03:41:20 ozaki-r Exp $ */ | | 1 | /* $NetBSD: ipsec.c,v 1.100 2017/06/14 02:00:43 ozaki-r Exp $ */ |
2 | /* $FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/sys/netipsec/ipsec.c,v 1.2.2.2 2003/07/01 01:38:13 sam Exp $ */ | | 2 | /* $FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/sys/netipsec/ipsec.c,v 1.2.2.2 2003/07/01 01:38:13 sam Exp $ */ |
3 | /* $KAME: ipsec.c,v 1.103 2001/05/24 07:14:18 sakane Exp $ */ | | 3 | /* $KAME: ipsec.c,v 1.103 2001/05/24 07:14:18 sakane Exp $ */ |
4 | | | 4 | |
5 | /* | | 5 | /* |
6 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | | 6 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. |
7 | * All rights reserved. | | 7 | * All rights reserved. |
8 | * | | 8 | * |
9 | * Redistribution and use in source and binary forms, with or without | | 9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions | | 10 | * modification, are permitted provided that the following conditions |
11 | * are met: | | 11 | * are met: |
12 | * 1. Redistributions of source code must retain the above copyright | | 12 | * 1. Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. | | 13 | * notice, this list of conditions and the following disclaimer. |
14 | * 2. Redistributions in binary form must reproduce the above copyright | | 14 | * 2. Redistributions in binary form must reproduce the above copyright |
| @@ -22,27 +22,27 @@ | | | @@ -22,27 +22,27 @@ |
22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | | 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE |
25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
31 | * SUCH DAMAGE. | | 31 | * SUCH DAMAGE. |
32 | */ | | 32 | */ |
33 | | | 33 | |
34 | #include <sys/cdefs.h> | | 34 | #include <sys/cdefs.h> |
35 | __KERNEL_RCSID(0, "$NetBSD: ipsec.c,v 1.99 2017/06/02 03:41:20 ozaki-r Exp $"); | | 35 | __KERNEL_RCSID(0, "$NetBSD: ipsec.c,v 1.100 2017/06/14 02:00:43 ozaki-r Exp $"); |
36 | | | 36 | |
37 | /* | | 37 | /* |
38 | * IPsec controller part. | | 38 | * IPsec controller part. |
39 | */ | | 39 | */ |
40 | | | 40 | |
41 | #if defined(_KERNEL_OPT) | | 41 | #if defined(_KERNEL_OPT) |
42 | #include "opt_inet.h" | | 42 | #include "opt_inet.h" |
43 | #include "opt_ipsec.h" | | 43 | #include "opt_ipsec.h" |
44 | #endif | | 44 | #endif |
45 | | | 45 | |
46 | #include <sys/param.h> | | 46 | #include <sys/param.h> |
47 | #include <sys/systm.h> | | 47 | #include <sys/systm.h> |
48 | #include <sys/mbuf.h> | | 48 | #include <sys/mbuf.h> |
| @@ -227,30 +227,28 @@ ipsec_checkpcbcache(struct mbuf *m, stru | | | @@ -227,30 +227,28 @@ ipsec_checkpcbcache(struct mbuf *m, stru |
227 | if (pcbsp->sp_cache[dir].cachesp->state != IPSEC_SPSTATE_ALIVE) { | | 227 | if (pcbsp->sp_cache[dir].cachesp->state != IPSEC_SPSTATE_ALIVE) { |
228 | ipsec_invalpcbcache(pcbsp, dir); | | 228 | ipsec_invalpcbcache(pcbsp, dir); |
229 | return NULL; | | 229 | return NULL; |
230 | } | | 230 | } |
231 | if ((pcbsp->sp_cacheflags & IPSEC_PCBSP_CONNECTED) == 0) { | | 231 | if ((pcbsp->sp_cacheflags & IPSEC_PCBSP_CONNECTED) == 0) { |
232 | if (ipsec_setspidx(m, &spidx, 1) != 0) | | 232 | if (ipsec_setspidx(m, &spidx, 1) != 0) |
233 | return NULL; | | 233 | return NULL; |
234 | | | 234 | |
235 | /* | | 235 | /* |
236 | * We have to make an exact match here since the cached rule | | 236 | * We have to make an exact match here since the cached rule |
237 | * might have lower priority than a rule that would otherwise | | 237 | * might have lower priority than a rule that would otherwise |
238 | * have matched the packet. | | 238 | * have matched the packet. |
239 | */ | | 239 | */ |
240 | | | | |
241 | if (memcmp(&pcbsp->sp_cache[dir].cacheidx, &spidx, sizeof(spidx))) | | 240 | if (memcmp(&pcbsp->sp_cache[dir].cacheidx, &spidx, sizeof(spidx))) |
242 | return NULL; | | 241 | return NULL; |
243 | | | | |
244 | } else { | | 242 | } else { |
245 | /* | | 243 | /* |
246 | * The pcb is connected, and the L4 code is sure that: | | 244 | * The pcb is connected, and the L4 code is sure that: |
247 | * - outgoing side uses inp_[lf]addr | | 245 | * - outgoing side uses inp_[lf]addr |
248 | * - incoming side looks up policy after inpcb lookup | | 246 | * - incoming side looks up policy after inpcb lookup |
249 | * and address pair is know to be stable. We do not need | | 247 | * and address pair is know to be stable. We do not need |
250 | * to generate spidx again, nor check the address match again. | | 248 | * to generate spidx again, nor check the address match again. |
251 | * | | 249 | * |
252 | * For IPv4/v6 SOCK_STREAM sockets, this assumptions holds | | 250 | * For IPv4/v6 SOCK_STREAM sockets, this assumptions holds |
253 | * and there are calls to ipsec_pcbconn() from in_pcbconnect(). | | 251 | * and there are calls to ipsec_pcbconn() from in_pcbconnect(). |
254 | */ | | 252 | */ |
255 | } | | 253 | } |
256 | | | 254 | |
| @@ -286,56 +284,56 @@ ipsec_fillpcbcache(struct inpcbpolicy *p | | | @@ -286,56 +284,56 @@ ipsec_fillpcbcache(struct inpcbpolicy *p |
286 | "DP cause refcnt++:%d SP:%p\n", | | 284 | "DP cause refcnt++:%d SP:%p\n", |
287 | pcbsp->sp_cache[dir].cachesp->refcnt, | | 285 | pcbsp->sp_cache[dir].cachesp->refcnt, |
288 | pcbsp->sp_cache[dir].cachesp); | | 286 | pcbsp->sp_cache[dir].cachesp); |
289 | | | 287 | |
290 | /* | | 288 | /* |
291 | * If the PCB is connected, we can remember a hint to | | 289 | * If the PCB is connected, we can remember a hint to |
292 | * possibly short-circuit IPsec processing in other places. | | 290 | * possibly short-circuit IPsec processing in other places. |
293 | */ | | 291 | */ |
294 | if (pcbsp->sp_cacheflags & IPSEC_PCBSP_CONNECTED) { | | 292 | if (pcbsp->sp_cacheflags & IPSEC_PCBSP_CONNECTED) { |
295 | switch (pcbsp->sp_cache[dir].cachesp->policy) { | | 293 | switch (pcbsp->sp_cache[dir].cachesp->policy) { |
296 | case IPSEC_POLICY_NONE: | | 294 | case IPSEC_POLICY_NONE: |
297 | case IPSEC_POLICY_BYPASS: | | 295 | case IPSEC_POLICY_BYPASS: |
298 | pcbsp->sp_cache[dir].cachehint = | | 296 | pcbsp->sp_cache[dir].cachehint = |
299 | IPSEC_PCBHINT_NO; | | 297 | IPSEC_PCBHINT_NO; |
300 | break; | | 298 | break; |
301 | default: | | 299 | default: |
302 | pcbsp->sp_cache[dir].cachehint = | | 300 | pcbsp->sp_cache[dir].cachehint = |
303 | IPSEC_PCBHINT_YES; | | 301 | IPSEC_PCBHINT_YES; |
304 | } | | 302 | } |
305 | } | | 303 | } |
306 | } | | 304 | } |
307 | pcbsp->sp_cache[dir].cachegen = ipsec_spdgen; | | 305 | pcbsp->sp_cache[dir].cachegen = ipsec_spdgen; |
308 | | | 306 | |
309 | return 0; | | 307 | return 0; |
310 | } | | 308 | } |
311 | | | 309 | |
312 | static int | | 310 | static int |
313 | ipsec_invalpcbcache(struct inpcbpolicy *pcbsp, int dir) | | 311 | ipsec_invalpcbcache(struct inpcbpolicy *pcbsp, int dir) |
314 | { | | 312 | { |
315 | int i; | | 313 | int i; |
316 | | | 314 | |
317 | KASSERT(inph_locked(pcbsp->sp_inph)); | | 315 | KASSERT(inph_locked(pcbsp->sp_inph)); |
318 | | | 316 | |
319 | for (i = IPSEC_DIR_INBOUND; i <= IPSEC_DIR_OUTBOUND; i++) { | | 317 | for (i = IPSEC_DIR_INBOUND; i <= IPSEC_DIR_OUTBOUND; i++) { |
320 | if (dir != IPSEC_DIR_ANY && i != dir) | | 318 | if (dir != IPSEC_DIR_ANY && i != dir) |
321 | continue; | | 319 | continue; |
322 | if (pcbsp->sp_cache[i].cachesp) | | 320 | if (pcbsp->sp_cache[i].cachesp) |
323 | KEY_FREESP(&pcbsp->sp_cache[i].cachesp); | | 321 | KEY_FREESP(&pcbsp->sp_cache[i].cachesp); |
324 | pcbsp->sp_cache[i].cachesp = NULL; | | 322 | pcbsp->sp_cache[i].cachesp = NULL; |
325 | pcbsp->sp_cache[i].cachehint = IPSEC_PCBHINT_UNKNOWN; | | 323 | pcbsp->sp_cache[i].cachehint = IPSEC_PCBHINT_UNKNOWN; |
326 | pcbsp->sp_cache[i].cachegen = 0; | | 324 | pcbsp->sp_cache[i].cachegen = 0; |
327 | memset(&pcbsp->sp_cache[i].cacheidx, 0, | | 325 | memset(&pcbsp->sp_cache[i].cacheidx, 0, |
328 | sizeof(pcbsp->sp_cache[i].cacheidx)); | | 326 | sizeof(pcbsp->sp_cache[i].cacheidx)); |
329 | } | | 327 | } |
330 | return 0; | | 328 | return 0; |
331 | } | | 329 | } |
332 | | | 330 | |
333 | void | | 331 | void |
334 | ipsec_pcbconn(struct inpcbpolicy *pcbsp) | | 332 | ipsec_pcbconn(struct inpcbpolicy *pcbsp) |
335 | { | | 333 | { |
336 | | | 334 | |
337 | KASSERT(inph_locked(pcbsp->sp_inph)); | | 335 | KASSERT(inph_locked(pcbsp->sp_inph)); |
338 | | | 336 | |
339 | pcbsp->sp_cacheflags |= IPSEC_PCBSP_CONNECTED; | | 337 | pcbsp->sp_cacheflags |= IPSEC_PCBSP_CONNECTED; |
340 | ipsec_invalpcbcache(pcbsp, IPSEC_DIR_ANY); | | 338 | ipsec_invalpcbcache(pcbsp, IPSEC_DIR_ANY); |
341 | } | | 339 | } |
| @@ -906,29 +904,29 @@ ipsec4_setspidx_inpcb(struct mbuf *m, st | | | @@ -906,29 +904,29 @@ ipsec4_setspidx_inpcb(struct mbuf *m, st |
906 | | | 904 | |
907 | KASSERT(pcb != NULL); | | 905 | KASSERT(pcb != NULL); |
908 | KASSERT(pcb->inp_sp != NULL); | | 906 | KASSERT(pcb->inp_sp != NULL); |
909 | KASSERT(pcb->inp_sp->sp_out != NULL); | | 907 | KASSERT(pcb->inp_sp->sp_out != NULL); |
910 | KASSERT(pcb->inp_sp->sp_in != NULL); | | 908 | KASSERT(pcb->inp_sp->sp_in != NULL); |
911 | | | 909 | |
912 | error = ipsec_setspidx(m, &pcb->inp_sp->sp_in->spidx, 1); | | 910 | error = ipsec_setspidx(m, &pcb->inp_sp->sp_in->spidx, 1); |
913 | if (error == 0) { | | 911 | if (error == 0) { |
914 | pcb->inp_sp->sp_in->spidx.dir = IPSEC_DIR_INBOUND; | | 912 | pcb->inp_sp->sp_in->spidx.dir = IPSEC_DIR_INBOUND; |
915 | pcb->inp_sp->sp_out->spidx = pcb->inp_sp->sp_in->spidx; | | 913 | pcb->inp_sp->sp_out->spidx = pcb->inp_sp->sp_in->spidx; |
916 | pcb->inp_sp->sp_out->spidx.dir = IPSEC_DIR_OUTBOUND; | | 914 | pcb->inp_sp->sp_out->spidx.dir = IPSEC_DIR_OUTBOUND; |
917 | } else { | | 915 | } else { |
918 | memset(&pcb->inp_sp->sp_in->spidx, 0, | | 916 | memset(&pcb->inp_sp->sp_in->spidx, 0, |
919 | sizeof (pcb->inp_sp->sp_in->spidx)); | | 917 | sizeof(pcb->inp_sp->sp_in->spidx)); |
920 | memset(&pcb->inp_sp->sp_out->spidx, 0, | | 918 | memset(&pcb->inp_sp->sp_out->spidx, 0, |
921 | sizeof (pcb->inp_sp->sp_in->spidx)); | | 919 | sizeof(pcb->inp_sp->sp_in->spidx)); |
922 | } | | 920 | } |
923 | return error; | | 921 | return error; |
924 | } | | 922 | } |
925 | | | 923 | |
926 | #ifdef INET6 | | 924 | #ifdef INET6 |
927 | static int | | 925 | static int |
928 | ipsec6_setspidx_in6pcb(struct mbuf *m, struct in6pcb *pcb) | | 926 | ipsec6_setspidx_in6pcb(struct mbuf *m, struct in6pcb *pcb) |
929 | { | | 927 | { |
930 | struct secpolicyindex *spidx; | | 928 | struct secpolicyindex *spidx; |
931 | int error; | | 929 | int error; |
932 | | | 930 | |
933 | KASSERT(pcb != NULL); | | 931 | KASSERT(pcb != NULL); |
934 | KASSERT(pcb->in6p_sp != NULL); | | 932 | KASSERT(pcb->in6p_sp != NULL); |
| @@ -1123,31 +1121,29 @@ static int | | | @@ -1123,31 +1121,29 @@ static int |
1123 | ipsec4_setspidx_ipaddr(struct mbuf *m, struct secpolicyindex *spidx) | | 1121 | ipsec4_setspidx_ipaddr(struct mbuf *m, struct secpolicyindex *spidx) |
1124 | { | | 1122 | { |
1125 | static const struct sockaddr_in template = { | | 1123 | static const struct sockaddr_in template = { |
1126 | sizeof (struct sockaddr_in), | | 1124 | sizeof (struct sockaddr_in), |
1127 | AF_INET, | | 1125 | AF_INET, |
1128 | 0, { 0 }, { 0, 0, 0, 0, 0, 0, 0, 0 } | | 1126 | 0, { 0 }, { 0, 0, 0, 0, 0, 0, 0, 0 } |
1129 | }; | | 1127 | }; |
1130 | | | 1128 | |
1131 | spidx->src.sin = template; | | 1129 | spidx->src.sin = template; |
1132 | spidx->dst.sin = template; | | 1130 | spidx->dst.sin = template; |
1133 | | | 1131 | |
1134 | if (m->m_len < sizeof (struct ip)) { | | 1132 | if (m->m_len < sizeof (struct ip)) { |
1135 | m_copydata(m, offsetof(struct ip, ip_src), | | 1133 | m_copydata(m, offsetof(struct ip, ip_src), |
1136 | sizeof (struct in_addr), | | 1134 | sizeof(struct in_addr), &spidx->src.sin.sin_addr); |
1137 | &spidx->src.sin.sin_addr); | | | |
1138 | m_copydata(m, offsetof(struct ip, ip_dst), | | 1135 | m_copydata(m, offsetof(struct ip, ip_dst), |
1139 | sizeof (struct in_addr), | | 1136 | sizeof(struct in_addr), &spidx->dst.sin.sin_addr); |
1140 | &spidx->dst.sin.sin_addr); | | | |
1141 | } else { | | 1137 | } else { |
1142 | struct ip *ip = mtod(m, struct ip *); | | 1138 | struct ip *ip = mtod(m, struct ip *); |
1143 | spidx->src.sin.sin_addr = ip->ip_src; | | 1139 | spidx->src.sin.sin_addr = ip->ip_src; |
1144 | spidx->dst.sin.sin_addr = ip->ip_dst; | | 1140 | spidx->dst.sin.sin_addr = ip->ip_dst; |
1145 | } | | 1141 | } |
1146 | | | 1142 | |
1147 | spidx->prefs = sizeof(struct in_addr) << 3; | | 1143 | spidx->prefs = sizeof(struct in_addr) << 3; |
1148 | spidx->prefd = sizeof(struct in_addr) << 3; | | 1144 | spidx->prefd = sizeof(struct in_addr) << 3; |
1149 | | | 1145 | |
1150 | return 0; | | 1146 | return 0; |
1151 | } | | 1147 | } |
1152 | | | 1148 | |
1153 | #ifdef INET6 | | 1149 | #ifdef INET6 |