1 /* $OpenBSD: pfkey.c,v 1.16 2005/07/09 21:31:24 hshoexer 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.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34
35 #include "ipsecctl.h"
36 #include "pfkey.h"
37
38 #define ROUNDUP(x) (((x) + (PFKEYV2_CHUNK - 1)) & ~(PFKEYV2_CHUNK - 1))
39 #define IOV_CNT 20
40
41 static int fd;
42 static u_int32_t sadb_msg_seq = 1;
43
44 static int pfkey_flow(int, u_int8_t, u_int8_t, u_int8_t,
45 struct ipsec_addr *, struct ipsec_addr *,
46 struct ipsec_addr *, struct ipsec_auth, u_int8_t);
47 static int pfkey_sa(int, u_int8_t, u_int8_t, u_int32_t,
48 struct ipsec_addr *, struct ipsec_addr *,
49 struct ipsec_key *);
50 static int pfkey_reply(int);
51 int pfkey_parse(struct sadb_msg *, struct ipsec_rule *);
52 int pfkey_ipsec_flush(void);
53 int pfkey_ipsec_establish(int, struct ipsec_rule *);
54 int pfkey_init(void);
55
56 static int
pfkey_flow(int sd,u_int8_t satype,u_int8_t action,u_int8_t direction,struct ipsec_addr * src,struct ipsec_addr * dst,struct ipsec_addr * peer,struct ipsec_auth auth,u_int8_t flowtype)57 pfkey_flow(int sd, u_int8_t satype, u_int8_t action, u_int8_t direction,
58 struct ipsec_addr *src, struct ipsec_addr *dst, struct ipsec_addr *peer,
59 struct ipsec_auth auth, u_int8_t flowtype)
60 {
61 struct sadb_msg smsg;
62 struct sadb_address sa_src, sa_dst, sa_peer, sa_smask, sa_dmask;
63 struct sadb_protocol sa_flowtype, sa_protocol;
64 struct sadb_ident *sa_srcid, *sa_dstid;
65 struct sockaddr_storage ssrc, sdst, speer, smask, dmask;
66 struct iovec iov[IOV_CNT];
67 ssize_t n;
68 int iov_cnt, len, ret = 0;
69
70 sa_srcid = sa_dstid = NULL;
71
72 bzero(&ssrc, sizeof(ssrc));
73 bzero(&smask, sizeof(smask));
74 switch (src->af) {
75 case AF_INET:
76 ((struct sockaddr_in *)&ssrc)->sin_addr = src->v4;
77 ssrc.ss_len = sizeof(struct sockaddr_in);
78 ssrc.ss_family = AF_INET;
79 ((struct sockaddr_in *)&smask)->sin_addr = src->v4mask.mask;
80 break;
81 case AF_INET6:
82 default:
83 warnx("unsupported address family %d", src->af);
84 return -1;
85 }
86 smask.ss_family = ssrc.ss_family;
87 smask.ss_len = ssrc.ss_len;
88
89 bzero(&sdst, sizeof(sdst));
90 bzero(&dmask, sizeof(dmask));
91 switch (dst->af) {
92 case AF_INET:
93 ((struct sockaddr_in *)&sdst)->sin_addr = dst->v4;
94 sdst.ss_len = sizeof(struct sockaddr_in);
95 sdst.ss_family = AF_INET;
96 ((struct sockaddr_in *)&dmask)->sin_addr = dst->v4mask.mask;
97 break;
98 case AF_INET6:
99 default:
100 warnx("unsupported address family %d", dst->af);
101 return -1;
102 }
103 dmask.ss_family = sdst.ss_family;
104 dmask.ss_len = sdst.ss_len;
105
106 bzero(&speer, sizeof(speer));
107 if (peer) {
108 switch (peer->af) {
109 case AF_INET:
110 ((struct sockaddr_in *)&speer)->sin_addr = peer->v4;
111 speer.ss_len = sizeof(struct sockaddr_in);
112 speer.ss_family = AF_INET;
113 break;
114 case AF_INET6:
115 default:
116 warnx("unsupported address family %d", peer->af);
117 return -1;
118 }
119 }
120
121 bzero(&smsg, sizeof(smsg));
122 smsg.sadb_msg_version = PF_KEY_V2;
123 smsg.sadb_msg_seq = sadb_msg_seq++;
124 smsg.sadb_msg_pid = getpid();
125 smsg.sadb_msg_len = sizeof(smsg) / 8;
126 smsg.sadb_msg_type = action;
127 smsg.sadb_msg_satype = satype;
128
129 bzero(&sa_flowtype, sizeof(sa_flowtype));
130 sa_flowtype.sadb_protocol_exttype = SADB_X_EXT_FLOW_TYPE;
131 sa_flowtype.sadb_protocol_len = sizeof(sa_flowtype) / 8;
132 sa_flowtype.sadb_protocol_direction = direction;
133
134 switch (flowtype) {
135 case TYPE_USE:
136 sa_flowtype.sadb_protocol_proto = SADB_X_FLOW_TYPE_USE;
137 break;
138 case TYPE_REQUIRE:
139 sa_flowtype.sadb_protocol_proto = SADB_X_FLOW_TYPE_REQUIRE;
140 break;
141 default:
142 warnx("unsupported flowtype %d", flowtype);
143 return -1;
144 }
145
146 bzero(&sa_protocol, sizeof(sa_protocol));
147 sa_protocol.sadb_protocol_exttype = SADB_X_EXT_PROTOCOL;
148 sa_protocol.sadb_protocol_len = sizeof(sa_protocol) / 8;
149 sa_protocol.sadb_protocol_direction = 0;
150 sa_protocol.sadb_protocol_proto = IPPROTO_IP;
151
152 bzero(&sa_src, sizeof(sa_src));
153 sa_src.sadb_address_exttype = SADB_X_EXT_SRC_FLOW;
154 sa_src.sadb_address_len = (sizeof(sa_src) + ROUNDUP(ssrc.ss_len)) / 8;
155
156 bzero(&sa_smask, sizeof(sa_smask));
157 sa_smask.sadb_address_exttype = SADB_X_EXT_SRC_MASK;
158 sa_smask.sadb_address_len =
159 (sizeof(sa_smask) + ROUNDUP(smask.ss_len)) / 8;
160
161 bzero(&sa_dst, sizeof(sa_dst));
162 sa_dst.sadb_address_exttype = SADB_X_EXT_DST_FLOW;
163 sa_dst.sadb_address_len = (sizeof(sa_dst) + ROUNDUP(sdst.ss_len)) / 8;
164
165 bzero(&sa_dmask, sizeof(sa_dmask));
166 sa_dmask.sadb_address_exttype = SADB_X_EXT_DST_MASK;
167 sa_dmask.sadb_address_len =
168 (sizeof(sa_dmask) + ROUNDUP(dmask.ss_len)) / 8;
169
170 bzero(&sa_peer, sizeof(sa_peer));
171 sa_peer.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
172 sa_peer.sadb_address_len =
173 (sizeof(sa_peer) + ROUNDUP(speer.ss_len)) / 8;
174
175 if (auth.srcid) {
176 len = ROUNDUP(strlen(auth.srcid) + 1) + sizeof(*sa_srcid);
177
178 sa_srcid = calloc(len, sizeof(u_int8_t));
179 if (sa_srcid == NULL)
180 err(1, "calloc");
181
182 sa_srcid->sadb_ident_type = auth.idtype;
183 sa_srcid->sadb_ident_len = len / 8;
184 sa_srcid->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC;
185
186 strlcpy((char *)(sa_srcid + 1), auth.srcid,
187 ROUNDUP(strlen(auth.srcid) + 1));
188 }
189 if (auth.dstid) {
190 len = ROUNDUP(strlen(auth.dstid) + 1) + sizeof(*sa_dstid);
191
192 sa_dstid = calloc(len, sizeof(u_int8_t));
193 if (sa_dstid == NULL)
194 err(1, "calloc");
195
196 sa_dstid->sadb_ident_type = auth.idtype;
197 sa_dstid->sadb_ident_len = len / 8;
198 sa_dstid->sadb_ident_exttype = SADB_EXT_IDENTITY_DST;
199
200 strlcpy((char *)(sa_dstid + 1), auth.dstid,
201 ROUNDUP(strlen(auth.dstid) + 1));
202 }
203
204 iov_cnt = 0;
205
206 /* header */
207 iov[iov_cnt].iov_base = &smsg;
208 iov[iov_cnt].iov_len = sizeof(smsg);
209 iov_cnt++;
210
211 /* add flow type */
212 iov[iov_cnt].iov_base = &sa_flowtype;
213 iov[iov_cnt].iov_len = sizeof(sa_flowtype);
214 smsg.sadb_msg_len += sa_flowtype.sadb_protocol_len;
215 iov_cnt++;
216
217 /* remote peer */
218 if (peer) {
219 iov[iov_cnt].iov_base = &sa_peer;
220 iov[iov_cnt].iov_len = sizeof(sa_peer);
221 iov_cnt++;
222 iov[iov_cnt].iov_base = &speer;
223 iov[iov_cnt].iov_len = ROUNDUP(speer.ss_len);
224 smsg.sadb_msg_len += sa_peer.sadb_address_len;
225 iov_cnt++;
226 }
227
228 /* src addr */
229 iov[iov_cnt].iov_base = &sa_src;
230 iov[iov_cnt].iov_len = sizeof(sa_src);
231 iov_cnt++;
232 iov[iov_cnt].iov_base = &ssrc;
233 iov[iov_cnt].iov_len = ROUNDUP(ssrc.ss_len);
234 smsg.sadb_msg_len += sa_src.sadb_address_len;
235 iov_cnt++;
236
237 /* src mask */
238 iov[iov_cnt].iov_base = &sa_smask;
239 iov[iov_cnt].iov_len = sizeof(sa_smask);
240 iov_cnt++;
241 iov[iov_cnt].iov_base = &smask;
242 iov[iov_cnt].iov_len = ROUNDUP(smask.ss_len);
243 smsg.sadb_msg_len += sa_smask.sadb_address_len;
244 iov_cnt++;
245
246 /* dest addr */
247 iov[iov_cnt].iov_base = &sa_dst;
248 iov[iov_cnt].iov_len = sizeof(sa_dst);
249 iov_cnt++;
250 iov[iov_cnt].iov_base = &sdst;
251 iov[iov_cnt].iov_len = ROUNDUP(sdst.ss_len);
252 smsg.sadb_msg_len += sa_dst.sadb_address_len;
253 iov_cnt++;
254
255 /* dst mask */
256 iov[iov_cnt].iov_base = &sa_dmask;
257 iov[iov_cnt].iov_len = sizeof(sa_dmask);
258 iov_cnt++;
259 iov[iov_cnt].iov_base = &dmask;
260 iov[iov_cnt].iov_len = ROUNDUP(dmask.ss_len);
261 smsg.sadb_msg_len += sa_dmask.sadb_address_len;
262 iov_cnt++;
263
264 /* add protocol */
265 iov[iov_cnt].iov_base = &sa_protocol;
266 iov[iov_cnt].iov_len = sizeof(sa_protocol);
267 smsg.sadb_msg_len += sa_protocol.sadb_protocol_len;
268 iov_cnt++;
269
270 if (sa_srcid) {
271 /* src identity */
272 iov[iov_cnt].iov_base = sa_srcid;
273 iov[iov_cnt].iov_len = sa_srcid->sadb_ident_len * 8;
274 smsg.sadb_msg_len += sa_srcid->sadb_ident_len;
275 iov_cnt++;
276 }
277 if (sa_dstid) {
278 /* dst identity */
279 iov[iov_cnt].iov_base = sa_dstid;
280 iov[iov_cnt].iov_len = sa_dstid->sadb_ident_len * 8;
281 smsg.sadb_msg_len += sa_dstid->sadb_ident_len;
282 iov_cnt++;
283 }
284 len = smsg.sadb_msg_len * 8;
285 if ((n = writev(sd, iov, iov_cnt)) == -1) {
286 warn("writev failed");
287 ret = -1;
288 goto out;
289 }
290 if (n != len) {
291 warnx("short write");
292 ret = -1;
293 }
294
295 out:
296 if (sa_srcid)
297 free(sa_srcid);
298 if (sa_dstid)
299 free(sa_dstid);
300
301 return ret;
302 }
303
304 static int
pfkey_sa(int sd,u_int8_t satype,u_int8_t action,u_int32_t spi,struct ipsec_addr * src,struct ipsec_addr * dst,struct ipsec_key * key)305 pfkey_sa(int sd, u_int8_t satype, u_int8_t action, u_int32_t spi,
306 struct ipsec_addr *src, struct ipsec_addr *dst, struct ipsec_key *key)
307 {
308 struct sadb_msg smsg;
309 struct sadb_sa sa;
310 struct sadb_address sa_src, sa_dst;
311 struct sadb_key sa_key;
312 struct sockaddr_storage ssrc, sdst;
313 struct iovec iov[IOV_CNT];
314 ssize_t n;
315 int iov_cnt, len, ret = 0;
316
317 bzero(&ssrc, sizeof(ssrc));
318 switch (src->af) {
319 case AF_INET:
320 ((struct sockaddr_in *)&ssrc)->sin_addr = src->v4;
321 ssrc.ss_len = sizeof(struct sockaddr_in);
322 ssrc.ss_family = AF_INET;
323 break;
324 case AF_INET6:
325 default:
326 warnx("unsupported address family %d", src->af);
327 return -1;
328 }
329
330 bzero(&sdst, sizeof(sdst));
331 switch (dst->af) {
332 case AF_INET:
333 ((struct sockaddr_in *)&sdst)->sin_addr = dst->v4;
334 sdst.ss_len = sizeof(struct sockaddr_in);
335 sdst.ss_family = AF_INET;
336 break;
337 case AF_INET6:
338 default:
339 warnx("unsupported address family %d", dst->af);
340 return -1;
341 }
342
343 bzero(&smsg, sizeof(smsg));
344 smsg.sadb_msg_version = PF_KEY_V2;
345 smsg.sadb_msg_seq = sadb_msg_seq++;
346 smsg.sadb_msg_pid = getpid();
347 smsg.sadb_msg_len = sizeof(smsg) / 8;
348 smsg.sadb_msg_type = action;
349 smsg.sadb_msg_satype = satype;
350
351 bzero(&sa, sizeof(sa));
352 sa.sadb_sa_len = sizeof(sa) / 8;
353 sa.sadb_sa_exttype = SADB_EXT_SA;
354 sa.sadb_sa_spi = htonl(spi);
355 sa.sadb_sa_state = SADB_SASTATE_MATURE;
356
357 bzero(&sa_src, sizeof(sa_src));
358 sa_src.sadb_address_len = (sizeof(sa_src) + ROUNDUP(ssrc.ss_len)) / 8;
359 sa_src.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
360
361 bzero(&sa_dst, sizeof(sa_dst));
362 sa_dst.sadb_address_len = (sizeof(sa_dst) + ROUNDUP(sdst.ss_len)) / 8;
363 sa_dst.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
364
365 if (action == SADB_ADD) {
366 if (!key) {
367 warnx("no key specified");
368 return -1;
369 }
370 bzero(&sa_key, sizeof(sa_key));
371 sa_key.sadb_key_len = (sizeof(sa_key) + ((key->len + 7) / 8)
372 * 8) / 8;
373 sa_key.sadb_key_exttype = SADB_EXT_KEY_AUTH;
374 sa_key.sadb_key_bits = 8 * key->len;
375 }
376
377 iov_cnt = 0;
378
379 /* header */
380 iov[iov_cnt].iov_base = &smsg;
381 iov[iov_cnt].iov_len = sizeof(smsg);
382 iov_cnt++;
383
384 /* sa */
385 iov[iov_cnt].iov_base = &sa;
386 iov[iov_cnt].iov_len = sizeof(sa);
387 smsg.sadb_msg_len += sa.sadb_sa_len;
388 iov_cnt++;
389
390 /* src addr */
391 iov[iov_cnt].iov_base = &sa_src;
392 iov[iov_cnt].iov_len = sizeof(sa_src);
393 iov_cnt++;
394 iov[iov_cnt].iov_base = &ssrc;
395 iov[iov_cnt].iov_len = ROUNDUP(ssrc.ss_len);
396 smsg.sadb_msg_len += sa_src.sadb_address_len;
397 iov_cnt++;
398
399 /* dst addr */
400 iov[iov_cnt].iov_base = &sa_dst;
401 iov[iov_cnt].iov_len = sizeof(sa_dst);
402 iov_cnt++;
403 iov[iov_cnt].iov_base = &sdst;
404 iov[iov_cnt].iov_len = ROUNDUP(sdst.ss_len);
405 smsg.sadb_msg_len += sa_dst.sadb_address_len;
406 iov_cnt++;
407
408 if (action == SADB_ADD) {
409 /* key */
410 iov[iov_cnt].iov_base = &sa_key;
411 iov[iov_cnt].iov_len = sizeof(sa_key);
412 iov_cnt++;
413 iov[iov_cnt].iov_base = key->data;
414 iov[iov_cnt].iov_len = ((key->len + 7) / 8) * 8;
415 smsg.sadb_msg_len += sa_key.sadb_key_len;
416 iov_cnt++;
417 }
418
419 len = smsg.sadb_msg_len * 8;
420 if ((n = writev(sd, iov, iov_cnt)) == -1) {
421 warn("writev failed");
422 ret = -1;
423 } else if (n != len) {
424 warnx("short write");
425 ret = -1;
426 }
427
428 return ret;
429 }
430
431 static int
pfkey_reply(int sd)432 pfkey_reply(int sd)
433 {
434 struct sadb_msg hdr;
435 ssize_t len;
436 u_int8_t *data;
437
438 if (recv(sd, &hdr, sizeof(hdr), MSG_PEEK) != sizeof(hdr)) {
439 warnx("short read");
440 return -1;
441 }
442 if (hdr.sadb_msg_errno != 0) {
443 errno = hdr.sadb_msg_errno;
444 warn("PF_KEY failed");
445 return -1;
446 }
447 len = hdr.sadb_msg_len * PFKEYV2_CHUNK;
448 if ((data = malloc(len)) == NULL)
449 err(1, NULL);
450 if (read(sd, data, len) != len) {
451 warn("PF_KEY short read");
452 bzero(data, len);
453 free(data);
454 return -1;
455 }
456 bzero(data, len);
457 free(data);
458
459 return 0;
460 }
461
462 int
pfkey_parse(struct sadb_msg * msg,struct ipsec_rule * rule)463 pfkey_parse(struct sadb_msg *msg, struct ipsec_rule *rule)
464 {
465 struct sadb_ext *ext;
466 struct sadb_address *saddr;
467 struct sadb_protocol *sproto;
468 struct sadb_ident *sident;
469 struct sockaddr *sa;
470 int len;
471
472 switch (msg->sadb_msg_satype) {
473 case SADB_SATYPE_ESP:
474 rule->proto = IPSEC_ESP;
475 break;
476 case SADB_SATYPE_AH:
477 rule->proto = IPSEC_AH;
478 break;
479 case SADB_X_SATYPE_IPCOMP:
480 default:
481 return (1);
482 }
483
484 for (ext = (struct sadb_ext *)(msg + 1);
485 (size_t)((u_int8_t *)ext - (u_int8_t *)msg) <
486 msg->sadb_msg_len * PFKEYV2_CHUNK && ext->sadb_ext_len > 0;
487 ext = (struct sadb_ext *)((u_int8_t *)ext +
488 ext->sadb_ext_len * PFKEYV2_CHUNK)) {
489 switch (ext->sadb_ext_type) {
490 case SADB_EXT_ADDRESS_SRC:
491 #ifdef notyet
492 saddr = (struct sadb_address *)ext;
493 sa = (struct sockaddr *)(saddr + 1);
494
495 rule->local = calloc(1, sizeof(struct ipsec_addr));
496 if (rule->local == NULL)
497 err(1, "malloc");
498
499 switch (sa->sa_family) {
500 case AF_INET:
501 bcopy(&((struct sockaddr_in *)sa)->sin_addr,
502 &rule->local->v4, sizeof(struct in_addr));
503 memset(&rule->local->v4mask, 0xff,
504 sizeof(u_int32_t));
505 rule->local->af = AF_INET;
506 break;
507 default:
508 return (1);
509 }
510 #endif
511 break;
512
513
514 case SADB_EXT_ADDRESS_DST:
515 saddr = (struct sadb_address *)ext;
516 sa = (struct sockaddr *)(saddr + 1);
517
518 rule->peer = calloc(1, sizeof(struct ipsec_addr));
519 if (rule->peer == NULL)
520 err(1, "malloc");
521
522 switch (sa->sa_family) {
523 case AF_INET:
524 bcopy(&((struct sockaddr_in *)sa)->sin_addr,
525 &rule->peer->v4, sizeof(struct in_addr));
526 memset(&rule->peer->v4mask, 0xff,
527 sizeof(u_int32_t));
528 rule->peer->af = AF_INET;
529 break;
530 default:
531 return (1);
532 }
533 break;
534
535 case SADB_EXT_IDENTITY_SRC:
536 sident = (struct sadb_ident *)ext;
537 len = (sident->sadb_ident_len * sizeof(uint64_t)) -
538 sizeof(struct sadb_ident);
539
540 rule->auth.srcid = calloc(1, len);
541 if (rule->auth.srcid == NULL)
542 err(1, "calloc");
543
544 strlcpy(rule->auth.srcid, (char *)(sident + 1), len);
545 break;
546
547 case SADB_EXT_IDENTITY_DST:
548 sident = (struct sadb_ident *)ext;
549 len = (sident->sadb_ident_len * sizeof(uint64_t)) -
550 sizeof(struct sadb_ident);
551
552 rule->auth.dstid = calloc(1, len);
553 if (rule->auth.dstid == NULL)
554 err(1, "calloc");
555
556 strlcpy(rule->auth.dstid, (char *)(sident + 1), len);
557 break;
558
559 case SADB_X_EXT_PROTOCOL:
560 /* XXX nothing yet? */
561 break;
562
563 case SADB_X_EXT_FLOW_TYPE:
564 sproto = (struct sadb_protocol *)ext;
565
566 switch (sproto->sadb_protocol_direction) {
567 case IPSP_DIRECTION_IN:
568 rule->direction = IPSEC_IN;
569 break;
570 case IPSP_DIRECTION_OUT:
571 rule->direction = IPSEC_OUT;
572 break;
573 default:
574 return (1);
575 }
576 switch (sproto->sadb_protocol_proto) {
577 case SADB_X_FLOW_TYPE_USE:
578 rule->flowtype = TYPE_USE;
579 break;
580 case SADB_X_FLOW_TYPE_ACQUIRE:
581 rule->flowtype = TYPE_ACQUIRE;
582 break;
583 case SADB_X_FLOW_TYPE_REQUIRE:
584 rule->flowtype = TYPE_REQUIRE;
585 break;
586 case SADB_X_FLOW_TYPE_DENY:
587 rule->flowtype = TYPE_DENY;
588 break;
589 case SADB_X_FLOW_TYPE_BYPASS:
590 rule->flowtype = TYPE_BYPASS;
591 break;
592 case SADB_X_FLOW_TYPE_DONTACQ:
593 rule->flowtype = TYPE_DONTACQ;
594 break;
595 default:
596 rule->flowtype = TYPE_UNKNOWN;
597 break;
598 }
599 break;
600
601 case SADB_X_EXT_SRC_FLOW:
602 saddr = (struct sadb_address *)ext;
603 sa = (struct sockaddr *)(saddr + 1);
604
605 if (rule->src == NULL) {
606 rule->src = calloc(1,
607 sizeof(struct ipsec_addr));
608 if (rule->src == NULL)
609 err(1, "calloc");
610 }
611
612 switch (sa->sa_family) {
613 case AF_INET:
614 bcopy(&((struct sockaddr_in *)sa)->sin_addr,
615 &rule->src->v4, sizeof(struct in_addr));
616 rule->src->af = AF_INET;
617 break;
618 default:
619 return (1);
620 }
621 break;
622
623 case SADB_X_EXT_DST_FLOW:
624 saddr = (struct sadb_address *)ext;
625 sa = (struct sockaddr *)(saddr + 1);
626
627 if (rule->dst == NULL) {
628 rule->dst = calloc(1,
629 sizeof(struct ipsec_addr));
630 if (rule->dst == NULL)
631 err(1, "calloc");
632 }
633
634 switch (sa->sa_family) {
635 case AF_INET:
636 bcopy(&((struct sockaddr_in *)sa)->sin_addr,
637 &rule->dst->v4, sizeof(struct in_addr));
638 rule->dst->af = AF_INET;
639 break;
640
641 default:
642 return (1);
643 }
644 break;
645
646
647 case SADB_X_EXT_SRC_MASK:
648 saddr = (struct sadb_address *)ext;
649 sa = (struct sockaddr *)(saddr + 1);
650
651 if (rule->src == NULL) {
652 rule->src = calloc(1,
653 sizeof(struct ipsec_addr));
654 if (rule->src == NULL)
655 err(1, "calloc");
656 }
657
658 switch (sa->sa_family) {
659 case AF_INET:
660 bcopy(&((struct sockaddr_in *)sa)->sin_addr,
661 &rule->src->v4mask.mask,
662 sizeof(struct in_addr));
663 rule->src->af = AF_INET;
664 break;
665
666 default:
667 return (1);
668 }
669 break;
670
671 case SADB_X_EXT_DST_MASK:
672 saddr = (struct sadb_address *)ext;
673 sa = (struct sockaddr *)(saddr + 1);
674
675 if (rule->dst == NULL) {
676 rule->dst = calloc(1,
677 sizeof(struct ipsec_addr));
678 if (rule->dst == NULL)
679 err(1, "calloc");
680 }
681
682 switch (sa->sa_family) {
683 case AF_INET:
684 bcopy(&((struct sockaddr_in *)sa)->sin_addr,
685 &rule->dst->v4mask.mask,
686 sizeof(struct in_addr));
687 rule->dst->af = AF_INET;
688 break;
689
690 default:
691 return (1);
692 }
693 break;
694
695 default:
696 return (1);
697 }
698 }
699
700 return (0);
701 }
702
703 int
pfkey_ipsec_establish(int action,struct ipsec_rule * r)704 pfkey_ipsec_establish(int action, struct ipsec_rule *r)
705 {
706 int ret;
707 u_int8_t satype, direction;
708
709 if (r->type == RULE_FLOW) {
710 switch (r->proto) {
711 case IPSEC_ESP:
712 satype = SADB_SATYPE_ESP;
713 break;
714 case IPSEC_AH:
715 satype = SADB_SATYPE_AH;
716 break;
717 case IPSEC_COMP:
718 default:
719 return -1;
720 }
721
722 switch (r->direction) {
723 case IPSEC_IN:
724 direction = IPSP_DIRECTION_IN;
725 break;
726 case IPSEC_OUT:
727 direction = IPSP_DIRECTION_OUT;
728 break;
729 default:
730 return -1;
731 }
732
733 switch (action) {
734 case PFK_ACTION_ADD:
735 ret = pfkey_flow(fd, satype, SADB_X_ADDFLOW, direction,
736 r->src, r->dst, r->peer, r->auth, r->flowtype);
737 break;
738 case PFK_ACTION_DELETE:
739 /* No peer for flow deletion. */
740 ret = pfkey_flow(fd, satype, SADB_X_DELFLOW, direction,
741 r->src, r->dst, NULL, r->auth, r->flowtype);
742 break;
743 default:
744 return -1;
745 }
746 } else if (r->type == RULE_SA) {
747 satype = SADB_X_SATYPE_TCPSIGNATURE;
748 switch (action) {
749 case PFK_ACTION_ADD:
750 ret = pfkey_sa(fd, satype, SADB_ADD, r->spi,
751 r->src, r->dst, r->key);
752 break;
753 case PFK_ACTION_DELETE:
754 ret = pfkey_sa(fd, satype, SADB_DELETE, r->spi,
755 r->src, r->dst, r->key);
756 break;
757 default:
758 return -1;
759 }
760 } else
761 return -1;
762
763 if (ret < 0)
764 return -1;
765 if (pfkey_reply(fd) < 0)
766 return -1;
767
768 return 0;
769 }
770
771 int
pfkey_ipsec_flush(void)772 pfkey_ipsec_flush(void)
773 {
774 struct sadb_msg smsg;
775 struct iovec iov[IOV_CNT];
776 ssize_t n;
777 int iov_cnt, len;
778
779 bzero(&smsg, sizeof(smsg));
780 smsg.sadb_msg_version = PF_KEY_V2;
781 smsg.sadb_msg_seq = sadb_msg_seq++;
782 smsg.sadb_msg_pid = getpid();
783 smsg.sadb_msg_len = sizeof(smsg) / 8;
784 smsg.sadb_msg_type = SADB_FLUSH;
785 smsg.sadb_msg_satype = SADB_SATYPE_UNSPEC;
786
787 iov_cnt = 0;
788
789 iov[iov_cnt].iov_base = &smsg;
790 iov[iov_cnt].iov_len = sizeof(smsg);
791 iov_cnt++;
792
793 len = smsg.sadb_msg_len * 8;
794 if ((n = writev(fd, iov, iov_cnt)) == -1) {
795 warn("writev failed");
796 return -1;
797 }
798 if (n != len) {
799 warnx("short write");
800 return -1;
801 }
802 if (pfkey_reply(fd) < 0)
803 return -1;
804
805 return 0;
806 }
807
808 int
pfkey_init(void)809 pfkey_init(void)
810 {
811 if ((fd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) == -1)
812 err(1, "failed to open PF_KEY socket");
813
814 return 0;
815 }
816