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