Bug Summary

File:net/pfkeyv2.c
Warning:line 1080, column 11
Although the value stored to 'satype' is used in the enclosing expression, the value is never actually read from 'satype'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name pfkeyv2.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/net/pfkeyv2.c
1/* $OpenBSD: pfkeyv2.c,v 1.229 2021/12/19 23:30:08 bluhm Exp $ */
2
3/*
4 * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995
5 *
6 * NRL grants permission for redistribution and use in source and binary
7 * forms, with or without modification, of the software and documentation
8 * created at NRL provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgements:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * This product includes software developed at the Information
20 * Technology Division, US Naval Research Laboratory.
21 * 4. Neither the name of the NRL nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS
26 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
28 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR
29 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * The views and conclusions contained in the software and documentation
38 * are those of the authors and should not be interpreted as representing
39 * official policies, either expressed or implied, of the US Naval
40 * Research Laboratory (NRL).
41 */
42
43/*
44 * Copyright (c) 1995, 1996, 1997, 1998, 1999 Craig Metz. All rights reserved.
45 *
46 * Redistribution and use in source and binary forms, with or without
47 * modification, are permitted provided that the following conditions
48 * are met:
49 * 1. Redistributions of source code must retain the above copyright
50 * notice, this list of conditions and the following disclaimer.
51 * 2. Redistributions in binary form must reproduce the above copyright
52 * notice, this list of conditions and the following disclaimer in the
53 * documentation and/or other materials provided with the distribution.
54 * 3. Neither the name of the author nor the names of any contributors
55 * may be used to endorse or promote products derived from this software
56 * without specific prior written permission.
57 *
58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 * SUCH DAMAGE.
69 */
70
71#include "pf.h"
72
73#include <sys/param.h>
74#include <sys/socket.h>
75#include <sys/socketvar.h>
76#include <sys/protosw.h>
77#include <sys/domain.h>
78#include <sys/systm.h>
79#include <sys/mbuf.h>
80#include <sys/kernel.h>
81#include <sys/proc.h>
82#include <sys/pool.h>
83#include <sys/mutex.h>
84
85#include <net/route.h>
86#include <netinet/ip_ipsp.h>
87#include <net/pfkeyv2.h>
88#include <net/radix.h>
89#include <netinet/ip_ah.h>
90#include <netinet/ip_esp.h>
91#include <netinet/ip_ipcomp.h>
92#include <crypto/blf.h>
93
94#if NPF1 > 0
95#include <net/if.h>
96#include <net/pfvar.h>
97#endif
98
99#define PFKEYSNDQ8192 8192
100#define PFKEYRCVQ8192 8192
101
102static const struct sadb_alg ealgs[] = {
103 { SADB_EALG_NULL11, 0, 0, 0 },
104 { SADB_EALG_3DESCBC3, 64, 192, 192 },
105 { SADB_X_EALG_BLF7, 64, 40, BLF_MAXKEYLEN((16 -2)*4) * 8},
106 { SADB_X_EALG_CAST6, 64, 40, 128},
107 { SADB_X_EALG_AES12, 128, 128, 256},
108 { SADB_X_EALG_AESCTR13, 128, 128 + 32, 256 + 32}
109};
110
111static const struct sadb_alg aalgs[] = {
112 { SADB_AALG_SHA1HMAC3, 0, 160, 160 },
113 { SADB_AALG_MD5HMAC2, 0, 128, 128 },
114 { SADB_X_AALG_RIPEMD160HMAC8, 0, 160, 160 },
115 { SADB_X_AALG_SHA2_2565, 0, 256, 256 },
116 { SADB_X_AALG_SHA2_3846, 0, 384, 384 },
117 { SADB_X_AALG_SHA2_5127, 0, 512, 512 }
118};
119
120static const struct sadb_alg calgs[] = {
121 { SADB_X_CALG_DEFLATE2, 0, 0, 0}
122};
123
124struct pool pkpcb_pool;
125#define PFKEY_MSG_MAXSZ4096 4096
126const struct sockaddr pfkey_addr = { 2, PF_KEY30, };
127const struct domain pfkeydomain;
128
129/*
130 * pfkey PCB
131 *
132 * Locks used to protect struct members in this file:
133 * I immutable after creation
134 * a atomic operations
135 * l pkptable's lock
136 * s socket lock
137 */
138struct pkpcb {
139 struct socket *kcb_socket; /* [I] associated socket */
140
141 SRPL_ENTRY(pkpcb)struct { struct srp se_next; } kcb_list; /* [l] */
142 struct refcnt kcb_refcnt; /* [a] */
143 int kcb_flags; /* [s] */
144 uint32_t kcb_reg; /* [s] Inc if SATYPE_MAX > 31 */
145 uint32_t kcb_pid; /* [I] */
146 unsigned int kcb_rdomain; /* [I] routing domain */
147};
148#define sotokeycb(so)((struct pkpcb *)(so)->so_pcb) ((struct pkpcb *)(so)->so_pcb)
149#define keylock(kp)solock((kp)->kcb_socket) solock((kp)->kcb_socket)
150#define keyunlock(kp, s)sounlock((kp)->kcb_socket, s) sounlock((kp)->kcb_socket, s)
151
152
153struct dump_state {
154 struct sadb_msg *sadb_msg;
155 struct socket *socket;
156};
157
158struct pkptable {
159 SRPL_HEAD(, pkpcb)struct srpl pkp_list;
160 struct srpl_rc pkp_rc;
161 struct rwlock pkp_lk;
162};
163
164struct pkptable pkptable;
165struct mutex pfkeyv2_mtx = MUTEX_INITIALIZER(IPL_MPFLOOR){ ((void *)0), ((((0x9)) > 0x0 && ((0x9)) < 0x9
) ? 0x9 : ((0x9))), 0x0 }
;
166static uint32_t pfkeyv2_seq = 1;
167static int nregistered = 0;
168static int npromisc = 0;
169
170void pfkey_init(void);
171
172int pfkeyv2_attach(struct socket *, int);
173int pfkeyv2_detach(struct socket *);
174int pfkeyv2_usrreq(struct socket *, int, struct mbuf *, struct mbuf *,
175 struct mbuf *, struct proc *);
176int pfkeyv2_output(struct mbuf *, struct socket *, struct sockaddr *,
177 struct mbuf *);
178int pfkey_sendup(struct pkpcb *, struct mbuf *, int);
179int pfkeyv2_sa_flush(struct tdb *, void *, int);
180int pfkeyv2_policy_flush(struct ipsec_policy *, void *, unsigned int);
181int pfkeyv2_sysctl_policydumper(struct ipsec_policy *, void *, unsigned int);
182
183void keycb_ref(void *, void *);
184void keycb_unref(void *, void *);
185
186/*
187 * Wrapper around m_devget(); copy data from contiguous buffer to mbuf
188 * chain.
189 */
190int
191pfdatatopacket(void *data, int len, struct mbuf **packet)
192{
193 if (!(*packet = m_devget(data, len, 0)))
194 return (ENOMEM12);
195
196 /* Make sure, all data gets zeroized on free */
197 (*packet)->m_flagsm_hdr.mh_flags |= M_ZEROIZE0x2000;
198
199 return (0);
200}
201
202const struct protosw pfkeysw[] = {
203{
204 .pr_type = SOCK_RAW3,
205 .pr_domain = &pfkeydomain,
206 .pr_protocol = PF_KEY_V22,
207 .pr_flags = PR_ATOMIC0x01 | PR_ADDR0x02,
208 .pr_output = pfkeyv2_output,
209 .pr_usrreq = pfkeyv2_usrreq,
210 .pr_attach = pfkeyv2_attach,
211 .pr_detach = pfkeyv2_detach,
212 .pr_sysctl = pfkeyv2_sysctl,
213}
214};
215
216const struct domain pfkeydomain = {
217 .dom_family = PF_KEY30,
218 .dom_name = "PF_KEY",
219 .dom_init = pfkey_init,
220 .dom_protosw = pfkeysw,
221 .dom_protoswNPROTOSW = &pfkeysw[nitems(pfkeysw)(sizeof((pfkeysw)) / sizeof((pfkeysw)[0]))],
222};
223
224void
225keycb_ref(void *null, void *v)
226{
227 struct pkpcb *kp = v;
228
229 refcnt_take(&kp->kcb_refcnt);
230}
231
232void
233keycb_unref(void *null, void *v)
234{
235 struct pkpcb *kp = v;
236
237 refcnt_rele_wake(&kp->kcb_refcnt);
238}
239
240void
241pfkey_init(void)
242{
243 rn_init(sizeof(struct sockaddr_encap));
244 srpl_rc_init(&pkptable.pkp_rc, keycb_ref, keycb_unref, NULL((void *)0));
245 rw_init(&pkptable.pkp_lk, "pfkey")_rw_init_flags(&pkptable.pkp_lk, "pfkey", 0, ((void *)0));
246 SRPL_INIT(&pkptable.pkp_list)srp_init(&(&pkptable.pkp_list)->sl_head);
247 pool_init(&pkpcb_pool, sizeof(struct pkpcb), 0,
248 IPL_SOFTNET0x5, PR_WAITOK0x0001, "pkpcb", NULL((void *)0));
249 pool_init(&ipsec_policy_pool, sizeof(struct ipsec_policy), 0,
250 IPL_SOFTNET0x5, 0, "ipsec policy", NULL((void *)0));
251 pool_init(&ipsec_acquire_pool, sizeof(struct ipsec_acquire), 0,
252 IPL_SOFTNET0x5, 0, "ipsec acquire", NULL((void *)0));
253}
254
255
256/*
257 * Attach a new PF_KEYv2 socket.
258 */
259int
260pfkeyv2_attach(struct socket *so, int proto)
261{
262 struct pkpcb *kp;
263 int error;
264
265 if ((so->so_state & SS_PRIV0x080) == 0)
266 return EACCES13;
267
268 error = soreserve(so, PFKEYSNDQ8192, PFKEYRCVQ8192);
269 if (error)
270 return (error);
271
272 kp = pool_get(&pkpcb_pool, PR_WAITOK0x0001|PR_ZERO0x0008);
273 so->so_pcb = kp;
274 refcnt_init(&kp->kcb_refcnt);
275 kp->kcb_socket = so;
276 kp->kcb_pid = curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
->p_p->ps_pid;
277 kp->kcb_rdomain = rtable_l2(curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
->p_p->ps_rtableid);
278
279 so->so_options |= SO_USELOOPBACK0x0040;
280 soisconnected(so);
281
282 rw_enter(&pkptable.pkp_lk, RW_WRITE0x0001UL);
283 SRPL_INSERT_HEAD_LOCKED(&pkptable.pkp_rc, &pkptable.pkp_list, kp, kcb_list)do { void *head; srp_init(&(kp)->kcb_list.se_next); head
= srp_get_locked(&(&pkptable.pkp_list)->sl_head);
if (head != ((void *)0)) { (&pkptable.pkp_rc)->srpl_ref
(&(&pkptable.pkp_rc)->srpl_gc.srp_gc_cookie, head)
; srp_update_locked(&(&pkptable.pkp_rc)->srpl_gc, &
(kp)->kcb_list.se_next, head); } (&pkptable.pkp_rc)->
srpl_ref(&(&pkptable.pkp_rc)->srpl_gc.srp_gc_cookie
, kp); srp_update_locked(&(&pkptable.pkp_rc)->srpl_gc
, &(&pkptable.pkp_list)->sl_head, (kp)); } while (
0)
;
284 rw_exit(&pkptable.pkp_lk);
285
286 return (0);
287}
288
289/*
290 * Close a PF_KEYv2 socket.
291 */
292int
293pfkeyv2_detach(struct socket *so)
294{
295 struct pkpcb *kp;
296
297 soassertlocked(so);
298
299 kp = sotokeycb(so)((struct pkpcb *)(so)->so_pcb);
300 if (kp == NULL((void *)0))
301 return ENOTCONN57;
302
303 if (kp->kcb_flags &
304 (PFKEYV2_SOCKETFLAGS_REGISTERED1|PFKEYV2_SOCKETFLAGS_PROMISC2)) {
305 mtx_enter(&pfkeyv2_mtx);
306 if (kp->kcb_flags & PFKEYV2_SOCKETFLAGS_REGISTERED1)
307 nregistered--;
308
309 if (kp->kcb_flags & PFKEYV2_SOCKETFLAGS_PROMISC2)
310 npromisc--;
311 mtx_leave(&pfkeyv2_mtx);
312 }
313
314 rw_enter(&pkptable.pkp_lk, RW_WRITE0x0001UL);
315 SRPL_REMOVE_LOCKED(&pkptable.pkp_rc, &pkptable.pkp_list, kp, pkpcb,do { struct srp *ref; struct pkpcb *c, *n; ref = &(&pkptable
.pkp_list)->sl_head; while ((c = srp_get_locked(ref)) != (
kp)) ref = &c->kcb_list.se_next; n = srp_get_locked(&
(c)->kcb_list.se_next); if (n != ((void *)0)) (&pkptable
.pkp_rc)->srpl_ref(&(&pkptable.pkp_rc)->srpl_gc
.srp_gc_cookie, n); srp_update_locked(&(&pkptable.pkp_rc
)->srpl_gc, ref, n); srp_update_locked(&(&pkptable
.pkp_rc)->srpl_gc, &c->kcb_list.se_next, ((void *)0
)); } while (0)
316 kcb_list)do { struct srp *ref; struct pkpcb *c, *n; ref = &(&pkptable
.pkp_list)->sl_head; while ((c = srp_get_locked(ref)) != (
kp)) ref = &c->kcb_list.se_next; n = srp_get_locked(&
(c)->kcb_list.se_next); if (n != ((void *)0)) (&pkptable
.pkp_rc)->srpl_ref(&(&pkptable.pkp_rc)->srpl_gc
.srp_gc_cookie, n); srp_update_locked(&(&pkptable.pkp_rc
)->srpl_gc, ref, n); srp_update_locked(&(&pkptable
.pkp_rc)->srpl_gc, &c->kcb_list.se_next, ((void *)0
)); } while (0)
;
317 rw_exit(&pkptable.pkp_lk);
318
319 sounlock(so, SL_LOCKED0x42);
320 /* wait for all references to drop */
321 refcnt_finalize(&kp->kcb_refcnt, "pfkeyrefs");
322 solock(so);
323
324 so->so_pcb = NULL((void *)0);
325 KASSERT((so->so_state & SS_NOFDREF) == 0)(((so->so_state & 0x001) == 0) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/net/pfkeyv2.c", 325, "(so->so_state & SS_NOFDREF) == 0"
))
;
326 pool_put(&pkpcb_pool, kp);
327
328 return (0);
329}
330
331int
332pfkeyv2_usrreq(struct socket *so, int req, struct mbuf *m,
333 struct mbuf *nam, struct mbuf *control, struct proc *p)
334{
335 struct pkpcb *kp;
336 int error = 0;
337
338 if (req == PRU_CONTROL11)
339 return (EOPNOTSUPP45);
340
341 soassertlocked(so);
342
343 if (control && control->m_lenm_hdr.mh_len) {
344 error = EOPNOTSUPP45;
345 goto release;
346 }
347
348 kp = sotokeycb(so)((struct pkpcb *)(so)->so_pcb);
349 if (kp == NULL((void *)0)) {
350 error = EINVAL22;
351 goto release;
352 }
353
354 switch (req) {
355 /* no connect, bind, accept. Socket is connected from the start */
356 case PRU_CONNECT4:
357 case PRU_BIND2:
358 case PRU_CONNECT217:
359 case PRU_LISTEN3:
360 case PRU_ACCEPT5:
361 error = EOPNOTSUPP45;
362 break;
363
364 case PRU_DISCONNECT6:
365 case PRU_ABORT10:
366 soisdisconnected(so);
367 break;
368 case PRU_SHUTDOWN7:
369 socantsendmore(so);
370 break;
371 case PRU_SENSE12:
372 /* stat: don't bother with a blocksize. */
373 break;
374
375 /* minimal support, just implement a fake peer address */
376 case PRU_SOCKADDR15:
377 error = EINVAL22;
378 break;
379 case PRU_PEERADDR16:
380 bcopy(&pfkey_addr, mtod(nam, caddr_t)((caddr_t)((nam)->m_hdr.mh_data)), pfkey_addr.sa_len);
381 nam->m_lenm_hdr.mh_len = pfkey_addr.sa_len;
382 break;
383
384 case PRU_RCVOOB13:
385 case PRU_RCVD8:
386 case PRU_SENDOOB14:
387 error = EOPNOTSUPP45;
388 break;
389 case PRU_SEND9:
390 if (nam) {
391 error = EISCONN56;
392 break;
393 }
394 error = (*so->so_proto->pr_output)(m, so, NULL((void *)0), NULL((void *)0));
395 m = NULL((void *)0);
396 break;
397 default:
398 panic("pfkeyv2_usrreq");
399 }
400
401 release:
402 if (req != PRU_RCVD8 && req != PRU_RCVOOB13 && req != PRU_SENSE12) {
403 m_freem(control);
404 m_freem(m);
405 }
406 return (error);
407}
408
409int
410pfkeyv2_output(struct mbuf *mbuf, struct socket *so,
411 struct sockaddr *dstaddr, struct mbuf *control)
412{
413 void *message;
414 int error = 0;
415
416#ifdef DIAGNOSTIC1
417 if (!mbuf || !(mbuf->m_flagsm_hdr.mh_flags & M_PKTHDR0x0002)) {
418 error = EINVAL22;
419 goto ret;
420 }
421#endif /* DIAGNOSTIC */
422
423 if (mbuf->m_pkthdrM_dat.MH.MH_pkthdr.len > PFKEY_MSG_MAXSZ4096) {
424 error = EMSGSIZE40;
425 goto ret;
426 }
427
428 if (!(message = malloc((unsigned long) mbuf->m_pkthdrM_dat.MH.MH_pkthdr.len,
429 M_PFKEY74, M_DONTWAIT0x0002))) {
430 error = ENOMEM12;
431 goto ret;
432 }
433
434 m_copydata(mbuf, 0, mbuf->m_pkthdrM_dat.MH.MH_pkthdr.len, message);
435
436 /*
437 * The socket can't be closed concurrently because the file
438 * descriptor reference is still held.
439 */
440
441 sounlock(so, SL_LOCKED0x42);
442 error = pfkeyv2_send(so, message, mbuf->m_pkthdrM_dat.MH.MH_pkthdr.len);
443 solock(so);
444
445ret:
446 m_freem(mbuf);
447 return (error);
448}
449
450int
451pfkey_sendup(struct pkpcb *kp, struct mbuf *m0, int more)
452{
453 struct socket *so = kp->kcb_socket;
454 struct mbuf *m;
455
456 soassertlocked(so);
457
458 if (more) {
459 if (!(m = m_dup_pkt(m0, 0, M_DONTWAIT0x0002)))
460 return (ENOMEM12);
461 } else
462 m = m0;
463
464 if (!sbappendaddr(so, &so->so_rcv, &pfkey_addr, m, NULL((void *)0))) {
465 m_freem(m);
466 return (ENOBUFS55);
467 }
468
469 sorwakeup(so);
470 return (0);
471}
472
473/*
474 * Send a PFKEYv2 message, possibly to many receivers, based on the
475 * satype of the socket (which is set by the REGISTER message), and the
476 * third argument.
477 */
478int
479pfkeyv2_sendmessage(void **headers, int mode, struct socket *so,
480 u_int8_t satype, int count, u_int rdomain)
481{
482 int i, j, rval, s;
483 void *p, *buffer = NULL((void *)0);
484 struct mbuf *packet;
485 struct pkpcb *kp;
486 struct sadb_msg *smsg;
487 struct srp_ref sr;
488
489 /* Find out how much space we'll need... */
490 j = sizeof(struct sadb_msg);
491
492 for (i = 1; i <= SADB_EXT_MAX39; i++)
493 if (headers[i])
494 j += ((struct sadb_ext *)headers[i])->sadb_ext_len *
495 sizeof(uint64_t);
496
497 /* ...and allocate it */
498 if (!(buffer = malloc(j + sizeof(struct sadb_msg), M_PFKEY74,
499 M_NOWAIT0x0002))) {
500 rval = ENOMEM12;
501 goto ret;
502 }
503
504 p = buffer + sizeof(struct sadb_msg);
505 bcopy(headers[0], p, sizeof(struct sadb_msg));
506 ((struct sadb_msg *) p)->sadb_msg_len = j / sizeof(uint64_t);
507 p += sizeof(struct sadb_msg);
508
509 /* Copy payloads in the packet */
510 for (i = 1; i <= SADB_EXT_MAX39; i++)
511 if (headers[i]) {
512 ((struct sadb_ext *) headers[i])->sadb_ext_type = i;
513 bcopy(headers[i], p, EXTLEN(headers[i])(((struct sadb_ext *)(headers[i]))->sadb_ext_len * sizeof(
uint64_t))
);
514 p += EXTLEN(headers[i])(((struct sadb_ext *)(headers[i]))->sadb_ext_len * sizeof(
uint64_t))
;
515 }
516
517 if ((rval = pfdatatopacket(buffer + sizeof(struct sadb_msg),
518 j, &packet)) != 0)
519 goto ret;
520
521 switch (mode) {
522 case PFKEYV2_SENDMESSAGE_UNICAST1:
523 /*
524 * Send message to the specified socket, plus all
525 * promiscuous listeners.
526 */
527 s = solock(so);
528 pfkey_sendup(sotokeycb(so)((struct pkpcb *)(so)->so_pcb), packet, 0);
529 sounlock(so, s);
530
531 /*
532 * Promiscuous messages contain the original message
533 * encapsulated in another sadb_msg header.
534 */
535 bzero(buffer, sizeof(struct sadb_msg))__builtin_bzero((buffer), (sizeof(struct sadb_msg)));
536 smsg = (struct sadb_msg *) buffer;
537 smsg->sadb_msg_version = PF_KEY_V22;
538 smsg->sadb_msg_type = SADB_X_PROMISC11;
539 smsg->sadb_msg_len = (sizeof(struct sadb_msg) + j) /
540 sizeof(uint64_t);
541 smsg->sadb_msg_seq = 0;
542
543 /* Copy to mbuf chain */
544 if ((rval = pfdatatopacket(buffer, sizeof(struct sadb_msg) + j,
545 &packet)) != 0)
546 goto ret;
547
548 /*
549 * Search for promiscuous listeners, skipping the
550 * original destination.
551 */
552 SRPL_FOREACH(kp, &sr, &pkptable.pkp_list, kcb_list)for ((kp) = srp_enter((&sr), &(&pkptable.pkp_list
)->sl_head); (kp) != ((void *)0); (kp) = srp_follow((&
sr), &(kp)->kcb_list.se_next))
{
553 if (kp->kcb_socket == so || kp->kcb_rdomain != rdomain)
554 continue;
555
556 s = keylock(kp)solock((kp)->kcb_socket);
557 if (kp->kcb_flags & PFKEYV2_SOCKETFLAGS_PROMISC2)
558 pfkey_sendup(kp, packet, 1);
559 keyunlock(kp, s)sounlock((kp)->kcb_socket, s);
560 }
561 SRPL_LEAVE(&sr)srp_leave((&sr));
562 m_freem(packet);
563 break;
564
565 case PFKEYV2_SENDMESSAGE_REGISTERED2:
566 /*
567 * Send the message to all registered sockets that match
568 * the specified satype (e.g., all IPSEC-ESP negotiators)
569 */
570 SRPL_FOREACH(kp, &sr, &pkptable.pkp_list, kcb_list)for ((kp) = srp_enter((&sr), &(&pkptable.pkp_list
)->sl_head); (kp) != ((void *)0); (kp) = srp_follow((&
sr), &(kp)->kcb_list.se_next))
{
571 if (kp->kcb_rdomain != rdomain)
572 continue;
573
574 s = keylock(kp)solock((kp)->kcb_socket);
575 if (kp->kcb_flags & PFKEYV2_SOCKETFLAGS_REGISTERED1) {
576 if (!satype) {
577 /* Just send to everyone registered */
578 pfkey_sendup(kp, packet, 1);
579 } else {
580 /* Check for specified satype */
581 if ((1 << satype) & kp->kcb_reg)
582 pfkey_sendup(kp, packet, 1);
583 }
584 }
585 keyunlock(kp, s)sounlock((kp)->kcb_socket, s);
586 }
587 SRPL_LEAVE(&sr)srp_leave((&sr));
588 /* Free last/original copy of the packet */
589 m_freem(packet);
590
591 /* Encapsulate the original message "inside" an sadb_msg header */
592 bzero(buffer, sizeof(struct sadb_msg))__builtin_bzero((buffer), (sizeof(struct sadb_msg)));
593 smsg = (struct sadb_msg *) buffer;
594 smsg->sadb_msg_version = PF_KEY_V22;
595 smsg->sadb_msg_type = SADB_X_PROMISC11;
596 smsg->sadb_msg_len = (sizeof(struct sadb_msg) + j) /
597 sizeof(uint64_t);
598 smsg->sadb_msg_seq = 0;
599
600 /* Convert to mbuf chain */
601 if ((rval = pfdatatopacket(buffer, sizeof(struct sadb_msg) + j,
602 &packet)) != 0)
603 goto ret;
604
605 /* Send to all registered promiscuous listeners */
606 SRPL_FOREACH(kp, &sr, &pkptable.pkp_list, kcb_list)for ((kp) = srp_enter((&sr), &(&pkptable.pkp_list
)->sl_head); (kp) != ((void *)0); (kp) = srp_follow((&
sr), &(kp)->kcb_list.se_next))
{
607 if (kp->kcb_rdomain != rdomain)
608 continue;
609
610 s = keylock(kp)solock((kp)->kcb_socket);
611 if ((kp->kcb_flags & PFKEYV2_SOCKETFLAGS_PROMISC2) &&
612 !(kp->kcb_flags & PFKEYV2_SOCKETFLAGS_REGISTERED1))
613 pfkey_sendup(kp, packet, 1);
614 keyunlock(kp, s)sounlock((kp)->kcb_socket, s);
615 }
616 SRPL_LEAVE(&sr)srp_leave((&sr));
617 m_freem(packet);
618 break;
619
620 case PFKEYV2_SENDMESSAGE_BROADCAST3:
621 /* Send message to all sockets */
622 SRPL_FOREACH(kp, &sr, &pkptable.pkp_list, kcb_list)for ((kp) = srp_enter((&sr), &(&pkptable.pkp_list
)->sl_head); (kp) != ((void *)0); (kp) = srp_follow((&
sr), &(kp)->kcb_list.se_next))
{
623 if (kp->kcb_rdomain != rdomain)
624 continue;
625
626 s = keylock(kp)solock((kp)->kcb_socket);
627 pfkey_sendup(kp, packet, 1);
628 keyunlock(kp, s)sounlock((kp)->kcb_socket, s);
629 }
630 SRPL_LEAVE(&sr)srp_leave((&sr));
631 m_freem(packet);
632 break;
633 }
634
635ret:
636 if (buffer != NULL((void *)0)) {
637 explicit_bzero(buffer, j + sizeof(struct sadb_msg));
638 free(buffer, M_PFKEY74, j + sizeof(struct sadb_msg));
639 }
640
641 return (rval);
642}
643
644/*
645 * Get SPD information for an ACQUIRE. We setup the message such that
646 * the SRC/DST payloads are relative to us (regardless of whether the
647 * SPD rule was for incoming or outgoing packets).
648 */
649int
650pfkeyv2_policy(struct ipsec_acquire *ipa, void **headers, void **buffer,
651 int *bufferlen)
652{
653 union sockaddr_union sunion;
654 struct sadb_protocol *sp;
655 int rval, i, dir;
656 void *p;
657
658 /* Find out how big a buffer we need */
659 i = 4 * sizeof(struct sadb_address) + sizeof(struct sadb_protocol);
660 bzero(&sunion, sizeof(union sockaddr_union))__builtin_bzero((&sunion), (sizeof(union sockaddr_union))
)
;
661
662 switch (ipa->ipa_info.sen_type) {
663 case SENT_IP40x0001:
664 i += 4 * PADUP(sizeof(struct sockaddr_in))(((sizeof(struct sockaddr_in)) + sizeof(uint64_t) - 1) & ~
(sizeof(uint64_t) - 1))
;
665 sunion.sa.sa_family = AF_INET2;
666 sunion.sa.sa_len = sizeof(struct sockaddr_in);
667 dir = ipa->ipa_info.sen_directionSen.Sip4.Direction;
668 break;
669
670#ifdef INET61
671 case SENT_IP60x0002:
672 i += 4 * PADUP(sizeof(struct sockaddr_in6))(((sizeof(struct sockaddr_in6)) + sizeof(uint64_t) - 1) &
~(sizeof(uint64_t) - 1))
;
673 sunion.sa.sa_family = AF_INET624;
674 sunion.sa.sa_len = sizeof(struct sockaddr_in6);
675 dir = ipa->ipa_info.sen_ip6_directionSen.Sip6.Direction;
676 break;
677#endif /* INET6 */
678
679 default:
680 return (EINVAL22);
681 }
682
683 if (!(p = malloc(i, M_PFKEY74, M_NOWAIT0x0002 | M_ZERO0x0008))) {
684 rval = ENOMEM12;
685 goto ret;
686 } else {
687 *buffer = p;
688 *bufferlen = i;
689 }
690
691 if (dir == IPSP_DIRECTION_OUT0x2)
692 headers[SADB_X_EXT_SRC_FLOW21] = p;
693 else
694 headers[SADB_X_EXT_DST_FLOW22] = p;
695 switch (sunion.sa.sa_family) {
696 case AF_INET2:
697 sunion.sin.sin_addr = ipa->ipa_info.sen_ip_srcSen.Sip4.Src;
698 sunion.sin.sin_port = ipa->ipa_info.sen_sportSen.Sip4.Sport;
699 break;
700
701#ifdef INET61
702 case AF_INET624:
703 sunion.sin6.sin6_addr = ipa->ipa_info.sen_ip6_srcSen.Sip6.Src;
704 sunion.sin6.sin6_port = ipa->ipa_info.sen_ip6_sportSen.Sip6.Sport;
705 break;
706#endif /* INET6 */
707 }
708 export_address(&p, &sunion.sa);
709
710 if (dir == IPSP_DIRECTION_OUT0x2)
711 headers[SADB_X_EXT_SRC_MASK17] = p;
712 else
713 headers[SADB_X_EXT_DST_MASK18] = p;
714 switch (sunion.sa.sa_family) {
715 case AF_INET2:
716 sunion.sin.sin_addr = ipa->ipa_mask.sen_ip_srcSen.Sip4.Src;
717 sunion.sin.sin_port = ipa->ipa_mask.sen_sportSen.Sip4.Sport;
718 break;
719
720#ifdef INET61
721 case AF_INET624:
722 sunion.sin6.sin6_addr = ipa->ipa_mask.sen_ip6_srcSen.Sip6.Src;
723 sunion.sin6.sin6_port = ipa->ipa_mask.sen_ip6_sportSen.Sip6.Sport;
724 break;
725#endif /* INET6 */
726 }
727 export_address(&p, &sunion.sa);
728
729 if (dir == IPSP_DIRECTION_OUT0x2)
730 headers[SADB_X_EXT_DST_FLOW22] = p;
731 else
732 headers[SADB_X_EXT_SRC_FLOW21] = p;
733 switch (sunion.sa.sa_family) {
734 case AF_INET2:
735 sunion.sin.sin_addr = ipa->ipa_info.sen_ip_dstSen.Sip4.Dst;
736 sunion.sin.sin_port = ipa->ipa_info.sen_dportSen.Sip4.Dport;
737 break;
738
739#ifdef INET61
740 case AF_INET624:
741 sunion.sin6.sin6_addr = ipa->ipa_info.sen_ip6_dstSen.Sip6.Dst;
742 sunion.sin6.sin6_port = ipa->ipa_info.sen_ip6_dportSen.Sip6.Dport;
743 break;
744#endif /* INET6 */
745 }
746 export_address(&p, &sunion.sa);
747
748 if (dir == IPSP_DIRECTION_OUT0x2)
749 headers[SADB_X_EXT_DST_MASK18] = p;
750 else
751 headers[SADB_X_EXT_SRC_MASK17] = p;
752 switch (sunion.sa.sa_family) {
753 case AF_INET2:
754 sunion.sin.sin_addr = ipa->ipa_mask.sen_ip_dstSen.Sip4.Dst;
755 sunion.sin.sin_port = ipa->ipa_mask.sen_dportSen.Sip4.Dport;
756 break;
757
758#ifdef INET61
759 case AF_INET624:
760 sunion.sin6.sin6_addr = ipa->ipa_mask.sen_ip6_dstSen.Sip6.Dst;
761 sunion.sin6.sin6_port = ipa->ipa_mask.sen_ip6_dportSen.Sip6.Dport;
762 break;
763#endif /* INET6 */
764 }
765 export_address(&p, &sunion.sa);
766
767 headers[SADB_X_EXT_FLOW_TYPE20] = p;
768 sp = p;
769 sp->sadb_protocol_len = sizeof(struct sadb_protocol) /
770 sizeof(u_int64_t);
771 switch (sunion.sa.sa_family) {
772 case AF_INET2:
773 if (ipa->ipa_mask.sen_protoSen.Sip4.Proto)
774 sp->sadb_protocol_proto = ipa->ipa_info.sen_protoSen.Sip4.Proto;
775 sp->sadb_protocol_direction = ipa->ipa_info.sen_directionSen.Sip4.Direction;
776 break;
777
778#ifdef INET61
779 case AF_INET624:
780 if (ipa->ipa_mask.sen_ip6_protoSen.Sip6.Proto)
781 sp->sadb_protocol_proto = ipa->ipa_info.sen_ip6_protoSen.Sip6.Proto;
782 sp->sadb_protocol_direction = ipa->ipa_info.sen_ip6_directionSen.Sip6.Direction;
783 break;
784#endif /* INET6 */
785 }
786
787 rval = 0;
788
789ret:
790 return (rval);
791}
792
793/*
794 * Get all the information contained in an SA to a PFKEYV2 message.
795 */
796int
797pfkeyv2_get(struct tdb *tdb, void **headers, void **buffer, int *lenp,
798 int *lenused)
799{
800 int rval, i;
801 void *p;
802
803 NET_ASSERT_LOCKED()do { int _s = rw_status(&netlock); if ((splassert_ctl >
0) && (_s != 0x0001UL && _s != 0x0002UL)) splassert_fail
(0x0002UL, _s, __func__); } while (0)
;
804
805 /* Find how much space we need */
806 i = sizeof(struct sadb_sa) + sizeof(struct sadb_lifetime) +
807 sizeof(struct sadb_x_counter);
808
809 if (tdb->tdb_soft_allocations || tdb->tdb_soft_bytes ||
810 tdb->tdb_soft_timeout || tdb->tdb_soft_first_use)
811 i += sizeof(struct sadb_lifetime);
812
813 if (tdb->tdb_exp_allocations || tdb->tdb_exp_bytes ||
814 tdb->tdb_exp_timeout || tdb->tdb_exp_first_use)
815 i += sizeof(struct sadb_lifetime);
816
817 if (tdb->tdb_last_used)
818 i += sizeof(struct sadb_lifetime);
819
820 i += sizeof(struct sadb_address) + PADUP(tdb->tdb_src.sa.sa_len)(((tdb->tdb_src.sa.sa_len) + sizeof(uint64_t) - 1) & ~
(sizeof(uint64_t) - 1))
;
821 i += sizeof(struct sadb_address) + PADUP(tdb->tdb_dst.sa.sa_len)(((tdb->tdb_dst.sa.sa_len) + sizeof(uint64_t) - 1) & ~
(sizeof(uint64_t) - 1))
;
822
823 if (tdb->tdb_ids) {
824 i += sizeof(struct sadb_ident) + PADUP(tdb->tdb_ids->id_local->len)(((tdb->tdb_ids->id_local->len) + sizeof(uint64_t) -
1) & ~(sizeof(uint64_t) - 1))
;
825 i += sizeof(struct sadb_ident) + PADUP(tdb->tdb_ids->id_remote->len)(((tdb->tdb_ids->id_remote->len) + sizeof(uint64_t) -
1) & ~(sizeof(uint64_t) - 1))
;
826 }
827
828 if (tdb->tdb_amxkey)
829 i += sizeof(struct sadb_key) + PADUP(tdb->tdb_amxkeylen)(((tdb->tdb_amxkeylen) + sizeof(uint64_t) - 1) & ~(sizeof
(uint64_t) - 1))
;
830
831 if (tdb->tdb_emxkey)
832 i += sizeof(struct sadb_key) + PADUP(tdb->tdb_emxkeylen)(((tdb->tdb_emxkeylen) + sizeof(uint64_t) - 1) & ~(sizeof
(uint64_t) - 1))
;
833
834 if (tdb->tdb_filter.sen_type) {
835 i += 2 * sizeof(struct sadb_protocol);
836
837 /* We'll need four of them: src, src mask, dst, dst mask. */
838 switch (tdb->tdb_filter.sen_type) {
839 case SENT_IP40x0001:
840 i += 4 * PADUP(sizeof(struct sockaddr_in))(((sizeof(struct sockaddr_in)) + sizeof(uint64_t) - 1) & ~
(sizeof(uint64_t) - 1))
;
841 i += 4 * sizeof(struct sadb_address);
842 break;
843#ifdef INET61
844 case SENT_IP60x0002:
845 i += 4 * PADUP(sizeof(struct sockaddr_in6))(((sizeof(struct sockaddr_in6)) + sizeof(uint64_t) - 1) &
~(sizeof(uint64_t) - 1))
;
846 i += 4 * sizeof(struct sadb_address);
847 break;
848#endif /* INET6 */
849 default:
850 rval = EINVAL22;
851 goto ret;
852 }
853 }
854
855 if (tdb->tdb_onext) {
856 i += sizeof(struct sadb_sa);
857 i += sizeof(struct sadb_address) +
858 PADUP(tdb->tdb_onext->tdb_dst.sa.sa_len)(((tdb->tdb_onext->tdb_dst.sa.sa_len) + sizeof(uint64_t
) - 1) & ~(sizeof(uint64_t) - 1))
;
859 i += sizeof(struct sadb_protocol);
860 }
861
862 if (tdb->tdb_udpencap_port)
863 i += sizeof(struct sadb_x_udpencap);
864
865 i += sizeof(struct sadb_x_replay);
866
867 if (tdb->tdb_mtu > 0)
868 i+= sizeof(struct sadb_x_mtu);
869
870 if (tdb->tdb_rdomain != tdb->tdb_rdomain_post)
871 i += sizeof(struct sadb_x_rdomain);
872
873#if NPF1 > 0
874 if (tdb->tdb_tag)
875 i += sizeof(struct sadb_x_tag) + PADUP(PF_TAG_NAME_SIZE)(((64) + sizeof(uint64_t) - 1) & ~(sizeof(uint64_t) - 1));
876 if (tdb->tdb_tap)
877 i += sizeof(struct sadb_x_tap);
878#endif
879
880 if (lenp)
881 *lenp = i;
882
883 if (buffer == NULL((void *)0)) {
884 rval = 0;
885 goto ret;
886 }
887
888 if (!(p = malloc(i, M_PFKEY74, M_NOWAIT0x0002 | M_ZERO0x0008))) {
889 rval = ENOMEM12;
890 goto ret;
891 } else
892 *buffer = p;
893
894 headers[SADB_EXT_SA1] = p;
895
896 export_sa(&p, tdb); /* Export SA information (mostly flags) */
897
898 /* Export lifetimes where applicable */
899 headers[SADB_EXT_LIFETIME_CURRENT2] = p;
900 export_lifetime(&p, tdb, PFKEYV2_LIFETIME_CURRENT2);
901
902 if (tdb->tdb_soft_allocations || tdb->tdb_soft_bytes ||
903 tdb->tdb_soft_first_use || tdb->tdb_soft_timeout) {
904 headers[SADB_EXT_LIFETIME_SOFT4] = p;
905 export_lifetime(&p, tdb, PFKEYV2_LIFETIME_SOFT1);
906 }
907
908 if (tdb->tdb_exp_allocations || tdb->tdb_exp_bytes ||
909 tdb->tdb_exp_first_use || tdb->tdb_exp_timeout) {
910 headers[SADB_EXT_LIFETIME_HARD3] = p;
911 export_lifetime(&p, tdb, PFKEYV2_LIFETIME_HARD0);
912 }
913
914 if (tdb->tdb_last_used) {
915 headers[SADB_X_EXT_LIFETIME_LASTUSE32] = p;
916 export_lifetime(&p, tdb, PFKEYV2_LIFETIME_LASTUSE3);
917 }
918
919 /* Export TDB source address */
920 headers[SADB_EXT_ADDRESS_SRC5] = p;
921 export_address(&p, &tdb->tdb_src.sa);
922
923 /* Export TDB destination address */
924 headers[SADB_EXT_ADDRESS_DST6] = p;
925 export_address(&p, &tdb->tdb_dst.sa);
926
927 /* Export source/destination identities, if present */
928 if (tdb->tdb_ids)
929 export_identities(&p, tdb->tdb_ids, tdb->tdb_ids_swapped, headers);
930
931 /* Export authentication key, if present */
932 if (tdb->tdb_amxkey) {
933 headers[SADB_EXT_KEY_AUTH8] = p;
934 export_key(&p, tdb, PFKEYV2_AUTHENTICATION_KEY1);
935 }
936
937 /* Export encryption key, if present */
938 if (tdb->tdb_emxkey) {
939 headers[SADB_EXT_KEY_ENCRYPT9] = p;
940 export_key(&p, tdb, PFKEYV2_ENCRYPTION_KEY0);
941 }
942
943 /* Export flow/filter, if present */
944 if (tdb->tdb_filter.sen_type)
945 export_flow(&p, IPSP_IPSEC_USE0, &tdb->tdb_filter,
946 &tdb->tdb_filtermask, headers);
947
948 if (tdb->tdb_onext) {
949 headers[SADB_X_EXT_SA223] = p;
950 export_sa(&p, tdb->tdb_onext);
951 headers[SADB_X_EXT_DST224] = p;
952 export_address(&p, &tdb->tdb_onext->tdb_dst.sa);
953 headers[SADB_X_EXT_SATYPE235] = p;
954 export_satype(&p, tdb->tdb_onext);
955 }
956
957 /* Export UDP encapsulation port, if present */
958 if (tdb->tdb_udpencap_port) {
959 headers[SADB_X_EXT_UDPENCAP31] = p;
960 export_udpencap(&p, tdb);
961 }
962
963 headers[SADB_X_EXT_REPLAY39] = p;
964 export_replay(&p, tdb);
965
966 if (tdb->tdb_mtu > 0) {
967 headers[SADB_X_EXT_MTU38] = p;
968 export_mtu(&p, tdb);
969 }
970
971 /* Export rdomain switch, if present */
972 if (tdb->tdb_rdomain != tdb->tdb_rdomain_post) {
973 headers[SADB_X_EXT_RDOMAIN37] = p;
974 export_rdomain(&p, tdb);
975 }
976
977#if NPF1 > 0
978 /* Export tag information, if present */
979 if (tdb->tdb_tag) {
980 headers[SADB_X_EXT_TAG33] = p;
981 export_tag(&p, tdb);
982 }
983
984 /* Export tap enc(4) device information, if present */
985 if (tdb->tdb_tap) {
986 headers[SADB_X_EXT_TAP34] = p;
987 export_tap(&p, tdb);
988 }
989#endif
990
991 headers[SADB_X_EXT_COUNTER36] = p;
992 export_counter(&p, tdb);
993
994 if (lenused)
995 *lenused = p - *buffer;
996 rval = 0;
997
998 ret:
999 return (rval);
1000}
1001
1002/*
1003 * Dump a TDB.
1004 */
1005int
1006pfkeyv2_dump_walker(struct tdb *tdb, void *state, int last)
1007{
1008 struct dump_state *dump_state = (struct dump_state *) state;
1009 void *headers[SADB_EXT_MAX39+1], *buffer;
1010 int buflen;
1011 int rval;
1012
1013 /* If not satype was specified, dump all TDBs */
1014 if (!dump_state->sadb_msg->sadb_msg_satype ||
1015 (tdb->tdb_satype == dump_state->sadb_msg->sadb_msg_satype)) {
1016 bzero(headers, sizeof(headers))__builtin_bzero((headers), (sizeof(headers)));
1017 headers[0] = (void *) dump_state->sadb_msg;
1018
1019 /* Get the information from the TDB to a PFKEYv2 message */
1020 if ((rval = pfkeyv2_get(tdb, headers, &buffer, &buflen, NULL((void *)0))) != 0)
1021 return (rval);
1022
1023 if (last)
1024 ((struct sadb_msg *)headers[0])->sadb_msg_seq = 0;
1025
1026 /* Send the message to the specified socket */
1027 rval = pfkeyv2_sendmessage(headers,
1028 PFKEYV2_SENDMESSAGE_UNICAST1, dump_state->socket, 0, 0,
1029 tdb->tdb_rdomain);
1030
1031 explicit_bzero(buffer, buflen);
1032 free(buffer, M_PFKEY74, buflen);
1033 if (rval)
1034 return (rval);
1035 }
1036
1037 return (0);
1038}
1039
1040/*
1041 * Delete an SA.
1042 */
1043int
1044pfkeyv2_sa_flush(struct tdb *tdb, void *satype_vp, int last)
1045{
1046 if (!(*((u_int8_t *) satype_vp)) ||
1047 tdb->tdb_satype == *((u_int8_t *) satype_vp))
1048 tdb_delete(tdb);
1049 return (0);
1050}
1051
1052/*
1053 * Convert between SATYPEs and IPsec protocols, taking into consideration
1054 * sysctl variables enabling/disabling ESP/AH and the presence of the old
1055 * IPsec transforms.
1056 */
1057int
1058pfkeyv2_get_proto_alg(u_int8_t satype, u_int8_t *sproto, int *alg)
1059{
1060 switch (satype) {
1061#ifdef IPSEC1
1062 case SADB_SATYPE_AH1:
1063 if (!ah_enable)
1064 return (EOPNOTSUPP45);
1065
1066 *sproto = IPPROTO_AH51;
1067
1068 if(alg != NULL((void *)0))
1069 *alg = satype = XF_AH2;
1070
1071 break;
1072
1073 case SADB_SATYPE_ESP2:
1074 if (!esp_enable)
1075 return (EOPNOTSUPP45);
1076
1077 *sproto = IPPROTO_ESP50;
1078
1079 if(alg != NULL((void *)0))
1080 *alg = satype = XF_ESP3;
Although the value stored to 'satype' is used in the enclosing expression, the value is never actually read from 'satype'
1081
1082 break;
1083
1084 case SADB_X_SATYPE_IPIP7:
1085 *sproto = IPPROTO_IPIP4;
1086
1087 if (alg != NULL((void *)0))
1088 *alg = XF_IP41;
1089
1090 break;
1091
1092 case SADB_X_SATYPE_IPCOMP9:
1093 if (!ipcomp_enable)
1094 return (EOPNOTSUPP45);
1095
1096 *sproto = IPPROTO_IPCOMP108;
1097
1098 if(alg != NULL((void *)0))
1099 *alg = satype = XF_IPCOMP6;
1100
1101 break;
1102#endif /* IPSEC */
1103#ifdef TCP_SIGNATURE1
1104 case SADB_X_SATYPE_TCPSIGNATURE8:
1105 *sproto = IPPROTO_TCP6;
1106
1107 if (alg != NULL((void *)0))
1108 *alg = XF_TCPSIGNATURE5;
1109
1110 break;
1111#endif /* TCP_SIGNATURE */
1112
1113 default: /* Nothing else supported */
1114 return (EOPNOTSUPP45);
1115 }
1116
1117 return (0);
1118}
1119
1120/*
1121 * Handle all messages from userland to kernel.
1122 */
1123int
1124pfkeyv2_send(struct socket *so, void *message, int len)
1125{
1126 int i, j, rval = 0, mode = PFKEYV2_SENDMESSAGE_BROADCAST3;
1127 int delflag = 0;
1128 struct sockaddr_encap encapdst, encapnetmask;
1129 struct ipsec_policy *ipo;
1130 struct ipsec_acquire *ipa;
1131 struct radix_node_head *rnh;
1132 struct radix_node *rn = NULL((void *)0);
1133 struct pkpcb *kp, *bkp;
1134 void *freeme = NULL((void *)0), *freeme2 = NULL((void *)0), *freeme3 = NULL((void *)0);
1135 int freeme_sz = 0, freeme2_sz = 0, freeme3_sz = 0;
1136 void *bckptr = NULL((void *)0);
1137 void *headers[SADB_EXT_MAX39 + 1];
1138 union sockaddr_union *sunionp;
1139 struct tdb *sa1 = NULL((void *)0), *sa2 = NULL((void *)0);
1140 struct sadb_msg *smsg;
1141 struct sadb_spirange *sprng;
1142 struct sadb_sa *ssa;
1143 struct sadb_supported *ssup;
1144 struct sadb_ident *sid, *did;
1145 struct srp_ref sr;
1146 struct sadb_x_rdomain *srdomain;
1147 u_int rdomain = 0;
1148 int promisc, s;
1149
1150 mtx_enter(&pfkeyv2_mtx);
1151 promisc = npromisc;
1152 mtx_leave(&pfkeyv2_mtx);
1153
1154 /* Verify that we received this over a legitimate pfkeyv2 socket */
1155 bzero(headers, sizeof(headers))__builtin_bzero((headers), (sizeof(headers)));
1156
1157 kp = sotokeycb(so)((struct pkpcb *)(so)->so_pcb);
1158 if (!kp) {
1159 rval = EINVAL22;
1160 goto ret;
1161 }
1162
1163 rdomain = kp->kcb_rdomain;
1164
1165 /* If we have any promiscuous listeners, send them a copy of the message */
1166 if (promisc) {
1167 struct mbuf *packet;
1168
1169 freeme_sz = sizeof(struct sadb_msg) + len;
1170 if (!(freeme = malloc(freeme_sz, M_PFKEY74, M_NOWAIT0x0002))) {
1171 rval = ENOMEM12;
1172 goto ret;
1173 }
1174
1175 /* Initialize encapsulating header */
1176 bzero(freeme, sizeof(struct sadb_msg))__builtin_bzero((freeme), (sizeof(struct sadb_msg)));
1177 smsg = (struct sadb_msg *) freeme;
1178 smsg->sadb_msg_version = PF_KEY_V22;
1179 smsg->sadb_msg_type = SADB_X_PROMISC11;
1180 smsg->sadb_msg_len = (sizeof(struct sadb_msg) + len) /
1181 sizeof(uint64_t);
1182 smsg->sadb_msg_seq = curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
->p_p->ps_pid;
1183
1184 bcopy(message, freeme + sizeof(struct sadb_msg), len);
1185
1186 /* Convert to mbuf chain */
1187 if ((rval = pfdatatopacket(freeme, freeme_sz, &packet)) != 0)
1188 goto ret;
1189
1190 /* Send to all promiscuous listeners */
1191 SRPL_FOREACH(bkp, &sr, &pkptable.pkp_list, kcb_list)for ((bkp) = srp_enter((&sr), &(&pkptable.pkp_list
)->sl_head); (bkp) != ((void *)0); (bkp) = srp_follow((&
sr), &(bkp)->kcb_list.se_next))
{
1192 if (bkp->kcb_rdomain != kp->kcb_rdomain)
1193 continue;
1194
1195 s = keylock(bkp)solock((bkp)->kcb_socket);
1196 if (bkp->kcb_flags & PFKEYV2_SOCKETFLAGS_PROMISC2)
1197 pfkey_sendup(bkp, packet, 1);
1198 keyunlock(bkp, s)sounlock((bkp)->kcb_socket, s);
1199 }
1200 SRPL_LEAVE(&sr)srp_leave((&sr));
1201
1202 m_freem(packet);
1203
1204 /* Paranoid */
1205 explicit_bzero(freeme, freeme_sz);
1206 free(freeme, M_PFKEY74, freeme_sz);
1207 freeme = NULL((void *)0);
1208 freeme_sz = 0;
1209 }
1210
1211 /* Validate message format */
1212 if ((rval = pfkeyv2_parsemessage(message, len, headers)) != 0)
1213 goto ret;
1214
1215 /* use specified rdomain */
1216 srdomain = (struct sadb_x_rdomain *) headers[SADB_X_EXT_RDOMAIN37];
1217 if (srdomain) {
1218 if (!rtable_exists(srdomain->sadb_x_rdomain_dom1) ||
1219 !rtable_exists(srdomain->sadb_x_rdomain_dom2)) {
1220 rval = EINVAL22;
1221 goto ret;
1222 }
1223 rdomain = srdomain->sadb_x_rdomain_dom1;
1224 }
1225
1226 smsg = (struct sadb_msg *) headers[0];
1227 switch (smsg->sadb_msg_type) {
1228 case SADB_GETSPI1: /* Reserve an SPI */
1229 sa1 = malloc(sizeof (*sa1), M_PFKEY74, M_NOWAIT0x0002 | M_ZERO0x0008);
1230 if (sa1 == NULL((void *)0)) {
1231 rval = ENOMEM12;
1232 goto ret;
1233 }
1234
1235 sa1->tdb_satype = smsg->sadb_msg_satype;
1236 if ((rval = pfkeyv2_get_proto_alg(sa1->tdb_satype,
1237 &sa1->tdb_sproto, 0)))
1238 goto ret;
1239
1240 import_address(&sa1->tdb_src.sa, headers[SADB_EXT_ADDRESS_SRC5]);
1241 import_address(&sa1->tdb_dst.sa, headers[SADB_EXT_ADDRESS_DST6]);
1242
1243 /* Find an unused SA identifier */
1244 sprng = (struct sadb_spirange *) headers[SADB_EXT_SPIRANGE16];
1245 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1246 sa1->tdb_spi = reserve_spi(rdomain,
1247 sprng->sadb_spirange_min, sprng->sadb_spirange_max,
1248 &sa1->tdb_src, &sa1->tdb_dst, sa1->tdb_sproto, &rval);
1249 if (sa1->tdb_spi == 0) {
1250 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1251 goto ret;
1252 }
1253
1254 /* Send a message back telling what the SA (the SPI really) is */
1255 freeme_sz = sizeof(struct sadb_sa);
1256 if (!(freeme = malloc(freeme_sz, M_PFKEY74, M_NOWAIT0x0002 | M_ZERO0x0008))) {
1257 rval = ENOMEM12;
1258 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1259 goto ret;
1260 }
1261
1262 headers[SADB_EXT_SPIRANGE16] = NULL((void *)0);
1263 headers[SADB_EXT_SA1] = freeme;
1264 bckptr = freeme;
1265
1266 /* We really only care about the SPI, but we'll export the SA */
1267 export_sa((void **) &bckptr, sa1);
1268 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1269 break;
1270
1271 case SADB_UPDATE2:
1272 ssa = (struct sadb_sa *) headers[SADB_EXT_SA1];
1273 sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST6] +
1274 sizeof(struct sadb_address));
1275
1276 /* Either all or none of the flow must be included */
1277 if ((headers[SADB_X_EXT_SRC_FLOW21] ||
1278 headers[SADB_X_EXT_PROTOCOL19] ||
1279 headers[SADB_X_EXT_FLOW_TYPE20] ||
1280 headers[SADB_X_EXT_DST_FLOW22] ||
1281 headers[SADB_X_EXT_SRC_MASK17] ||
1282 headers[SADB_X_EXT_DST_MASK18]) &&
1283 !(headers[SADB_X_EXT_SRC_FLOW21] &&
1284 headers[SADB_X_EXT_PROTOCOL19] &&
1285 headers[SADB_X_EXT_FLOW_TYPE20] &&
1286 headers[SADB_X_EXT_DST_FLOW22] &&
1287 headers[SADB_X_EXT_SRC_MASK17] &&
1288 headers[SADB_X_EXT_DST_MASK18])) {
1289 rval = EINVAL22;
1290 goto ret;
1291 }
1292#ifdef IPSEC1
1293 /* UDP encap has to be enabled and is only supported for ESP */
1294 if (headers[SADB_X_EXT_UDPENCAP31] &&
1295 (!udpencap_enable ||
1296 smsg->sadb_msg_satype != SADB_SATYPE_ESP2)) {
1297 rval = EINVAL22;
1298 goto ret;
1299 }
1300#endif /* IPSEC */
1301
1302 /* Find TDB */
1303 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1304 sa2 = gettdb(rdomain, ssa->sadb_sa_spi, sunionp,gettdb_dir((rdomain),(ssa->sadb_sa_spi),(sunionp),(( (smsg
->sadb_msg_satype) == 1 ? 51 : (smsg->sadb_msg_satype) ==
2 ? 50 : (smsg->sadb_msg_satype) == 8 ? 6 : (smsg->sadb_msg_satype
) == 9 ? 108: 4 )),0)
1305 SADB_X_GETSPROTO(smsg->sadb_msg_satype))gettdb_dir((rdomain),(ssa->sadb_sa_spi),(sunionp),(( (smsg
->sadb_msg_satype) == 1 ? 51 : (smsg->sadb_msg_satype) ==
2 ? 50 : (smsg->sadb_msg_satype) == 8 ? 6 : (smsg->sadb_msg_satype
) == 9 ? 108: 4 )),0)
;
1306
1307 /* If there's no such SA, we're done */
1308 if (sa2 == NULL((void *)0)) {
1309 rval = ESRCH3;
1310 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1311 goto ret;
1312 }
1313
1314 /* If this is a reserved SA */
1315 if (sa2->tdb_flags & TDBF_INVALID0x00010) {
1316 struct tdb *newsa;
1317 struct ipsecinit ii;
1318 int alg;
1319
1320 /* Create new TDB */
1321 newsa = tdb_alloc(rdomain);
1322 newsa->tdb_satype = smsg->sadb_msg_satype;
1323
1324 if ((rval = pfkeyv2_get_proto_alg(newsa->tdb_satype,
1325 &newsa->tdb_sproto, &alg))) {
1326 tdb_unref(newsa);
1327 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1328 goto ret;
1329 }
1330
1331 /* Initialize SA */
1332 bzero(&ii, sizeof(struct ipsecinit))__builtin_bzero((&ii), (sizeof(struct ipsecinit)));
1333 import_sa(newsa, headers[SADB_EXT_SA1], &ii);
1334 import_address(&newsa->tdb_src.sa,
1335 headers[SADB_EXT_ADDRESS_SRC5]);
1336 import_address(&newsa->tdb_dst.sa,
1337 headers[SADB_EXT_ADDRESS_DST6]);
1338 import_lifetime(newsa,
1339 headers[SADB_EXT_LIFETIME_CURRENT2],
1340 PFKEYV2_LIFETIME_CURRENT2);
1341 import_lifetime(newsa, headers[SADB_EXT_LIFETIME_SOFT4],
1342 PFKEYV2_LIFETIME_SOFT1);
1343 import_lifetime(newsa, headers[SADB_EXT_LIFETIME_HARD3],
1344 PFKEYV2_LIFETIME_HARD0);
1345 import_key(&ii, headers[SADB_EXT_KEY_AUTH8],
1346 PFKEYV2_AUTHENTICATION_KEY1);
1347 import_key(&ii, headers[SADB_EXT_KEY_ENCRYPT9],
1348 PFKEYV2_ENCRYPTION_KEY0);
1349 newsa->tdb_ids_swapped = 1; /* only on TDB_UPDATE */
1350 import_identities(&newsa->tdb_ids,
1351 newsa->tdb_ids_swapped,
1352 headers[SADB_EXT_IDENTITY_SRC10],
1353 headers[SADB_EXT_IDENTITY_DST11]);
1354 if ((rval = import_flow(&newsa->tdb_filter,
1355 &newsa->tdb_filtermask,
1356 headers[SADB_X_EXT_SRC_FLOW21],
1357 headers[SADB_X_EXT_SRC_MASK17],
1358 headers[SADB_X_EXT_DST_FLOW22],
1359 headers[SADB_X_EXT_DST_MASK18],
1360 headers[SADB_X_EXT_PROTOCOL19],
1361 headers[SADB_X_EXT_FLOW_TYPE20]))) {
1362 tdb_unref(newsa);
1363 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1364 goto ret;
1365 }
1366 import_udpencap(newsa, headers[SADB_X_EXT_UDPENCAP31]);
1367 import_rdomain(newsa, headers[SADB_X_EXT_RDOMAIN37]);
1368#if NPF1 > 0
1369 import_tag(newsa, headers[SADB_X_EXT_TAG33]);
1370 import_tap(newsa, headers[SADB_X_EXT_TAP34]);
1371#endif
1372
1373 /* Exclude sensitive data from reply message. */
1374 headers[SADB_EXT_KEY_AUTH8] = NULL((void *)0);
1375 headers[SADB_EXT_KEY_ENCRYPT9] = NULL((void *)0);
1376 headers[SADB_X_EXT_LOCAL_AUTH28] = NULL((void *)0);
1377 headers[SADB_X_EXT_REMOTE_AUTH29] = NULL((void *)0);
1378
1379 newsa->tdb_seq = smsg->sadb_msg_seq;
1380
1381 rval = tdb_init(newsa, alg, &ii);
1382 if (rval) {
1383 rval = EINVAL22;
1384 tdb_unref(newsa);
1385 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1386 goto ret;
1387 }
1388
1389 newsa->tdb_cur_allocations = sa2->tdb_cur_allocations;
1390
1391 /* Delete old version of the SA, insert new one */
1392 tdb_delete(sa2);
1393 puttdb(newsa);
1394 } else {
1395 /*
1396 * The SA is already initialized, so we're only allowed to
1397 * change lifetimes and some other information; we're
1398 * not allowed to change keys, addresses or identities.
1399 */
1400 if (headers[SADB_EXT_KEY_AUTH8] ||
1401 headers[SADB_EXT_KEY_ENCRYPT9] ||
1402 headers[SADB_EXT_IDENTITY_SRC10] ||
1403 headers[SADB_EXT_IDENTITY_DST11] ||
1404 headers[SADB_EXT_SENSITIVITY12]) {
1405 rval = EINVAL22;
1406 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1407 goto ret;
1408 }
1409
1410 import_sa(sa2, headers[SADB_EXT_SA1], NULL((void *)0));
1411 import_lifetime(sa2,
1412 headers[SADB_EXT_LIFETIME_CURRENT2],
1413 PFKEYV2_LIFETIME_CURRENT2);
1414 import_lifetime(sa2, headers[SADB_EXT_LIFETIME_SOFT4],
1415 PFKEYV2_LIFETIME_SOFT1);
1416 import_lifetime(sa2, headers[SADB_EXT_LIFETIME_HARD3],
1417 PFKEYV2_LIFETIME_HARD0);
1418 import_udpencap(sa2, headers[SADB_X_EXT_UDPENCAP31]);
1419#if NPF1 > 0
1420 import_tag(sa2, headers[SADB_X_EXT_TAG33]);
1421 import_tap(sa2, headers[SADB_X_EXT_TAP34]);
1422#endif
1423 if (headers[SADB_EXT_ADDRESS_SRC5] ||
1424 headers[SADB_EXT_ADDRESS_PROXY7]) {
1425 mtx_enter(&tdb_sadb_mtx);
1426 tdb_unlink_locked(sa2);
1427 import_address((struct sockaddr *)&sa2->tdb_src,
1428 headers[SADB_EXT_ADDRESS_SRC5]);
1429 import_address((struct sockaddr *)&sa2->tdb_dst,
1430 headers[SADB_EXT_ADDRESS_PROXY7]);
1431 puttdb_locked(sa2);
1432 mtx_leave(&tdb_sadb_mtx);
1433 }
1434 }
1435 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1436
1437 break;
1438 case SADB_ADD3:
1439 ssa = (struct sadb_sa *) headers[SADB_EXT_SA1];
1440 sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST6] +
1441 sizeof(struct sadb_address));
1442
1443 /* Either all or none of the flow must be included */
1444 if ((headers[SADB_X_EXT_SRC_FLOW21] ||
1445 headers[SADB_X_EXT_PROTOCOL19] ||
1446 headers[SADB_X_EXT_FLOW_TYPE20] ||
1447 headers[SADB_X_EXT_DST_FLOW22] ||
1448 headers[SADB_X_EXT_SRC_MASK17] ||
1449 headers[SADB_X_EXT_DST_MASK18]) &&
1450 !(headers[SADB_X_EXT_SRC_FLOW21] &&
1451 headers[SADB_X_EXT_PROTOCOL19] &&
1452 headers[SADB_X_EXT_FLOW_TYPE20] &&
1453 headers[SADB_X_EXT_DST_FLOW22] &&
1454 headers[SADB_X_EXT_SRC_MASK17] &&
1455 headers[SADB_X_EXT_DST_MASK18])) {
1456 rval = EINVAL22;
1457 goto ret;
1458 }
1459#ifdef IPSEC1
1460 /* UDP encap has to be enabled and is only supported for ESP */
1461 if (headers[SADB_X_EXT_UDPENCAP31] &&
1462 (!udpencap_enable ||
1463 smsg->sadb_msg_satype != SADB_SATYPE_ESP2)) {
1464 rval = EINVAL22;
1465 goto ret;
1466 }
1467#endif /* IPSEC */
1468
1469 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1470 sa2 = gettdb(rdomain, ssa->sadb_sa_spi, sunionp,gettdb_dir((rdomain),(ssa->sadb_sa_spi),(sunionp),(( (smsg
->sadb_msg_satype) == 1 ? 51 : (smsg->sadb_msg_satype) ==
2 ? 50 : (smsg->sadb_msg_satype) == 8 ? 6 : (smsg->sadb_msg_satype
) == 9 ? 108: 4 )),0)
1471 SADB_X_GETSPROTO(smsg->sadb_msg_satype))gettdb_dir((rdomain),(ssa->sadb_sa_spi),(sunionp),(( (smsg
->sadb_msg_satype) == 1 ? 51 : (smsg->sadb_msg_satype) ==
2 ? 50 : (smsg->sadb_msg_satype) == 8 ? 6 : (smsg->sadb_msg_satype
) == 9 ? 108: 4 )),0)
;
1472
1473 /* We can't add an existing SA! */
1474 if (sa2 != NULL((void *)0)) {
1475 rval = EEXIST17;
1476 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1477 goto ret;
1478 }
1479
1480 /* We can only add "mature" SAs */
1481 if (ssa->sadb_sa_state != SADB_SASTATE_MATURE1) {
1482 rval = EINVAL22;
1483 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1484 goto ret;
1485 }
1486
1487 {
1488 struct tdb *newsa;
1489 struct ipsecinit ii;
1490 int alg;
1491
1492 /* Create new TDB */
1493 newsa = tdb_alloc(rdomain);
1494 newsa->tdb_satype = smsg->sadb_msg_satype;
1495
1496 if ((rval = pfkeyv2_get_proto_alg(newsa->tdb_satype,
1497 &newsa->tdb_sproto, &alg))) {
1498 tdb_unref(newsa);
1499 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1500 goto ret;
1501 }
1502
1503 /* Initialize SA */
1504 bzero(&ii, sizeof(struct ipsecinit))__builtin_bzero((&ii), (sizeof(struct ipsecinit)));
1505 import_sa(newsa, headers[SADB_EXT_SA1], &ii);
1506 import_address(&newsa->tdb_src.sa,
1507 headers[SADB_EXT_ADDRESS_SRC5]);
1508 import_address(&newsa->tdb_dst.sa,
1509 headers[SADB_EXT_ADDRESS_DST6]);
1510
1511 import_lifetime(newsa,
1512 headers[SADB_EXT_LIFETIME_CURRENT2],
1513 PFKEYV2_LIFETIME_CURRENT2);
1514 import_lifetime(newsa, headers[SADB_EXT_LIFETIME_SOFT4],
1515 PFKEYV2_LIFETIME_SOFT1);
1516 import_lifetime(newsa, headers[SADB_EXT_LIFETIME_HARD3],
1517 PFKEYV2_LIFETIME_HARD0);
1518
1519 import_key(&ii, headers[SADB_EXT_KEY_AUTH8],
1520 PFKEYV2_AUTHENTICATION_KEY1);
1521 import_key(&ii, headers[SADB_EXT_KEY_ENCRYPT9],
1522 PFKEYV2_ENCRYPTION_KEY0);
1523
1524 import_identities(&newsa->tdb_ids,
1525 newsa->tdb_ids_swapped,
1526 headers[SADB_EXT_IDENTITY_SRC10],
1527 headers[SADB_EXT_IDENTITY_DST11]);
1528
1529 if ((rval = import_flow(&newsa->tdb_filter,
1530 &newsa->tdb_filtermask,
1531 headers[SADB_X_EXT_SRC_FLOW21],
1532 headers[SADB_X_EXT_SRC_MASK17],
1533 headers[SADB_X_EXT_DST_FLOW22],
1534 headers[SADB_X_EXT_DST_MASK18],
1535 headers[SADB_X_EXT_PROTOCOL19],
1536 headers[SADB_X_EXT_FLOW_TYPE20]))) {
1537 tdb_unref(newsa);
1538 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1539 goto ret;
1540 }
1541 import_udpencap(newsa, headers[SADB_X_EXT_UDPENCAP31]);
1542 import_rdomain(newsa, headers[SADB_X_EXT_RDOMAIN37]);
1543#if NPF1 > 0
1544 import_tag(newsa, headers[SADB_X_EXT_TAG33]);
1545 import_tap(newsa, headers[SADB_X_EXT_TAP34]);
1546#endif
1547
1548 /* Exclude sensitive data from reply message. */
1549 headers[SADB_EXT_KEY_AUTH8] = NULL((void *)0);
1550 headers[SADB_EXT_KEY_ENCRYPT9] = NULL((void *)0);
1551 headers[SADB_X_EXT_LOCAL_AUTH28] = NULL((void *)0);
1552 headers[SADB_X_EXT_REMOTE_AUTH29] = NULL((void *)0);
1553
1554 newsa->tdb_seq = smsg->sadb_msg_seq;
1555
1556 rval = tdb_init(newsa, alg, &ii);
1557 if (rval) {
1558 rval = EINVAL22;
1559 tdb_unref(newsa);
1560 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1561 goto ret;
1562 }
1563
1564 /* Add TDB in table */
1565 puttdb(newsa);
1566 }
1567 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1568
1569 break;
1570
1571 case SADB_DELETE4:
1572 ssa = (struct sadb_sa *) headers[SADB_EXT_SA1];
1573 sunionp =
1574 (union sockaddr_union *)(headers[SADB_EXT_ADDRESS_DST6] +
1575 sizeof(struct sadb_address));
1576
1577 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1578 sa2 = gettdb(rdomain, ssa->sadb_sa_spi, sunionp,gettdb_dir((rdomain),(ssa->sadb_sa_spi),(sunionp),(( (smsg
->sadb_msg_satype) == 1 ? 51 : (smsg->sadb_msg_satype) ==
2 ? 50 : (smsg->sadb_msg_satype) == 8 ? 6 : (smsg->sadb_msg_satype
) == 9 ? 108: 4 )),0)
1579 SADB_X_GETSPROTO(smsg->sadb_msg_satype))gettdb_dir((rdomain),(ssa->sadb_sa_spi),(sunionp),(( (smsg
->sadb_msg_satype) == 1 ? 51 : (smsg->sadb_msg_satype) ==
2 ? 50 : (smsg->sadb_msg_satype) == 8 ? 6 : (smsg->sadb_msg_satype
) == 9 ? 108: 4 )),0)
;
1580 if (sa2 == NULL((void *)0)) {
1581 rval = ESRCH3;
1582 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1583 goto ret;
1584 }
1585
1586 tdb_delete(sa2);
1587 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1588
1589 break;
1590
1591 case SADB_X_ASKPOLICY15:
1592 /* Get the relevant policy */
1593 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1594 ipa = ipsec_get_acquire(((struct sadb_x_policy *) headers[SADB_X_EXT_POLICY25])->sadb_x_policy_seq);
1595 if (ipa == NULL((void *)0)) {
1596 rval = ESRCH3;
1597 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1598 goto ret;
1599 }
1600
1601 rval = pfkeyv2_policy(ipa, headers, &freeme, &freeme_sz);
1602 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1603 if (rval)
1604 mode = PFKEYV2_SENDMESSAGE_UNICAST1;
1605
1606 break;
1607
1608 case SADB_GET5:
1609 ssa = (struct sadb_sa *) headers[SADB_EXT_SA1];
1610 sunionp =
1611 (union sockaddr_union *)(headers[SADB_EXT_ADDRESS_DST6] +
1612 sizeof(struct sadb_address));
1613
1614 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1615 sa2 = gettdb(rdomain, ssa->sadb_sa_spi, sunionp,gettdb_dir((rdomain),(ssa->sadb_sa_spi),(sunionp),(( (smsg
->sadb_msg_satype) == 1 ? 51 : (smsg->sadb_msg_satype) ==
2 ? 50 : (smsg->sadb_msg_satype) == 8 ? 6 : (smsg->sadb_msg_satype
) == 9 ? 108: 4 )),0)
1616 SADB_X_GETSPROTO(smsg->sadb_msg_satype))gettdb_dir((rdomain),(ssa->sadb_sa_spi),(sunionp),(( (smsg
->sadb_msg_satype) == 1 ? 51 : (smsg->sadb_msg_satype) ==
2 ? 50 : (smsg->sadb_msg_satype) == 8 ? 6 : (smsg->sadb_msg_satype
) == 9 ? 108: 4 )),0)
;
1617 if (sa2 == NULL((void *)0)) {
1618 rval = ESRCH3;
1619 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1620 goto ret;
1621 }
1622
1623 rval = pfkeyv2_get(sa2, headers, &freeme, &freeme_sz, NULL((void *)0));
1624 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1625 if (rval)
1626 mode = PFKEYV2_SENDMESSAGE_UNICAST1;
1627
1628 break;
1629
1630 case SADB_REGISTER7:
1631 s = keylock(kp)solock((kp)->kcb_socket);
1632 if (!(kp->kcb_flags & PFKEYV2_SOCKETFLAGS_REGISTERED1)) {
1633 kp->kcb_flags |= PFKEYV2_SOCKETFLAGS_REGISTERED1;
1634 mtx_enter(&pfkeyv2_mtx);
1635 nregistered++;
1636 mtx_leave(&pfkeyv2_mtx);
1637 }
1638 keyunlock(kp, s)sounlock((kp)->kcb_socket, s);
1639
1640 freeme_sz = sizeof(struct sadb_supported) + sizeof(ealgs);
1641 if (!(freeme = malloc(freeme_sz, M_PFKEY74, M_NOWAIT0x0002 | M_ZERO0x0008))) {
1642 rval = ENOMEM12;
1643 goto ret;
1644 }
1645
1646 ssup = (struct sadb_supported *) freeme;
1647 ssup->sadb_supported_len = freeme_sz / sizeof(uint64_t);
1648
1649 {
1650 void *p = freeme + sizeof(struct sadb_supported);
1651
1652 bcopy(&ealgs[0], p, sizeof(ealgs));
1653 }
1654
1655 headers[SADB_EXT_SUPPORTED_ENCRYPT15] = freeme;
1656
1657 freeme2_sz = sizeof(struct sadb_supported) + sizeof(aalgs);
1658 if (!(freeme2 = malloc(freeme2_sz, M_PFKEY74,
1659 M_NOWAIT0x0002 | M_ZERO0x0008))) {
1660 rval = ENOMEM12;
1661 goto ret;
1662 }
1663
1664 /* Keep track what this socket has registered for */
1665 s = keylock(kp)solock((kp)->kcb_socket);
1666 kp->kcb_reg |=
1667 (1 << ((struct sadb_msg *)message)->sadb_msg_satype);
1668 keyunlock(kp, s)sounlock((kp)->kcb_socket, s);
1669
1670 ssup = (struct sadb_supported *) freeme2;
1671 ssup->sadb_supported_len = freeme2_sz / sizeof(uint64_t);
1672
1673 {
1674 void *p = freeme2 + sizeof(struct sadb_supported);
1675
1676 bcopy(&aalgs[0], p, sizeof(aalgs));
1677 }
1678
1679 headers[SADB_EXT_SUPPORTED_AUTH14] = freeme2;
1680
1681 freeme3_sz = sizeof(struct sadb_supported) + sizeof(calgs);
1682 if (!(freeme3 = malloc(freeme3_sz, M_PFKEY74,
1683 M_NOWAIT0x0002 | M_ZERO0x0008))) {
1684 rval = ENOMEM12;
1685 goto ret;
1686 }
1687
1688 ssup = (struct sadb_supported *) freeme3;
1689 ssup->sadb_supported_len = freeme3_sz / sizeof(uint64_t);
1690
1691 {
1692 void *p = freeme3 + sizeof(struct sadb_supported);
1693
1694 bcopy(&calgs[0], p, sizeof(calgs));
1695 }
1696
1697 headers[SADB_X_EXT_SUPPORTED_COMP30] = freeme3;
1698
1699 break;
1700
1701 case SADB_ACQUIRE6:
1702 case SADB_EXPIRE8:
1703 /* Nothing to handle */
1704 rval = 0;
1705 break;
1706
1707 case SADB_FLUSH9:
1708 rval = 0;
1709
1710 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1711 switch (smsg->sadb_msg_satype) {
1712 case SADB_SATYPE_UNSPEC0:
1713 spd_table_walk(rdomain, pfkeyv2_policy_flush, NULL((void *)0));
1714 /* FALLTHROUGH */
1715 case SADB_SATYPE_AH1:
1716 case SADB_SATYPE_ESP2:
1717 case SADB_X_SATYPE_IPIP7:
1718 case SADB_X_SATYPE_IPCOMP9:
1719#ifdef TCP_SIGNATURE1
1720 case SADB_X_SATYPE_TCPSIGNATURE8:
1721#endif /* TCP_SIGNATURE */
1722 tdb_walk(rdomain, pfkeyv2_sa_flush,
1723 (u_int8_t *) &(smsg->sadb_msg_satype));
1724
1725 break;
1726
1727 default:
1728 rval = EINVAL22; /* Unknown/unsupported type */
1729 }
1730 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1731
1732 break;
1733
1734 case SADB_DUMP10:
1735 {
1736 struct dump_state dump_state;
1737 dump_state.sadb_msg = (struct sadb_msg *) headers[0];
1738 dump_state.socket = so;
1739
1740 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1741 rval = tdb_walk(rdomain, pfkeyv2_dump_walker, &dump_state);
1742 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1743 if (!rval)
1744 goto realret;
1745 if ((rval == ENOMEM12) || (rval == ENOBUFS55))
1746 rval = 0;
1747 }
1748 break;
1749
1750 case SADB_X_GRPSPIS14:
1751 {
1752 struct tdb *tdb1, *tdb2, *tdb3;
1753 struct sadb_protocol *sa_proto;
1754
1755 ssa = (struct sadb_sa *) headers[SADB_EXT_SA1];
1756 sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST6] +
1757 sizeof(struct sadb_address));
1758
1759 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1760 tdb1 = gettdb(rdomain, ssa->sadb_sa_spi, sunionp,gettdb_dir((rdomain),(ssa->sadb_sa_spi),(sunionp),(( (smsg
->sadb_msg_satype) == 1 ? 51 : (smsg->sadb_msg_satype) ==
2 ? 50 : (smsg->sadb_msg_satype) == 8 ? 6 : (smsg->sadb_msg_satype
) == 9 ? 108: 4 )),0)
1761 SADB_X_GETSPROTO(smsg->sadb_msg_satype))gettdb_dir((rdomain),(ssa->sadb_sa_spi),(sunionp),(( (smsg
->sadb_msg_satype) == 1 ? 51 : (smsg->sadb_msg_satype) ==
2 ? 50 : (smsg->sadb_msg_satype) == 8 ? 6 : (smsg->sadb_msg_satype
) == 9 ? 108: 4 )),0)
;
1762 if (tdb1 == NULL((void *)0)) {
1763 rval = ESRCH3;
1764 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1765 goto ret;
1766 }
1767
1768 ssa = (struct sadb_sa *) headers[SADB_X_EXT_SA223];
1769 sunionp = (union sockaddr_union *) (headers[SADB_X_EXT_DST224] +
1770 sizeof(struct sadb_address));
1771 sa_proto = (struct sadb_protocol *) headers[SADB_X_EXT_SATYPE235];
1772
1773 /* optionally fetch tdb2 from rdomain2 */
1774 tdb2 = gettdb(srdomain ? srdomain->sadb_x_rdomain_dom2 : rdomain,gettdb_dir((srdomain ? srdomain->sadb_x_rdomain_dom2 : rdomain
),(ssa->sadb_sa_spi),(sunionp),(( (sa_proto->sadb_protocol_proto
) == 1 ? 51 : (sa_proto->sadb_protocol_proto) == 2 ? 50 : (
sa_proto->sadb_protocol_proto) == 8 ? 6 : (sa_proto->sadb_protocol_proto
) == 9 ? 108: 4 )),0)
1775 ssa->sadb_sa_spi, sunionp,gettdb_dir((srdomain ? srdomain->sadb_x_rdomain_dom2 : rdomain
),(ssa->sadb_sa_spi),(sunionp),(( (sa_proto->sadb_protocol_proto
) == 1 ? 51 : (sa_proto->sadb_protocol_proto) == 2 ? 50 : (
sa_proto->sadb_protocol_proto) == 8 ? 6 : (sa_proto->sadb_protocol_proto
) == 9 ? 108: 4 )),0)
1776 SADB_X_GETSPROTO(sa_proto->sadb_protocol_proto))gettdb_dir((srdomain ? srdomain->sadb_x_rdomain_dom2 : rdomain
),(ssa->sadb_sa_spi),(sunionp),(( (sa_proto->sadb_protocol_proto
) == 1 ? 51 : (sa_proto->sadb_protocol_proto) == 2 ? 50 : (
sa_proto->sadb_protocol_proto) == 8 ? 6 : (sa_proto->sadb_protocol_proto
) == 9 ? 108: 4 )),0)
;
1777 if (tdb2 == NULL((void *)0)) {
1778 tdb_unref(tdb1);
1779 rval = ESRCH3;
1780 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1781 goto ret;
1782 }
1783
1784 /* Detect cycles */
1785 for (tdb3 = tdb2; tdb3; tdb3 = tdb3->tdb_onext)
1786 if (tdb3 == tdb1) {
1787 tdb_unref(tdb1);
1788 tdb_unref(tdb2);
1789 rval = ESRCH3;
1790 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1791 goto ret;
1792 }
1793
1794 /* Maintenance */
1795 if ((tdb1->tdb_onext) &&
1796 (tdb1->tdb_onext->tdb_inext == tdb1)) {
1797 tdb_unref(tdb1->tdb_onext->tdb_inext);
1798 tdb1->tdb_onext->tdb_inext = NULL((void *)0);
1799 }
1800
1801 if ((tdb2->tdb_inext) &&
1802 (tdb2->tdb_inext->tdb_onext == tdb2)) {
1803 tdb_unref(tdb2->tdb_inext->tdb_onext);
1804 tdb2->tdb_inext->tdb_onext = NULL((void *)0);
1805 }
1806
1807 /* Link them */
1808 tdb1->tdb_onext = tdb2;
1809 tdb2->tdb_inext = tdb1;
1810 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1811 }
1812 break;
1813
1814 case SADB_X_DELFLOW13:
1815 delflag = 1;
1816 /*FALLTHROUGH*/
1817 case SADB_X_ADDFLOW12:
1818 {
1819 struct sadb_protocol *sab;
1820 union sockaddr_union *ssrc;
1821 int exists = 0;
1822
1823 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1824 if ((rnh = spd_table_add(rdomain)) == NULL((void *)0)) {
1825 rval = ENOMEM12;
1826 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1827 goto ret;
1828 }
1829
1830 sab = (struct sadb_protocol *) headers[SADB_X_EXT_FLOW_TYPE20];
1831
1832 if ((sab->sadb_protocol_direction != IPSP_DIRECTION_IN0x1) &&
1833 (sab->sadb_protocol_direction != IPSP_DIRECTION_OUT0x2)) {
1834 rval = EINVAL22;
1835 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1836 goto ret;
1837 }
1838
1839 /* If the security protocol wasn't specified, pretend it was ESP */
1840 if (smsg->sadb_msg_satype == 0)
1841 smsg->sadb_msg_satype = SADB_SATYPE_ESP2;
1842
1843 if (headers[SADB_EXT_ADDRESS_DST6])
1844 sunionp = (union sockaddr_union *)
1845 (headers[SADB_EXT_ADDRESS_DST6] +
1846 sizeof(struct sadb_address));
1847 else
1848 sunionp = NULL((void *)0);
1849
1850 if (headers[SADB_EXT_ADDRESS_SRC5])
1851 ssrc = (union sockaddr_union *)
1852 (headers[SADB_EXT_ADDRESS_SRC5] +
1853 sizeof(struct sadb_address));
1854 else
1855 ssrc = NULL((void *)0);
1856
1857 if ((rval = import_flow(&encapdst, &encapnetmask,
1858 headers[SADB_X_EXT_SRC_FLOW21], headers[SADB_X_EXT_SRC_MASK17],
1859 headers[SADB_X_EXT_DST_FLOW22], headers[SADB_X_EXT_DST_MASK18],
1860 headers[SADB_X_EXT_PROTOCOL19],
1861 headers[SADB_X_EXT_FLOW_TYPE20]))) {
1862 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1863 goto ret;
1864 }
1865
1866 /* Determine whether the exact same SPD entry already exists. */
1867 if ((rn = rn_match(&encapdst, rnh)) != NULL((void *)0)) {
1868 ipo = (struct ipsec_policy *)rn;
1869
1870 /* Verify that the entry is identical */
1871 if (bcmp(&ipo->ipo_addr, &encapdst,
1872 sizeof(struct sockaddr_encap)) ||
1873 bcmp(&ipo->ipo_mask, &encapnetmask,
1874 sizeof(struct sockaddr_encap)))
1875 ipo = NULL((void *)0); /* Fall through */
1876 else
1877 exists = 1;
1878 } else
1879 ipo = NULL((void *)0);
1880
1881 /*
1882 * If the existing policy is static, only delete or update
1883 * it if the new one is also static.
1884 */
1885 if (exists && (ipo->ipo_flags & IPSP_POLICY_STATIC0x0002)) {
1886 if (!(sab->sadb_protocol_flags &
1887 SADB_X_POLICYFLAGS_POLICY0x0001)) {
1888 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1889 goto ret;
1890 }
1891 }
1892
1893 /* Delete ? */
1894 if (delflag) {
1895 if (exists) {
1896 rval = ipsec_delete_policy(ipo);
1897 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1898 goto ret;
1899 }
1900
1901 /* If we were asked to delete something non-existent, error. */
1902 rval = ESRCH3;
1903 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1904 break;
1905 }
1906
1907 if (!exists) {
1908 /* Allocate policy entry */
1909 ipo = pool_get(&ipsec_policy_pool, PR_NOWAIT0x0002|PR_ZERO0x0008);
1910 if (ipo == NULL((void *)0)) {
1911 rval = ENOMEM12;
1912 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1913 goto ret;
1914 }
1915 }
1916
1917 switch (sab->sadb_protocol_proto) {
1918 case SADB_X_FLOW_TYPE_USE1:
1919 ipo->ipo_type = IPSP_IPSEC_USE0;
1920 break;
1921
1922 case SADB_X_FLOW_TYPE_ACQUIRE2:
1923 ipo->ipo_type = IPSP_IPSEC_ACQUIRE1;
1924 break;
1925
1926 case SADB_X_FLOW_TYPE_REQUIRE3:
1927 ipo->ipo_type = IPSP_IPSEC_REQUIRE2;
1928 break;
1929
1930 case SADB_X_FLOW_TYPE_DENY5:
1931 ipo->ipo_type = IPSP_DENY4;
1932 break;
1933
1934 case SADB_X_FLOW_TYPE_BYPASS4:
1935 ipo->ipo_type = IPSP_PERMIT3;
1936 break;
1937
1938 case SADB_X_FLOW_TYPE_DONTACQ6:
1939 ipo->ipo_type = IPSP_IPSEC_DONTACQ5;
1940 break;
1941
1942 default:
1943 if (!exists)
1944 pool_put(&ipsec_policy_pool, ipo);
1945 else
1946 ipsec_delete_policy(ipo);
1947
1948 rval = EINVAL22;
1949 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1950 goto ret;
1951 }
1952
1953 if (sab->sadb_protocol_flags & SADB_X_POLICYFLAGS_POLICY0x0001)
1954 ipo->ipo_flags |= IPSP_POLICY_STATIC0x0002;
1955
1956 if (sunionp)
1957 bcopy(sunionp, &ipo->ipo_dst,
1958 sizeof(union sockaddr_union));
1959 else
1960 bzero(&ipo->ipo_dst, sizeof(union sockaddr_union))__builtin_bzero((&ipo->ipo_dst), (sizeof(union sockaddr_union
)))
;
1961
1962 if (ssrc)
1963 bcopy(ssrc, &ipo->ipo_src,
1964 sizeof(union sockaddr_union));
1965 else
1966 bzero(&ipo->ipo_src, sizeof(union sockaddr_union))__builtin_bzero((&ipo->ipo_src), (sizeof(union sockaddr_union
)))
;
1967
1968 ipo->ipo_sproto = SADB_X_GETSPROTO(smsg->sadb_msg_satype)( (smsg->sadb_msg_satype) == 1 ? 51 : (smsg->sadb_msg_satype
) == 2 ? 50 : (smsg->sadb_msg_satype) == 8 ? 6 : (smsg->
sadb_msg_satype) == 9 ? 108: 4 )
;
1969
1970 if (ipo->ipo_ids) {
1971 ipsp_ids_free(ipo->ipo_ids);
1972 ipo->ipo_ids = NULL((void *)0);
1973 }
1974
1975 if ((sid = headers[SADB_EXT_IDENTITY_SRC10]) != NULL((void *)0) &&
1976 (did = headers[SADB_EXT_IDENTITY_DST11]) != NULL((void *)0)) {
1977 import_identities(&ipo->ipo_ids, 0, sid, did);
1978 if (ipo->ipo_ids == NULL((void *)0)) {
1979 if (exists)
1980 ipsec_delete_policy(ipo);
1981 else
1982 pool_put(&ipsec_policy_pool, ipo);
1983 rval = ENOBUFS55;
1984 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1985 goto ret;
1986 }
1987 }
1988
1989 /* Flow type */
1990 if (!exists) {
1991 /* Initialize policy entry */
1992 bcopy(&encapdst, &ipo->ipo_addr,
1993 sizeof(struct sockaddr_encap));
1994 bcopy(&encapnetmask, &ipo->ipo_mask,
1995 sizeof(struct sockaddr_encap));
1996
1997 TAILQ_INIT(&ipo->ipo_acquires)do { (&ipo->ipo_acquires)->tqh_first = ((void *)0);
(&ipo->ipo_acquires)->tqh_last = &(&ipo->
ipo_acquires)->tqh_first; } while (0)
;
1998 ipo->ipo_rdomain = rdomain;
1999 ipo->ipo_ref_count = 1;
2000
2001 /* Add SPD entry */
2002 if ((rnh = spd_table_get(rdomain)) == NULL((void *)0) ||
2003 (rn = rn_addroute((caddr_t)&ipo->ipo_addr,
2004 (caddr_t)&ipo->ipo_mask, rnh,
2005 ipo->ipo_nodes, 0)) == NULL((void *)0)) {
2006 /* Remove from linked list of policies on TDB */
2007 mtx_enter(&ipo_tdb_mtx);
2008 if (ipo->ipo_tdb != NULL((void *)0)) {
2009 TAILQ_REMOVE(do { if (((ipo)->ipo_tdb_next.tqe_next) != ((void *)0)) (ipo
)->ipo_tdb_next.tqe_next->ipo_tdb_next.tqe_prev = (ipo)
->ipo_tdb_next.tqe_prev; else (&ipo->ipo_tdb->tdb_policy_head
)->tqh_last = (ipo)->ipo_tdb_next.tqe_prev; *(ipo)->
ipo_tdb_next.tqe_prev = (ipo)->ipo_tdb_next.tqe_next; ((ipo
)->ipo_tdb_next.tqe_prev) = ((void *)-1); ((ipo)->ipo_tdb_next
.tqe_next) = ((void *)-1); } while (0)
2010 &ipo->ipo_tdb->tdb_policy_head,do { if (((ipo)->ipo_tdb_next.tqe_next) != ((void *)0)) (ipo
)->ipo_tdb_next.tqe_next->ipo_tdb_next.tqe_prev = (ipo)
->ipo_tdb_next.tqe_prev; else (&ipo->ipo_tdb->tdb_policy_head
)->tqh_last = (ipo)->ipo_tdb_next.tqe_prev; *(ipo)->
ipo_tdb_next.tqe_prev = (ipo)->ipo_tdb_next.tqe_next; ((ipo
)->ipo_tdb_next.tqe_prev) = ((void *)-1); ((ipo)->ipo_tdb_next
.tqe_next) = ((void *)-1); } while (0)
2011 ipo, ipo_tdb_next)do { if (((ipo)->ipo_tdb_next.tqe_next) != ((void *)0)) (ipo
)->ipo_tdb_next.tqe_next->ipo_tdb_next.tqe_prev = (ipo)
->ipo_tdb_next.tqe_prev; else (&ipo->ipo_tdb->tdb_policy_head
)->tqh_last = (ipo)->ipo_tdb_next.tqe_prev; *(ipo)->
ipo_tdb_next.tqe_prev = (ipo)->ipo_tdb_next.tqe_next; ((ipo
)->ipo_tdb_next.tqe_prev) = ((void *)-1); ((ipo)->ipo_tdb_next
.tqe_next) = ((void *)-1); } while (0)
;
2012 tdb_unref(ipo->ipo_tdb);
2013 ipo->ipo_tdb = NULL((void *)0);
2014 }
2015 mtx_leave(&ipo_tdb_mtx);
2016 if (ipo->ipo_ids)
2017 ipsp_ids_free(ipo->ipo_ids);
2018 pool_put(&ipsec_policy_pool, ipo);
2019 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2020 goto ret;
2021 }
2022 TAILQ_INSERT_HEAD(&ipsec_policy_head, ipo, ipo_list)do { if (((ipo)->ipo_list.tqe_next = (&ipsec_policy_head
)->tqh_first) != ((void *)0)) (&ipsec_policy_head)->
tqh_first->ipo_list.tqe_prev = &(ipo)->ipo_list.tqe_next
; else (&ipsec_policy_head)->tqh_last = &(ipo)->
ipo_list.tqe_next; (&ipsec_policy_head)->tqh_first = (
ipo); (ipo)->ipo_list.tqe_prev = &(&ipsec_policy_head
)->tqh_first; } while (0)
;
2023 ipsec_in_use++;
2024 } else {
2025 ipo->ipo_last_searched = ipo->ipo_flags = 0;
2026 }
2027 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2028 }
2029 break;
2030
2031 case SADB_X_PROMISC11:
2032 if (len >= 2 * sizeof(struct sadb_msg)) {
2033 struct mbuf *packet;
2034
2035 if ((rval = pfdatatopacket(message, len, &packet)) != 0)
2036 goto ret;
2037
2038 SRPL_FOREACH(bkp, &sr, &pkptable.pkp_list, kcb_list)for ((bkp) = srp_enter((&sr), &(&pkptable.pkp_list
)->sl_head); (bkp) != ((void *)0); (bkp) = srp_follow((&
sr), &(bkp)->kcb_list.se_next))
{
2039 if (bkp == kp || bkp->kcb_rdomain != kp->kcb_rdomain)
2040 continue;
2041
2042 if (!smsg->sadb_msg_seq ||
2043 (smsg->sadb_msg_seq == kp->kcb_pid)) {
2044 s = keylock(bkp)solock((bkp)->kcb_socket);
2045 pfkey_sendup(bkp, packet, 1);
2046 keyunlock(bkp, s)sounlock((bkp)->kcb_socket, s);
2047 }
2048 }
2049 SRPL_LEAVE(&sr)srp_leave((&sr));
2050
2051 m_freem(packet);
2052 } else {
2053 if (len != sizeof(struct sadb_msg)) {
2054 rval = EINVAL22;
2055 goto ret;
2056 }
2057
2058 s = keylock(kp)solock((kp)->kcb_socket);
2059 i = (kp->kcb_flags &
2060 PFKEYV2_SOCKETFLAGS_PROMISC2) ? 1 : 0;
2061 j = smsg->sadb_msg_satype ? 1 : 0;
2062
2063 if (i ^ j) {
2064 if (j) {
2065 kp->kcb_flags |=
2066 PFKEYV2_SOCKETFLAGS_PROMISC2;
2067 mtx_enter(&pfkeyv2_mtx);
2068 npromisc++;
2069 mtx_leave(&pfkeyv2_mtx);
2070 } else {
2071 kp->kcb_flags &=
2072 ~PFKEYV2_SOCKETFLAGS_PROMISC2;
2073 mtx_enter(&pfkeyv2_mtx);
2074 npromisc--;
2075 mtx_leave(&pfkeyv2_mtx);
2076 }
2077 }
2078 keyunlock(kp, s)sounlock((kp)->kcb_socket, s);
2079 }
2080
2081 break;
2082
2083 default:
2084 rval = EINVAL22;
2085 goto ret;
2086 }
2087
2088ret:
2089 if (rval) {
2090 if ((rval == EINVAL22) || (rval == ENOMEM12) || (rval == ENOBUFS55))
2091 goto realret;
2092
2093 for (i = 1; i <= SADB_EXT_MAX39; i++)
2094 headers[i] = NULL((void *)0);
2095
2096 smsg->sadb_msg_errno = abs(rval);
2097 } else {
2098 uint64_t seen = 0LL;
2099
2100 for (i = 1; i <= SADB_EXT_MAX39; i++)
2101 if (headers[i])
2102 seen |= (1LL << i);
2103
2104 if ((seen & sadb_exts_allowed_out[smsg->sadb_msg_type])
2105 != seen) {
2106 rval = EPERM1;
2107 goto realret;
2108 }
2109
2110 if ((seen & sadb_exts_required_out[smsg->sadb_msg_type]) !=
2111 sadb_exts_required_out[smsg->sadb_msg_type]) {
2112 rval = EPERM1;
2113 goto realret;
2114 }
2115 }
2116
2117 rval = pfkeyv2_sendmessage(headers, mode, so, 0, 0, kp->kcb_rdomain);
2118
2119realret:
2120
2121 if (freeme != NULL((void *)0))
2122 explicit_bzero(freeme, freeme_sz);
2123 free(freeme, M_PFKEY74, freeme_sz);
2124 free(freeme2, M_PFKEY74, freeme2_sz);
2125 free(freeme3, M_PFKEY74, freeme3_sz);
2126
2127 explicit_bzero(message, len);
2128 free(message, M_PFKEY74, len);
2129
2130 free(sa1, M_PFKEY74, sizeof(*sa1));
2131
2132 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2133 tdb_unref(sa2);
2134 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2135
2136 return (rval);
2137}
2138
2139/*
2140 * Send an ACQUIRE message to key management, to get a new SA.
2141 */
2142int
2143pfkeyv2_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw,
2144 union sockaddr_union *laddr, u_int32_t *seq, struct sockaddr_encap *ddst)
2145{
2146 void *p, *headers[SADB_EXT_MAX39 + 1], *buffer = NULL((void *)0);
2147 struct sadb_comb *sadb_comb;
2148 struct sadb_address *sadd;
2149 struct sadb_prop *sa_prop;
2150 struct sadb_msg *smsg;
2151 int rval = 0;
2152 int i, j, registered;
2153
2154 mtx_enter(&pfkeyv2_mtx);
2155 *seq = pfkeyv2_seq++;
2156
2157 registered = nregistered;
2158 mtx_leave(&pfkeyv2_mtx);
2159
2160 if (!registered) {
2161 rval = ESRCH3;
2162 goto ret;
2163 }
2164
2165 /* How large a buffer do we need... XXX we only do one proposal for now */
2166 i = sizeof(struct sadb_msg) +
2167 (laddr == NULL((void *)0) ? 0 : sizeof(struct sadb_address) +
2168 PADUP(ipo->ipo_src.sa.sa_len)(((ipo->ipo_src.sa.sa_len) + sizeof(uint64_t) - 1) & ~
(sizeof(uint64_t) - 1))
) +
2169 sizeof(struct sadb_address) + PADUP(gw->sa.sa_len)(((gw->sa.sa_len) + sizeof(uint64_t) - 1) & ~(sizeof(uint64_t
) - 1))
+
2170 sizeof(struct sadb_prop) + 1 * sizeof(struct sadb_comb);
2171
2172 if (ipo->ipo_ids) {
2173 i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_ids->id_local->len)(((ipo->ipo_ids->id_local->len) + sizeof(uint64_t) -
1) & ~(sizeof(uint64_t) - 1))
;
2174 i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_ids->id_remote->len)(((ipo->ipo_ids->id_remote->len) + sizeof(uint64_t) -
1) & ~(sizeof(uint64_t) - 1))
;
2175 }
2176
2177 /* Allocate */
2178 if (!(p = malloc(i, M_PFKEY74, M_NOWAIT0x0002 | M_ZERO0x0008))) {
2179 rval = ENOMEM12;
2180 goto ret;
2181 }
2182
2183 bzero(headers, sizeof(headers))__builtin_bzero((headers), (sizeof(headers)));
2184
2185 buffer = p;
2186
2187 headers[0] = p;
2188 p += sizeof(struct sadb_msg);
2189
2190 smsg = (struct sadb_msg *) headers[0];
2191 smsg->sadb_msg_version = PF_KEY_V22;
2192 smsg->sadb_msg_type = SADB_ACQUIRE6;
2193 smsg->sadb_msg_len = i / sizeof(uint64_t);
2194 smsg->sadb_msg_seq = *seq;
2195
2196 if (ipo->ipo_sproto == IPPROTO_ESP50)
2197 smsg->sadb_msg_satype = SADB_SATYPE_ESP2;
2198 else if (ipo->ipo_sproto == IPPROTO_AH51)
2199 smsg->sadb_msg_satype = SADB_SATYPE_AH1;
2200 else if (ipo->ipo_sproto == IPPROTO_IPCOMP108)
2201 smsg->sadb_msg_satype = SADB_X_SATYPE_IPCOMP9;
2202
2203 if (laddr) {
2204 headers[SADB_EXT_ADDRESS_SRC5] = p;
2205 p += sizeof(struct sadb_address) + PADUP(laddr->sa.sa_len)(((laddr->sa.sa_len) + sizeof(uint64_t) - 1) & ~(sizeof
(uint64_t) - 1))
;
2206 sadd = (struct sadb_address *) headers[SADB_EXT_ADDRESS_SRC5];
2207 sadd->sadb_address_len = (sizeof(struct sadb_address) +
2208 laddr->sa.sa_len + sizeof(uint64_t) - 1) /
2209 sizeof(uint64_t);
2210 bcopy(laddr, headers[SADB_EXT_ADDRESS_SRC5] +
2211 sizeof(struct sadb_address), laddr->sa.sa_len);
2212 }
2213
2214 headers[SADB_EXT_ADDRESS_DST6] = p;
2215 p += sizeof(struct sadb_address) + PADUP(gw->sa.sa_len)(((gw->sa.sa_len) + sizeof(uint64_t) - 1) & ~(sizeof(uint64_t
) - 1))
;
2216 sadd = (struct sadb_address *) headers[SADB_EXT_ADDRESS_DST6];
2217 sadd->sadb_address_len = (sizeof(struct sadb_address) +
2218 gw->sa.sa_len + sizeof(uint64_t) - 1) / sizeof(uint64_t);
2219 bcopy(gw, headers[SADB_EXT_ADDRESS_DST6] + sizeof(struct sadb_address),
2220 gw->sa.sa_len);
2221
2222 if (ipo->ipo_ids)
2223 export_identities(&p, ipo->ipo_ids, 0, headers);
2224
2225 headers[SADB_EXT_PROPOSAL13] = p;
2226 p += sizeof(struct sadb_prop);
2227 sa_prop = (struct sadb_prop *) headers[SADB_EXT_PROPOSAL13];
2228 sa_prop->sadb_prop_num = 1; /* XXX One proposal only */
2229 sa_prop->sadb_prop_len = (sizeof(struct sadb_prop) +
2230 (sizeof(struct sadb_comb) * sa_prop->sadb_prop_num)) /
2231 sizeof(uint64_t);
2232
2233 sadb_comb = p;
2234
2235 /* XXX Should actually ask the crypto layer what's supported */
2236 for (j = 0; j < sa_prop->sadb_prop_num; j++) {
2237 sadb_comb->sadb_comb_flags = 0;
2238#ifdef IPSEC1
2239 if (ipsec_require_pfs)
2240 sadb_comb->sadb_comb_flags |= SADB_SAFLAGS_PFS0x001;
2241
2242 /* Set the encryption algorithm */
2243 if (ipo->ipo_sproto == IPPROTO_ESP50) {
2244 if (!strncasecmp(ipsec_def_enc, "aes",
2245 sizeof("aes"))) {
2246 sadb_comb->sadb_comb_encrypt = SADB_X_EALG_AES12;
2247 sadb_comb->sadb_comb_encrypt_minbits = 128;
2248 sadb_comb->sadb_comb_encrypt_maxbits = 256;
2249 } else if (!strncasecmp(ipsec_def_enc, "aesctr",
2250 sizeof("aesctr"))) {
2251 sadb_comb->sadb_comb_encrypt = SADB_X_EALG_AESCTR13;
2252 sadb_comb->sadb_comb_encrypt_minbits = 128+32;
2253 sadb_comb->sadb_comb_encrypt_maxbits = 256+32;
2254 } else if (!strncasecmp(ipsec_def_enc, "3des",
2255 sizeof("3des"))) {
2256 sadb_comb->sadb_comb_encrypt = SADB_EALG_3DESCBC3;
2257 sadb_comb->sadb_comb_encrypt_minbits = 192;
2258 sadb_comb->sadb_comb_encrypt_maxbits = 192;
2259 } else if (!strncasecmp(ipsec_def_enc, "blowfish",
2260 sizeof("blowfish"))) {
2261 sadb_comb->sadb_comb_encrypt = SADB_X_EALG_BLF7;
2262 sadb_comb->sadb_comb_encrypt_minbits = 40;
2263 sadb_comb->sadb_comb_encrypt_maxbits = BLF_MAXKEYLEN((16 -2)*4) * 8;
2264 } else if (!strncasecmp(ipsec_def_enc, "cast128",
2265 sizeof("cast128"))) {
2266 sadb_comb->sadb_comb_encrypt = SADB_X_EALG_CAST6;
2267 sadb_comb->sadb_comb_encrypt_minbits = 40;
2268 sadb_comb->sadb_comb_encrypt_maxbits = 128;
2269 }
2270 } else if (ipo->ipo_sproto == IPPROTO_IPCOMP108) {
2271 /* Set the compression algorithm */
2272 if (!strncasecmp(ipsec_def_comp, "deflate",
2273 sizeof("deflate"))) {
2274 sadb_comb->sadb_comb_encrypt = SADB_X_CALG_DEFLATE2;
2275 sadb_comb->sadb_comb_encrypt_minbits = 0;
2276 sadb_comb->sadb_comb_encrypt_maxbits = 0;
2277 }
2278 }
2279
2280 /* Set the authentication algorithm */
2281 if (!strncasecmp(ipsec_def_auth, "hmac-sha1",
2282 sizeof("hmac-sha1"))) {
2283 sadb_comb->sadb_comb_auth = SADB_AALG_SHA1HMAC3;
2284 sadb_comb->sadb_comb_auth_minbits = 160;
2285 sadb_comb->sadb_comb_auth_maxbits = 160;
2286 } else if (!strncasecmp(ipsec_def_auth, "hmac-ripemd160",
2287 sizeof("hmac_ripemd160"))) {
2288 sadb_comb->sadb_comb_auth = SADB_X_AALG_RIPEMD160HMAC8;
2289 sadb_comb->sadb_comb_auth_minbits = 160;
2290 sadb_comb->sadb_comb_auth_maxbits = 160;
2291 } else if (!strncasecmp(ipsec_def_auth, "hmac-md5",
2292 sizeof("hmac-md5"))) {
2293 sadb_comb->sadb_comb_auth = SADB_AALG_MD5HMAC2;
2294 sadb_comb->sadb_comb_auth_minbits = 128;
2295 sadb_comb->sadb_comb_auth_maxbits = 128;
2296 } else if (!strncasecmp(ipsec_def_auth, "hmac-sha2-256",
2297 sizeof("hmac-sha2-256"))) {
2298 sadb_comb->sadb_comb_auth = SADB_X_AALG_SHA2_2565;
2299 sadb_comb->sadb_comb_auth_minbits = 256;
2300 sadb_comb->sadb_comb_auth_maxbits = 256;
2301 } else if (!strncasecmp(ipsec_def_auth, "hmac-sha2-384",
2302 sizeof("hmac-sha2-384"))) {
2303 sadb_comb->sadb_comb_auth = SADB_X_AALG_SHA2_3846;
2304 sadb_comb->sadb_comb_auth_minbits = 384;
2305 sadb_comb->sadb_comb_auth_maxbits = 384;
2306 } else if (!strncasecmp(ipsec_def_auth, "hmac-sha2-512",
2307 sizeof("hmac-sha2-512"))) {
2308 sadb_comb->sadb_comb_auth = SADB_X_AALG_SHA2_5127;
2309 sadb_comb->sadb_comb_auth_minbits = 512;
2310 sadb_comb->sadb_comb_auth_maxbits = 512;
2311 }
2312
2313 sadb_comb->sadb_comb_soft_allocations = ipsec_soft_allocations;
2314 sadb_comb->sadb_comb_hard_allocations = ipsec_exp_allocations;
2315
2316 sadb_comb->sadb_comb_soft_bytes = ipsec_soft_bytes;
2317 sadb_comb->sadb_comb_hard_bytes = ipsec_exp_bytes;
2318
2319 sadb_comb->sadb_comb_soft_addtime = ipsec_soft_timeout;
2320 sadb_comb->sadb_comb_hard_addtime = ipsec_exp_timeout;
2321
2322 sadb_comb->sadb_comb_soft_usetime = ipsec_soft_first_use;
2323 sadb_comb->sadb_comb_hard_usetime = ipsec_exp_first_use;
2324#endif
2325 sadb_comb++;
2326 }
2327
2328 /* Send the ACQUIRE message to all compliant registered listeners. */
2329 if ((rval = pfkeyv2_sendmessage(headers,
2330 PFKEYV2_SENDMESSAGE_REGISTERED2, NULL((void *)0), smsg->sadb_msg_satype, 0,
2331 ipo->ipo_rdomain)) != 0)
2332 goto ret;
2333
2334 rval = 0;
2335ret:
2336 if (buffer != NULL((void *)0)) {
2337 explicit_bzero(buffer, i);
2338 free(buffer, M_PFKEY74, i);
2339 }
2340
2341 return (rval);
2342}
2343
2344/*
2345 * Notify key management that an expiration went off. The second argument
2346 * specifies the type of expiration (soft or hard).
2347 */
2348int
2349pfkeyv2_expire(struct tdb *tdb, u_int16_t type)
2350{
2351 void *p, *headers[SADB_EXT_MAX39+1], *buffer = NULL((void *)0);
2352 struct sadb_msg *smsg;
2353 int rval = 0;
2354 int i;
2355
2356 NET_ASSERT_LOCKED()do { int _s = rw_status(&netlock); if ((splassert_ctl >
0) && (_s != 0x0001UL && _s != 0x0002UL)) splassert_fail
(0x0002UL, _s, __func__); } while (0)
;
2357
2358 switch (tdb->tdb_sproto) {
2359 case IPPROTO_AH51:
2360 case IPPROTO_ESP50:
2361 case IPPROTO_IPIP4:
2362 case IPPROTO_IPCOMP108:
2363#ifdef TCP_SIGNATURE1
2364 case IPPROTO_TCP6:
2365#endif /* TCP_SIGNATURE */
2366 break;
2367
2368 default:
2369 rval = EOPNOTSUPP45;
2370 goto ret;
2371 }
2372
2373 i = sizeof(struct sadb_msg) + sizeof(struct sadb_sa) +
2374 2 * sizeof(struct sadb_lifetime) +
2375 sizeof(struct sadb_address) + PADUP(tdb->tdb_src.sa.sa_len)(((tdb->tdb_src.sa.sa_len) + sizeof(uint64_t) - 1) & ~
(sizeof(uint64_t) - 1))
+
2376 sizeof(struct sadb_address) + PADUP(tdb->tdb_dst.sa.sa_len)(((tdb->tdb_dst.sa.sa_len) + sizeof(uint64_t) - 1) & ~
(sizeof(uint64_t) - 1))
;
2377
2378 if (!(p = malloc(i, M_PFKEY74, M_NOWAIT0x0002 | M_ZERO0x0008))) {
2379 rval = ENOMEM12;
2380 goto ret;
2381 }
2382
2383 bzero(headers, sizeof(headers))__builtin_bzero((headers), (sizeof(headers)));
2384
2385 buffer = p;
2386
2387 headers[0] = p;
2388 p += sizeof(struct sadb_msg);
2389
2390 smsg = (struct sadb_msg *) headers[0];
2391 smsg->sadb_msg_version = PF_KEY_V22;
2392 smsg->sadb_msg_type = SADB_EXPIRE8;
2393 smsg->sadb_msg_satype = tdb->tdb_satype;
2394 smsg->sadb_msg_len = i / sizeof(uint64_t);
2395
2396 mtx_enter(&pfkeyv2_mtx);
2397 smsg->sadb_msg_seq = pfkeyv2_seq++;
2398 mtx_leave(&pfkeyv2_mtx);
2399
2400 headers[SADB_EXT_SA1] = p;
2401 export_sa(&p, tdb);
2402
2403 headers[SADB_EXT_LIFETIME_CURRENT2] = p;
2404 export_lifetime(&p, tdb, PFKEYV2_LIFETIME_CURRENT2);
2405
2406 headers[type] = p;
2407 export_lifetime(&p, tdb, type == SADB_EXT_LIFETIME_SOFT4 ?
2408 PFKEYV2_LIFETIME_SOFT1 : PFKEYV2_LIFETIME_HARD0);
2409
2410 headers[SADB_EXT_ADDRESS_SRC5] = p;
2411 export_address(&p, &tdb->tdb_src.sa);
2412
2413 headers[SADB_EXT_ADDRESS_DST6] = p;
2414 export_address(&p, &tdb->tdb_dst.sa);
2415
2416 if ((rval = pfkeyv2_sendmessage(headers, PFKEYV2_SENDMESSAGE_BROADCAST3,
2417 NULL((void *)0), 0, 0, tdb->tdb_rdomain)) != 0)
2418 goto ret;
2419 /* XXX */
2420 if (tdb->tdb_rdomain != tdb->tdb_rdomain_post)
2421 if ((rval = pfkeyv2_sendmessage(headers,
2422 PFKEYV2_SENDMESSAGE_BROADCAST3, NULL((void *)0), 0, 0,
2423 tdb->tdb_rdomain_post)) != 0)
2424 goto ret;
2425
2426 rval = 0;
2427
2428 ret:
2429 if (buffer != NULL((void *)0)) {
2430 explicit_bzero(buffer, i);
2431 free(buffer, M_PFKEY74, i);
2432 }
2433
2434 return (rval);
2435}
2436
2437struct pfkeyv2_sysctl_walk {
2438 void *w_where;
2439 size_t w_len;
2440 int w_op;
2441 u_int8_t w_satype;
2442};
2443
2444int
2445pfkeyv2_sysctl_walker(struct tdb *tdb, void *arg, int last)
2446{
2447 struct pfkeyv2_sysctl_walk *w = (struct pfkeyv2_sysctl_walk *)arg;
2448 void *buffer = NULL((void *)0);
2449 int error = 0;
2450 int usedlen, buflen, i;
2451
2452 if (w->w_satype != SADB_SATYPE_UNSPEC0 &&
2453 w->w_satype != tdb->tdb_satype)
2454 return (0);
2455
2456 if (w->w_where) {
2457 void *headers[SADB_EXT_MAX39+1];
2458 struct sadb_msg msg;
2459
2460 bzero(headers, sizeof(headers))__builtin_bzero((headers), (sizeof(headers)));
2461 if ((error = pfkeyv2_get(tdb, headers, &buffer, &buflen,
2462 &usedlen)) != 0)
2463 goto done;
2464 if (w->w_len < sizeof(msg) + usedlen) {
2465 error = ENOMEM12;
2466 goto done;
2467 }
2468 /* prepend header */
2469 bzero(&msg, sizeof(msg))__builtin_bzero((&msg), (sizeof(msg)));
2470 msg.sadb_msg_version = PF_KEY_V22;
2471 msg.sadb_msg_satype = tdb->tdb_satype;
2472 msg.sadb_msg_type = SADB_DUMP10;
2473 msg.sadb_msg_len = (sizeof(msg) + usedlen) / sizeof(uint64_t);
2474 if ((error = copyout(&msg, w->w_where, sizeof(msg))) != 0)
2475 goto done;
2476 w->w_where += sizeof(msg);
2477 w->w_len -= sizeof(msg);
2478 /* set extension type */
2479 for (i = 1; i <= SADB_EXT_MAX39; i++)
2480 if (headers[i])
2481 ((struct sadb_ext *)
2482 headers[i])->sadb_ext_type = i;
2483 if ((error = copyout(buffer, w->w_where, usedlen)) != 0)
2484 goto done;
2485 w->w_where += usedlen;
2486 w->w_len -= usedlen;
2487 } else {
2488 if ((error = pfkeyv2_get(tdb, NULL((void *)0), NULL((void *)0), &buflen, NULL((void *)0))) != 0)
2489 return (error);
2490 w->w_len += buflen;
2491 w->w_len += sizeof(struct sadb_msg);
2492 }
2493
2494done:
2495 if (buffer != NULL((void *)0)) {
2496 explicit_bzero(buffer, buflen);
2497 free(buffer, M_PFKEY74, buflen);
2498 }
2499 return (error);
2500}
2501
2502int
2503pfkeyv2_dump_policy(struct ipsec_policy *ipo, void **headers, void **buffer,
2504 int *lenp)
2505{
2506 int i, rval, perm;
2507 void *p;
2508
2509 /* Find how much space we need. */
2510 i = 2 * sizeof(struct sadb_protocol);
2511
2512 /* We'll need four of them: src, src mask, dst, dst mask. */
2513 switch (ipo->ipo_addr.sen_type) {
2514 case SENT_IP40x0001:
2515 i += 4 * PADUP(sizeof(struct sockaddr_in))(((sizeof(struct sockaddr_in)) + sizeof(uint64_t) - 1) & ~
(sizeof(uint64_t) - 1))
;
2516 i += 4 * sizeof(struct sadb_address);
2517 break;
2518#ifdef INET61
2519 case SENT_IP60x0002:
2520 i += 4 * PADUP(sizeof(struct sockaddr_in6))(((sizeof(struct sockaddr_in6)) + sizeof(uint64_t) - 1) &
~(sizeof(uint64_t) - 1))
;
2521 i += 4 * sizeof(struct sadb_address);
2522 break;
2523#endif /* INET6 */
2524 default:
2525 return (EINVAL22);
2526 }
2527
2528 /* Local address, might be zeroed. */
2529 switch (ipo->ipo_src.sa.sa_family) {
2530 case 0:
2531 break;
2532 case AF_INET2:
2533 i += PADUP(sizeof(struct sockaddr_in))(((sizeof(struct sockaddr_in)) + sizeof(uint64_t) - 1) & ~
(sizeof(uint64_t) - 1))
;
2534 i += sizeof(struct sadb_address);
2535 break;
2536#ifdef INET61
2537 case AF_INET624:
2538 i += PADUP(sizeof(struct sockaddr_in6))(((sizeof(struct sockaddr_in6)) + sizeof(uint64_t) - 1) &
~(sizeof(uint64_t) - 1))
;
2539 i += sizeof(struct sadb_address);
2540 break;
2541#endif /* INET6 */
2542 default:
2543 return (EINVAL22);
2544 }
2545
2546 /* Remote address, might be zeroed. XXX ??? */
2547 switch (ipo->ipo_dst.sa.sa_family) {
2548 case 0:
2549 break;
2550 case AF_INET2:
2551 i += PADUP(sizeof(struct sockaddr_in))(((sizeof(struct sockaddr_in)) + sizeof(uint64_t) - 1) & ~
(sizeof(uint64_t) - 1))
;
2552 i += sizeof(struct sadb_address);
2553 break;
2554#ifdef INET61
2555 case AF_INET624:
2556 i += PADUP(sizeof(struct sockaddr_in6))(((sizeof(struct sockaddr_in6)) + sizeof(uint64_t) - 1) &
~(sizeof(uint64_t) - 1))
;
2557 i += sizeof(struct sadb_address);
2558 break;
2559#endif /* INET6 */
2560 default:
2561 return (EINVAL22);
2562 }
2563
2564 if (ipo->ipo_ids) {
2565 i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_ids->id_local->len)(((ipo->ipo_ids->id_local->len) + sizeof(uint64_t) -
1) & ~(sizeof(uint64_t) - 1))
;
2566 i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_ids->id_remote->len)(((ipo->ipo_ids->id_remote->len) + sizeof(uint64_t) -
1) & ~(sizeof(uint64_t) - 1))
;
2567 }
2568
2569 if (lenp)
2570 *lenp = i;
2571
2572 if (buffer == NULL((void *)0)) {
2573 rval = 0;
2574 goto ret;
2575 }
2576
2577 if (!(p = malloc(i, M_PFKEY74, M_NOWAIT0x0002 | M_ZERO0x0008))) {
2578 rval = ENOMEM12;
2579 goto ret;
2580 } else
2581 *buffer = p;
2582
2583 /* Local address. */
2584 if (ipo->ipo_src.sa.sa_family) {
2585 headers[SADB_EXT_ADDRESS_SRC5] = p;
2586 export_address(&p, &ipo->ipo_src.sa);
2587 }
2588
2589 /* Remote address. */
2590 if (ipo->ipo_dst.sa.sa_family) {
2591 headers[SADB_EXT_ADDRESS_DST6] = p;
2592 export_address(&p, &ipo->ipo_dst.sa);
2593 }
2594
2595 /* Get actual flow. */
2596 export_flow(&p, ipo->ipo_type, &ipo->ipo_addr, &ipo->ipo_mask,
2597 headers);
2598
2599 /* Add ids only when we are root. */
2600 perm = suser(curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
);
2601 if (perm == 0 && ipo->ipo_ids)
2602 export_identities(&p, ipo->ipo_ids, 0, headers);
2603
2604 rval = 0;
2605ret:
2606 return (rval);
2607}
2608
2609int
2610pfkeyv2_sysctl_policydumper(struct ipsec_policy *ipo, void *arg,
2611 unsigned int tableid)
2612{
2613 struct pfkeyv2_sysctl_walk *w = (struct pfkeyv2_sysctl_walk *)arg;
2614 void *buffer = 0;
2615 int i, buflen, error = 0;
2616
2617 if (w->w_where) {
2618 void *headers[SADB_EXT_MAX39 + 1];
2619 struct sadb_msg msg;
2620
2621 bzero(headers, sizeof(headers))__builtin_bzero((headers), (sizeof(headers)));
2622 if ((error = pfkeyv2_dump_policy(ipo, headers, &buffer,
2623 &buflen)) != 0)
2624 goto done;
2625 if (w->w_len < buflen) {
2626 error = ENOMEM12;
2627 goto done;
2628 }
2629 /* prepend header */
2630 bzero(&msg, sizeof(msg))__builtin_bzero((&msg), (sizeof(msg)));
2631 msg.sadb_msg_version = PF_KEY_V22;
2632 if (ipo->ipo_sproto == IPPROTO_ESP50)
2633 msg.sadb_msg_satype = SADB_SATYPE_ESP2;
2634 else if (ipo->ipo_sproto == IPPROTO_AH51)
2635 msg.sadb_msg_satype = SADB_SATYPE_AH1;
2636 else if (ipo->ipo_sproto == IPPROTO_IPCOMP108)
2637 msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP9;
2638 else if (ipo->ipo_sproto == IPPROTO_IPIP4)
2639 msg.sadb_msg_satype = SADB_X_SATYPE_IPIP7;
2640 msg.sadb_msg_type = SADB_X_SPDDUMP16;
2641 msg.sadb_msg_len = (sizeof(msg) + buflen) / sizeof(uint64_t);
2642 if ((error = copyout(&msg, w->w_where, sizeof(msg))) != 0)
2643 goto done;
2644 w->w_where += sizeof(msg);
2645 w->w_len -= sizeof(msg);
2646 /* set extension type */
2647 for (i = 1; i <= SADB_EXT_MAX39; i++)
2648 if (headers[i])
2649 ((struct sadb_ext *)
2650 headers[i])->sadb_ext_type = i;
2651 if ((error = copyout(buffer, w->w_where, buflen)) != 0)
2652 goto done;
2653 w->w_where += buflen;
2654 w->w_len -= buflen;
2655 } else {
2656 if ((error = pfkeyv2_dump_policy(ipo, NULL((void *)0), NULL((void *)0),
2657 &buflen)) != 0)
2658 goto done;
2659 w->w_len += buflen;
2660 w->w_len += sizeof(struct sadb_msg);
2661 }
2662
2663done:
2664 if (buffer)
2665 free(buffer, M_PFKEY74, buflen);
2666 return (error);
2667}
2668
2669int
2670pfkeyv2_policy_flush(struct ipsec_policy *ipo, void *arg, unsigned int tableid)
2671{
2672 int error;
2673
2674 error = ipsec_delete_policy(ipo);
2675 if (error == 0)
2676 error = EAGAIN35;
2677
2678 return (error);
2679}
2680
2681int
2682pfkeyv2_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
2683 void *new, size_t newlen)
2684{
2685 struct pfkeyv2_sysctl_walk w;
2686 int error = EINVAL22;
2687 u_int rdomain;
2688 u_int tableid;
2689
2690 if (new)
2691 return (EPERM1);
2692 if (namelen < 1)
2693 return (EINVAL22);
2694 w.w_op = name[0];
2695 w.w_satype = name[1];
2696 w.w_where = oldp;
2697 w.w_len = oldp ? *oldlenp : 0;
2698
2699 if (namelen == 3) {
2700 tableid = name[2];
2701 if (!rtable_exists(tableid))
2702 return (ENOENT2);
2703 } else
2704 tableid = curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
->p_p->ps_rtableid;
2705 rdomain = rtable_l2(tableid);
2706
2707 switch(w.w_op) {
2708 case NET_KEY_SADB_DUMP1:
2709 if ((error = suser(curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
)) != 0)
2710 return (error);
2711 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2712 error = tdb_walk(rdomain, pfkeyv2_sysctl_walker, &w);
2713 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2714 if (oldp)
2715 *oldlenp = w.w_where - oldp;
2716 else
2717 *oldlenp = w.w_len;
2718 break;
2719
2720 case NET_KEY_SPD_DUMP2:
2721 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2722 error = spd_table_walk(rdomain,
2723 pfkeyv2_sysctl_policydumper, &w);
2724 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2725 if (oldp)
2726 *oldlenp = w.w_where - oldp;
2727 else
2728 *oldlenp = w.w_len;
2729 break;
2730 }
2731
2732 return (error);
2733}