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' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |
42 | static int fd; |
43 | static u_int32_t sadb_msg_seq = 1; |
44 | |
45 | static 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); |
50 | static 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); |
55 | static 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); |
58 | static int pfkey_reply(int, u_int8_t **, ssize_t *); |
59 | int pfkey_parse(struct sadb_msg *, struct ipsec_rule *); |
60 | int pfkey_ipsec_flush(void); |
61 | int pfkey_ipsec_establish(int, struct ipsec_rule *); |
62 | int pfkey_init(void); |
63 | |
64 | static int |
65 | pfkey_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 | |
389 | static int |
390 | pfkey_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 | |
640 | static int |
641 | pfkey_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 | |
774 | static int |
775 | pfkey_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 | |
810 | int |
811 | pfkey_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 | |
1112 | int |
1113 | pfkey_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 | |
1255 | int |
1256 | pfkey_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 | |
1292 | static int |
1293 | pfkey_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 | |
1313 | int |
1314 | pfkey_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 | |
1355 | int |
1356 | pfkey_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 | } |