Bug Summary

File:src/sbin/ipsecctl/pfkey.c
Warning:line 270, column 14
Result of 'calloc' is converted to a pointer of type 'struct sadb_ident', which is incompatible with sizeof operand type 'u_int8_t'

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 pfkey.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 pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sbin/ipsecctl/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sbin/ipsecctl -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/sbin/ipsecctl/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 -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/sbin/ipsecctl/pfkey.c
1/* $OpenBSD: pfkey.c,v 1.63 2021/10/22 12:30:54 bluhm Exp $ */
2/*
3 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
4 * Copyright (c) 2003, 2004 Markus Friedl <markus@openbsd.org>
5 * Copyright (c) 2004, 2005 Hans-Joerg Hoexer <hshoexer@openbsd.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <sys/types.h>
21#include <sys/queue.h>
22#include <sys/uio.h>
23#include <sys/socket.h>
24#include <netinet/in.h>
25#include <netinet/ip_ipsp.h>
26#include <net/pfkeyv2.h>
27
28#include <err.h>
29#include <errno(*__errno()).h>
30#include <stdio.h>
31#include <string.h>
32#include <stdlib.h>
33#include <poll.h>
34#include <unistd.h>
35
36#include "ipsecctl.h"
37#include "pfkey.h"
38
39#define ROUNDUP(x)(((x) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t) - 1
))
(((x) + (PFKEYV2_CHUNKsizeof(u_int64_t) - 1)) & ~(PFKEYV2_CHUNKsizeof(u_int64_t) - 1))
40#define IOV_CNT20 20
41
42static int fd;
43static u_int32_t sadb_msg_seq = 1;
44
45static int pfkey_flow(int, u_int8_t, u_int8_t, u_int8_t, u_int8_t,
46 struct ipsec_addr_wrap *, u_int16_t,
47 struct ipsec_addr_wrap *, u_int16_t,
48 struct ipsec_addr_wrap *, struct ipsec_addr_wrap *,
49 struct ipsec_auth *, u_int8_t);
50static int pfkey_sa(int, u_int8_t, u_int8_t, u_int32_t,
51 struct ipsec_addr_wrap *, struct ipsec_addr_wrap *,
52 u_int8_t, u_int16_t,
53 struct ipsec_transforms *, struct ipsec_key *,
54 struct ipsec_key *, u_int8_t);
55static int pfkey_sabundle(int, u_int8_t, u_int8_t, u_int8_t,
56 struct ipsec_addr_wrap *, u_int32_t,
57 struct ipsec_addr_wrap *, u_int32_t);
58static int pfkey_reply(int, u_int8_t **, ssize_t *);
59int pfkey_parse(struct sadb_msg *, struct ipsec_rule *);
60int pfkey_ipsec_flush(void);
61int pfkey_ipsec_establish(int, struct ipsec_rule *);
62int pfkey_init(void);
63
64static int
65pfkey_flow(int sd, u_int8_t satype, u_int8_t action, u_int8_t direction,
66 u_int8_t proto, struct ipsec_addr_wrap *src, u_int16_t sport,
67 struct ipsec_addr_wrap *dst, u_int16_t dport,
68 struct ipsec_addr_wrap *local, struct ipsec_addr_wrap *peer,
69 struct ipsec_auth *auth, u_int8_t flowtype)
70{
71 struct sadb_msg smsg;
72 struct sadb_address sa_src, sa_dst, sa_local, sa_peer, sa_smask,
73 sa_dmask;
74 struct sadb_protocol sa_flowtype, sa_protocol;
75 struct sadb_ident *sa_srcid, *sa_dstid;
76 struct sockaddr_storage ssrc, sdst, slocal, speer, smask, dmask;
77 struct iovec iov[IOV_CNT20];
78 ssize_t n;
79 int iov_cnt, len, ret = 0;
80
81 sa_srcid = sa_dstid = NULL((void *)0);
82
83 bzero(&ssrc, sizeof(ssrc));
84 bzero(&smask, sizeof(smask));
85 ssrc.ss_family = smask.ss_family = src->af;
86 switch (src->af) {
87 case AF_INET2:
88 ((struct sockaddr_in *)&ssrc)->sin_addr = src->address.v4ipa.v4;
89 ssrc.ss_len = sizeof(struct sockaddr_in);
90 ((struct sockaddr_in *)&smask)->sin_addr = src->mask.v4ipa.v4;
91 if (sport) {
92 ((struct sockaddr_in *)&ssrc)->sin_port = sport;
93 ((struct sockaddr_in *)&smask)->sin_port = 0xffff;
94 }
95 break;
96 case AF_INET624:
97 ((struct sockaddr_in6 *)&ssrc)->sin6_addr = src->address.v6ipa.v6;
98 ssrc.ss_len = sizeof(struct sockaddr_in6);
99 ((struct sockaddr_in6 *)&smask)->sin6_addr = src->mask.v6ipa.v6;
100 if (sport) {
101 ((struct sockaddr_in6 *)&ssrc)->sin6_port = sport;
102 ((struct sockaddr_in6 *)&smask)->sin6_port = 0xffff;
103 }
104 break;
105 default:
106 warnx("unsupported address family %d", src->af);
107 return -1;
108 }
109 smask.ss_len = ssrc.ss_len;
110
111 bzero(&sdst, sizeof(sdst));
112 bzero(&dmask, sizeof(dmask));
113 sdst.ss_family = dmask.ss_family = dst->af;
114 switch (dst->af) {
115 case AF_INET2:
116 ((struct sockaddr_in *)&sdst)->sin_addr = dst->address.v4ipa.v4;
117 sdst.ss_len = sizeof(struct sockaddr_in);
118 ((struct sockaddr_in *)&dmask)->sin_addr = dst->mask.v4ipa.v4;
119 if (dport) {
120 ((struct sockaddr_in *)&sdst)->sin_port = dport;
121 ((struct sockaddr_in *)&dmask)->sin_port = 0xffff;
122 }
123 break;
124 case AF_INET624:
125 ((struct sockaddr_in6 *)&sdst)->sin6_addr = dst->address.v6ipa.v6;
126 sdst.ss_len = sizeof(struct sockaddr_in6);
127 ((struct sockaddr_in6 *)&dmask)->sin6_addr = dst->mask.v6ipa.v6;
128 if (dport) {
129 ((struct sockaddr_in6 *)&sdst)->sin6_port = dport;
130 ((struct sockaddr_in6 *)&dmask)->sin6_port = 0xffff;
131 }
132 break;
133 default:
134 warnx("unsupported address family %d", dst->af);
135 return -1;
136 }
137 dmask.ss_len = sdst.ss_len;
138
139 bzero(&slocal, sizeof(slocal));
140 if (local) {
141 slocal.ss_family = local->af;
142 switch (local->af) {
143 case AF_INET2:
144 ((struct sockaddr_in *)&slocal)->sin_addr =
145 local->address.v4ipa.v4;
146 slocal.ss_len = sizeof(struct sockaddr_in);
147 break;
148 case AF_INET624:
149 ((struct sockaddr_in6 *)&slocal)->sin6_addr =
150 local->address.v6ipa.v6;
151 slocal.ss_len = sizeof(struct sockaddr_in6);
152 break;
153 default:
154 warnx("unsupported address family %d", local->af);
155 return -1;
156 }
157 }
158
159 bzero(&speer, sizeof(speer));
160 if (peer) {
161 speer.ss_family = peer->af;
162 switch (peer->af) {
163 case AF_INET2:
164 ((struct sockaddr_in *)&speer)->sin_addr =
165 peer->address.v4ipa.v4;
166 speer.ss_len = sizeof(struct sockaddr_in);
167 break;
168 case AF_INET624:
169 ((struct sockaddr_in6 *)&speer)->sin6_addr =
170 peer->address.v6ipa.v6;
171 speer.ss_len = sizeof(struct sockaddr_in6);
172 break;
173 default:
174 warnx("unsupported address family %d", peer->af);
175 return -1;
176 }
177 }
178
179 bzero(&smsg, sizeof(smsg));
180 smsg.sadb_msg_version = PF_KEY_V22;
181 smsg.sadb_msg_seq = sadb_msg_seq++;
182 smsg.sadb_msg_pid = getpid();
183 smsg.sadb_msg_len = sizeof(smsg) / 8;
184 smsg.sadb_msg_type = action;
185 smsg.sadb_msg_satype = satype;
186
187 bzero(&sa_flowtype, sizeof(sa_flowtype));
188 sa_flowtype.sadb_protocol_exttype = SADB_X_EXT_FLOW_TYPE20;
189 sa_flowtype.sadb_protocol_len = sizeof(sa_flowtype) / 8;
190 sa_flowtype.sadb_protocol_direction = direction;
191
192 switch (flowtype) {
193 case TYPE_USE:
194 sa_flowtype.sadb_protocol_proto = SADB_X_FLOW_TYPE_USE1;
195 break;
196 case TYPE_ACQUIRE:
197 sa_flowtype.sadb_protocol_proto = SADB_X_FLOW_TYPE_ACQUIRE2;
198 break;
199 case TYPE_REQUIRE:
200 sa_flowtype.sadb_protocol_proto = SADB_X_FLOW_TYPE_REQUIRE3;
201 break;
202 case TYPE_DENY:
203 sa_flowtype.sadb_protocol_proto = SADB_X_FLOW_TYPE_DENY5;
204 break;
205 case TYPE_BYPASS:
206 sa_flowtype.sadb_protocol_proto = SADB_X_FLOW_TYPE_BYPASS4;
207 break;
208 case TYPE_DONTACQ:
209 sa_flowtype.sadb_protocol_proto = SADB_X_FLOW_TYPE_DONTACQ6;
210 break;
211 default:
212 warnx("unsupported flowtype %d", flowtype);
213 return -1;
214 }
215
216 bzero(&sa_protocol, sizeof(sa_protocol));
217 sa_protocol.sadb_protocol_exttype = SADB_X_EXT_PROTOCOL19;
218 sa_protocol.sadb_protocol_len = sizeof(sa_protocol) / 8;
219 sa_protocol.sadb_protocol_direction = 0;
220 sa_protocol.sadb_protocol_proto = proto;
221
222 bzero(&sa_src, sizeof(sa_src));
223 sa_src.sadb_address_exttype = SADB_X_EXT_SRC_FLOW21;
224 sa_src.sadb_address_len = (sizeof(sa_src) + ROUNDUP(ssrc.ss_len)(((ssrc.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
) / 8;
225
226 bzero(&sa_smask, sizeof(sa_smask));
227 sa_smask.sadb_address_exttype = SADB_X_EXT_SRC_MASK17;
228 sa_smask.sadb_address_len =
229 (sizeof(sa_smask) + ROUNDUP(smask.ss_len)(((smask.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
) / 8;
230
231 bzero(&sa_dst, sizeof(sa_dst));
232 sa_dst.sadb_address_exttype = SADB_X_EXT_DST_FLOW22;
233 sa_dst.sadb_address_len = (sizeof(sa_dst) + ROUNDUP(sdst.ss_len)(((sdst.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
) / 8;
234
235 bzero(&sa_dmask, sizeof(sa_dmask));
236 sa_dmask.sadb_address_exttype = SADB_X_EXT_DST_MASK18;
237 sa_dmask.sadb_address_len =
238 (sizeof(sa_dmask) + ROUNDUP(dmask.ss_len)(((dmask.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
) / 8;
239
240 if (local) {
241 bzero(&sa_local, sizeof(sa_local));
242 sa_local.sadb_address_exttype = SADB_EXT_ADDRESS_SRC5;
243 sa_local.sadb_address_len =
244 (sizeof(sa_local) + ROUNDUP(slocal.ss_len)(((slocal.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
) / 8;
245 }
246 if (peer) {
247 bzero(&sa_peer, sizeof(sa_peer));
248 sa_peer.sadb_address_exttype = SADB_EXT_ADDRESS_DST6;
249 sa_peer.sadb_address_len =
250 (sizeof(sa_peer) + ROUNDUP(speer.ss_len)(((speer.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
) / 8;
251 }
252
253 if (auth && auth->srcid) {
254 len = ROUNDUP(strlen(auth->srcid) + 1)(((strlen(auth->srcid) + 1) + (sizeof(u_int64_t) - 1)) &
~(sizeof(u_int64_t) - 1))
+ sizeof(*sa_srcid);
255
256 sa_srcid = calloc(len, sizeof(u_int8_t));
257 if (sa_srcid == NULL((void *)0))
258 err(1, "pfkey_flow: calloc");
259
260 sa_srcid->sadb_ident_type = auth->srcid_type;
261 sa_srcid->sadb_ident_len = len / 8;
262 sa_srcid->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC10;
263
264 strlcpy((char *)(sa_srcid + 1), auth->srcid,
265 ROUNDUP(strlen(auth->srcid) + 1)(((strlen(auth->srcid) + 1) + (sizeof(u_int64_t) - 1)) &
~(sizeof(u_int64_t) - 1))
);
266 }
267 if (auth && auth->dstid) {
268 len = ROUNDUP(strlen(auth->dstid) + 1)(((strlen(auth->dstid) + 1) + (sizeof(u_int64_t) - 1)) &
~(sizeof(u_int64_t) - 1))
+ sizeof(*sa_dstid);
269
270 sa_dstid = calloc(len, sizeof(u_int8_t));
Result of 'calloc' is converted to a pointer of type 'struct sadb_ident', which is incompatible with sizeof operand type 'u_int8_t'
271 if (sa_dstid == NULL((void *)0))
272 err(1, "pfkey_flow: calloc");
273
274 sa_dstid->sadb_ident_type = auth->dstid_type;
275 sa_dstid->sadb_ident_len = len / 8;
276 sa_dstid->sadb_ident_exttype = SADB_EXT_IDENTITY_DST11;
277
278 strlcpy((char *)(sa_dstid + 1), auth->dstid,
279 ROUNDUP(strlen(auth->dstid) + 1)(((strlen(auth->dstid) + 1) + (sizeof(u_int64_t) - 1)) &
~(sizeof(u_int64_t) - 1))
);
280 }
281
282 iov_cnt = 0;
283
284 /* header */
285 iov[iov_cnt].iov_base = &smsg;
286 iov[iov_cnt].iov_len = sizeof(smsg);
287 iov_cnt++;
288
289 /* add flow type */
290 iov[iov_cnt].iov_base = &sa_flowtype;
291 iov[iov_cnt].iov_len = sizeof(sa_flowtype);
292 smsg.sadb_msg_len += sa_flowtype.sadb_protocol_len;
293 iov_cnt++;
294
295 /* local ip */
296 if (local) {
297 iov[iov_cnt].iov_base = &sa_local;
298 iov[iov_cnt].iov_len = sizeof(sa_local);
299 iov_cnt++;
300 iov[iov_cnt].iov_base = &slocal;
301 iov[iov_cnt].iov_len = ROUNDUP(slocal.ss_len)(((slocal.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
;
302 smsg.sadb_msg_len += sa_local.sadb_address_len;
303 iov_cnt++;
304 }
305
306 /* remote peer */
307 if (peer) {
308 iov[iov_cnt].iov_base = &sa_peer;
309 iov[iov_cnt].iov_len = sizeof(sa_peer);
310 iov_cnt++;
311 iov[iov_cnt].iov_base = &speer;
312 iov[iov_cnt].iov_len = ROUNDUP(speer.ss_len)(((speer.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
;
313 smsg.sadb_msg_len += sa_peer.sadb_address_len;
314 iov_cnt++;
315 }
316
317 /* src addr */
318 iov[iov_cnt].iov_base = &sa_src;
319 iov[iov_cnt].iov_len = sizeof(sa_src);
320 iov_cnt++;
321 iov[iov_cnt].iov_base = &ssrc;
322 iov[iov_cnt].iov_len = ROUNDUP(ssrc.ss_len)(((ssrc.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
;
323 smsg.sadb_msg_len += sa_src.sadb_address_len;
324 iov_cnt++;
325
326 /* src mask */
327 iov[iov_cnt].iov_base = &sa_smask;
328 iov[iov_cnt].iov_len = sizeof(sa_smask);
329 iov_cnt++;
330 iov[iov_cnt].iov_base = &smask;
331 iov[iov_cnt].iov_len = ROUNDUP(smask.ss_len)(((smask.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
;
332 smsg.sadb_msg_len += sa_smask.sadb_address_len;
333 iov_cnt++;
334
335 /* dest addr */
336 iov[iov_cnt].iov_base = &sa_dst;
337 iov[iov_cnt].iov_len = sizeof(sa_dst);
338 iov_cnt++;
339 iov[iov_cnt].iov_base = &sdst;
340 iov[iov_cnt].iov_len = ROUNDUP(sdst.ss_len)(((sdst.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
;
341 smsg.sadb_msg_len += sa_dst.sadb_address_len;
342 iov_cnt++;
343
344 /* dst mask */
345 iov[iov_cnt].iov_base = &sa_dmask;
346 iov[iov_cnt].iov_len = sizeof(sa_dmask);
347 iov_cnt++;
348 iov[iov_cnt].iov_base = &dmask;
349 iov[iov_cnt].iov_len = ROUNDUP(dmask.ss_len)(((dmask.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
;
350 smsg.sadb_msg_len += sa_dmask.sadb_address_len;
351 iov_cnt++;
352
353 /* add protocol */
354 iov[iov_cnt].iov_base = &sa_protocol;
355 iov[iov_cnt].iov_len = sizeof(sa_protocol);
356 smsg.sadb_msg_len += sa_protocol.sadb_protocol_len;
357 iov_cnt++;
358
359 if (sa_srcid) {
360 /* src identity */
361 iov[iov_cnt].iov_base = sa_srcid;
362 iov[iov_cnt].iov_len = sa_srcid->sadb_ident_len * 8;
363 smsg.sadb_msg_len += sa_srcid->sadb_ident_len;
364 iov_cnt++;
365 }
366 if (sa_dstid) {
367 /* dst identity */
368 iov[iov_cnt].iov_base = sa_dstid;
369 iov[iov_cnt].iov_len = sa_dstid->sadb_ident_len * 8;
370 smsg.sadb_msg_len += sa_dstid->sadb_ident_len;
371 iov_cnt++;
372 }
373 len = smsg.sadb_msg_len * 8;
374
375 do {
376 n = writev(sd, iov, iov_cnt);
377 } while (n == -1 && (errno(*__errno()) == EAGAIN35 || errno(*__errno()) == EINTR4));
378 if (n == -1) {
379 warn("writev failed");
380 ret = -1;
381 }
382
383 free(sa_srcid);
384 free(sa_dstid);
385
386 return ret;
387}
388
389static int
390pfkey_sa(int sd, u_int8_t satype, u_int8_t action, u_int32_t spi,
391 struct ipsec_addr_wrap *src, struct ipsec_addr_wrap *dst,
392 u_int8_t encap, u_int16_t dport,
393 struct ipsec_transforms *xfs, struct ipsec_key *authkey,
394 struct ipsec_key *enckey, u_int8_t tmode)
395{
396 struct sadb_msg smsg;
397 struct sadb_sa sa;
398 struct sadb_address sa_src, sa_dst;
399 struct sadb_key sa_authkey, sa_enckey;
400 struct sadb_x_udpencap udpencap;
401 struct sockaddr_storage ssrc, sdst;
402 struct iovec iov[IOV_CNT20];
403 ssize_t n;
404 int iov_cnt, len, ret = 0;
405
406 bzero(&ssrc, sizeof(ssrc));
407 ssrc.ss_family = src->af;
408 switch (src->af) {
409 case AF_INET2:
410 ((struct sockaddr_in *)&ssrc)->sin_addr = src->address.v4ipa.v4;
411 ssrc.ss_len = sizeof(struct sockaddr_in);
412 break;
413 case AF_INET624:
414 ((struct sockaddr_in6 *)&ssrc)->sin6_addr = src->address.v6ipa.v6;
415 ssrc.ss_len = sizeof(struct sockaddr_in6);
416 break;
417 default:
418 warnx("unsupported address family %d", src->af);
419 return -1;
420 }
421
422 bzero(&sdst, sizeof(sdst));
423 sdst.ss_family = dst->af;
424 switch (dst->af) {
425 case AF_INET2:
426 ((struct sockaddr_in *)&sdst)->sin_addr = dst->address.v4ipa.v4;
427 sdst.ss_len = sizeof(struct sockaddr_in);
428 break;
429 case AF_INET624:
430 ((struct sockaddr_in6 *)&sdst)->sin6_addr = dst->address.v6ipa.v6;
431 sdst.ss_len = sizeof(struct sockaddr_in6);
432 break;
433 default:
434 warnx("unsupported address family %d", dst->af);
435 return -1;
436 }
437
438 bzero(&smsg, sizeof(smsg));
439 smsg.sadb_msg_version = PF_KEY_V22;
440 smsg.sadb_msg_seq = sadb_msg_seq++;
441 smsg.sadb_msg_pid = getpid();
442 smsg.sadb_msg_len = sizeof(smsg) / 8;
443 smsg.sadb_msg_type = action;
444 smsg.sadb_msg_satype = satype;
445
446 bzero(&sa, sizeof(sa));
447 sa.sadb_sa_len = sizeof(sa) / 8;
448 sa.sadb_sa_exttype = SADB_EXT_SA1;
449 sa.sadb_sa_spi = htonl(spi)(__uint32_t)(__builtin_constant_p(spi) ? (__uint32_t)(((__uint32_t
)(spi) & 0xff) << 24 | ((__uint32_t)(spi) & 0xff00
) << 8 | ((__uint32_t)(spi) & 0xff0000) >> 8 |
((__uint32_t)(spi) & 0xff000000) >> 24) : __swap32md
(spi))
;
450 sa.sadb_sa_state = SADB_SASTATE_MATURE1;
451
452 if (satype != SADB_X_SATYPE_IPIP7 && tmode == IPSEC_TUNNEL)
453 sa.sadb_sa_flags |= SADB_X_SAFLAGS_TUNNEL0x004;
454
455 if (xfs && xfs->authxf) {
456 switch (xfs->authxf->id) {
457 case AUTHXF_NONE:
458 break;
459 case AUTHXF_HMAC_MD5:
460 sa.sadb_sa_auth = SADB_AALG_MD5HMAC2;
461 break;
462 case AUTHXF_HMAC_RIPEMD160:
463 sa.sadb_sa_auth = SADB_X_AALG_RIPEMD160HMAC8;
464 break;
465 case AUTHXF_HMAC_SHA1:
466 sa.sadb_sa_auth = SADB_AALG_SHA1HMAC3;
467 break;
468 case AUTHXF_HMAC_SHA2_256:
469 sa.sadb_sa_auth = SADB_X_AALG_SHA2_2565;
470 break;
471 case AUTHXF_HMAC_SHA2_384:
472 sa.sadb_sa_auth = SADB_X_AALG_SHA2_3846;
473 break;
474 case AUTHXF_HMAC_SHA2_512:
475 sa.sadb_sa_auth = SADB_X_AALG_SHA2_5127;
476 break;
477 default:
478 warnx("unsupported authentication algorithm %d",
479 xfs->authxf->id);
480 }
481 }
482 if (xfs && xfs->encxf) {
483 switch (xfs->encxf->id) {
484 case ENCXF_NONE:
485 break;
486 case ENCXF_3DES_CBC:
487 sa.sadb_sa_encrypt = SADB_EALG_3DESCBC3;
488 break;
489 case ENCXF_AES:
490 case ENCXF_AES_128:
491 case ENCXF_AES_192:
492 case ENCXF_AES_256:
493 sa.sadb_sa_encrypt = SADB_X_EALG_AES12;
494 break;
495 case ENCXF_AESCTR:
496 case ENCXF_AES_128_CTR:
497 case ENCXF_AES_192_CTR:
498 case ENCXF_AES_256_CTR:
499 sa.sadb_sa_encrypt = SADB_X_EALG_AESCTR13;
500 break;
501 case ENCXF_AES_128_GCM:
502 case ENCXF_AES_192_GCM:
503 case ENCXF_AES_256_GCM:
504 sa.sadb_sa_encrypt = SADB_X_EALG_AESGCM1620;
505 break;
506 case ENCXF_AES_128_GMAC:
507 case ENCXF_AES_192_GMAC:
508 case ENCXF_AES_256_GMAC:
509 sa.sadb_sa_encrypt = SADB_X_EALG_AESGMAC21;
510 break;
511 case ENCXF_BLOWFISH:
512 sa.sadb_sa_encrypt = SADB_X_EALG_BLF7;
513 break;
514 case ENCXF_CAST128:
515 sa.sadb_sa_encrypt = SADB_X_EALG_CAST6;
516 break;
517 case ENCXF_NULL:
518 sa.sadb_sa_encrypt = SADB_EALG_NULL11;
519 break;
520 default:
521 warnx("unsupported encryption algorithm %d",
522 xfs->encxf->id);
523 }
524 }
525 if (xfs && xfs->compxf) {
526 switch (xfs->compxf->id) {
527 case COMPXF_DEFLATE:
528 sa.sadb_sa_encrypt = SADB_X_CALG_DEFLATE2;
529 break;
530 default:
531 warnx("unsupported compression algorithm %d",
532 xfs->compxf->id);
533 }
534 }
535
536 bzero(&sa_src, sizeof(sa_src));
537 sa_src.sadb_address_len = (sizeof(sa_src) + ROUNDUP(ssrc.ss_len)(((ssrc.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
) / 8;
538 sa_src.sadb_address_exttype = SADB_EXT_ADDRESS_SRC5;
539
540 bzero(&sa_dst, sizeof(sa_dst));
541 sa_dst.sadb_address_len = (sizeof(sa_dst) + ROUNDUP(sdst.ss_len)(((sdst.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
) / 8;
542 sa_dst.sadb_address_exttype = SADB_EXT_ADDRESS_DST6;
543
544 if (encap) {
545 sa.sadb_sa_flags |= SADB_X_SAFLAGS_UDPENCAP0x200;
546 udpencap.sadb_x_udpencap_exttype = SADB_X_EXT_UDPENCAP31;
547 udpencap.sadb_x_udpencap_len = sizeof(udpencap) / 8;
548 udpencap.sadb_x_udpencap_port = htons(dport)(__uint16_t)(__builtin_constant_p(dport) ? (__uint16_t)(((__uint16_t
)(dport) & 0xffU) << 8 | ((__uint16_t)(dport) &
0xff00U) >> 8) : __swap16md(dport))
;
549 }
550 if (action == SADB_ADD3 && !authkey && !enckey && satype !=
551 SADB_X_SATYPE_IPCOMP9 && satype != SADB_X_SATYPE_IPIP7) { /* XXX ENCNULL */
552 warnx("no key specified");
553 return -1;
554 }
555 if (authkey) {
556 bzero(&sa_authkey, sizeof(sa_authkey));
557 sa_authkey.sadb_key_len = (sizeof(sa_authkey) +
558 ((authkey->len + 7) / 8) * 8) / 8;
559 sa_authkey.sadb_key_exttype = SADB_EXT_KEY_AUTH8;
560 sa_authkey.sadb_key_bits = 8 * authkey->len;
561 }
562 if (enckey) {
563 bzero(&sa_enckey, sizeof(sa_enckey));
564 sa_enckey.sadb_key_len = (sizeof(sa_enckey) +
565 ((enckey->len + 7) / 8) * 8) / 8;
566 sa_enckey.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT9;
567 sa_enckey.sadb_key_bits = 8 * enckey->len;
568 }
569
570 iov_cnt = 0;
571
572 /* header */
573 iov[iov_cnt].iov_base = &smsg;
574 iov[iov_cnt].iov_len = sizeof(smsg);
575 iov_cnt++;
576
577 /* sa */
578 iov[iov_cnt].iov_base = &sa;
579 iov[iov_cnt].iov_len = sizeof(sa);
580 smsg.sadb_msg_len += sa.sadb_sa_len;
581 iov_cnt++;
582
583 /* src addr */
584 iov[iov_cnt].iov_base = &sa_src;
585 iov[iov_cnt].iov_len = sizeof(sa_src);
586 iov_cnt++;
587 iov[iov_cnt].iov_base = &ssrc;
588 iov[iov_cnt].iov_len = ROUNDUP(ssrc.ss_len)(((ssrc.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
;
589 smsg.sadb_msg_len += sa_src.sadb_address_len;
590 iov_cnt++;
591
592 /* dst addr */
593 iov[iov_cnt].iov_base = &sa_dst;
594 iov[iov_cnt].iov_len = sizeof(sa_dst);
595 iov_cnt++;
596 iov[iov_cnt].iov_base = &sdst;
597 iov[iov_cnt].iov_len = ROUNDUP(sdst.ss_len)(((sdst.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
;
598 smsg.sadb_msg_len += sa_dst.sadb_address_len;
599 iov_cnt++;
600
601 if (encap) {
602 iov[iov_cnt].iov_base = &udpencap;
603 iov[iov_cnt].iov_len = sizeof(udpencap);
604 smsg.sadb_msg_len += udpencap.sadb_x_udpencap_len;
605 iov_cnt++;
606 }
607 if (authkey) {
608 /* authentication key */
609 iov[iov_cnt].iov_base = &sa_authkey;
610 iov[iov_cnt].iov_len = sizeof(sa_authkey);
611 iov_cnt++;
612 iov[iov_cnt].iov_base = authkey->data;
613 iov[iov_cnt].iov_len = ((authkey->len + 7) / 8) * 8;
614 smsg.sadb_msg_len += sa_authkey.sadb_key_len;
615 iov_cnt++;
616 }
617 if (enckey) {
618 /* encryption key */
619 iov[iov_cnt].iov_base = &sa_enckey;
620 iov[iov_cnt].iov_len = sizeof(sa_enckey);
621 iov_cnt++;
622 iov[iov_cnt].iov_base = enckey->data;
623 iov[iov_cnt].iov_len = ((enckey->len + 7) / 8) * 8;
624 smsg.sadb_msg_len += sa_enckey.sadb_key_len;
625 iov_cnt++;
626 }
627
628 len = smsg.sadb_msg_len * 8;
629 if ((n = writev(sd, iov, iov_cnt)) == -1) {
630 warn("writev failed");
631 ret = -1;
632 } else if (n != len) {
633 warnx("short write");
634 ret = -1;
635 }
636
637 return ret;
638}
639
640static int
641pfkey_sabundle(int sd, u_int8_t satype, u_int8_t satype2, u_int8_t action,
642 struct ipsec_addr_wrap *dst, u_int32_t spi, struct ipsec_addr_wrap *dst2,
643 u_int32_t spi2)
644{
645 struct sadb_msg smsg;
646 struct sadb_sa sa1, sa2;
647 struct sadb_address sa_dst, sa_dst2;
648 struct sockaddr_storage sdst, sdst2;
649 struct sadb_protocol sa_proto;
650 struct iovec iov[IOV_CNT20];
651 ssize_t n;
652 int iov_cnt, len, ret = 0;
653
654 bzero(&sdst, sizeof(sdst));
655 sdst.ss_family = dst->af;
656 switch (dst->af) {
657 case AF_INET2:
658 ((struct sockaddr_in *)&sdst)->sin_addr = dst->address.v4ipa.v4;
659 sdst.ss_len = sizeof(struct sockaddr_in);
660 break;
661 case AF_INET624:
662 ((struct sockaddr_in6 *)&sdst)->sin6_addr = dst->address.v6ipa.v6;
663 sdst.ss_len = sizeof(struct sockaddr_in6);
664 break;
665 default:
666 warnx("unsupported address family %d", dst->af);
667 return -1;
668 }
669
670 bzero(&sdst2, sizeof(sdst2));
671 sdst2.ss_family = dst2->af;
672 switch (dst2->af) {
673 case AF_INET2:
674 ((struct sockaddr_in *)&sdst2)->sin_addr = dst2->address.v4ipa.v4;
675 sdst2.ss_len = sizeof(struct sockaddr_in);
676 break;
677 case AF_INET624:
678 ((struct sockaddr_in6 *)&sdst2)->sin6_addr = dst2->address.v6ipa.v6;
679 sdst2.ss_len = sizeof(struct sockaddr_in6);
680 break;
681 default:
682 warnx("unsupported address family %d", dst2->af);
683 return -1;
684 }
685
686 bzero(&smsg, sizeof(smsg));
687 smsg.sadb_msg_version = PF_KEY_V22;
688 smsg.sadb_msg_seq = sadb_msg_seq++;
689 smsg.sadb_msg_pid = getpid();
690 smsg.sadb_msg_len = sizeof(smsg) / 8;
691 smsg.sadb_msg_type = action;
692 smsg.sadb_msg_satype = satype;
693
694 bzero(&sa1, sizeof(sa1));
695 sa1.sadb_sa_len = sizeof(sa1) / 8;
696 sa1.sadb_sa_exttype = SADB_EXT_SA1;
697 sa1.sadb_sa_spi = htonl(spi)(__uint32_t)(__builtin_constant_p(spi) ? (__uint32_t)(((__uint32_t
)(spi) & 0xff) << 24 | ((__uint32_t)(spi) & 0xff00
) << 8 | ((__uint32_t)(spi) & 0xff0000) >> 8 |
((__uint32_t)(spi) & 0xff000000) >> 24) : __swap32md
(spi))
;
698 sa1.sadb_sa_state = SADB_SASTATE_MATURE1;
699
700 bzero(&sa2, sizeof(sa2));
701 sa2.sadb_sa_len = sizeof(sa2) / 8;
702 sa2.sadb_sa_exttype = SADB_X_EXT_SA223;
703 sa2.sadb_sa_spi = htonl(spi2)(__uint32_t)(__builtin_constant_p(spi2) ? (__uint32_t)(((__uint32_t
)(spi2) & 0xff) << 24 | ((__uint32_t)(spi2) & 0xff00
) << 8 | ((__uint32_t)(spi2) & 0xff0000) >> 8
| ((__uint32_t)(spi2) & 0xff000000) >> 24) : __swap32md
(spi2))
;
704 sa2.sadb_sa_state = SADB_SASTATE_MATURE1;
705 iov_cnt = 0;
706
707 bzero(&sa_dst, sizeof(sa_dst));
708 sa_dst.sadb_address_exttype = SADB_EXT_ADDRESS_DST6;
709 sa_dst.sadb_address_len = (sizeof(sa_dst) + ROUNDUP(sdst.ss_len)(((sdst.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
) / 8;
710
711 bzero(&sa_dst2, sizeof(sa_dst2));
712 sa_dst2.sadb_address_exttype = SADB_X_EXT_DST224;
713 sa_dst2.sadb_address_len = (sizeof(sa_dst2) + ROUNDUP(sdst2.ss_len)(((sdst2.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
) / 8;
714
715 bzero(&sa_proto, sizeof(sa_proto));
716 sa_proto.sadb_protocol_exttype = SADB_X_EXT_SATYPE235;
717 sa_proto.sadb_protocol_len = sizeof(sa_proto) / 8;
718 sa_proto.sadb_protocol_direction = 0;
719 sa_proto.sadb_protocol_proto = satype2;
720
721 /* header */
722 iov[iov_cnt].iov_base = &smsg;
723 iov[iov_cnt].iov_len = sizeof(smsg);
724 iov_cnt++;
725
726 /* sa */
727 iov[iov_cnt].iov_base = &sa1;
728 iov[iov_cnt].iov_len = sizeof(sa1);
729 smsg.sadb_msg_len += sa1.sadb_sa_len;
730 iov_cnt++;
731
732 /* dst addr */
733 iov[iov_cnt].iov_base = &sa_dst;
734 iov[iov_cnt].iov_len = sizeof(sa_dst);
735 iov_cnt++;
736 iov[iov_cnt].iov_base = &sdst;
737 iov[iov_cnt].iov_len = ROUNDUP(sdst.ss_len)(((sdst.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
;
738 smsg.sadb_msg_len += sa_dst.sadb_address_len;
739 iov_cnt++;
740
741 /* second sa */
742 iov[iov_cnt].iov_base = &sa2;
743 iov[iov_cnt].iov_len = sizeof(sa2);
744 smsg.sadb_msg_len += sa2.sadb_sa_len;
745 iov_cnt++;
746
747 /* second dst addr */
748 iov[iov_cnt].iov_base = &sa_dst2;
749 iov[iov_cnt].iov_len = sizeof(sa_dst2);
750 iov_cnt++;
751 iov[iov_cnt].iov_base = &sdst2;
752 iov[iov_cnt].iov_len = ROUNDUP(sdst2.ss_len)(((sdst2.ss_len) + (sizeof(u_int64_t) - 1)) & ~(sizeof(u_int64_t
) - 1))
;
753 smsg.sadb_msg_len += sa_dst2.sadb_address_len;
754 iov_cnt++;
755
756 /* SA type */
757 iov[iov_cnt].iov_base = &sa_proto;
758 iov[iov_cnt].iov_len = sizeof(sa_proto);
759 smsg.sadb_msg_len += sa_proto.sadb_protocol_len;
760 iov_cnt++;
761
762 len = smsg.sadb_msg_len * 8;
763 if ((n = writev(sd, iov, iov_cnt)) == -1) {
764 warn("writev failed");
765 ret = -1;
766 } else if (n != len) {
767 warnx("short write");
768 ret = -1;
769 }
770
771 return (ret);
772}
773
774static int
775pfkey_reply(int sd, u_int8_t **datap, ssize_t *lenp)
776{
777 struct sadb_msg hdr;
778 ssize_t len;
779 u_int8_t *data;
780
781 if (recv(sd, &hdr, sizeof(hdr), MSG_PEEK0x2) != sizeof(hdr)) {
782 warnx("short read");
783 return -1;
784 }
785 len = hdr.sadb_msg_len * PFKEYV2_CHUNKsizeof(u_int64_t);
786 if ((data = malloc(len)) == NULL((void *)0))
787 err(1, "pfkey_reply: malloc");
788 if (read(sd, data, len) != len) {
789 warn("PF_KEY short read");
790 freezero(data, len);
791 return -1;
792 }
793 if (datap) {
794 *datap = data;
795 if (lenp)
796 *lenp = len;
797 } else {
798 freezero(data, len);
799 }
800 if (datap == NULL((void *)0) && hdr.sadb_msg_errno != 0) {
801 errno(*__errno()) = hdr.sadb_msg_errno;
802 if (errno(*__errno()) != EEXIST17) {
803 warn("PF_KEY failed");
804 return -1;
805 }
806 }
807 return 0;
808}
809
810int
811pfkey_parse(struct sadb_msg *msg, struct ipsec_rule *rule)
812{
813 struct sadb_ext *ext;
814 struct sadb_address *saddr;
815 struct sadb_protocol *sproto;
816 struct sadb_ident *sident;
817 struct sockaddr *sa;
818 struct sockaddr_in *sa_in;
819 struct sockaddr_in6 *sa_in6;
820 int len;
821
822 switch (msg->sadb_msg_satype) {
823 case SADB_SATYPE_ESP2:
824 rule->satype = IPSEC_ESP;
825 break;
826 case SADB_SATYPE_AH1:
827 rule->satype = IPSEC_AH;
828 break;
829 case SADB_X_SATYPE_IPCOMP9:
830 rule->satype = IPSEC_IPCOMP;
831 break;
832 case SADB_X_SATYPE_IPIP7:
833 rule->satype = IPSEC_IPIP;
834 break;
835 default:
836 return (1);
837 }
838
839 for (ext = (struct sadb_ext *)(msg + 1);
840 (size_t)((u_int8_t *)ext - (u_int8_t *)msg) <
841 msg->sadb_msg_len * PFKEYV2_CHUNKsizeof(u_int64_t) && ext->sadb_ext_len > 0;
842 ext = (struct sadb_ext *)((u_int8_t *)ext +
843 ext->sadb_ext_len * PFKEYV2_CHUNKsizeof(u_int64_t))) {
844 switch (ext->sadb_ext_type) {
845 case SADB_EXT_ADDRESS_SRC5:
846 saddr = (struct sadb_address *)ext;
847 sa = (struct sockaddr *)(saddr + 1);
848
849 rule->local = calloc(1, sizeof(struct ipsec_addr_wrap));
850 if (rule->local == NULL((void *)0))
851 err(1, "pfkey_parse: calloc");
852
853 rule->local->af = sa->sa_family;
854 switch (sa->sa_family) {
855 case AF_INET2:
856 bcopy(&((struct sockaddr_in *)sa)->sin_addr,
857 &rule->local->address.v4ipa.v4,
858 sizeof(struct in_addr));
859 set_ipmask(rule->local, 32);
860 break;
861 case AF_INET624:
862 bcopy(&((struct sockaddr_in6 *)sa)->sin6_addr,
863 &rule->local->address.v6ipa.v6,
864 sizeof(struct in6_addr));
865 set_ipmask(rule->local, 128);
866 break;
867 default:
868 return (1);
869 }
870 break;
871
872
873 case SADB_EXT_ADDRESS_DST6:
874 saddr = (struct sadb_address *)ext;
875 sa = (struct sockaddr *)(saddr + 1);
876
877 rule->peer = calloc(1, sizeof(struct ipsec_addr_wrap));
878 if (rule->peer == NULL((void *)0))
879 err(1, "pfkey_parse: calloc");
880
881 rule->peer->af = sa->sa_family;
882 switch (sa->sa_family) {
883 case AF_INET2:
884 bcopy(&((struct sockaddr_in *)sa)->sin_addr,
885 &rule->peer->address.v4ipa.v4,
886 sizeof(struct in_addr));
887 set_ipmask(rule->peer, 32);
888 break;
889 case AF_INET624:
890 bcopy(&((struct sockaddr_in6 *)sa)->sin6_addr,
891 &rule->peer->address.v6ipa.v6,
892 sizeof(struct in6_addr));
893 set_ipmask(rule->peer, 128);
894 break;
895 default:
896 return (1);
897 }
898 break;
899
900 case SADB_EXT_IDENTITY_SRC10:
901 sident = (struct sadb_ident *)ext;
902 len = (sident->sadb_ident_len * sizeof(uint64_t)) -
903 sizeof(struct sadb_ident);
904
905 if (rule->auth == NULL((void *)0)) {
906 rule->auth = calloc(1, sizeof(struct
907 ipsec_auth));
908 if (rule->auth == NULL((void *)0))
909 err(1, "pfkey_parse: calloc");
910 }
911
912 rule->auth->srcid = calloc(1, len);
913 if (rule->auth->srcid == NULL((void *)0))
914 err(1, "pfkey_parse: calloc");
915
916 strlcpy(rule->auth->srcid, (char *)(sident + 1), len);
917 break;
918
919 case SADB_EXT_IDENTITY_DST11:
920 sident = (struct sadb_ident *)ext;
921 len = (sident->sadb_ident_len * sizeof(uint64_t)) -
922 sizeof(struct sadb_ident);
923
924 if (rule->auth == NULL((void *)0)) {
925 rule->auth = calloc(1, sizeof(struct
926 ipsec_auth));
927 if (rule->auth == NULL((void *)0))
928 err(1, "pfkey_parse: calloc");
929 }
930
931 rule->auth->dstid = calloc(1, len);
932 if (rule->auth->dstid == NULL((void *)0))
933 err(1, "pfkey_parse: calloc");
934
935 strlcpy(rule->auth->dstid, (char *)(sident + 1), len);
936 break;
937
938 case SADB_X_EXT_PROTOCOL19:
939 sproto = (struct sadb_protocol *)ext;
940 if (sproto->sadb_protocol_direction == 0)
941 rule->proto = sproto->sadb_protocol_proto;
942 break;
943
944 case SADB_X_EXT_FLOW_TYPE20:
945 sproto = (struct sadb_protocol *)ext;
946
947 switch (sproto->sadb_protocol_direction) {
948 case IPSP_DIRECTION_IN0x1:
949 rule->direction = IPSEC_IN;
950 break;
951 case IPSP_DIRECTION_OUT0x2:
952 rule->direction = IPSEC_OUT;
953 break;
954 default:
955 return (1);
956 }
957 switch (sproto->sadb_protocol_proto) {
958 case SADB_X_FLOW_TYPE_USE1:
959 rule->flowtype = TYPE_USE;
960 break;
961 case SADB_X_FLOW_TYPE_ACQUIRE2:
962 rule->flowtype = TYPE_ACQUIRE;
963 break;
964 case SADB_X_FLOW_TYPE_REQUIRE3:
965 rule->flowtype = TYPE_REQUIRE;
966 break;
967 case SADB_X_FLOW_TYPE_DENY5:
968 rule->flowtype = TYPE_DENY;
969 break;
970 case SADB_X_FLOW_TYPE_BYPASS4:
971 rule->flowtype = TYPE_BYPASS;
972 break;
973 case SADB_X_FLOW_TYPE_DONTACQ6:
974 rule->flowtype = TYPE_DONTACQ;
975 break;
976 default:
977 rule->flowtype = TYPE_UNKNOWN;
978 break;
979 }
980 break;
981
982 case SADB_X_EXT_SRC_FLOW21:
983 saddr = (struct sadb_address *)ext;
984 sa = (struct sockaddr *)(saddr + 1);
985
986 if (rule->src == NULL((void *)0)) {
987 rule->src = calloc(1,
988 sizeof(struct ipsec_addr_wrap));
989 if (rule->src == NULL((void *)0))
990 err(1, "pfkey_parse: calloc");
991 }
992
993 rule->src->af = sa->sa_family;
994 switch (sa->sa_family) {
995 case AF_INET2:
996 bcopy(&((struct sockaddr_in *)sa)->sin_addr,
997 &rule->src->address.v4ipa.v4,
998 sizeof(struct in_addr));
999 rule->sport =
1000 ((struct sockaddr_in *)sa)->sin_port;
1001 break;
1002 case AF_INET624:
1003 bcopy(&((struct sockaddr_in6 *)sa)->sin6_addr,
1004 &rule->src->address.v6ipa.v6,
1005 sizeof(struct in6_addr));
1006 rule->sport =
1007 ((struct sockaddr_in6 *)sa)->sin6_port;
1008 break;
1009 default:
1010 return (1);
1011 }
1012 break;
1013
1014 case SADB_X_EXT_DST_FLOW22:
1015 saddr = (struct sadb_address *)ext;
1016 sa = (struct sockaddr *)(saddr + 1);
1017
1018 if (rule->dst == NULL((void *)0)) {
1019 rule->dst = calloc(1,
1020 sizeof(struct ipsec_addr_wrap));
1021 if (rule->dst == NULL((void *)0))
1022 err(1, "pfkey_parse: calloc");
1023 }
1024
1025 rule->dst->af = sa->sa_family;
1026 switch (sa->sa_family) {
1027 case AF_INET2:
1028 bcopy(&((struct sockaddr_in *)sa)->sin_addr,
1029 &rule->dst->address.v4ipa.v4,
1030 sizeof(struct in_addr));
1031 rule->dport =
1032 ((struct sockaddr_in *)sa)->sin_port;
1033 break;
1034 case AF_INET624:
1035 bcopy(&((struct sockaddr_in6 *)sa)->sin6_addr,
1036 &rule->dst->address.v6ipa.v6,
1037 sizeof(struct in6_addr));
1038 rule->dport =
1039 ((struct sockaddr_in6 *)sa)->sin6_port;
1040 break;
1041 default:
1042 return (1);
1043 }
1044 break;
1045
1046
1047 case SADB_X_EXT_SRC_MASK17:
1048 saddr = (struct sadb_address *)ext;
1049 sa = (struct sockaddr *)(saddr + 1);
1050
1051 if (rule->src == NULL((void *)0)) {
1052 rule->src = calloc(1,
1053 sizeof(struct ipsec_addr_wrap));
1054 if (rule->src == NULL((void *)0))
1055 err(1, "pfkey_parse: calloc");
1056 }
1057
1058 rule->src->af = sa->sa_family;
1059 switch (sa->sa_family) {
1060 case AF_INET2:
1061 sa_in = (struct sockaddr_in *)sa;
1062 bcopy(&sa_in->sin_addr, &rule->src->mask.v4ipa.v4,
1063 sizeof(struct in_addr));
1064 break;
1065 case AF_INET624:
1066 sa_in6 = (struct sockaddr_in6 *)sa;
1067 bcopy(&sa_in6->sin6_addr, &rule->src->mask.v6ipa.v6,
1068 sizeof(struct in6_addr));
1069 break;
1070
1071 default:
1072 return (1);
1073 }
1074 break;
1075
1076 case SADB_X_EXT_DST_MASK18:
1077 saddr = (struct sadb_address *)ext;
1078 sa = (struct sockaddr *)(saddr + 1);
1079
1080 if (rule->dst == NULL((void *)0)) {
1081 rule->dst = calloc(1,
1082 sizeof(struct ipsec_addr_wrap));
1083 if (rule->dst == NULL((void *)0))
1084 err(1, "pfkey_parse: calloc");
1085 }
1086
1087 rule->dst->af = sa->sa_family;
1088 switch (sa->sa_family) {
1089 case AF_INET2:
1090 sa_in = (struct sockaddr_in *)sa;
1091 bcopy(&sa_in->sin_addr, &rule->dst->mask.v4ipa.v4,
1092 sizeof(struct in_addr));
1093 break;
1094 case AF_INET624:
1095 sa_in6 = (struct sockaddr_in6 *)sa;
1096 bcopy(&sa_in6->sin6_addr, &rule->dst->mask.v6ipa.v6,
1097 sizeof(struct in6_addr));
1098 break;
1099 default:
1100 return (1);
1101 }
1102 break;
1103
1104 default:
1105 return (1);
1106 }
1107 }
1108
1109 return (0);
1110}
1111
1112int
1113pfkey_ipsec_establish(int action, struct ipsec_rule *r)
1114{
1115 int ret;
1116 u_int8_t satype, satype2, direction;
1117
1118 if (r->type == RULE_FLOW0x01) {
1119 switch (r->satype) {
1120 case IPSEC_ESP:
1121 satype = SADB_SATYPE_ESP2;
1122 break;
1123 case IPSEC_AH:
1124 satype = SADB_SATYPE_AH1;
1125 break;
1126 case IPSEC_IPCOMP:
1127 satype = SADB_X_SATYPE_IPCOMP9;
1128 break;
1129 case IPSEC_IPIP:
1130 satype = SADB_X_SATYPE_IPIP7;
1131 break;
1132 default:
1133 return -1;
1134 }
1135
1136 switch (r->direction) {
1137 case IPSEC_IN:
1138 direction = IPSP_DIRECTION_IN0x1;
1139 break;
1140 case IPSEC_OUT:
1141 direction = IPSP_DIRECTION_OUT0x2;
1142 break;
1143 default:
1144 return -1;
1145 }
1146
1147 switch (action) {
1148 case ACTION_ADD:
1149 ret = pfkey_flow(fd, satype, SADB_X_ADDFLOW12, direction,
1150 r->proto, r->src, r->sport, r->dst, r->dport,
1151 r->local, r->peer, r->auth, r->flowtype);
1152 break;
1153 case ACTION_DELETE:
1154 /* No peer for flow deletion. */
1155 ret = pfkey_flow(fd, satype, SADB_X_DELFLOW13, direction,
1156 r->proto, r->src, r->sport, r->dst, r->dport,
1157 NULL((void *)0), NULL((void *)0), NULL((void *)0), r->flowtype);
1158 break;
1159 default:
1160 return -1;
1161 }
1162 } else if (r->type == RULE_SA0x02) {
1163 switch (r->satype) {
1164 case IPSEC_AH:
1165 satype = SADB_SATYPE_AH1;
1166 break;
1167 case IPSEC_ESP:
1168 satype = SADB_SATYPE_ESP2;
1169 break;
1170 case IPSEC_IPCOMP:
1171 satype = SADB_X_SATYPE_IPCOMP9;
1172 break;
1173 case IPSEC_TCPMD5:
1174 satype = SADB_X_SATYPE_TCPSIGNATURE8;
1175 break;
1176 case IPSEC_IPIP:
1177 satype = SADB_X_SATYPE_IPIP7;
1178 break;
1179 default:
1180 return -1;
1181 }
1182 switch (action) {
1183 case ACTION_ADD:
1184 ret = pfkey_sa(fd, satype, SADB_ADD3, r->spi,
1185 r->src, r->dst, r->udpencap, r->udpdport,
1186 r->xfs, r->authkey, r->enckey, r->tmode);
1187 break;
1188 case ACTION_DELETE:
1189 ret = pfkey_sa(fd, satype, SADB_DELETE4, r->spi,
1190 r->src, r->dst, 0, 0, r->xfs, NULL((void *)0), NULL((void *)0), r->tmode);
1191 break;
1192 default:
1193 return -1;
1194 }
1195 } else if (r->type == RULE_BUNDLE0x08) {
1196 switch (r->satype) {
1197 case IPSEC_AH:
1198 satype = SADB_SATYPE_AH1;
1199 break;
1200 case IPSEC_ESP:
1201 satype = SADB_SATYPE_ESP2;
1202 break;
1203 case IPSEC_IPCOMP:
1204 satype = SADB_X_SATYPE_IPCOMP9;
1205 break;
1206 case IPSEC_TCPMD5:
1207 satype = SADB_X_SATYPE_TCPSIGNATURE8;
1208 break;
1209 case IPSEC_IPIP:
1210 satype = SADB_X_SATYPE_IPIP7;
1211 break;
1212 default:
1213 return -1;
1214 }
1215 switch (r->proto2) {
1216 case IPSEC_AH:
1217 satype2 = SADB_SATYPE_AH1;
1218 break;
1219 case IPSEC_ESP:
1220 satype2 = SADB_SATYPE_ESP2;
1221 break;
1222 case IPSEC_IPCOMP:
1223 satype2 = SADB_X_SATYPE_IPCOMP9;
1224 break;
1225 case IPSEC_TCPMD5:
1226 satype2 = SADB_X_SATYPE_TCPSIGNATURE8;
1227 break;
1228 case IPSEC_IPIP:
1229 satype2 = SADB_X_SATYPE_IPIP7;
1230 break;
1231 default:
1232 return -1;
1233 }
1234 switch (action) {
1235 case ACTION_ADD:
1236 ret = pfkey_sabundle(fd, satype, satype2,
1237 SADB_X_GRPSPIS14, r->dst, r->spi, r->dst2, r->spi2);
1238 break;
1239 case ACTION_DELETE:
1240 return 0;
1241 default:
1242 return -1;
1243 }
1244 } else
1245 return -1;
1246
1247 if (ret < 0)
1248 return -1;
1249 if (pfkey_reply(fd, NULL((void *)0), NULL((void *)0)) < 0)
1250 return -1;
1251
1252 return 0;
1253}
1254
1255int
1256pfkey_ipsec_flush(void)
1257{
1258 struct sadb_msg smsg;
1259 struct iovec iov[IOV_CNT20];
1260 ssize_t n;
1261 int iov_cnt, len;
1262
1263 bzero(&smsg, sizeof(smsg));
1264 smsg.sadb_msg_version = PF_KEY_V22;
1265 smsg.sadb_msg_seq = sadb_msg_seq++;
1266 smsg.sadb_msg_pid = getpid();
1267 smsg.sadb_msg_len = sizeof(smsg) / 8;
1268 smsg.sadb_msg_type = SADB_FLUSH9;
1269 smsg.sadb_msg_satype = SADB_SATYPE_UNSPEC0;
1270
1271 iov_cnt = 0;
1272
1273 iov[iov_cnt].iov_base = &smsg;
1274 iov[iov_cnt].iov_len = sizeof(smsg);
1275 iov_cnt++;
1276
1277 len = smsg.sadb_msg_len * 8;
1278 if ((n = writev(fd, iov, iov_cnt)) == -1) {
1279 warn("writev failed");
1280 return -1;
1281 }
1282 if (n != len) {
1283 warnx("short write");
1284 return -1;
1285 }
1286 if (pfkey_reply(fd, NULL((void *)0), NULL((void *)0)) < 0)
1287 return -1;
1288
1289 return 0;
1290}
1291
1292static int
1293pfkey_promisc(void)
1294{
1295 struct sadb_msg msg;
1296
1297 memset(&msg, 0, sizeof(msg));
1298 msg.sadb_msg_version = PF_KEY_V22;
1299 msg.sadb_msg_seq = sadb_msg_seq++;
1300 msg.sadb_msg_pid = getpid();
1301 msg.sadb_msg_len = sizeof(msg) / PFKEYV2_CHUNKsizeof(u_int64_t);
1302 msg.sadb_msg_type = SADB_X_PROMISC11;
1303 msg.sadb_msg_satype = 1; /* enable */
1304 if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) {
1305 warn("pfkey_promisc: write failed");
1306 return -1;
1307 }
1308 if (pfkey_reply(fd, NULL((void *)0), NULL((void *)0)) < 0)
1309 return -1;
1310 return 0;
1311}
1312
1313int
1314pfkey_monitor(int opts)
1315{
1316 struct pollfd pfd[1];
1317 struct sadb_msg *msg;
1318 u_int8_t *data;
1319 ssize_t len;
1320 int n;
1321
1322 if (pfkey_init() < 0)
1323 return -1;
1324 if (pfkey_promisc() < 0)
1325 return -1;
1326
1327 pfd[0].fd = fd;
1328 pfd[0].events = POLLIN0x0001;
1329 for (;;) {
1330 if ((n = poll(pfd, 1, -1)) == -1)
1331 err(2, "poll");
1332 if (n == 0)
1333 break;
1334 if ((pfd[0].revents & POLLIN0x0001) == 0)
1335 continue;
1336 if (pfkey_reply(fd, &data, &len) < 0)
1337 continue;
1338 msg = (struct sadb_msg *)data;
1339 if (msg->sadb_msg_type == SADB_X_PROMISC11) {
1340 /* remove extra header from promisc messages */
1341 if ((msg->sadb_msg_len * PFKEYV2_CHUNKsizeof(u_int64_t)) >=
1342 2 * sizeof(struct sadb_msg)) {
1343 msg++;
1344 }
1345 }
1346 pfkey_monitor_sa(msg, opts);
1347 if (opts & IPSECCTL_OPT_VERBOSE0x0010)
1348 pfkey_print_raw(data, len);
1349 freezero(data, len);
1350 }
1351 close(fd);
1352 return 0;
1353}
1354
1355int
1356pfkey_init(void)
1357{
1358 if ((fd = socket(PF_KEY30, SOCK_RAW3, PF_KEY_V22)) == -1)
1359 err(1, "pfkey_init: failed to open PF_KEY socket");
1360
1361 return 0;
1362}