Bug Summary

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