1
|
diff --git a/sys/netinet/in.h b/sys/netinet/in.h
|
2
|
index db9a590..69a7bbe 100644
|
3
|
--- a/sys/netinet/in.h
|
4
|
+++ b/sys/netinet/in.h
|
5
|
@@ -697,7 +697,8 @@ int getsourcefilter(int, uint32_t, struct sockaddr *, socklen_t,
|
6
|
#define IPCTL_FASTFORWARDING 14 /* use fast IP forwarding code */
|
7
|
#define IPCTL_KEEPFAITH 15 /* FAITH IPv4->IPv6 translater ctl */
|
8
|
#define IPCTL_GIF_TTL 16 /* default TTL for gif encap packet */
|
9
|
-#define IPCTL_MAXID 17
|
10
|
+#define IPCTL_IPSEC_INUSE 17
|
11
|
+#define IPCTL_MAXID 18
|
12
|
|
13
|
#endif /* __BSD_VISIBLE */
|
14
|
|
15
|
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
|
16
|
index 010f0e3..83ef2b7 100644
|
17
|
--- a/sys/netinet/ip_input.c
|
18
|
+++ b/sys/netinet/ip_input.c
|
19
|
@@ -97,6 +97,11 @@ SYSCTL_VNET_INT(_net_inet_ip, IPCTL_FORWARDING, forwarding, CTLFLAG_RW,
|
20
|
&VNET_NAME(ipforwarding), 0,
|
21
|
"Enable IP forwarding between interfaces");
|
22
|
|
23
|
+VNET_DEFINE(int, ipipsec_in_use);
|
24
|
+SYSCTL_VNET_INT(_net_inet_ip, IPCTL_IPSEC_INUSE, ipsec_in_use, CTLFLAG_RW,
|
25
|
+ &VNET_NAME(ipipsec_in_use), 0,
|
26
|
+ "Enable IPSec processing of packets");
|
27
|
+
|
28
|
static VNET_DEFINE(int, ipsendredirects) = 1; /* XXX */
|
29
|
#define V_ipsendredirects VNET(ipsendredirects)
|
30
|
SYSCTL_VNET_INT(_net_inet_ip, IPCTL_SENDREDIRECTS, redirect, CTLFLAG_RW,
|
31
|
@@ -471,7 +476,7 @@ tooshort:
|
32
|
/*
|
33
|
* Bypass packet filtering for packets previously handled by IPsec.
|
34
|
*/
|
35
|
- if (ip_ipsec_filtertunnel(m))
|
36
|
+ if (V_ipipsec_in_use && ip_ipsec_filtertunnel(m))
|
37
|
goto passin;
|
38
|
#endif /* IPSEC */
|
39
|
|
40
|
@@ -678,7 +683,7 @@ passin:
|
41
|
m_freem(m);
|
42
|
} else {
|
43
|
#ifdef IPSEC
|
44
|
- if (ip_ipsec_fwd(m))
|
45
|
+ if (V_ipipsec_in_use && ip_ipsec_fwd(m))
|
46
|
goto bad;
|
47
|
#endif /* IPSEC */
|
48
|
ip_forward(m, dchg);
|
49
|
@@ -725,7 +730,7 @@ ours:
|
50
|
* note that we do not visit this with protocols with pcb layer
|
51
|
* code - like udp/tcp/raw ip.
|
52
|
*/
|
53
|
- if (ip_ipsec_input(m))
|
54
|
+ if (V_ipipsec_in_use && ip_ipsec_input(m))
|
55
|
goto bad;
|
56
|
#endif /* IPSEC */
|
57
|
|
58
|
@@ -1521,7 +1526,8 @@ ip_forward(struct mbuf *m, int srcrt)
|
59
|
* If IPsec is configured for this path,
|
60
|
* override any possibly mtu value set by ip_output.
|
61
|
*/
|
62
|
- mtu = ip_ipsec_mtu(mcopy, mtu);
|
63
|
+ if (V_ipipsec_in_use)
|
64
|
+ mtu = ip_ipsec_mtu(mcopy, mtu);
|
65
|
#endif /* IPSEC */
|
66
|
/*
|
67
|
* If the MTU was set before make sure we are below the
|
68
|
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
|
69
|
index e40507c..e3193a8 100644
|
70
|
--- a/sys/netinet/ip_output.c
|
71
|
+++ b/sys/netinet/ip_output.c
|
72
|
@@ -476,18 +476,20 @@ again:
|
73
|
|
74
|
sendit:
|
75
|
#ifdef IPSEC
|
76
|
- switch(ip_ipsec_output(&m, inp, &flags, &error)) {
|
77
|
- case 1:
|
78
|
- goto bad;
|
79
|
- case -1:
|
80
|
- goto done;
|
81
|
- case 0:
|
82
|
- default:
|
83
|
- break; /* Continue with packet processing. */
|
84
|
+ if (V_ipipsec_in_use) {
|
85
|
+ switch(ip_ipsec_output(&m, inp, &flags, &error)) {
|
86
|
+ case 1:
|
87
|
+ goto bad;
|
88
|
+ case -1:
|
89
|
+ goto done;
|
90
|
+ case 0:
|
91
|
+ default:
|
92
|
+ break; /* Continue with packet processing. */
|
93
|
+ }
|
94
|
+ /* Update variables that are affected by ipsec4_output(). */
|
95
|
+ ip = mtod(m, struct ip *);
|
96
|
+ hlen = ip->ip_hl << 2;
|
97
|
}
|
98
|
- /* Update variables that are affected by ipsec4_output(). */
|
99
|
- ip = mtod(m, struct ip *);
|
100
|
- hlen = ip->ip_hl << 2;
|
101
|
#endif /* IPSEC */
|
102
|
|
103
|
/* Jump over all PFIL processing if hooks are not active. */
|
104
|
diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
|
105
|
index b2251ac..de08849 100644
|
106
|
--- a/sys/netinet/ip_var.h
|
107
|
+++ b/sys/netinet/ip_var.h
|
108
|
@@ -176,6 +176,7 @@ struct sockopt;
|
109
|
VNET_DECLARE(u_short, ip_id); /* ip packet ctr, for ids */
|
110
|
VNET_DECLARE(int, ip_defttl); /* default IP ttl */
|
111
|
VNET_DECLARE(int, ipforwarding); /* ip forwarding */
|
112
|
+VNET_DECLARE(int, ipipsec_in_use);
|
113
|
#ifdef IPSTEALTH
|
114
|
VNET_DECLARE(int, ipstealth); /* stealth forwarding */
|
115
|
#endif
|
116
|
@@ -191,6 +192,7 @@ extern struct pr_usrreqs rip_usrreqs;
|
117
|
#define V_ip_id VNET(ip_id)
|
118
|
#define V_ip_defttl VNET(ip_defttl)
|
119
|
#define V_ipforwarding VNET(ipforwarding)
|
120
|
+#define V_ipipsec_in_use VNET(ipipsec_in_use)
|
121
|
#ifdef IPSTEALTH
|
122
|
#define V_ipstealth VNET(ipstealth)
|
123
|
#endif
|
124
|
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
|
125
|
index b43e4c7..ad97aab 100644
|
126
|
--- a/sys/netinet6/ip6_input.c
|
127
|
+++ b/sys/netinet6/ip6_input.c
|
128
|
@@ -133,6 +133,7 @@ static struct netisr_handler ip6_nh = {
|
129
|
.nh_policy = NETISR_POLICY_FLOW,
|
130
|
};
|
131
|
|
132
|
+#define V_ipipsec_in_use VNET(ipipsec_in_use)
|
133
|
VNET_DECLARE(struct callout, in6_tmpaddrtimer_ch);
|
134
|
#define V_in6_tmpaddrtimer_ch VNET(in6_tmpaddrtimer_ch)
|
135
|
|
136
|
@@ -1004,6 +1005,7 @@ passin:
|
137
|
}
|
138
|
|
139
|
#ifdef IPSEC
|
140
|
+ if (V_ipipsec_in_use) {
|
141
|
/*
|
142
|
* enforce IPsec policy checking if we are seeing last header.
|
143
|
* note that we do not visit this with protocols with pcb layer
|
144
|
@@ -1011,6 +1013,7 @@ passin:
|
145
|
*/
|
146
|
if (ip6_ipsec_input(m, nxt))
|
147
|
goto bad;
|
148
|
+ }
|
149
|
#endif /* IPSEC */
|
150
|
|
151
|
/*
|
152
|
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
|
153
|
index 171a918..4e9da2e 100644
|
154
|
--- a/sys/netinet6/ip6_output.c
|
155
|
+++ b/sys/netinet6/ip6_output.c
|
156
|
@@ -147,6 +147,7 @@ static int ip6_getpmtu(struct route_in6 *, struct route_in6 *,
|
157
|
struct ifnet *, struct in6_addr *, u_long *, int *, u_int);
|
158
|
static int copypktopts(struct ip6_pktopts *, struct ip6_pktopts *, int);
|
159
|
|
160
|
+#define V_ipipsec_in_use VNET(ipipsec_in_use)
|
161
|
|
162
|
/*
|
163
|
* Make an extension header from option data. hp is the source, and
|
164
|
@@ -294,33 +295,35 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
|
165
|
}
|
166
|
|
167
|
#ifdef IPSEC
|
168
|
- /*
|
169
|
- * IPSec checking which handles several cases.
|
170
|
- * FAST IPSEC: We re-injected the packet.
|
171
|
- */
|
172
|
- switch(ip6_ipsec_output(&m, inp, &flags, &error, &ifp, &sp))
|
173
|
- {
|
174
|
- case 1: /* Bad packet */
|
175
|
- goto freehdrs;
|
176
|
- case -1: /* Do IPSec */
|
177
|
- needipsec = 1;
|
178
|
+ if (V_ipipsec_in_use) {
|
179
|
/*
|
180
|
- * Do delayed checksums now, as we may send before returning.
|
181
|
+ * IPSec checking which handles several cases.
|
182
|
+ * FAST IPSEC: We re-injected the packet.
|
183
|
*/
|
184
|
- if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) {
|
185
|
- plen = m->m_pkthdr.len - sizeof(*ip6);
|
186
|
- in6_delayed_cksum(m, plen, sizeof(struct ip6_hdr));
|
187
|
- m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6;
|
188
|
- }
|
189
|
+ switch(ip6_ipsec_output(&m, inp, &flags, &error, &ifp, &sp))
|
190
|
+ {
|
191
|
+ case 1: /* Bad packet */
|
192
|
+ goto freehdrs;
|
193
|
+ case -1: /* Do IPSec */
|
194
|
+ needipsec = 1;
|
195
|
+ /*
|
196
|
+ * Do delayed checksums now, as we may send before returning.
|
197
|
+ */
|
198
|
+ if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) {
|
199
|
+ plen = m->m_pkthdr.len - sizeof(*ip6);
|
200
|
+ in6_delayed_cksum(m, plen, sizeof(struct ip6_hdr));
|
201
|
+ m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6;
|
202
|
+ }
|
203
|
#ifdef SCTP
|
204
|
- if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6) {
|
205
|
- sctp_delayed_cksum(m, sizeof(struct ip6_hdr));
|
206
|
- m->m_pkthdr.csum_flags &= ~CSUM_SCTP_IPV6;
|
207
|
- }
|
208
|
+ if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6) {
|
209
|
+ sctp_delayed_cksum(m, sizeof(struct ip6_hdr));
|
210
|
+ m->m_pkthdr.csum_flags &= ~CSUM_SCTP_IPV6;
|
211
|
+ }
|
212
|
#endif
|
213
|
- case 0: /* No IPSec */
|
214
|
- default:
|
215
|
- break;
|
216
|
+ case 0: /* No IPSec */
|
217
|
+ default:
|
218
|
+ break;
|
219
|
+ }
|
220
|
}
|
221
|
#endif /* IPSEC */
|
222
|
|
223
|
@@ -421,67 +424,69 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
|
224
|
IPPROTO_ROUTING);
|
225
|
|
226
|
#ifdef IPSEC
|
227
|
- if (!needipsec)
|
228
|
- goto skip_ipsec2;
|
229
|
-
|
230
|
- /*
|
231
|
- * pointers after IPsec headers are not valid any more.
|
232
|
- * other pointers need a great care too.
|
233
|
- * (IPsec routines should not mangle mbufs prior to AH/ESP)
|
234
|
- */
|
235
|
- exthdrs.ip6e_dest2 = NULL;
|
236
|
-
|
237
|
- if (exthdrs.ip6e_rthdr) {
|
238
|
- rh = mtod(exthdrs.ip6e_rthdr, struct ip6_rthdr *);
|
239
|
- segleft_org = rh->ip6r_segleft;
|
240
|
- rh->ip6r_segleft = 0;
|
241
|
- }
|
242
|
+ if (V_ipipsec_in_use) {
|
243
|
+ if (!needipsec)
|
244
|
+ goto skip_ipsec2;
|
245
|
|
246
|
- bzero(&state, sizeof(state));
|
247
|
- state.m = m;
|
248
|
- error = ipsec6_output_trans(&state, nexthdrp, mprev, sp, flags,
|
249
|
- &needipsectun);
|
250
|
- m = state.m;
|
251
|
- if (error == EJUSTRETURN) {
|
252
|
/*
|
253
|
- * We had a SP with a level of 'use' and no SA. We
|
254
|
- * will just continue to process the packet without
|
255
|
- * IPsec processing.
|
256
|
+ * pointers after IPsec headers are not valid any more.
|
257
|
+ * other pointers need a great care too.
|
258
|
+ * (IPsec routines should not mangle mbufs prior to AH/ESP)
|
259
|
*/
|
260
|
- ;
|
261
|
- } else if (error) {
|
262
|
- /* mbuf is already reclaimed in ipsec6_output_trans. */
|
263
|
- m = NULL;
|
264
|
- switch (error) {
|
265
|
- case EHOSTUNREACH:
|
266
|
- case ENETUNREACH:
|
267
|
- case EMSGSIZE:
|
268
|
- case ENOBUFS:
|
269
|
- case ENOMEM:
|
270
|
- break;
|
271
|
- default:
|
272
|
- printf("[%s:%d] (ipsec): error code %d\n",
|
273
|
- __func__, __LINE__, error);
|
274
|
- /* FALLTHROUGH */
|
275
|
- case ENOENT:
|
276
|
- /* don't show these error codes to the user */
|
277
|
- error = 0;
|
278
|
- break;
|
279
|
+ exthdrs.ip6e_dest2 = NULL;
|
280
|
+
|
281
|
+ if (exthdrs.ip6e_rthdr) {
|
282
|
+ rh = mtod(exthdrs.ip6e_rthdr, struct ip6_rthdr *);
|
283
|
+ segleft_org = rh->ip6r_segleft;
|
284
|
+ rh->ip6r_segleft = 0;
|
285
|
+ }
|
286
|
+
|
287
|
+ bzero(&state, sizeof(state));
|
288
|
+ state.m = m;
|
289
|
+ error = ipsec6_output_trans(&state, nexthdrp, mprev, sp, flags,
|
290
|
+ &needipsectun);
|
291
|
+ m = state.m;
|
292
|
+ if (error == EJUSTRETURN) {
|
293
|
+ /*
|
294
|
+ * We had a SP with a level of 'use' and no SA. We
|
295
|
+ * will just continue to process the packet without
|
296
|
+ * IPsec processing.
|
297
|
+ */
|
298
|
+ ;
|
299
|
+ } else if (error) {
|
300
|
+ /* mbuf is already reclaimed in ipsec6_output_trans. */
|
301
|
+ m = NULL;
|
302
|
+ switch (error) {
|
303
|
+ case EHOSTUNREACH:
|
304
|
+ case ENETUNREACH:
|
305
|
+ case EMSGSIZE:
|
306
|
+ case ENOBUFS:
|
307
|
+ case ENOMEM:
|
308
|
+ break;
|
309
|
+ default:
|
310
|
+ printf("[%s:%d] (ipsec): error code %d\n",
|
311
|
+ __func__, __LINE__, error);
|
312
|
+ /* FALLTHROUGH */
|
313
|
+ case ENOENT:
|
314
|
+ /* don't show these error codes to the user */
|
315
|
+ error = 0;
|
316
|
+ break;
|
317
|
+ }
|
318
|
+ goto bad;
|
319
|
+ } else if (!needipsectun) {
|
320
|
+ /*
|
321
|
+ * In the FAST IPSec case we have already
|
322
|
+ * re-injected the packet and it has been freed
|
323
|
+ * by the ipsec_done() function. So, just clean
|
324
|
+ * up after ourselves.
|
325
|
+ */
|
326
|
+ m = NULL;
|
327
|
+ goto done;
|
328
|
+ }
|
329
|
+ if (exthdrs.ip6e_rthdr) {
|
330
|
+ /* ah6_output doesn't modify mbuf chain */
|
331
|
+ rh->ip6r_segleft = segleft_org;
|
332
|
}
|
333
|
- goto bad;
|
334
|
- } else if (!needipsectun) {
|
335
|
- /*
|
336
|
- * In the FAST IPSec case we have already
|
337
|
- * re-injected the packet and it has been freed
|
338
|
- * by the ipsec_done() function. So, just clean
|
339
|
- * up after ourselves.
|
340
|
- */
|
341
|
- m = NULL;
|
342
|
- goto done;
|
343
|
- }
|
344
|
- if (exthdrs.ip6e_rthdr) {
|
345
|
- /* ah6_output doesn't modify mbuf chain */
|
346
|
- rh->ip6r_segleft = segleft_org;
|
347
|
}
|
348
|
skip_ipsec2:;
|
349
|
#endif /* IPSEC */
|
350
|
@@ -552,73 +557,75 @@ again:
|
351
|
}
|
352
|
|
353
|
#ifdef IPSEC
|
354
|
- /*
|
355
|
- * We may re-inject packets into the stack here.
|
356
|
- */
|
357
|
- if (needipsec && needipsectun) {
|
358
|
- struct ipsec_output_state state;
|
359
|
-
|
360
|
+ if (V_ipipsec_in_use) {
|
361
|
/*
|
362
|
- * All the extension headers will become inaccessible
|
363
|
- * (since they can be encrypted).
|
364
|
- * Don't panic, we need no more updates to extension headers
|
365
|
- * on inner IPv6 packet (since they are now encapsulated).
|
366
|
- *
|
367
|
- * IPv6 [ESP|AH] IPv6 [extension headers] payload
|
368
|
+ * We may re-inject packets into the stack here.
|
369
|
*/
|
370
|
- bzero(&exthdrs, sizeof(exthdrs));
|
371
|
- exthdrs.ip6e_ip6 = m;
|
372
|
-
|
373
|
- bzero(&state, sizeof(state));
|
374
|
- state.m = m;
|
375
|
- state.ro = (struct route *)ro;
|
376
|
- state.dst = (struct sockaddr *)dst;
|
377
|
-
|
378
|
- error = ipsec6_output_tunnel(&state, sp, flags);
|
379
|
+ if (needipsec && needipsectun) {
|
380
|
+ struct ipsec_output_state state;
|
381
|
|
382
|
- m = state.m;
|
383
|
- ro = (struct route_in6 *)state.ro;
|
384
|
- dst = (struct sockaddr_in6 *)state.dst;
|
385
|
- if (error == EJUSTRETURN) {
|
386
|
/*
|
387
|
- * We had a SP with a level of 'use' and no SA. We
|
388
|
- * will just continue to process the packet without
|
389
|
- * IPsec processing.
|
390
|
+ * All the extension headers will become inaccessible
|
391
|
+ * (since they can be encrypted).
|
392
|
+ * Don't panic, we need no more updates to extension headers
|
393
|
+ * on inner IPv6 packet (since they are now encapsulated).
|
394
|
+ *
|
395
|
+ * IPv6 [ESP|AH] IPv6 [extension headers] payload
|
396
|
*/
|
397
|
- ;
|
398
|
- } else if (error) {
|
399
|
- /* mbuf is already reclaimed in ipsec6_output_tunnel. */
|
400
|
- m0 = m = NULL;
|
401
|
- m = NULL;
|
402
|
- switch (error) {
|
403
|
- case EHOSTUNREACH:
|
404
|
- case ENETUNREACH:
|
405
|
- case EMSGSIZE:
|
406
|
- case ENOBUFS:
|
407
|
- case ENOMEM:
|
408
|
- break;
|
409
|
- default:
|
410
|
- printf("[%s:%d] (ipsec): error code %d\n",
|
411
|
- __func__, __LINE__, error);
|
412
|
- /* FALLTHROUGH */
|
413
|
- case ENOENT:
|
414
|
- /* don't show these error codes to the user */
|
415
|
- error = 0;
|
416
|
- break;
|
417
|
+ bzero(&exthdrs, sizeof(exthdrs));
|
418
|
+ exthdrs.ip6e_ip6 = m;
|
419
|
+
|
420
|
+ bzero(&state, sizeof(state));
|
421
|
+ state.m = m;
|
422
|
+ state.ro = (struct route *)ro;
|
423
|
+ state.dst = (struct sockaddr *)dst;
|
424
|
+
|
425
|
+ error = ipsec6_output_tunnel(&state, sp, flags);
|
426
|
+
|
427
|
+ m = state.m;
|
428
|
+ ro = (struct route_in6 *)state.ro;
|
429
|
+ dst = (struct sockaddr_in6 *)state.dst;
|
430
|
+ if (error == EJUSTRETURN) {
|
431
|
+ /*
|
432
|
+ * We had a SP with a level of 'use' and no SA. We
|
433
|
+ * will just continue to process the packet without
|
434
|
+ * IPsec processing.
|
435
|
+ */
|
436
|
+ ;
|
437
|
+ } else if (error) {
|
438
|
+ /* mbuf is already reclaimed in ipsec6_output_tunnel. */
|
439
|
+ m0 = m = NULL;
|
440
|
+ m = NULL;
|
441
|
+ switch (error) {
|
442
|
+ case EHOSTUNREACH:
|
443
|
+ case ENETUNREACH:
|
444
|
+ case EMSGSIZE:
|
445
|
+ case ENOBUFS:
|
446
|
+ case ENOMEM:
|
447
|
+ break;
|
448
|
+ default:
|
449
|
+ printf("[%s:%d] (ipsec): error code %d\n",
|
450
|
+ __func__, __LINE__, error);
|
451
|
+ /* FALLTHROUGH */
|
452
|
+ case ENOENT:
|
453
|
+ /* don't show these error codes to the user */
|
454
|
+ error = 0;
|
455
|
+ break;
|
456
|
+ }
|
457
|
+ goto bad;
|
458
|
+ } else {
|
459
|
+ /*
|
460
|
+ * In the FAST IPSec case we have already
|
461
|
+ * re-injected the packet and it has been freed
|
462
|
+ * by the ipsec_done() function. So, just clean
|
463
|
+ * up after ourselves.
|
464
|
+ */
|
465
|
+ m = NULL;
|
466
|
+ goto done;
|
467
|
}
|
468
|
- goto bad;
|
469
|
- } else {
|
470
|
- /*
|
471
|
- * In the FAST IPSec case we have already
|
472
|
- * re-injected the packet and it has been freed
|
473
|
- * by the ipsec_done() function. So, just clean
|
474
|
- * up after ourselves.
|
475
|
- */
|
476
|
- m = NULL;
|
477
|
- goto done;
|
478
|
- }
|
479
|
|
480
|
- exthdrs.ip6e_ip6 = m;
|
481
|
+ exthdrs.ip6e_ip6 = m;
|
482
|
+ }
|
483
|
}
|
484
|
#endif /* IPSEC */
|
485
|
|