Bug Summary

File:net/pfkeyv2.c
Warning:line 1099, 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.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name pfkeyv2.c -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 -ffp-contract=on -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 -target-feature +retpoline-external-thunk -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/llvm16/lib/clang/16 -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/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -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/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -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/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -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 SUSPEND -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 -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 -fcf-protection=branch -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 /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/net/pfkeyv2.c
1/* $OpenBSD: pfkeyv2.c,v 1.259 2023/10/11 22:13:16 tobhe 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)sounlock((kp)->kcb_socket) sounlock((kp)->kcb_socket)
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, int);
173int pfkeyv2_detach(struct socket *);
174int pfkeyv2_disconnect(struct socket *);
175int pfkeyv2_shutdown(struct socket *);
176int pfkeyv2_send(struct socket *, struct mbuf *, struct mbuf *,
177 struct mbuf *);
178int pfkeyv2_sockaddr(struct socket *, struct mbuf *);
179int pfkeyv2_peeraddr(struct socket *, struct mbuf *);
180int pfkeyv2_output(struct mbuf *, struct socket *);
181int pfkey_sendup(struct pkpcb *, struct mbuf *, int);
182int pfkeyv2_sa_flush(struct tdb *, void *, int);
183int pfkeyv2_policy_flush(struct ipsec_policy *, void *, unsigned int);
184int pfkeyv2_sysctl_policydumper(struct ipsec_policy *, void *, unsigned int);
185
186void keycb_ref(void *, void *);
187void keycb_unref(void *, void *);
188
189/*
190 * Wrapper around m_devget(); copy data from contiguous buffer to mbuf
191 * chain.
192 */
193int
194pfdatatopacket(void *data, int len, struct mbuf **packet)
195{
196 if (!(*packet = m_devget(data, len, 0)))
197 return (ENOMEM12);
198
199 /* Make sure, all data gets zeroized on free */
200 (*packet)->m_flagsm_hdr.mh_flags |= M_ZEROIZE0x2000;
201
202 return (0);
203}
204
205const struct pr_usrreqs pfkeyv2_usrreqs = {
206 .pru_attach = pfkeyv2_attach,
207 .pru_detach = pfkeyv2_detach,
208 .pru_disconnect = pfkeyv2_disconnect,
209 .pru_shutdown = pfkeyv2_shutdown,
210 .pru_send = pfkeyv2_send,
211 .pru_sockaddr = pfkeyv2_sockaddr,
212 .pru_peeraddr = pfkeyv2_peeraddr,
213};
214
215const struct protosw pfkeysw[] = {
216{
217 .pr_type = SOCK_RAW3,
218 .pr_domain = &pfkeydomain,
219 .pr_protocol = PF_KEY_V22,
220 .pr_flags = PR_ATOMIC0x0001 | PR_ADDR0x0002,
221 .pr_usrreqs = &pfkeyv2_usrreqs,
222 .pr_sysctl = pfkeyv2_sysctl,
223}
224};
225
226const struct domain pfkeydomain = {
227 .dom_family = PF_KEY30,
228 .dom_name = "PF_KEY",
229 .dom_init = pfkey_init,
230 .dom_protosw = pfkeysw,
231 .dom_protoswNPROTOSW = &pfkeysw[nitems(pfkeysw)(sizeof((pfkeysw)) / sizeof((pfkeysw)[0]))],
232};
233
234void
235keycb_ref(void *null, void *v)
236{
237 struct pkpcb *kp = v;
238
239 refcnt_take(&kp->kcb_refcnt);
240}
241
242void
243keycb_unref(void *null, void *v)
244{
245 struct pkpcb *kp = v;
246
247 refcnt_rele_wake(&kp->kcb_refcnt);
248}
249
250void
251pfkey_init(void)
252{
253 rn_init(sizeof(struct sockaddr_encap));
254 srpl_rc_init(&pkptable.pkp_rc, keycb_ref, keycb_unref, NULL((void *)0));
255 rw_init(&pkptable.pkp_lk, "pfkey")_rw_init_flags(&pkptable.pkp_lk, "pfkey", 0, ((void *)0));
256 SRPL_INIT(&pkptable.pkp_list)srp_init(&(&pkptable.pkp_list)->sl_head);
257 pool_init(&pkpcb_pool, sizeof(struct pkpcb), 0,
258 IPL_SOFTNET0x2, PR_WAITOK0x0001, "pkpcb", NULL((void *)0));
259 pool_init(&ipsec_policy_pool, sizeof(struct ipsec_policy), 0,
260 IPL_SOFTNET0x2, 0, "ipsec policy", NULL((void *)0));
261 pool_init(&ipsec_acquire_pool, sizeof(struct ipsec_acquire), 0,
262 IPL_SOFTNET0x2, 0, "ipsec acquire", NULL((void *)0));
263}
264
265
266/*
267 * Attach a new PF_KEYv2 socket.
268 */
269int
270pfkeyv2_attach(struct socket *so, int proto, int wait)
271{
272 struct pkpcb *kp;
273 int error;
274
275 if ((so->so_state & SS_PRIV0x080) == 0)
276 return EACCES13;
277
278 error = soreserve(so, PFKEYSNDQ8192, PFKEYRCVQ8192);
279 if (error)
280 return (error);
281
282 kp = pool_get(&pkpcb_pool, (wait == M_WAIT0x0001 ? PR_WAITOK0x0001 : PR_NOWAIT0x0002) |
283 PR_ZERO0x0008);
284 if (kp == NULL((void *)0))
285 return (ENOBUFS55);
286 so->so_pcb = kp;
287 refcnt_init(&kp->kcb_refcnt);
288 kp->kcb_socket = so;
289 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;
290 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);
291
292 so->so_options |= SO_USELOOPBACK0x0040;
293 soisconnected(so);
294
295 rw_enter(&pkptable.pkp_lk, RW_WRITE0x0001UL);
296 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)
;
297 rw_exit(&pkptable.pkp_lk);
298
299 return (0);
300}
301
302/*
303 * Close a PF_KEYv2 socket.
304 */
305int
306pfkeyv2_detach(struct socket *so)
307{
308 struct pkpcb *kp;
309
310 soassertlocked(so);
311
312 kp = sotokeycb(so)((struct pkpcb *)(so)->so_pcb);
313 if (kp == NULL((void *)0))
314 return ENOTCONN57;
315
316 if (kp->kcb_flags &
317 (PFKEYV2_SOCKETFLAGS_REGISTERED1|PFKEYV2_SOCKETFLAGS_PROMISC2)) {
318 mtx_enter(&pfkeyv2_mtx);
319 if (kp->kcb_flags & PFKEYV2_SOCKETFLAGS_REGISTERED1)
320 nregistered--;
321
322 if (kp->kcb_flags & PFKEYV2_SOCKETFLAGS_PROMISC2)
323 npromisc--;
324 mtx_leave(&pfkeyv2_mtx);
325 }
326
327 rw_enter(&pkptable.pkp_lk, RW_WRITE0x0001UL);
328 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)
329 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)
;
330 rw_exit(&pkptable.pkp_lk);
331
332 sounlock(so);
333 /* wait for all references to drop */
334 refcnt_finalize(&kp->kcb_refcnt, "pfkeyrefs");
335 solock(so);
336
337 so->so_pcb = NULL((void *)0);
338 KASSERT((so->so_state & SS_NOFDREF) == 0)(((so->so_state & 0x001) == 0) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/net/pfkeyv2.c", 338, "(so->so_state & SS_NOFDREF) == 0"
))
;
339 pool_put(&pkpcb_pool, kp);
340
341 return (0);
342}
343
344int
345pfkeyv2_disconnect(struct socket *so)
346{
347 soisdisconnected(so);
348 return (0);
349}
350
351int
352pfkeyv2_shutdown(struct socket *so)
353{
354 socantsendmore(so);
355 return (0);
356}
357
358int
359pfkeyv2_send(struct socket *so, struct mbuf *m, struct mbuf *nam,
360 struct mbuf *control)
361{
362 int error;
363
364 soassertlocked(so);
365
366 if (control && control->m_lenm_hdr.mh_len) {
367 error = EOPNOTSUPP45;
368 goto out;
369 }
370
371 if (nam) {
372 error = EISCONN56;
373 goto out;
374 }
375
376 error = pfkeyv2_output(m, so);
377 m = NULL((void *)0);
378
379out:
380 m_freem(control);
381 m_freem(m);
382
383 return (error);
384}
385
386int
387pfkeyv2_sockaddr(struct socket *so, struct mbuf *nam)
388{
389 return (EINVAL22);
390}
391
392int
393pfkeyv2_peeraddr(struct socket *so, struct mbuf *nam)
394{
395 /* minimal support, just implement a fake peer address */
396 bcopy(&pfkey_addr, mtod(nam, caddr_t)((caddr_t)((nam)->m_hdr.mh_data)), pfkey_addr.sa_len);
397 nam->m_lenm_hdr.mh_len = pfkey_addr.sa_len;
398 return (0);
399}
400
401int
402pfkeyv2_output(struct mbuf *mbuf, struct socket *so)
403{
404 void *message;
405 int error = 0;
406
407#ifdef DIAGNOSTIC1
408 if (!mbuf || !(mbuf->m_flagsm_hdr.mh_flags & M_PKTHDR0x0002)) {
409 error = EINVAL22;
410 goto ret;
411 }
412#endif /* DIAGNOSTIC */
413
414 if (mbuf->m_pkthdrM_dat.MH.MH_pkthdr.len > PFKEY_MSG_MAXSZ4096) {
415 error = EMSGSIZE40;
416 goto ret;
417 }
418
419 if (!(message = malloc((unsigned long) mbuf->m_pkthdrM_dat.MH.MH_pkthdr.len,
420 M_PFKEY74, M_DONTWAIT0x0002))) {
421 error = ENOMEM12;
422 goto ret;
423 }
424
425 m_copydata(mbuf, 0, mbuf->m_pkthdrM_dat.MH.MH_pkthdr.len, message);
426
427 /*
428 * The socket can't be closed concurrently because the file
429 * descriptor reference is still held.
430 */
431
432 sounlock(so);
433 error = pfkeyv2_dosend(so, message, mbuf->m_pkthdrM_dat.MH.MH_pkthdr.len);
434 solock(so);
435
436ret:
437 m_freem(mbuf);
438 return (error);
439}
440
441int
442pfkey_sendup(struct pkpcb *kp, struct mbuf *m0, int more)
443{
444 struct socket *so = kp->kcb_socket;
445 struct mbuf *m;
446
447 soassertlocked(so);
448
449 if (more) {
450 if (!(m = m_dup_pkt(m0, 0, M_DONTWAIT0x0002)))
451 return (ENOMEM12);
452 } else
453 m = m0;
454
455 if (!sbappendaddr(so, &so->so_rcv, &pfkey_addr, m, NULL((void *)0))) {
456 m_freem(m);
457 return (ENOBUFS55);
458 }
459
460 sorwakeup(so);
461 return (0);
462}
463
464/*
465 * Send a PFKEYv2 message, possibly to many receivers, based on the
466 * satype of the socket (which is set by the REGISTER message), and the
467 * third argument.
468 */
469int
470pfkeyv2_sendmessage(void **headers, int mode, struct socket *so,
471 u_int8_t satype, int count, u_int rdomain)
472{
473 int i, j, rval;
474 void *p, *buffer = NULL((void *)0);
475 struct mbuf *packet;
476 struct pkpcb *kp;
477 struct sadb_msg *smsg;
478 struct srp_ref sr;
479
480 /* Find out how much space we'll need... */
481 j = sizeof(struct sadb_msg);
482
483 for (i = 1; i <= SADB_EXT_MAX40; i++)
484 if (headers[i])
485 j += ((struct sadb_ext *)headers[i])->sadb_ext_len *
486 sizeof(uint64_t);
487
488 /* ...and allocate it */
489 if (!(buffer = malloc(j + sizeof(struct sadb_msg), M_PFKEY74,
490 M_NOWAIT0x0002))) {
491 rval = ENOMEM12;
492 goto ret;
493 }
494
495 p = buffer + sizeof(struct sadb_msg);
496 bcopy(headers[0], p, sizeof(struct sadb_msg));
497 ((struct sadb_msg *) p)->sadb_msg_len = j / sizeof(uint64_t);
498 p += sizeof(struct sadb_msg);
499
500 /* Copy payloads in the packet */
501 for (i = 1; i <= SADB_EXT_MAX40; i++)
502 if (headers[i]) {
503 ((struct sadb_ext *) headers[i])->sadb_ext_type = i;
504 bcopy(headers[i], p, EXTLEN(headers[i])(((struct sadb_ext *)(headers[i]))->sadb_ext_len * sizeof(
uint64_t))
);
505 p += EXTLEN(headers[i])(((struct sadb_ext *)(headers[i]))->sadb_ext_len * sizeof(
uint64_t))
;
506 }
507
508 if ((rval = pfdatatopacket(buffer + sizeof(struct sadb_msg),
509 j, &packet)) != 0)
510 goto ret;
511
512 switch (mode) {
513 case PFKEYV2_SENDMESSAGE_UNICAST1:
514 /*
515 * Send message to the specified socket, plus all
516 * promiscuous listeners.
517 */
518 solock(so);
519 pfkey_sendup(sotokeycb(so)((struct pkpcb *)(so)->so_pcb), packet, 0);
520 sounlock(so);
521
522 /*
523 * Promiscuous messages contain the original message
524 * encapsulated in another sadb_msg header.
525 */
526 bzero(buffer, sizeof(struct sadb_msg))__builtin_bzero((buffer), (sizeof(struct sadb_msg)));
527 smsg = (struct sadb_msg *) buffer;
528 smsg->sadb_msg_version = PF_KEY_V22;
529 smsg->sadb_msg_type = SADB_X_PROMISC11;
530 smsg->sadb_msg_len = (sizeof(struct sadb_msg) + j) /
531 sizeof(uint64_t);
532 smsg->sadb_msg_seq = 0;
533
534 /* Copy to mbuf chain */
535 if ((rval = pfdatatopacket(buffer, sizeof(struct sadb_msg) + j,
536 &packet)) != 0)
537 goto ret;
538
539 /*
540 * Search for promiscuous listeners, skipping the
541 * original destination.
542 */
543 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))
{
544 if (kp->kcb_socket == so || kp->kcb_rdomain != rdomain)
545 continue;
546
547 keylock(kp)solock((kp)->kcb_socket);
548 if (kp->kcb_flags & PFKEYV2_SOCKETFLAGS_PROMISC2)
549 pfkey_sendup(kp, packet, 1);
550 keyunlock(kp)sounlock((kp)->kcb_socket);
551 }
552 SRPL_LEAVE(&sr)srp_leave((&sr));
553 m_freem(packet);
554 break;
555
556 case PFKEYV2_SENDMESSAGE_REGISTERED2:
557 /*
558 * Send the message to all registered sockets that match
559 * the specified satype (e.g., all IPSEC-ESP negotiators)
560 */
561 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))
{
562 if (kp->kcb_rdomain != rdomain)
563 continue;
564
565 keylock(kp)solock((kp)->kcb_socket);
566 if (kp->kcb_flags & PFKEYV2_SOCKETFLAGS_REGISTERED1) {
567 if (!satype) {
568 /* Just send to everyone registered */
569 pfkey_sendup(kp, packet, 1);
570 } else {
571 /* Check for specified satype */
572 if ((1 << satype) & kp->kcb_reg)
573 pfkey_sendup(kp, packet, 1);
574 }
575 }
576 keyunlock(kp)sounlock((kp)->kcb_socket);
577 }
578 SRPL_LEAVE(&sr)srp_leave((&sr));
579 /* Free last/original copy of the packet */
580 m_freem(packet);
581
582 /* Encapsulate the original message "inside" an sadb_msg header */
583 bzero(buffer, sizeof(struct sadb_msg))__builtin_bzero((buffer), (sizeof(struct sadb_msg)));
584 smsg = (struct sadb_msg *) buffer;
585 smsg->sadb_msg_version = PF_KEY_V22;
586 smsg->sadb_msg_type = SADB_X_PROMISC11;
587 smsg->sadb_msg_len = (sizeof(struct sadb_msg) + j) /
588 sizeof(uint64_t);
589 smsg->sadb_msg_seq = 0;
590
591 /* Convert to mbuf chain */
592 if ((rval = pfdatatopacket(buffer, sizeof(struct sadb_msg) + j,
593 &packet)) != 0)
594 goto ret;
595
596 /* Send to all registered promiscuous listeners */
597 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))
{
598 if (kp->kcb_rdomain != rdomain)
599 continue;
600
601 keylock(kp)solock((kp)->kcb_socket);
602 if ((kp->kcb_flags & PFKEYV2_SOCKETFLAGS_PROMISC2) &&
603 !(kp->kcb_flags & PFKEYV2_SOCKETFLAGS_REGISTERED1))
604 pfkey_sendup(kp, packet, 1);
605 keyunlock(kp)sounlock((kp)->kcb_socket);
606 }
607 SRPL_LEAVE(&sr)srp_leave((&sr));
608 m_freem(packet);
609 break;
610
611 case PFKEYV2_SENDMESSAGE_BROADCAST3:
612 /* Send message to all sockets */
613 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))
{
614 if (kp->kcb_rdomain != rdomain)
615 continue;
616
617 keylock(kp)solock((kp)->kcb_socket);
618 pfkey_sendup(kp, packet, 1);
619 keyunlock(kp)sounlock((kp)->kcb_socket);
620 }
621 SRPL_LEAVE(&sr)srp_leave((&sr));
622 m_freem(packet);
623 break;
624 }
625
626ret:
627 if (buffer != NULL((void *)0)) {
628 explicit_bzero(buffer, j + sizeof(struct sadb_msg));
629 free(buffer, M_PFKEY74, j + sizeof(struct sadb_msg));
630 }
631
632 return (rval);
633}
634
635/*
636 * Get SPD information for an ACQUIRE. We setup the message such that
637 * the SRC/DST payloads are relative to us (regardless of whether the
638 * SPD rule was for incoming or outgoing packets).
639 */
640int
641pfkeyv2_policy(struct ipsec_acquire *ipa, void **headers, void **buffer,
642 int *bufferlen)
643{
644 union sockaddr_union sunion;
645 struct sadb_protocol *sp;
646 int rval, i, dir;
647 void *p;
648
649 /* Find out how big a buffer we need */
650 i = 4 * sizeof(struct sadb_address) + sizeof(struct sadb_protocol);
651 bzero(&sunion, sizeof(union sockaddr_union))__builtin_bzero((&sunion), (sizeof(union sockaddr_union))
)
;
652
653 switch (ipa->ipa_info.sen_type) {
654 case SENT_IP40x0001:
655 i += 4 * PADUP(sizeof(struct sockaddr_in))(((sizeof(struct sockaddr_in)) + sizeof(uint64_t) - 1) & ~
(sizeof(uint64_t) - 1))
;
656 sunion.sa.sa_family = AF_INET2;
657 sunion.sa.sa_len = sizeof(struct sockaddr_in);
658 dir = ipa->ipa_info.sen_directionSen.Sip4.Direction;
659 break;
660
661#ifdef INET61
662 case SENT_IP60x0002:
663 i += 4 * PADUP(sizeof(struct sockaddr_in6))(((sizeof(struct sockaddr_in6)) + sizeof(uint64_t) - 1) &
~(sizeof(uint64_t) - 1))
;
664 sunion.sa.sa_family = AF_INET624;
665 sunion.sa.sa_len = sizeof(struct sockaddr_in6);
666 dir = ipa->ipa_info.sen_ip6_directionSen.Sip6.Direction;
667 break;
668#endif /* INET6 */
669
670 default:
671 return (EINVAL22);
672 }
673
674 if (!(p = malloc(i, M_PFKEY74, M_NOWAIT0x0002 | M_ZERO0x0008))) {
675 rval = ENOMEM12;
676 goto ret;
677 } else {
678 *buffer = p;
679 *bufferlen = i;
680 }
681
682 if (dir == IPSP_DIRECTION_OUT0x2)
683 headers[SADB_X_EXT_SRC_FLOW21] = p;
684 else
685 headers[SADB_X_EXT_DST_FLOW22] = p;
686 switch (sunion.sa.sa_family) {
687 case AF_INET2:
688 sunion.sin.sin_addr = ipa->ipa_info.sen_ip_srcSen.Sip4.Src;
689 sunion.sin.sin_port = ipa->ipa_info.sen_sportSen.Sip4.Sport;
690 break;
691
692#ifdef INET61
693 case AF_INET624:
694 sunion.sin6.sin6_addr = ipa->ipa_info.sen_ip6_srcSen.Sip6.Src;
695 sunion.sin6.sin6_port = ipa->ipa_info.sen_ip6_sportSen.Sip6.Sport;
696 break;
697#endif /* INET6 */
698 }
699 export_address(&p, &sunion.sa);
700
701 if (dir == IPSP_DIRECTION_OUT0x2)
702 headers[SADB_X_EXT_SRC_MASK17] = p;
703 else
704 headers[SADB_X_EXT_DST_MASK18] = p;
705 switch (sunion.sa.sa_family) {
706 case AF_INET2:
707 sunion.sin.sin_addr = ipa->ipa_mask.sen_ip_srcSen.Sip4.Src;
708 sunion.sin.sin_port = ipa->ipa_mask.sen_sportSen.Sip4.Sport;
709 break;
710
711#ifdef INET61
712 case AF_INET624:
713 sunion.sin6.sin6_addr = ipa->ipa_mask.sen_ip6_srcSen.Sip6.Src;
714 sunion.sin6.sin6_port = ipa->ipa_mask.sen_ip6_sportSen.Sip6.Sport;
715 break;
716#endif /* INET6 */
717 }
718 export_address(&p, &sunion.sa);
719
720 if (dir == IPSP_DIRECTION_OUT0x2)
721 headers[SADB_X_EXT_DST_FLOW22] = p;
722 else
723 headers[SADB_X_EXT_SRC_FLOW21] = p;
724 switch (sunion.sa.sa_family) {
725 case AF_INET2:
726 sunion.sin.sin_addr = ipa->ipa_info.sen_ip_dstSen.Sip4.Dst;
727 sunion.sin.sin_port = ipa->ipa_info.sen_dportSen.Sip4.Dport;
728 break;
729
730#ifdef INET61
731 case AF_INET624:
732 sunion.sin6.sin6_addr = ipa->ipa_info.sen_ip6_dstSen.Sip6.Dst;
733 sunion.sin6.sin6_port = ipa->ipa_info.sen_ip6_dportSen.Sip6.Dport;
734 break;
735#endif /* INET6 */
736 }
737 export_address(&p, &sunion.sa);
738
739 if (dir == IPSP_DIRECTION_OUT0x2)
740 headers[SADB_X_EXT_DST_MASK18] = p;
741 else
742 headers[SADB_X_EXT_SRC_MASK17] = p;
743 switch (sunion.sa.sa_family) {
744 case AF_INET2:
745 sunion.sin.sin_addr = ipa->ipa_mask.sen_ip_dstSen.Sip4.Dst;
746 sunion.sin.sin_port = ipa->ipa_mask.sen_dportSen.Sip4.Dport;
747 break;
748
749#ifdef INET61
750 case AF_INET624:
751 sunion.sin6.sin6_addr = ipa->ipa_mask.sen_ip6_dstSen.Sip6.Dst;
752 sunion.sin6.sin6_port = ipa->ipa_mask.sen_ip6_dportSen.Sip6.Dport;
753 break;
754#endif /* INET6 */
755 }
756 export_address(&p, &sunion.sa);
757
758 headers[SADB_X_EXT_FLOW_TYPE20] = p;
759 sp = p;
760 sp->sadb_protocol_len = sizeof(struct sadb_protocol) /
761 sizeof(u_int64_t);
762 switch (sunion.sa.sa_family) {
763 case AF_INET2:
764 if (ipa->ipa_mask.sen_protoSen.Sip4.Proto)
765 sp->sadb_protocol_proto = ipa->ipa_info.sen_protoSen.Sip4.Proto;
766 sp->sadb_protocol_direction = ipa->ipa_info.sen_directionSen.Sip4.Direction;
767 break;
768
769#ifdef INET61
770 case AF_INET624:
771 if (ipa->ipa_mask.sen_ip6_protoSen.Sip6.Proto)
772 sp->sadb_protocol_proto = ipa->ipa_info.sen_ip6_protoSen.Sip6.Proto;
773 sp->sadb_protocol_direction = ipa->ipa_info.sen_ip6_directionSen.Sip6.Direction;
774 break;
775#endif /* INET6 */
776 }
777
778 rval = 0;
779
780ret:
781 return (rval);
782}
783
784/*
785 * Get all the information contained in an SA to a PFKEYV2 message.
786 */
787int
788pfkeyv2_get(struct tdb *tdb, void **headers, void **buffer, int *lenp,
789 int *lenused)
790{
791 int rval, i;
792 void *p;
793
794 NET_ASSERT_LOCKED()do { int _s = rw_status(&netlock); if ((splassert_ctl >
0) && (_s != 0x0001UL && _s != 0x0002UL)) splassert_fail
(0x0002UL, _s, __func__); } while (0)
;
795
796 /* Find how much space we need */
797 i = sizeof(struct sadb_sa) + sizeof(struct sadb_lifetime) +
798 sizeof(struct sadb_x_counter);
799
800 if (tdb->tdb_soft_allocations || tdb->tdb_soft_bytes ||
801 tdb->tdb_soft_timeout || tdb->tdb_soft_first_use)
802 i += sizeof(struct sadb_lifetime);
803
804 if (tdb->tdb_exp_allocations || tdb->tdb_exp_bytes ||
805 tdb->tdb_exp_timeout || tdb->tdb_exp_first_use)
806 i += sizeof(struct sadb_lifetime);
807
808 if (tdb->tdb_last_used)
809 i += sizeof(struct sadb_lifetime);
810
811 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))
;
812 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))
;
813
814 if (tdb->tdb_ids) {
815 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))
;
816 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))
;
817 }
818
819 if (tdb->tdb_amxkey)
820 i += sizeof(struct sadb_key) + PADUP(tdb->tdb_amxkeylen)(((tdb->tdb_amxkeylen) + sizeof(uint64_t) - 1) & ~(sizeof
(uint64_t) - 1))
;
821
822 if (tdb->tdb_emxkey)
823 i += sizeof(struct sadb_key) + PADUP(tdb->tdb_emxkeylen)(((tdb->tdb_emxkeylen) + sizeof(uint64_t) - 1) & ~(sizeof
(uint64_t) - 1))
;
824
825 if (tdb->tdb_filter.sen_type) {
826 i += 2 * sizeof(struct sadb_protocol);
827
828 /* We'll need four of them: src, src mask, dst, dst mask. */
829 switch (tdb->tdb_filter.sen_type) {
830 case SENT_IP40x0001:
831 i += 4 * PADUP(sizeof(struct sockaddr_in))(((sizeof(struct sockaddr_in)) + sizeof(uint64_t) - 1) & ~
(sizeof(uint64_t) - 1))
;
832 i += 4 * sizeof(struct sadb_address);
833 break;
834#ifdef INET61
835 case SENT_IP60x0002:
836 i += 4 * PADUP(sizeof(struct sockaddr_in6))(((sizeof(struct sockaddr_in6)) + sizeof(uint64_t) - 1) &
~(sizeof(uint64_t) - 1))
;
837 i += 4 * sizeof(struct sadb_address);
838 break;
839#endif /* INET6 */
840 default:
841 rval = EINVAL22;
842 goto ret;
843 }
844 }
845
846 if (tdb->tdb_onext) {
847 i += sizeof(struct sadb_sa);
848 i += sizeof(struct sadb_address) +
849 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))
;
850 i += sizeof(struct sadb_protocol);
851 }
852
853 if (tdb->tdb_udpencap_port)
854 i += sizeof(struct sadb_x_udpencap);
855
856 i += sizeof(struct sadb_x_replay);
857
858 if (tdb->tdb_mtu > 0)
859 i+= sizeof(struct sadb_x_mtu);
860
861 if (tdb->tdb_rdomain != tdb->tdb_rdomain_post)
862 i += sizeof(struct sadb_x_rdomain);
863
864#if NPF1 > 0
865 if (tdb->tdb_tag)
866 i += sizeof(struct sadb_x_tag) + PADUP(PF_TAG_NAME_SIZE)(((64) + sizeof(uint64_t) - 1) & ~(sizeof(uint64_t) - 1));
867 if (tdb->tdb_tap)
868 i += sizeof(struct sadb_x_tap);
869#endif
870
871 if (ISSET(tdb->tdb_flags, TDBF_IFACE)((tdb->tdb_flags) & (0x400000)))
872 i += sizeof(struct sadb_x_iface);
873
874 if (lenp)
875 *lenp = i;
876
877 if (buffer == NULL((void *)0)) {
878 rval = 0;
879 goto ret;
880 }
881
882 if (!(p = malloc(i, M_PFKEY74, M_NOWAIT0x0002 | M_ZERO0x0008))) {
883 rval = ENOMEM12;
884 goto ret;
885 } else
886 *buffer = p;
887
888 headers[SADB_EXT_SA1] = p;
889
890 export_sa(&p, tdb); /* Export SA information (mostly flags) */
891
892 /* Export lifetimes where applicable */
893 headers[SADB_EXT_LIFETIME_CURRENT2] = p;
894 export_lifetime(&p, tdb, PFKEYV2_LIFETIME_CURRENT2);
895
896 if (tdb->tdb_soft_allocations || tdb->tdb_soft_bytes ||
897 tdb->tdb_soft_first_use || tdb->tdb_soft_timeout) {
898 headers[SADB_EXT_LIFETIME_SOFT4] = p;
899 export_lifetime(&p, tdb, PFKEYV2_LIFETIME_SOFT1);
900 }
901
902 if (tdb->tdb_exp_allocations || tdb->tdb_exp_bytes ||
903 tdb->tdb_exp_first_use || tdb->tdb_exp_timeout) {
904 headers[SADB_EXT_LIFETIME_HARD3] = p;
905 export_lifetime(&p, tdb, PFKEYV2_LIFETIME_HARD0);
906 }
907
908 if (tdb->tdb_last_used) {
909 headers[SADB_X_EXT_LIFETIME_LASTUSE32] = p;
910 export_lifetime(&p, tdb, PFKEYV2_LIFETIME_LASTUSE3);
911 }
912
913 /* Export TDB source address */
914 headers[SADB_EXT_ADDRESS_SRC5] = p;
915 export_address(&p, &tdb->tdb_src.sa);
916
917 /* Export TDB destination address */
918 headers[SADB_EXT_ADDRESS_DST6] = p;
919 export_address(&p, &tdb->tdb_dst.sa);
920
921 /* Export source/destination identities, if present */
922 if (tdb->tdb_ids)
923 export_identities(&p, tdb->tdb_ids, tdb->tdb_ids_swapped, headers);
924
925 /* Export authentication key, if present */
926 if (tdb->tdb_amxkey) {
927 headers[SADB_EXT_KEY_AUTH8] = p;
928 export_key(&p, tdb, PFKEYV2_AUTHENTICATION_KEY1);
929 }
930
931 /* Export encryption key, if present */
932 if (tdb->tdb_emxkey) {
933 headers[SADB_EXT_KEY_ENCRYPT9] = p;
934 export_key(&p, tdb, PFKEYV2_ENCRYPTION_KEY0);
935 }
936
937 /* Export flow/filter, if present */
938 if (tdb->tdb_filter.sen_type)
939 export_flow(&p, IPSP_IPSEC_USE0, &tdb->tdb_filter,
940 &tdb->tdb_filtermask, headers);
941
942 if (tdb->tdb_onext) {
943 headers[SADB_X_EXT_SA223] = p;
944 export_sa(&p, tdb->tdb_onext);
945 headers[SADB_X_EXT_DST224] = p;
946 export_address(&p, &tdb->tdb_onext->tdb_dst.sa);
947 headers[SADB_X_EXT_SATYPE235] = p;
948 export_satype(&p, tdb->tdb_onext);
949 }
950
951 /* Export UDP encapsulation port, if present */
952 if (tdb->tdb_udpencap_port) {
953 headers[SADB_X_EXT_UDPENCAP31] = p;
954 export_udpencap(&p, tdb);
955 }
956
957 headers[SADB_X_EXT_REPLAY39] = p;
958 export_replay(&p, tdb);
959
960 if (tdb->tdb_mtu > 0) {
961 headers[SADB_X_EXT_MTU38] = p;
962 export_mtu(&p, tdb);
963 }
964
965 /* Export rdomain switch, if present */
966 if (tdb->tdb_rdomain != tdb->tdb_rdomain_post) {
967 headers[SADB_X_EXT_RDOMAIN37] = p;
968 export_rdomain(&p, tdb);
969 }
970
971#if NPF1 > 0
972 /* Export tag information, if present */
973 if (tdb->tdb_tag) {
974 headers[SADB_X_EXT_TAG33] = p;
975 export_tag(&p, tdb);
976 }
977
978 /* Export tap enc(4) device information, if present */
979 if (tdb->tdb_tap) {
980 headers[SADB_X_EXT_TAP34] = p;
981 export_tap(&p, tdb);
982 }
983#endif
984
985 /* Export sec(4) interface information, if present */
986 if (ISSET(tdb->tdb_flags, TDBF_IFACE)((tdb->tdb_flags) & (0x400000))) {
987 headers[SADB_X_EXT_IFACE40] = p;
988 export_iface(&p, tdb);
989 }
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_MAX40+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;
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;
Although the value stored to 'satype' is used in the enclosing expression, the value is never actually read from 'satype'
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_dosend(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_MAX40 + 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;
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 /* Validate message format */
1166 if ((rval = pfkeyv2_parsemessage(message, len, headers)) != 0)
1167 goto ret;
1168
1169 /* If we have any promiscuous listeners, send them a copy of the message */
1170 if (promisc) {
1171 struct mbuf *packet;
1172
1173 freeme_sz = sizeof(struct sadb_msg) + len;
1174 if (!(freeme = malloc(freeme_sz, M_PFKEY74, M_NOWAIT0x0002))) {
1175 rval = ENOMEM12;
1176 goto ret;
1177 }
1178
1179 /* Initialize encapsulating header */
1180 bzero(freeme, sizeof(struct sadb_msg))__builtin_bzero((freeme), (sizeof(struct sadb_msg)));
1181 smsg = (struct sadb_msg *) freeme;
1182 smsg->sadb_msg_version = PF_KEY_V22;
1183 smsg->sadb_msg_type = SADB_X_PROMISC11;
1184 smsg->sadb_msg_len = (sizeof(struct sadb_msg) + len) /
1185 sizeof(uint64_t);
1186 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;
1187
1188 bcopy(message, freeme + sizeof(struct sadb_msg), len);
1189
1190 /* Convert to mbuf chain */
1191 if ((rval = pfdatatopacket(freeme, freeme_sz, &packet)) != 0)
1192 goto ret;
1193
1194 /* Send to all promiscuous listeners */
1195 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))
{
1196 if (bkp->kcb_rdomain != kp->kcb_rdomain)
1197 continue;
1198
1199 keylock(bkp)solock((bkp)->kcb_socket);
1200 if (bkp->kcb_flags & PFKEYV2_SOCKETFLAGS_PROMISC2)
1201 pfkey_sendup(bkp, packet, 1);
1202 keyunlock(bkp)sounlock((bkp)->kcb_socket);
1203 }
1204 SRPL_LEAVE(&sr)srp_leave((&sr));
1205
1206 m_freem(packet);
1207
1208 /* Paranoid */
1209 explicit_bzero(freeme, freeme_sz);
1210 free(freeme, M_PFKEY74, freeme_sz);
1211 freeme = NULL((void *)0);
1212 freeme_sz = 0;
1213 }
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 import_iface(newsa, headers[SADB_X_EXT_IFACE40]);
1373
1374 /* Exclude sensitive data from reply message. */
1375 headers[SADB_EXT_KEY_AUTH8] = NULL((void *)0);
1376 headers[SADB_EXT_KEY_ENCRYPT9] = NULL((void *)0);
1377 headers[SADB_X_EXT_LOCAL_AUTH28] = NULL((void *)0);
1378 headers[SADB_X_EXT_REMOTE_AUTH29] = NULL((void *)0);
1379
1380 newsa->tdb_seq = smsg->sadb_msg_seq;
1381
1382 rval = tdb_init(newsa, alg, &ii);
1383 if (rval) {
1384 rval = EINVAL22;
1385 tdb_unref(newsa);
1386 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1387 goto ret;
1388 }
1389
1390 newsa->tdb_cur_allocations = sa2->tdb_cur_allocations;
1391
1392 /* Delete old version of the SA, insert new one */
1393 tdb_delete(sa2);
1394
1395 tdb_addtimeouts(newsa);
1396
1397 puttdb(newsa);
1398 } else {
1399 /*
1400 * The SA is already initialized, so we're only allowed to
1401 * change lifetimes and some other information; we're
1402 * not allowed to change keys, addresses or identities.
1403 */
1404 if (headers[SADB_EXT_KEY_AUTH8] ||
1405 headers[SADB_EXT_KEY_ENCRYPT9] ||
1406 headers[SADB_EXT_IDENTITY_SRC10] ||
1407 headers[SADB_EXT_IDENTITY_DST11] ||
1408 headers[SADB_EXT_SENSITIVITY12]) {
1409 rval = EINVAL22;
1410 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1411 goto ret;
1412 }
1413
1414 import_sa(sa2, headers[SADB_EXT_SA1], NULL((void *)0));
1415 import_lifetime(sa2,
1416 headers[SADB_EXT_LIFETIME_CURRENT2],
1417 PFKEYV2_LIFETIME_CURRENT2);
1418 import_lifetime(sa2, headers[SADB_EXT_LIFETIME_SOFT4],
1419 PFKEYV2_LIFETIME_SOFT1);
1420 import_lifetime(sa2, headers[SADB_EXT_LIFETIME_HARD3],
1421 PFKEYV2_LIFETIME_HARD0);
1422 import_udpencap(sa2, headers[SADB_X_EXT_UDPENCAP31]);
1423#if NPF1 > 0
1424 import_tag(sa2, headers[SADB_X_EXT_TAG33]);
1425 import_tap(sa2, headers[SADB_X_EXT_TAP34]);
1426#endif
1427 import_iface(sa2, headers[SADB_X_EXT_IFACE40]);
1428
1429 tdb_addtimeouts(sa2);
1430
1431 if (headers[SADB_EXT_ADDRESS_SRC5] ||
1432 headers[SADB_EXT_ADDRESS_PROXY7]) {
1433 mtx_enter(&tdb_sadb_mtx);
1434 tdb_unlink_locked(sa2);
1435 import_address((struct sockaddr *)&sa2->tdb_src,
1436 headers[SADB_EXT_ADDRESS_SRC5]);
1437 import_address((struct sockaddr *)&sa2->tdb_dst,
1438 headers[SADB_EXT_ADDRESS_PROXY7]);
1439 puttdb_locked(sa2);
1440 mtx_leave(&tdb_sadb_mtx);
1441 }
1442 }
1443 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1444
1445 break;
1446 case SADB_ADD3:
1447 ssa = (struct sadb_sa *) headers[SADB_EXT_SA1];
1448 sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST6] +
1449 sizeof(struct sadb_address));
1450
1451 /* Either all or none of the flow must be included */
1452 if ((headers[SADB_X_EXT_SRC_FLOW21] ||
1453 headers[SADB_X_EXT_PROTOCOL19] ||
1454 headers[SADB_X_EXT_FLOW_TYPE20] ||
1455 headers[SADB_X_EXT_DST_FLOW22] ||
1456 headers[SADB_X_EXT_SRC_MASK17] ||
1457 headers[SADB_X_EXT_DST_MASK18]) &&
1458 !(headers[SADB_X_EXT_SRC_FLOW21] &&
1459 headers[SADB_X_EXT_PROTOCOL19] &&
1460 headers[SADB_X_EXT_FLOW_TYPE20] &&
1461 headers[SADB_X_EXT_DST_FLOW22] &&
1462 headers[SADB_X_EXT_SRC_MASK17] &&
1463 headers[SADB_X_EXT_DST_MASK18])) {
1464 rval = EINVAL22;
1465 goto ret;
1466 }
1467#ifdef IPSEC1
1468 /* UDP encap has to be enabled and is only supported for ESP */
1469 if (headers[SADB_X_EXT_UDPENCAP31] &&
1470 (!udpencap_enable ||
1471 smsg->sadb_msg_satype != SADB_SATYPE_ESP2)) {
1472 rval = EINVAL22;
1473 goto ret;
1474 }
1475#endif /* IPSEC */
1476
1477 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1478 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)
1479 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)
;
1480
1481 /* We can't add an existing SA! */
1482 if (sa2 != NULL((void *)0)) {
1483 rval = EEXIST17;
1484 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1485 goto ret;
1486 }
1487
1488 /* We can only add "mature" SAs */
1489 if (ssa->sadb_sa_state != SADB_SASTATE_MATURE1) {
1490 rval = EINVAL22;
1491 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1492 goto ret;
1493 }
1494
1495 {
1496 struct tdb *newsa;
1497 struct ipsecinit ii;
1498 int alg;
1499
1500 /* Create new TDB */
1501 newsa = tdb_alloc(rdomain);
1502 newsa->tdb_satype = smsg->sadb_msg_satype;
1503
1504 if ((rval = pfkeyv2_get_proto_alg(newsa->tdb_satype,
1505 &newsa->tdb_sproto, &alg))) {
1506 tdb_unref(newsa);
1507 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1508 goto ret;
1509 }
1510
1511 /* Initialize SA */
1512 bzero(&ii, sizeof(struct ipsecinit))__builtin_bzero((&ii), (sizeof(struct ipsecinit)));
1513 import_sa(newsa, headers[SADB_EXT_SA1], &ii);
1514 import_address(&newsa->tdb_src.sa,
1515 headers[SADB_EXT_ADDRESS_SRC5]);
1516 import_address(&newsa->tdb_dst.sa,
1517 headers[SADB_EXT_ADDRESS_DST6]);
1518
1519 import_lifetime(newsa,
1520 headers[SADB_EXT_LIFETIME_CURRENT2],
1521 PFKEYV2_LIFETIME_CURRENT2);
1522 import_lifetime(newsa, headers[SADB_EXT_LIFETIME_SOFT4],
1523 PFKEYV2_LIFETIME_SOFT1);
1524 import_lifetime(newsa, headers[SADB_EXT_LIFETIME_HARD3],
1525 PFKEYV2_LIFETIME_HARD0);
1526
1527 import_key(&ii, headers[SADB_EXT_KEY_AUTH8],
1528 PFKEYV2_AUTHENTICATION_KEY1);
1529 import_key(&ii, headers[SADB_EXT_KEY_ENCRYPT9],
1530 PFKEYV2_ENCRYPTION_KEY0);
1531
1532 import_identities(&newsa->tdb_ids,
1533 newsa->tdb_ids_swapped,
1534 headers[SADB_EXT_IDENTITY_SRC10],
1535 headers[SADB_EXT_IDENTITY_DST11]);
1536
1537 if ((rval = import_flow(&newsa->tdb_filter,
1538 &newsa->tdb_filtermask,
1539 headers[SADB_X_EXT_SRC_FLOW21],
1540 headers[SADB_X_EXT_SRC_MASK17],
1541 headers[SADB_X_EXT_DST_FLOW22],
1542 headers[SADB_X_EXT_DST_MASK18],
1543 headers[SADB_X_EXT_PROTOCOL19],
1544 headers[SADB_X_EXT_FLOW_TYPE20]))) {
1545 tdb_unref(newsa);
1546 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1547 goto ret;
1548 }
1549 import_udpencap(newsa, headers[SADB_X_EXT_UDPENCAP31]);
1550 import_rdomain(newsa, headers[SADB_X_EXT_RDOMAIN37]);
1551#if NPF1 > 0
1552 import_tag(newsa, headers[SADB_X_EXT_TAG33]);
1553 import_tap(newsa, headers[SADB_X_EXT_TAP34]);
1554#endif
1555 import_iface(newsa, headers[SADB_X_EXT_IFACE40]);
1556
1557 /* Exclude sensitive data from reply message. */
1558 headers[SADB_EXT_KEY_AUTH8] = NULL((void *)0);
1559 headers[SADB_EXT_KEY_ENCRYPT9] = NULL((void *)0);
1560 headers[SADB_X_EXT_LOCAL_AUTH28] = NULL((void *)0);
1561 headers[SADB_X_EXT_REMOTE_AUTH29] = NULL((void *)0);
1562
1563 newsa->tdb_seq = smsg->sadb_msg_seq;
1564
1565 rval = tdb_init(newsa, alg, &ii);
1566 if (rval) {
1567 rval = EINVAL22;
1568 tdb_unref(newsa);
1569 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1570 goto ret;
1571 }
1572
1573 tdb_addtimeouts(newsa);
1574
1575 /* Add TDB in table */
1576 puttdb(newsa);
1577 }
1578 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1579
1580 break;
1581
1582 case SADB_DELETE4:
1583 ssa = (struct sadb_sa *) headers[SADB_EXT_SA1];
1584 sunionp =
1585 (union sockaddr_union *)(headers[SADB_EXT_ADDRESS_DST6] +
1586 sizeof(struct sadb_address));
1587
1588 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1589 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)
1590 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)
;
1591 if (sa2 == NULL((void *)0)) {
1592 rval = ESRCH3;
1593 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1594 goto ret;
1595 }
1596
1597 tdb_delete(sa2);
1598 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1599
1600 break;
1601
1602 case SADB_X_ASKPOLICY15:
1603 /* Get the relevant policy */
1604 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1605 ipa = ipsec_get_acquire(((struct sadb_x_policy *)
1606 headers[SADB_X_EXT_POLICY25])->sadb_x_policy_seq);
1607 if (ipa == NULL((void *)0)) {
1608 rval = ESRCH3;
1609 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1610 goto ret;
1611 }
1612
1613 rval = pfkeyv2_policy(ipa, headers, &freeme, &freeme_sz);
1614 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1615 ipsec_unref_acquire(ipa);
1616 if (rval)
1617 mode = PFKEYV2_SENDMESSAGE_UNICAST1;
1618
1619 break;
1620
1621 case SADB_GET5:
1622 ssa = (struct sadb_sa *) headers[SADB_EXT_SA1];
1623 sunionp =
1624 (union sockaddr_union *)(headers[SADB_EXT_ADDRESS_DST6] +
1625 sizeof(struct sadb_address));
1626
1627 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1628 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)
1629 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)
;
1630 if (sa2 == NULL((void *)0)) {
1631 rval = ESRCH3;
1632 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1633 goto ret;
1634 }
1635
1636 rval = pfkeyv2_get(sa2, headers, &freeme, &freeme_sz, NULL((void *)0));
1637 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1638 if (rval)
1639 mode = PFKEYV2_SENDMESSAGE_UNICAST1;
1640
1641 break;
1642
1643 case SADB_REGISTER7:
1644 keylock(kp)solock((kp)->kcb_socket);
1645 if (!(kp->kcb_flags & PFKEYV2_SOCKETFLAGS_REGISTERED1)) {
1646 kp->kcb_flags |= PFKEYV2_SOCKETFLAGS_REGISTERED1;
1647 mtx_enter(&pfkeyv2_mtx);
1648 nregistered++;
1649 mtx_leave(&pfkeyv2_mtx);
1650 }
1651 keyunlock(kp)sounlock((kp)->kcb_socket);
1652
1653 freeme_sz = sizeof(struct sadb_supported) + sizeof(ealgs);
1654 if (!(freeme = malloc(freeme_sz, M_PFKEY74, M_NOWAIT0x0002 | M_ZERO0x0008))) {
1655 rval = ENOMEM12;
1656 goto ret;
1657 }
1658
1659 ssup = (struct sadb_supported *) freeme;
1660 ssup->sadb_supported_len = freeme_sz / sizeof(uint64_t);
1661
1662 {
1663 void *p = freeme + sizeof(struct sadb_supported);
1664
1665 bcopy(&ealgs[0], p, sizeof(ealgs));
1666 }
1667
1668 headers[SADB_EXT_SUPPORTED_ENCRYPT15] = freeme;
1669
1670 freeme2_sz = sizeof(struct sadb_supported) + sizeof(aalgs);
1671 if (!(freeme2 = malloc(freeme2_sz, M_PFKEY74,
1672 M_NOWAIT0x0002 | M_ZERO0x0008))) {
1673 rval = ENOMEM12;
1674 goto ret;
1675 }
1676
1677 /* Keep track what this socket has registered for */
1678 keylock(kp)solock((kp)->kcb_socket);
1679 kp->kcb_reg |=
1680 (1 << ((struct sadb_msg *)message)->sadb_msg_satype);
1681 keyunlock(kp)sounlock((kp)->kcb_socket);
1682
1683 ssup = (struct sadb_supported *) freeme2;
1684 ssup->sadb_supported_len = freeme2_sz / sizeof(uint64_t);
1685
1686 {
1687 void *p = freeme2 + sizeof(struct sadb_supported);
1688
1689 bcopy(&aalgs[0], p, sizeof(aalgs));
1690 }
1691
1692 headers[SADB_EXT_SUPPORTED_AUTH14] = freeme2;
1693
1694 freeme3_sz = sizeof(struct sadb_supported) + sizeof(calgs);
1695 if (!(freeme3 = malloc(freeme3_sz, M_PFKEY74,
1696 M_NOWAIT0x0002 | M_ZERO0x0008))) {
1697 rval = ENOMEM12;
1698 goto ret;
1699 }
1700
1701 ssup = (struct sadb_supported *) freeme3;
1702 ssup->sadb_supported_len = freeme3_sz / sizeof(uint64_t);
1703
1704 {
1705 void *p = freeme3 + sizeof(struct sadb_supported);
1706
1707 bcopy(&calgs[0], p, sizeof(calgs));
1708 }
1709
1710 headers[SADB_X_EXT_SUPPORTED_COMP30] = freeme3;
1711
1712 break;
1713
1714 case SADB_ACQUIRE6:
1715 case SADB_EXPIRE8:
1716 /* Nothing to handle */
1717 rval = 0;
1718 break;
1719
1720 case SADB_FLUSH9:
1721 rval = 0;
1722
1723 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1724 switch (smsg->sadb_msg_satype) {
1725 case SADB_SATYPE_UNSPEC0:
1726 spd_table_walk(rdomain, pfkeyv2_policy_flush, NULL((void *)0));
1727 /* FALLTHROUGH */
1728 case SADB_SATYPE_AH1:
1729 case SADB_SATYPE_ESP2:
1730 case SADB_X_SATYPE_IPIP7:
1731 case SADB_X_SATYPE_IPCOMP9:
1732#ifdef TCP_SIGNATURE1
1733 case SADB_X_SATYPE_TCPSIGNATURE8:
1734#endif /* TCP_SIGNATURE */
1735 tdb_walk(rdomain, pfkeyv2_sa_flush,
1736 (u_int8_t *) &(smsg->sadb_msg_satype));
1737
1738 break;
1739
1740 default:
1741 rval = EINVAL22; /* Unknown/unsupported type */
1742 }
1743 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1744
1745 break;
1746
1747 case SADB_DUMP10:
1748 {
1749 struct dump_state dump_state;
1750 dump_state.sadb_msg = (struct sadb_msg *) headers[0];
1751 dump_state.socket = so;
1752
1753 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1754 rval = tdb_walk(rdomain, pfkeyv2_dump_walker, &dump_state);
1755 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1756 if (!rval)
1757 goto realret;
1758 if ((rval == ENOMEM12) || (rval == ENOBUFS55))
1759 rval = 0;
1760 }
1761 break;
1762
1763 case SADB_X_GRPSPIS14:
1764 {
1765 struct tdb *tdb1, *tdb2, *tdb3;
1766 struct sadb_protocol *sa_proto;
1767
1768 ssa = (struct sadb_sa *) headers[SADB_EXT_SA1];
1769 sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST6] +
1770 sizeof(struct sadb_address));
1771
1772 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1773 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)
1774 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)
;
1775 if (tdb1 == NULL((void *)0)) {
1776 rval = ESRCH3;
1777 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1778 goto ret;
1779 }
1780
1781 ssa = (struct sadb_sa *) headers[SADB_X_EXT_SA223];
1782 sunionp = (union sockaddr_union *) (headers[SADB_X_EXT_DST224] +
1783 sizeof(struct sadb_address));
1784 sa_proto = (struct sadb_protocol *) headers[SADB_X_EXT_SATYPE235];
1785
1786 /* optionally fetch tdb2 from rdomain2 */
1787 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)
1788 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)
1789 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)
;
1790 if (tdb2 == NULL((void *)0)) {
1791 tdb_unref(tdb1);
1792 rval = ESRCH3;
1793 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1794 goto ret;
1795 }
1796
1797 /* Detect cycles */
1798 for (tdb3 = tdb2; tdb3; tdb3 = tdb3->tdb_onext)
1799 if (tdb3 == tdb1) {
1800 tdb_unref(tdb1);
1801 tdb_unref(tdb2);
1802 rval = ESRCH3;
1803 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1804 goto ret;
1805 }
1806
1807 /* Maintenance */
1808 if ((tdb1->tdb_onext) &&
1809 (tdb1->tdb_onext->tdb_inext == tdb1)) {
1810 tdb_unref(tdb1->tdb_onext->tdb_inext);
1811 tdb1->tdb_onext->tdb_inext = NULL((void *)0);
1812 }
1813
1814 if ((tdb2->tdb_inext) &&
1815 (tdb2->tdb_inext->tdb_onext == tdb2)) {
1816 tdb_unref(tdb2->tdb_inext->tdb_onext);
1817 tdb2->tdb_inext->tdb_onext = NULL((void *)0);
1818 }
1819
1820 /* Link them */
1821 tdb1->tdb_onext = tdb2;
1822 tdb2->tdb_inext = tdb1;
1823 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1824 }
1825 break;
1826
1827 case SADB_X_DELFLOW13:
1828 delflag = 1;
1829 /*FALLTHROUGH*/
1830 case SADB_X_ADDFLOW12:
1831 {
1832 struct sadb_protocol *sab;
1833 union sockaddr_union *ssrc;
1834 int exists = 0;
1835
1836 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1837 if ((rnh = spd_table_add(rdomain)) == NULL((void *)0)) {
1838 rval = ENOMEM12;
1839 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1840 goto ret;
1841 }
1842
1843 sab = (struct sadb_protocol *) headers[SADB_X_EXT_FLOW_TYPE20];
1844
1845 if ((sab->sadb_protocol_direction != IPSP_DIRECTION_IN0x1) &&
1846 (sab->sadb_protocol_direction != IPSP_DIRECTION_OUT0x2)) {
1847 rval = EINVAL22;
1848 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1849 goto ret;
1850 }
1851
1852 /* If the security protocol wasn't specified, pretend it was ESP */
1853 if (smsg->sadb_msg_satype == 0)
1854 smsg->sadb_msg_satype = SADB_SATYPE_ESP2;
1855
1856 if (headers[SADB_EXT_ADDRESS_DST6])
1857 sunionp = (union sockaddr_union *)
1858 (headers[SADB_EXT_ADDRESS_DST6] +
1859 sizeof(struct sadb_address));
1860 else
1861 sunionp = NULL((void *)0);
1862
1863 if (headers[SADB_EXT_ADDRESS_SRC5])
1864 ssrc = (union sockaddr_union *)
1865 (headers[SADB_EXT_ADDRESS_SRC5] +
1866 sizeof(struct sadb_address));
1867 else
1868 ssrc = NULL((void *)0);
1869
1870 if ((rval = import_flow(&encapdst, &encapnetmask,
1871 headers[SADB_X_EXT_SRC_FLOW21], headers[SADB_X_EXT_SRC_MASK17],
1872 headers[SADB_X_EXT_DST_FLOW22], headers[SADB_X_EXT_DST_MASK18],
1873 headers[SADB_X_EXT_PROTOCOL19],
1874 headers[SADB_X_EXT_FLOW_TYPE20]))) {
1875 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1876 goto ret;
1877 }
1878
1879 /* Determine whether the exact same SPD entry already exists. */
1880 if ((rn = rn_match(&encapdst, rnh)) != NULL((void *)0)) {
1881 ipo = (struct ipsec_policy *)rn;
1882
1883 /* Verify that the entry is identical */
1884 if (bcmp(&ipo->ipo_addr, &encapdst,
1885 sizeof(struct sockaddr_encap)) ||
1886 bcmp(&ipo->ipo_mask, &encapnetmask,
1887 sizeof(struct sockaddr_encap)))
1888 ipo = NULL((void *)0); /* Fall through */
1889 else
1890 exists = 1;
1891 } else
1892 ipo = NULL((void *)0);
1893
1894 /*
1895 * If the existing policy is static, only delete or update
1896 * it if the new one is also static.
1897 */
1898 if (exists && (ipo->ipo_flags & IPSP_POLICY_STATIC0x0002)) {
1899 if (!(sab->sadb_protocol_flags &
1900 SADB_X_POLICYFLAGS_POLICY0x0001)) {
1901 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1902 goto ret;
1903 }
1904 }
1905
1906 /* Delete ? */
1907 if (delflag) {
1908 if (exists) {
1909 rval = ipsec_delete_policy(ipo);
1910 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1911 goto ret;
1912 }
1913
1914 /* If we were asked to delete something non-existent, error. */
1915 rval = ESRCH3;
1916 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1917 break;
1918 }
1919
1920 if (!exists) {
1921 /* Allocate policy entry */
1922 ipo = pool_get(&ipsec_policy_pool, PR_NOWAIT0x0002|PR_ZERO0x0008);
1923 if (ipo == NULL((void *)0)) {
1924 rval = ENOMEM12;
1925 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1926 goto ret;
1927 }
1928 }
1929
1930 switch (sab->sadb_protocol_proto) {
1931 case SADB_X_FLOW_TYPE_USE1:
1932 ipo->ipo_type = IPSP_IPSEC_USE0;
1933 break;
1934
1935 case SADB_X_FLOW_TYPE_ACQUIRE2:
1936 ipo->ipo_type = IPSP_IPSEC_ACQUIRE1;
1937 break;
1938
1939 case SADB_X_FLOW_TYPE_REQUIRE3:
1940 ipo->ipo_type = IPSP_IPSEC_REQUIRE2;
1941 break;
1942
1943 case SADB_X_FLOW_TYPE_DENY5:
1944 ipo->ipo_type = IPSP_DENY4;
1945 break;
1946
1947 case SADB_X_FLOW_TYPE_BYPASS4:
1948 ipo->ipo_type = IPSP_PERMIT3;
1949 break;
1950
1951 case SADB_X_FLOW_TYPE_DONTACQ6:
1952 ipo->ipo_type = IPSP_IPSEC_DONTACQ5;
1953 break;
1954
1955 default:
1956 if (!exists)
1957 pool_put(&ipsec_policy_pool, ipo);
1958 else
1959 ipsec_delete_policy(ipo);
1960
1961 rval = EINVAL22;
1962 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1963 goto ret;
1964 }
1965
1966 if (sab->sadb_protocol_flags & SADB_X_POLICYFLAGS_POLICY0x0001)
1967 ipo->ipo_flags |= IPSP_POLICY_STATIC0x0002;
1968
1969 if (sunionp)
1970 bcopy(sunionp, &ipo->ipo_dst,
1971 sizeof(union sockaddr_union));
1972 else
1973 bzero(&ipo->ipo_dst, sizeof(union sockaddr_union))__builtin_bzero((&ipo->ipo_dst), (sizeof(union sockaddr_union
)))
;
1974
1975 if (ssrc)
1976 bcopy(ssrc, &ipo->ipo_src,
1977 sizeof(union sockaddr_union));
1978 else
1979 bzero(&ipo->ipo_src, sizeof(union sockaddr_union))__builtin_bzero((&ipo->ipo_src), (sizeof(union sockaddr_union
)))
;
1980
1981 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 )
;
1982
1983 if (ipo->ipo_ids) {
1984 ipsp_ids_free(ipo->ipo_ids);
1985 ipo->ipo_ids = NULL((void *)0);
1986 }
1987
1988 if ((sid = headers[SADB_EXT_IDENTITY_SRC10]) != NULL((void *)0) &&
1989 (did = headers[SADB_EXT_IDENTITY_DST11]) != NULL((void *)0)) {
1990 import_identities(&ipo->ipo_ids, 0, sid, did);
1991 if (ipo->ipo_ids == NULL((void *)0)) {
1992 if (exists)
1993 ipsec_delete_policy(ipo);
1994 else
1995 pool_put(&ipsec_policy_pool, ipo);
1996 rval = ENOBUFS55;
1997 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1998 goto ret;
1999 }
2000 }
2001
2002 /* Flow type */
2003 if (!exists) {
2004 /* Initialize policy entry */
2005 bcopy(&encapdst, &ipo->ipo_addr,
2006 sizeof(struct sockaddr_encap));
2007 bcopy(&encapnetmask, &ipo->ipo_mask,
2008 sizeof(struct sockaddr_encap));
2009
2010 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)
;
2011 ipo->ipo_rdomain = rdomain;
2012 refcnt_init(&ipo->ipo_refcnt);
2013
2014 /* Add SPD entry */
2015 if ((rnh = spd_table_get(rdomain)) == NULL((void *)0) ||
2016 (rn = rn_addroute((caddr_t)&ipo->ipo_addr,
2017 (caddr_t)&ipo->ipo_mask, rnh,
2018 ipo->ipo_nodes, 0)) == NULL((void *)0)) {
2019 /* Remove from linked list of policies on TDB */
2020 mtx_enter(&ipo_tdb_mtx);
2021 if (ipo->ipo_tdb != NULL((void *)0)) {
2022 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)
2023 &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)
2024 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)
;
2025 tdb_unref(ipo->ipo_tdb);
2026 ipo->ipo_tdb = NULL((void *)0);
2027 }
2028 mtx_leave(&ipo_tdb_mtx);
2029 if (ipo->ipo_ids)
2030 ipsp_ids_free(ipo->ipo_ids);
2031 pool_put(&ipsec_policy_pool, ipo);
2032 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2033 goto ret;
2034 }
2035 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)
;
2036 ipsec_in_use++;
2037 } else {
2038 ipo->ipo_last_searched = ipo->ipo_flags = 0;
2039 }
2040 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2041 }
2042 break;
2043
2044 case SADB_X_PROMISC11:
2045 if (len >= 2 * sizeof(struct sadb_msg)) {
2046 struct mbuf *packet;
2047
2048 if ((rval = pfdatatopacket(message, len, &packet)) != 0)
2049 goto ret;
2050
2051 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))
{
2052 if (bkp == kp || bkp->kcb_rdomain != kp->kcb_rdomain)
2053 continue;
2054
2055 if (!smsg->sadb_msg_seq ||
2056 (smsg->sadb_msg_seq == kp->kcb_pid)) {
2057 keylock(bkp)solock((bkp)->kcb_socket);
2058 pfkey_sendup(bkp, packet, 1);
2059 keyunlock(bkp)sounlock((bkp)->kcb_socket);
2060 }
2061 }
2062 SRPL_LEAVE(&sr)srp_leave((&sr));
2063
2064 m_freem(packet);
2065 } else {
2066 if (len != sizeof(struct sadb_msg)) {
2067 rval = EINVAL22;
2068 goto ret;
2069 }
2070
2071 keylock(kp)solock((kp)->kcb_socket);
2072 i = (kp->kcb_flags &
2073 PFKEYV2_SOCKETFLAGS_PROMISC2) ? 1 : 0;
2074 j = smsg->sadb_msg_satype ? 1 : 0;
2075
2076 if (i ^ j) {
2077 if (j) {
2078 kp->kcb_flags |=
2079 PFKEYV2_SOCKETFLAGS_PROMISC2;
2080 mtx_enter(&pfkeyv2_mtx);
2081 npromisc++;
2082 mtx_leave(&pfkeyv2_mtx);
2083 } else {
2084 kp->kcb_flags &=
2085 ~PFKEYV2_SOCKETFLAGS_PROMISC2;
2086 mtx_enter(&pfkeyv2_mtx);
2087 npromisc--;
2088 mtx_leave(&pfkeyv2_mtx);
2089 }
2090 }
2091 keyunlock(kp)sounlock((kp)->kcb_socket);
2092 }
2093
2094 break;
2095
2096 default:
2097 rval = EINVAL22;
2098 goto ret;
2099 }
2100
2101ret:
2102 if (rval) {
2103 if ((rval == EINVAL22) || (rval == ENOMEM12) || (rval == ENOBUFS55))
2104 goto realret;
2105
2106 for (i = 1; i <= SADB_EXT_MAX40; i++)
2107 headers[i] = NULL((void *)0);
2108
2109 smsg->sadb_msg_errno = abs(rval);
2110 } else {
2111 uint64_t seen = 0LL;
2112
2113 for (i = 1; i <= SADB_EXT_MAX40; i++)
2114 if (headers[i])
2115 seen |= (1LL << i);
2116
2117 if ((seen & sadb_exts_allowed_out[smsg->sadb_msg_type])
2118 != seen) {
2119 rval = EPERM1;
2120 goto realret;
2121 }
2122
2123 if ((seen & sadb_exts_required_out[smsg->sadb_msg_type]) !=
2124 sadb_exts_required_out[smsg->sadb_msg_type]) {
2125 rval = EPERM1;
2126 goto realret;
2127 }
2128 }
2129
2130 rval = pfkeyv2_sendmessage(headers, mode, so, 0, 0, kp->kcb_rdomain);
2131
2132realret:
2133
2134 if (freeme != NULL((void *)0))
2135 explicit_bzero(freeme, freeme_sz);
2136 free(freeme, M_PFKEY74, freeme_sz);
2137 free(freeme2, M_PFKEY74, freeme2_sz);
2138 free(freeme3, M_PFKEY74, freeme3_sz);
2139
2140 explicit_bzero(message, len);
2141 free(message, M_PFKEY74, len);
2142
2143 free(sa1, M_PFKEY74, sizeof(*sa1));
2144
2145 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2146 tdb_unref(sa2);
2147 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2148
2149 return (rval);
2150}
2151
2152/*
2153 * Send an ACQUIRE message to key management, to get a new SA.
2154 */
2155int
2156pfkeyv2_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw,
2157 union sockaddr_union *laddr, u_int32_t *seq, struct sockaddr_encap *ddst)
2158{
2159 void *p, *headers[SADB_EXT_MAX40 + 1], *buffer = NULL((void *)0);
2160 struct sadb_comb *sadb_comb;
2161 struct sadb_address *sadd;
2162 struct sadb_prop *sa_prop;
2163 struct sadb_msg *smsg;
2164 int rval = 0;
2165 int i, j, registered;
2166
2167 mtx_enter(&pfkeyv2_mtx);
2168 *seq = pfkeyv2_seq++;
2169
2170 registered = nregistered;
2171 mtx_leave(&pfkeyv2_mtx);
2172
2173 if (!registered) {
2174 rval = ESRCH3;
2175 goto ret;
2176 }
2177
2178 /* How large a buffer do we need... XXX we only do one proposal for now */
2179 i = sizeof(struct sadb_msg) +
2180 (laddr == NULL((void *)0) ? 0 : sizeof(struct sadb_address) +
2181 PADUP(ipo->ipo_src.sa.sa_len)(((ipo->ipo_src.sa.sa_len) + sizeof(uint64_t) - 1) & ~
(sizeof(uint64_t) - 1))
) +
2182 sizeof(struct sadb_address) + PADUP(gw->sa.sa_len)(((gw->sa.sa_len) + sizeof(uint64_t) - 1) & ~(sizeof(uint64_t
) - 1))
+
2183 sizeof(struct sadb_prop) + 1 * sizeof(struct sadb_comb);
2184
2185 if (ipo->ipo_ids) {
2186 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))
;
2187 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))
;
2188 }
2189
2190 /* Allocate */
2191 if (!(p = malloc(i, M_PFKEY74, M_NOWAIT0x0002 | M_ZERO0x0008))) {
2192 rval = ENOMEM12;
2193 goto ret;
2194 }
2195
2196 bzero(headers, sizeof(headers))__builtin_bzero((headers), (sizeof(headers)));
2197
2198 buffer = p;
2199
2200 headers[0] = p;
2201 p += sizeof(struct sadb_msg);
2202
2203 smsg = (struct sadb_msg *) headers[0];
2204 smsg->sadb_msg_version = PF_KEY_V22;
2205 smsg->sadb_msg_type = SADB_ACQUIRE6;
2206 smsg->sadb_msg_len = i / sizeof(uint64_t);
2207 smsg->sadb_msg_seq = *seq;
2208
2209 if (ipo->ipo_sproto == IPPROTO_ESP50)
2210 smsg->sadb_msg_satype = SADB_SATYPE_ESP2;
2211 else if (ipo->ipo_sproto == IPPROTO_AH51)
2212 smsg->sadb_msg_satype = SADB_SATYPE_AH1;
2213 else if (ipo->ipo_sproto == IPPROTO_IPCOMP108)
2214 smsg->sadb_msg_satype = SADB_X_SATYPE_IPCOMP9;
2215
2216 if (laddr) {
2217 headers[SADB_EXT_ADDRESS_SRC5] = p;
2218 p += sizeof(struct sadb_address) + PADUP(laddr->sa.sa_len)(((laddr->sa.sa_len) + sizeof(uint64_t) - 1) & ~(sizeof
(uint64_t) - 1))
;
2219 sadd = (struct sadb_address *) headers[SADB_EXT_ADDRESS_SRC5];
2220 sadd->sadb_address_len = (sizeof(struct sadb_address) +
2221 laddr->sa.sa_len + sizeof(uint64_t) - 1) /
2222 sizeof(uint64_t);
2223 bcopy(laddr, headers[SADB_EXT_ADDRESS_SRC5] +
2224 sizeof(struct sadb_address), laddr->sa.sa_len);
2225 }
2226
2227 headers[SADB_EXT_ADDRESS_DST6] = p;
2228 p += sizeof(struct sadb_address) + PADUP(gw->sa.sa_len)(((gw->sa.sa_len) + sizeof(uint64_t) - 1) & ~(sizeof(uint64_t
) - 1))
;
2229 sadd = (struct sadb_address *) headers[SADB_EXT_ADDRESS_DST6];
2230 sadd->sadb_address_len = (sizeof(struct sadb_address) +
2231 gw->sa.sa_len + sizeof(uint64_t) - 1) / sizeof(uint64_t);
2232 bcopy(gw, headers[SADB_EXT_ADDRESS_DST6] + sizeof(struct sadb_address),
2233 gw->sa.sa_len);
2234
2235 if (ipo->ipo_ids)
2236 export_identities(&p, ipo->ipo_ids, 0, headers);
2237
2238 headers[SADB_EXT_PROPOSAL13] = p;
2239 p += sizeof(struct sadb_prop);
2240 sa_prop = (struct sadb_prop *) headers[SADB_EXT_PROPOSAL13];
2241 sa_prop->sadb_prop_num = 1; /* XXX One proposal only */
2242 sa_prop->sadb_prop_len = (sizeof(struct sadb_prop) +
2243 (sizeof(struct sadb_comb) * sa_prop->sadb_prop_num)) /
2244 sizeof(uint64_t);
2245
2246 sadb_comb = p;
2247
2248 /* XXX Should actually ask the crypto layer what's supported */
2249 for (j = 0; j < sa_prop->sadb_prop_num; j++) {
2250 sadb_comb->sadb_comb_flags = 0;
2251#ifdef IPSEC1
2252 if (ipsec_require_pfs)
2253 sadb_comb->sadb_comb_flags |= SADB_SAFLAGS_PFS0x001;
2254
2255 /* Set the encryption algorithm */
2256 if (ipo->ipo_sproto == IPPROTO_ESP50) {
2257 if (!strncasecmp(ipsec_def_enc, "aes",
2258 sizeof("aes"))) {
2259 sadb_comb->sadb_comb_encrypt = SADB_X_EALG_AES12;
2260 sadb_comb->sadb_comb_encrypt_minbits = 128;
2261 sadb_comb->sadb_comb_encrypt_maxbits = 256;
2262 } else if (!strncasecmp(ipsec_def_enc, "aesctr",
2263 sizeof("aesctr"))) {
2264 sadb_comb->sadb_comb_encrypt = SADB_X_EALG_AESCTR13;
2265 sadb_comb->sadb_comb_encrypt_minbits = 128+32;
2266 sadb_comb->sadb_comb_encrypt_maxbits = 256+32;
2267 } else if (!strncasecmp(ipsec_def_enc, "3des",
2268 sizeof("3des"))) {
2269 sadb_comb->sadb_comb_encrypt = SADB_EALG_3DESCBC3;
2270 sadb_comb->sadb_comb_encrypt_minbits = 192;
2271 sadb_comb->sadb_comb_encrypt_maxbits = 192;
2272 } else if (!strncasecmp(ipsec_def_enc, "blowfish",
2273 sizeof("blowfish"))) {
2274 sadb_comb->sadb_comb_encrypt = SADB_X_EALG_BLF7;
2275 sadb_comb->sadb_comb_encrypt_minbits = 40;
2276 sadb_comb->sadb_comb_encrypt_maxbits = BLF_MAXKEYLEN((16 -2)*4) * 8;
2277 } else if (!strncasecmp(ipsec_def_enc, "cast128",
2278 sizeof("cast128"))) {
2279 sadb_comb->sadb_comb_encrypt = SADB_X_EALG_CAST6;
2280 sadb_comb->sadb_comb_encrypt_minbits = 40;
2281 sadb_comb->sadb_comb_encrypt_maxbits = 128;
2282 }
2283 } else if (ipo->ipo_sproto == IPPROTO_IPCOMP108) {
2284 /* Set the compression algorithm */
2285 if (!strncasecmp(ipsec_def_comp, "deflate",
2286 sizeof("deflate"))) {
2287 sadb_comb->sadb_comb_encrypt = SADB_X_CALG_DEFLATE2;
2288 sadb_comb->sadb_comb_encrypt_minbits = 0;
2289 sadb_comb->sadb_comb_encrypt_maxbits = 0;
2290 }
2291 }
2292
2293 /* Set the authentication algorithm */
2294 if (!strncasecmp(ipsec_def_auth, "hmac-sha1",
2295 sizeof("hmac-sha1"))) {
2296 sadb_comb->sadb_comb_auth = SADB_AALG_SHA1HMAC3;
2297 sadb_comb->sadb_comb_auth_minbits = 160;
2298 sadb_comb->sadb_comb_auth_maxbits = 160;
2299 } else if (!strncasecmp(ipsec_def_auth, "hmac-ripemd160",
2300 sizeof("hmac_ripemd160"))) {
2301 sadb_comb->sadb_comb_auth = SADB_X_AALG_RIPEMD160HMAC8;
2302 sadb_comb->sadb_comb_auth_minbits = 160;
2303 sadb_comb->sadb_comb_auth_maxbits = 160;
2304 } else if (!strncasecmp(ipsec_def_auth, "hmac-md5",
2305 sizeof("hmac-md5"))) {
2306 sadb_comb->sadb_comb_auth = SADB_AALG_MD5HMAC2;
2307 sadb_comb->sadb_comb_auth_minbits = 128;
2308 sadb_comb->sadb_comb_auth_maxbits = 128;
2309 } else if (!strncasecmp(ipsec_def_auth, "hmac-sha2-256",
2310 sizeof("hmac-sha2-256"))) {
2311 sadb_comb->sadb_comb_auth = SADB_X_AALG_SHA2_2565;
2312 sadb_comb->sadb_comb_auth_minbits = 256;
2313 sadb_comb->sadb_comb_auth_maxbits = 256;
2314 } else if (!strncasecmp(ipsec_def_auth, "hmac-sha2-384",
2315 sizeof("hmac-sha2-384"))) {
2316 sadb_comb->sadb_comb_auth = SADB_X_AALG_SHA2_3846;
2317 sadb_comb->sadb_comb_auth_minbits = 384;
2318 sadb_comb->sadb_comb_auth_maxbits = 384;
2319 } else if (!strncasecmp(ipsec_def_auth, "hmac-sha2-512",
2320 sizeof("hmac-sha2-512"))) {
2321 sadb_comb->sadb_comb_auth = SADB_X_AALG_SHA2_5127;
2322 sadb_comb->sadb_comb_auth_minbits = 512;
2323 sadb_comb->sadb_comb_auth_maxbits = 512;
2324 }
2325
2326 sadb_comb->sadb_comb_soft_allocations = ipsec_soft_allocations;
2327 sadb_comb->sadb_comb_hard_allocations = ipsec_exp_allocations;
2328
2329 sadb_comb->sadb_comb_soft_bytes = ipsec_soft_bytes;
2330 sadb_comb->sadb_comb_hard_bytes = ipsec_exp_bytes;
2331
2332 sadb_comb->sadb_comb_soft_addtime = ipsec_soft_timeout;
2333 sadb_comb->sadb_comb_hard_addtime = ipsec_exp_timeout;
2334
2335 sadb_comb->sadb_comb_soft_usetime = ipsec_soft_first_use;
2336 sadb_comb->sadb_comb_hard_usetime = ipsec_exp_first_use;
2337#endif
2338 sadb_comb++;
2339 }
2340
2341 /* Send the ACQUIRE message to all compliant registered listeners. */
2342 if ((rval = pfkeyv2_sendmessage(headers,
2343 PFKEYV2_SENDMESSAGE_REGISTERED2, NULL((void *)0), smsg->sadb_msg_satype, 0,
2344 ipo->ipo_rdomain)) != 0)
2345 goto ret;
2346
2347 rval = 0;
2348ret:
2349 if (buffer != NULL((void *)0)) {
2350 explicit_bzero(buffer, i);
2351 free(buffer, M_PFKEY74, i);
2352 }
2353
2354 return (rval);
2355}
2356
2357/*
2358 * Notify key management that an expiration went off. The second argument
2359 * specifies the type of expiration (soft or hard).
2360 */
2361int
2362pfkeyv2_expire(struct tdb *tdb, u_int16_t type)
2363{
2364 void *p, *headers[SADB_EXT_MAX40+1], *buffer = NULL((void *)0);
2365 struct sadb_msg *smsg;
2366 int rval = 0;
2367 int i;
2368
2369 NET_ASSERT_LOCKED()do { int _s = rw_status(&netlock); if ((splassert_ctl >
0) && (_s != 0x0001UL && _s != 0x0002UL)) splassert_fail
(0x0002UL, _s, __func__); } while (0)
;
2370
2371 switch (tdb->tdb_sproto) {
2372 case IPPROTO_AH51:
2373 case IPPROTO_ESP50:
2374 case IPPROTO_IPIP4:
2375 case IPPROTO_IPCOMP108:
2376#ifdef TCP_SIGNATURE1
2377 case IPPROTO_TCP6:
2378#endif /* TCP_SIGNATURE */
2379 break;
2380
2381 default:
2382 rval = EOPNOTSUPP45;
2383 goto ret;
2384 }
2385
2386 i = sizeof(struct sadb_msg) + sizeof(struct sadb_sa) +
2387 2 * sizeof(struct sadb_lifetime) +
2388 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))
+
2389 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))
;
2390
2391 if (!(p = malloc(i, M_PFKEY74, M_NOWAIT0x0002 | M_ZERO0x0008))) {
2392 rval = ENOMEM12;
2393 goto ret;
2394 }
2395
2396 bzero(headers, sizeof(headers))__builtin_bzero((headers), (sizeof(headers)));
2397
2398 buffer = p;
2399
2400 headers[0] = p;
2401 p += sizeof(struct sadb_msg);
2402
2403 smsg = (struct sadb_msg *) headers[0];
2404 smsg->sadb_msg_version = PF_KEY_V22;
2405 smsg->sadb_msg_type = SADB_EXPIRE8;
2406 smsg->sadb_msg_satype = tdb->tdb_satype;
2407 smsg->sadb_msg_len = i / sizeof(uint64_t);
2408
2409 mtx_enter(&pfkeyv2_mtx);
2410 smsg->sadb_msg_seq = pfkeyv2_seq++;
2411 mtx_leave(&pfkeyv2_mtx);
2412
2413 headers[SADB_EXT_SA1] = p;
2414 export_sa(&p, tdb);
2415
2416 headers[SADB_EXT_LIFETIME_CURRENT2] = p;
2417 export_lifetime(&p, tdb, PFKEYV2_LIFETIME_CURRENT2);
2418
2419 headers[type] = p;
2420 export_lifetime(&p, tdb, type == SADB_EXT_LIFETIME_SOFT4 ?
2421 PFKEYV2_LIFETIME_SOFT1 : PFKEYV2_LIFETIME_HARD0);
2422
2423 headers[SADB_EXT_ADDRESS_SRC5] = p;
2424 export_address(&p, &tdb->tdb_src.sa);
2425
2426 headers[SADB_EXT_ADDRESS_DST6] = p;
2427 export_address(&p, &tdb->tdb_dst.sa);
2428
2429 if ((rval = pfkeyv2_sendmessage(headers, PFKEYV2_SENDMESSAGE_BROADCAST3,
2430 NULL((void *)0), 0, 0, tdb->tdb_rdomain)) != 0)
2431 goto ret;
2432 /* XXX */
2433 if (tdb->tdb_rdomain != tdb->tdb_rdomain_post)
2434 if ((rval = pfkeyv2_sendmessage(headers,
2435 PFKEYV2_SENDMESSAGE_BROADCAST3, NULL((void *)0), 0, 0,
2436 tdb->tdb_rdomain_post)) != 0)
2437 goto ret;
2438
2439 rval = 0;
2440
2441 ret:
2442 if (buffer != NULL((void *)0)) {
2443 explicit_bzero(buffer, i);
2444 free(buffer, M_PFKEY74, i);
2445 }
2446
2447 return (rval);
2448}
2449
2450struct pfkeyv2_sysctl_walk {
2451 void *w_where;
2452 size_t w_len;
2453 int w_op;
2454 u_int8_t w_satype;
2455};
2456
2457int
2458pfkeyv2_sysctl_walker(struct tdb *tdb, void *arg, int last)
2459{
2460 struct pfkeyv2_sysctl_walk *w = (struct pfkeyv2_sysctl_walk *)arg;
2461 void *buffer = NULL((void *)0);
2462 int error = 0;
2463 int usedlen, buflen, i;
2464
2465 if (w->w_satype != SADB_SATYPE_UNSPEC0 &&
2466 w->w_satype != tdb->tdb_satype)
2467 return (0);
2468
2469 if (w->w_where) {
2470 void *headers[SADB_EXT_MAX40+1];
2471 struct sadb_msg msg;
2472
2473 bzero(headers, sizeof(headers))__builtin_bzero((headers), (sizeof(headers)));
2474 if ((error = pfkeyv2_get(tdb, headers, &buffer, &buflen,
2475 &usedlen)) != 0)
2476 goto done;
2477 if (w->w_len < sizeof(msg) + usedlen) {
2478 error = ENOMEM12;
2479 goto done;
2480 }
2481 /* prepend header */
2482 bzero(&msg, sizeof(msg))__builtin_bzero((&msg), (sizeof(msg)));
2483 msg.sadb_msg_version = PF_KEY_V22;
2484 msg.sadb_msg_satype = tdb->tdb_satype;
2485 msg.sadb_msg_type = SADB_DUMP10;
2486 msg.sadb_msg_len = (sizeof(msg) + usedlen) / sizeof(uint64_t);
2487 if ((error = copyout(&msg, w->w_where, sizeof(msg))) != 0)
2488 goto done;
2489 w->w_where += sizeof(msg);
2490 w->w_len -= sizeof(msg);
2491 /* set extension type */
2492 for (i = 1; i <= SADB_EXT_MAX40; i++)
2493 if (headers[i])
2494 ((struct sadb_ext *)
2495 headers[i])->sadb_ext_type = i;
2496 if ((error = copyout(buffer, w->w_where, usedlen)) != 0)
2497 goto done;
2498 w->w_where += usedlen;
2499 w->w_len -= usedlen;
2500 } else {
2501 if ((error = pfkeyv2_get(tdb, NULL((void *)0), NULL((void *)0), &buflen, NULL((void *)0))) != 0)
2502 return (error);
2503 w->w_len += buflen;
2504 w->w_len += sizeof(struct sadb_msg);
2505 }
2506
2507done:
2508 if (buffer != NULL((void *)0)) {
2509 explicit_bzero(buffer, buflen);
2510 free(buffer, M_PFKEY74, buflen);
2511 }
2512 return (error);
2513}
2514
2515int
2516pfkeyv2_dump_policy(struct ipsec_policy *ipo, void **headers, void **buffer,
2517 int *lenp)
2518{
2519 int i, rval, perm;
2520 void *p;
2521
2522 /* Find how much space we need. */
2523 i = 2 * sizeof(struct sadb_protocol);
2524
2525 /* We'll need four of them: src, src mask, dst, dst mask. */
2526 switch (ipo->ipo_addr.sen_type) {
2527 case SENT_IP40x0001:
2528 i += 4 * PADUP(sizeof(struct sockaddr_in))(((sizeof(struct sockaddr_in)) + sizeof(uint64_t) - 1) & ~
(sizeof(uint64_t) - 1))
;
2529 i += 4 * sizeof(struct sadb_address);
2530 break;
2531#ifdef INET61
2532 case SENT_IP60x0002:
2533 i += 4 * PADUP(sizeof(struct sockaddr_in6))(((sizeof(struct sockaddr_in6)) + sizeof(uint64_t) - 1) &
~(sizeof(uint64_t) - 1))
;
2534 i += 4 * sizeof(struct sadb_address);
2535 break;
2536#endif /* INET6 */
2537 default:
2538 return (EINVAL22);
2539 }
2540
2541 /* Local address, might be zeroed. */
2542 switch (ipo->ipo_src.sa.sa_family) {
2543 case 0:
2544 break;
2545 case AF_INET2:
2546 i += PADUP(sizeof(struct sockaddr_in))(((sizeof(struct sockaddr_in)) + sizeof(uint64_t) - 1) & ~
(sizeof(uint64_t) - 1))
;
2547 i += sizeof(struct sadb_address);
2548 break;
2549#ifdef INET61
2550 case AF_INET624:
2551 i += PADUP(sizeof(struct sockaddr_in6))(((sizeof(struct sockaddr_in6)) + sizeof(uint64_t) - 1) &
~(sizeof(uint64_t) - 1))
;
2552 i += sizeof(struct sadb_address);
2553 break;
2554#endif /* INET6 */
2555 default:
2556 return (EINVAL22);
2557 }
2558
2559 /* Remote address, might be zeroed. XXX ??? */
2560 switch (ipo->ipo_dst.sa.sa_family) {
2561 case 0:
2562 break;
2563 case AF_INET2:
2564 i += PADUP(sizeof(struct sockaddr_in))(((sizeof(struct sockaddr_in)) + sizeof(uint64_t) - 1) & ~
(sizeof(uint64_t) - 1))
;
2565 i += sizeof(struct sadb_address);
2566 break;
2567#ifdef INET61
2568 case AF_INET624:
2569 i += PADUP(sizeof(struct sockaddr_in6))(((sizeof(struct sockaddr_in6)) + sizeof(uint64_t) - 1) &
~(sizeof(uint64_t) - 1))
;
2570 i += sizeof(struct sadb_address);
2571 break;
2572#endif /* INET6 */
2573 default:
2574 return (EINVAL22);
2575 }
2576
2577 if (ipo->ipo_ids) {
2578 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))
;
2579 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))
;
2580 }
2581
2582 if (lenp)
2583 *lenp = i;
2584
2585 if (buffer == NULL((void *)0)) {
2586 rval = 0;
2587 goto ret;
2588 }
2589
2590 if (!(p = malloc(i, M_PFKEY74, M_NOWAIT0x0002 | M_ZERO0x0008))) {
2591 rval = ENOMEM12;
2592 goto ret;
2593 } else
2594 *buffer = p;
2595
2596 /* Local address. */
2597 if (ipo->ipo_src.sa.sa_family) {
2598 headers[SADB_EXT_ADDRESS_SRC5] = p;
2599 export_address(&p, &ipo->ipo_src.sa);
2600 }
2601
2602 /* Remote address. */
2603 if (ipo->ipo_dst.sa.sa_family) {
2604 headers[SADB_EXT_ADDRESS_DST6] = p;
2605 export_address(&p, &ipo->ipo_dst.sa);
2606 }
2607
2608 /* Get actual flow. */
2609 export_flow(&p, ipo->ipo_type, &ipo->ipo_addr, &ipo->ipo_mask,
2610 headers);
2611
2612 /* Add ids only when we are root. */
2613 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
);
2614 if (perm == 0 && ipo->ipo_ids)
2615 export_identities(&p, ipo->ipo_ids, 0, headers);
2616
2617 rval = 0;
2618ret:
2619 return (rval);
2620}
2621
2622int
2623pfkeyv2_sysctl_policydumper(struct ipsec_policy *ipo, void *arg,
2624 unsigned int tableid)
2625{
2626 struct pfkeyv2_sysctl_walk *w = (struct pfkeyv2_sysctl_walk *)arg;
2627 void *buffer = NULL((void *)0);
2628 int i, buflen, error = 0;
2629
2630 if (w->w_where) {
2631 void *headers[SADB_EXT_MAX40 + 1];
2632 struct sadb_msg msg;
2633
2634 bzero(headers, sizeof(headers))__builtin_bzero((headers), (sizeof(headers)));
2635 if ((error = pfkeyv2_dump_policy(ipo, headers, &buffer,
2636 &buflen)) != 0)
2637 goto done;
2638 if (w->w_len < buflen) {
2639 error = ENOMEM12;
2640 goto done;
2641 }
2642 /* prepend header */
2643 bzero(&msg, sizeof(msg))__builtin_bzero((&msg), (sizeof(msg)));
2644 msg.sadb_msg_version = PF_KEY_V22;
2645 if (ipo->ipo_sproto == IPPROTO_ESP50)
2646 msg.sadb_msg_satype = SADB_SATYPE_ESP2;
2647 else if (ipo->ipo_sproto == IPPROTO_AH51)
2648 msg.sadb_msg_satype = SADB_SATYPE_AH1;
2649 else if (ipo->ipo_sproto == IPPROTO_IPCOMP108)
2650 msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP9;
2651 else if (ipo->ipo_sproto == IPPROTO_IPIP4)
2652 msg.sadb_msg_satype = SADB_X_SATYPE_IPIP7;
2653 msg.sadb_msg_type = SADB_X_SPDDUMP16;
2654 msg.sadb_msg_len = (sizeof(msg) + buflen) / sizeof(uint64_t);
2655 if ((error = copyout(&msg, w->w_where, sizeof(msg))) != 0)
2656 goto done;
2657 w->w_where += sizeof(msg);
2658 w->w_len -= sizeof(msg);
2659 /* set extension type */
2660 for (i = 1; i <= SADB_EXT_MAX40; i++)
2661 if (headers[i])
2662 ((struct sadb_ext *)
2663 headers[i])->sadb_ext_type = i;
2664 if ((error = copyout(buffer, w->w_where, buflen)) != 0)
2665 goto done;
2666 w->w_where += buflen;
2667 w->w_len -= buflen;
2668 } else {
2669 if ((error = pfkeyv2_dump_policy(ipo, NULL((void *)0), NULL((void *)0),
2670 &buflen)) != 0)
2671 goto done;
2672 w->w_len += buflen;
2673 w->w_len += sizeof(struct sadb_msg);
2674 }
2675
2676done:
2677 if (buffer)
2678 free(buffer, M_PFKEY74, buflen);
2679 return (error);
2680}
2681
2682int
2683pfkeyv2_policy_flush(struct ipsec_policy *ipo, void *arg, unsigned int tableid)
2684{
2685 int error;
2686
2687 error = ipsec_delete_policy(ipo);
2688 if (error == 0)
2689 error = EAGAIN35;
2690
2691 return (error);
2692}
2693
2694int
2695pfkeyv2_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
2696 void *new, size_t newlen)
2697{
2698 struct pfkeyv2_sysctl_walk w;
2699 int error = EINVAL22;
2700 u_int rdomain;
2701 u_int tableid;
2702
2703 if (new)
2704 return (EPERM1);
2705 if (namelen < 1)
2706 return (EINVAL22);
2707 w.w_op = name[0];
2708 w.w_satype = name[1];
2709 w.w_where = oldp;
2710 w.w_len = oldp ? *oldlenp : 0;
2711
2712 if (namelen == 3) {
2713 tableid = name[2];
2714 if (!rtable_exists(tableid))
2715 return (ENOENT2);
2716 } else
2717 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;
2718 rdomain = rtable_l2(tableid);
2719
2720 switch(w.w_op) {
2721 case NET_KEY_SADB_DUMP1:
2722 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)
2723 return (error);
2724 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2725 error = tdb_walk(rdomain, pfkeyv2_sysctl_walker, &w);
2726 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2727 if (oldp)
2728 *oldlenp = w.w_where - oldp;
2729 else
2730 *oldlenp = w.w_len;
2731 break;
2732
2733 case NET_KEY_SPD_DUMP2:
2734 NET_LOCK_SHARED()do { rw_enter_read(&netlock); } while (0);
2735 error = spd_table_walk(rdomain,
2736 pfkeyv2_sysctl_policydumper, &w);
2737 NET_UNLOCK_SHARED()do { rw_exit_read(&netlock); } while (0);
2738 if (oldp)
2739 *oldlenp = w.w_where - oldp;
2740 else
2741 *oldlenp = w.w_len;
2742 break;
2743 }
2744
2745 return (error);
2746}