Bug Summary

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

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;
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,
Although the value stored to 'rn' is used in the enclosing expression, the value is never actually read from 'rn'
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}