xref: /openbsd-src/usr.sbin/bgpd/pfkey.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: pfkey.c,v 1.45 2015/09/13 10:22:16 florian Exp $ */
2 
3 /*
4  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5  * Copyright (c) 2003, 2004 Markus Friedl <markus@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/socket.h>
22 #include <sys/uio.h>
23 #include <net/pfkeyv2.h>
24 #include <netinet/ip_ipsp.h>
25 #include <ctype.h>
26 #include <errno.h>
27 #include <limits.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 
32 #include "bgpd.h"
33 #include "session.h"
34 
35 #define	PFKEY2_CHUNK sizeof(u_int64_t)
36 #define	ROUNDUP(x) (((x) + (PFKEY2_CHUNK - 1)) & ~(PFKEY2_CHUNK - 1))
37 #define	IOV_CNT	20
38 
39 static u_int32_t	sadb_msg_seq = 0;
40 static u_int32_t	pid = 0; /* should pid_t but pfkey needs u_int32_t */
41 static int		fd;
42 
43 int	pfkey_reply(int, u_int32_t *);
44 int	pfkey_send(int, uint8_t, uint8_t, uint8_t,
45 	    struct bgpd_addr *, struct bgpd_addr *,
46 	    u_int32_t, uint8_t, int, char *, uint8_t, int, char *,
47 	    uint16_t, uint16_t);
48 int	pfkey_sa_add(struct bgpd_addr *, struct bgpd_addr *, u_int8_t, char *,
49 	    u_int32_t *);
50 int	pfkey_sa_remove(struct bgpd_addr *, struct bgpd_addr *, u_int32_t *);
51 int	pfkey_md5sig_establish(struct peer *);
52 int	pfkey_md5sig_remove(struct peer *);
53 int	pfkey_ipsec_establish(struct peer *);
54 int	pfkey_ipsec_remove(struct peer *);
55 
56 #define pfkey_flow(fd, satype, cmd, dir, from, to, sport, dport) \
57 	pfkey_send(fd, satype, cmd, dir, from, to, \
58 	    0, 0, 0, NULL, 0, 0, NULL, sport, dport)
59 
60 int
61 pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir,
62     struct bgpd_addr *src, struct bgpd_addr *dst, u_int32_t spi,
63     uint8_t aalg, int alen, char *akey, uint8_t ealg, int elen, char *ekey,
64     uint16_t sport, uint16_t dport)
65 {
66 	struct sadb_msg		smsg;
67 	struct sadb_sa		sa;
68 	struct sadb_address	sa_src, sa_dst, sa_peer, sa_smask, sa_dmask;
69 	struct sadb_key		sa_akey, sa_ekey;
70 	struct sadb_spirange	sa_spirange;
71 	struct sadb_protocol	sa_flowtype, sa_protocol;
72 	struct iovec		iov[IOV_CNT];
73 	ssize_t			n;
74 	int			len = 0;
75 	int			iov_cnt;
76 	struct sockaddr_storage	ssrc, sdst, speer, smask, dmask;
77 	struct sockaddr		*saptr;
78 
79 	if (!pid)
80 		pid = getpid();
81 
82 	/* we need clean sockaddr... no ports set */
83 	bzero(&ssrc, sizeof(ssrc));
84 	bzero(&smask, sizeof(smask));
85 	if ((saptr = addr2sa(src, 0)))
86 		memcpy(&ssrc, saptr, sizeof(ssrc));
87 	switch (src->aid) {
88 	case AID_INET:
89 		memset(&((struct sockaddr_in *)&smask)->sin_addr, 0xff, 32/8);
90 		break;
91 	case AID_INET6:
92 		memset(&((struct sockaddr_in6 *)&smask)->sin6_addr, 0xff,
93 		    128/8);
94 		break;
95 	case AID_UNSPEC:
96 		ssrc.ss_len = sizeof(struct sockaddr);
97 		break;
98 	default:
99 		return (-1);
100 	}
101 	smask.ss_family = ssrc.ss_family;
102 	smask.ss_len = ssrc.ss_len;
103 
104 	bzero(&sdst, sizeof(sdst));
105 	bzero(&dmask, sizeof(dmask));
106 	if ((saptr = addr2sa(dst, 0)))
107 		memcpy(&sdst, saptr, sizeof(sdst));
108 	switch (dst->aid) {
109 	case AID_INET:
110 		memset(&((struct sockaddr_in *)&dmask)->sin_addr, 0xff, 32/8);
111 		break;
112 	case AID_INET6:
113 		memset(&((struct sockaddr_in6 *)&dmask)->sin6_addr, 0xff,
114 		    128/8);
115 		break;
116 	case AID_UNSPEC:
117 		sdst.ss_len = sizeof(struct sockaddr);
118 		break;
119 	default:
120 		return (-1);
121 	}
122 	dmask.ss_family = sdst.ss_family;
123 	dmask.ss_len = sdst.ss_len;
124 
125 	bzero(&smsg, sizeof(smsg));
126 	smsg.sadb_msg_version = PF_KEY_V2;
127 	smsg.sadb_msg_seq = ++sadb_msg_seq;
128 	smsg.sadb_msg_pid = pid;
129 	smsg.sadb_msg_len = sizeof(smsg) / 8;
130 	smsg.sadb_msg_type = mtype;
131 	smsg.sadb_msg_satype = satype;
132 
133 	switch (mtype) {
134 	case SADB_GETSPI:
135 		bzero(&sa_spirange, sizeof(sa_spirange));
136 		sa_spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE;
137 		sa_spirange.sadb_spirange_len = sizeof(sa_spirange) / 8;
138 		sa_spirange.sadb_spirange_min = 0x100;
139 		sa_spirange.sadb_spirange_max = 0xffffffff;
140 		sa_spirange.sadb_spirange_reserved = 0;
141 		break;
142 	case SADB_ADD:
143 	case SADB_UPDATE:
144 	case SADB_DELETE:
145 		bzero(&sa, sizeof(sa));
146 		sa.sadb_sa_exttype = SADB_EXT_SA;
147 		sa.sadb_sa_len = sizeof(sa) / 8;
148 		sa.sadb_sa_replay = 0;
149 		sa.sadb_sa_spi = spi;
150 		sa.sadb_sa_state = SADB_SASTATE_MATURE;
151 		break;
152 	case SADB_X_ADDFLOW:
153 	case SADB_X_DELFLOW:
154 		bzero(&sa_flowtype, sizeof(sa_flowtype));
155 		sa_flowtype.sadb_protocol_exttype = SADB_X_EXT_FLOW_TYPE;
156 		sa_flowtype.sadb_protocol_len = sizeof(sa_flowtype) / 8;
157 		sa_flowtype.sadb_protocol_direction = dir;
158 		sa_flowtype.sadb_protocol_proto = SADB_X_FLOW_TYPE_REQUIRE;
159 
160 		bzero(&sa_protocol, sizeof(sa_protocol));
161 		sa_protocol.sadb_protocol_exttype = SADB_X_EXT_PROTOCOL;
162 		sa_protocol.sadb_protocol_len = sizeof(sa_protocol) / 8;
163 		sa_protocol.sadb_protocol_direction = 0;
164 		sa_protocol.sadb_protocol_proto = 6;
165 		break;
166 	}
167 
168 	bzero(&sa_src, sizeof(sa_src));
169 	sa_src.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
170 	sa_src.sadb_address_len = (sizeof(sa_src) + ROUNDUP(ssrc.ss_len)) / 8;
171 
172 	bzero(&sa_dst, sizeof(sa_dst));
173 	sa_dst.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
174 	sa_dst.sadb_address_len = (sizeof(sa_dst) + ROUNDUP(sdst.ss_len)) / 8;
175 
176 	sa.sadb_sa_auth = aalg;
177 	sa.sadb_sa_encrypt = SADB_X_EALG_AES; /* XXX */
178 
179 	switch (mtype) {
180 	case SADB_ADD:
181 	case SADB_UPDATE:
182 		bzero(&sa_akey, sizeof(sa_akey));
183 		sa_akey.sadb_key_exttype = SADB_EXT_KEY_AUTH;
184 		sa_akey.sadb_key_len = (sizeof(sa_akey) +
185 		    ((alen + 7) / 8) * 8) / 8;
186 		sa_akey.sadb_key_bits = 8 * alen;
187 
188 		bzero(&sa_ekey, sizeof(sa_ekey));
189 		sa_ekey.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
190 		sa_ekey.sadb_key_len = (sizeof(sa_ekey) +
191 		    ((elen + 7) / 8) * 8) / 8;
192 		sa_ekey.sadb_key_bits = 8 * elen;
193 
194 		break;
195 	case SADB_X_ADDFLOW:
196 	case SADB_X_DELFLOW:
197 		/* sa_peer always points to the remote machine */
198 		if (dir == IPSP_DIRECTION_IN) {
199 			speer = ssrc;
200 			sa_peer = sa_src;
201 		} else {
202 			speer = sdst;
203 			sa_peer = sa_dst;
204 		}
205 		sa_peer.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
206 		sa_peer.sadb_address_len =
207 		    (sizeof(sa_peer) + ROUNDUP(speer.ss_len)) / 8;
208 
209 		/* for addflow we also use src/dst as the flow destination */
210 		sa_src.sadb_address_exttype = SADB_X_EXT_SRC_FLOW;
211 		sa_dst.sadb_address_exttype = SADB_X_EXT_DST_FLOW;
212 
213 		bzero(&smask, sizeof(smask));
214 		switch (src->aid) {
215 		case AID_INET:
216 			smask.ss_len = sizeof(struct sockaddr_in);
217 			smask.ss_family = AF_INET;
218 			memset(&((struct sockaddr_in *)&smask)->sin_addr,
219 			    0xff, 32/8);
220 			if (sport) {
221 				((struct sockaddr_in *)&ssrc)->sin_port =
222 				    htons(sport);
223 				((struct sockaddr_in *)&smask)->sin_port =
224 				    htons(0xffff);
225 			}
226 			break;
227 		case AID_INET6:
228 			smask.ss_len = sizeof(struct sockaddr_in6);
229 			smask.ss_family = AF_INET6;
230 			memset(&((struct sockaddr_in6 *)&smask)->sin6_addr,
231 			    0xff, 128/8);
232 			if (sport) {
233 				((struct sockaddr_in6 *)&ssrc)->sin6_port =
234 				    htons(sport);
235 				((struct sockaddr_in6 *)&smask)->sin6_port =
236 				    htons(0xffff);
237 			}
238 			break;
239 		}
240 		bzero(&dmask, sizeof(dmask));
241 		switch (dst->aid) {
242 		case AID_INET:
243 			dmask.ss_len = sizeof(struct sockaddr_in);
244 			dmask.ss_family = AF_INET;
245 			memset(&((struct sockaddr_in *)&dmask)->sin_addr,
246 			    0xff, 32/8);
247 			if (dport) {
248 				((struct sockaddr_in *)&sdst)->sin_port =
249 				    htons(dport);
250 				((struct sockaddr_in *)&dmask)->sin_port =
251 				    htons(0xffff);
252 			}
253 			break;
254 		case AID_INET6:
255 			dmask.ss_len = sizeof(struct sockaddr_in6);
256 			dmask.ss_family = AF_INET6;
257 			memset(&((struct sockaddr_in6 *)&dmask)->sin6_addr,
258 			    0xff, 128/8);
259 			if (dport) {
260 				((struct sockaddr_in6 *)&sdst)->sin6_port =
261 				    htons(dport);
262 				((struct sockaddr_in6 *)&dmask)->sin6_port =
263 				    htons(0xffff);
264 			}
265 			break;
266 		}
267 
268 		bzero(&sa_smask, sizeof(sa_smask));
269 		sa_smask.sadb_address_exttype = SADB_X_EXT_SRC_MASK;
270 		sa_smask.sadb_address_len =
271 		    (sizeof(sa_smask) + ROUNDUP(smask.ss_len)) / 8;
272 
273 		bzero(&sa_dmask, sizeof(sa_dmask));
274 		sa_dmask.sadb_address_exttype = SADB_X_EXT_DST_MASK;
275 		sa_dmask.sadb_address_len =
276 		    (sizeof(sa_dmask) + ROUNDUP(dmask.ss_len)) / 8;
277 		break;
278 	}
279 
280 	iov_cnt = 0;
281 
282 	/* msghdr */
283 	iov[iov_cnt].iov_base = &smsg;
284 	iov[iov_cnt].iov_len = sizeof(smsg);
285 	iov_cnt++;
286 
287 	switch (mtype) {
288 	case SADB_ADD:
289 	case SADB_UPDATE:
290 	case SADB_DELETE:
291 		/* SA hdr */
292 		iov[iov_cnt].iov_base = &sa;
293 		iov[iov_cnt].iov_len = sizeof(sa);
294 		smsg.sadb_msg_len += sa.sadb_sa_len;
295 		iov_cnt++;
296 		break;
297 	case SADB_GETSPI:
298 		/* SPI range */
299 		iov[iov_cnt].iov_base = &sa_spirange;
300 		iov[iov_cnt].iov_len = sizeof(sa_spirange);
301 		smsg.sadb_msg_len += sa_spirange.sadb_spirange_len;
302 		iov_cnt++;
303 		break;
304 	case SADB_X_ADDFLOW:
305 		/* sa_peer always points to the remote machine */
306 		iov[iov_cnt].iov_base = &sa_peer;
307 		iov[iov_cnt].iov_len = sizeof(sa_peer);
308 		iov_cnt++;
309 		iov[iov_cnt].iov_base = &speer;
310 		iov[iov_cnt].iov_len = ROUNDUP(speer.ss_len);
311 		smsg.sadb_msg_len += sa_peer.sadb_address_len;
312 		iov_cnt++;
313 
314 		/* FALLTHROUGH */
315 	case SADB_X_DELFLOW:
316 		/* add flow type */
317 		iov[iov_cnt].iov_base = &sa_flowtype;
318 		iov[iov_cnt].iov_len = sizeof(sa_flowtype);
319 		smsg.sadb_msg_len += sa_flowtype.sadb_protocol_len;
320 		iov_cnt++;
321 
322 		/* add protocol */
323 		iov[iov_cnt].iov_base = &sa_protocol;
324 		iov[iov_cnt].iov_len = sizeof(sa_protocol);
325 		smsg.sadb_msg_len += sa_protocol.sadb_protocol_len;
326 		iov_cnt++;
327 
328 		/* add flow masks */
329 		iov[iov_cnt].iov_base = &sa_smask;
330 		iov[iov_cnt].iov_len = sizeof(sa_smask);
331 		iov_cnt++;
332 		iov[iov_cnt].iov_base = &smask;
333 		iov[iov_cnt].iov_len = ROUNDUP(smask.ss_len);
334 		smsg.sadb_msg_len += sa_smask.sadb_address_len;
335 		iov_cnt++;
336 
337 		iov[iov_cnt].iov_base = &sa_dmask;
338 		iov[iov_cnt].iov_len = sizeof(sa_dmask);
339 		iov_cnt++;
340 		iov[iov_cnt].iov_base = &dmask;
341 		iov[iov_cnt].iov_len = ROUNDUP(dmask.ss_len);
342 		smsg.sadb_msg_len += sa_dmask.sadb_address_len;
343 		iov_cnt++;
344 		break;
345 	}
346 
347 	/* dest addr */
348 	iov[iov_cnt].iov_base = &sa_dst;
349 	iov[iov_cnt].iov_len = sizeof(sa_dst);
350 	iov_cnt++;
351 	iov[iov_cnt].iov_base = &sdst;
352 	iov[iov_cnt].iov_len = ROUNDUP(sdst.ss_len);
353 	smsg.sadb_msg_len += sa_dst.sadb_address_len;
354 	iov_cnt++;
355 
356 	/* src addr */
357 	iov[iov_cnt].iov_base = &sa_src;
358 	iov[iov_cnt].iov_len = sizeof(sa_src);
359 	iov_cnt++;
360 	iov[iov_cnt].iov_base = &ssrc;
361 	iov[iov_cnt].iov_len = ROUNDUP(ssrc.ss_len);
362 	smsg.sadb_msg_len += sa_src.sadb_address_len;
363 	iov_cnt++;
364 
365 	switch (mtype) {
366 	case SADB_ADD:
367 	case SADB_UPDATE:
368 		if (alen) {
369 			/* auth key */
370 			iov[iov_cnt].iov_base = &sa_akey;
371 			iov[iov_cnt].iov_len = sizeof(sa_akey);
372 			iov_cnt++;
373 			iov[iov_cnt].iov_base = akey;
374 			iov[iov_cnt].iov_len = ((alen + 7) / 8) * 8;
375 			smsg.sadb_msg_len += sa_akey.sadb_key_len;
376 			iov_cnt++;
377 		}
378 		if (elen) {
379 			/* encryption key */
380 			iov[iov_cnt].iov_base = &sa_ekey;
381 			iov[iov_cnt].iov_len = sizeof(sa_ekey);
382 			iov_cnt++;
383 			iov[iov_cnt].iov_base = ekey;
384 			iov[iov_cnt].iov_len = ((elen + 7) / 8) * 8;
385 			smsg.sadb_msg_len += sa_ekey.sadb_key_len;
386 			iov_cnt++;
387 		}
388 		break;
389 	}
390 
391 	len = smsg.sadb_msg_len * 8;
392 	do {
393 		n = writev(sd, iov, iov_cnt);
394 	} while (n == -1 && (errno == EAGAIN || errno == EINTR));
395 
396 	if (n == -1) {
397 		log_warn("writev (%d/%d)", iov_cnt, len);
398 		return (-1);
399 	}
400 
401 	return (0);
402 }
403 
404 int
405 pfkey_read(int sd, struct sadb_msg *h)
406 {
407 	struct sadb_msg hdr;
408 
409 	if (recv(sd, &hdr, sizeof(hdr), MSG_PEEK) != sizeof(hdr)) {
410 		if (errno == EAGAIN || errno == EINTR)
411 			return (0);
412 		log_warn("pfkey peek");
413 		return (-1);
414 	}
415 
416 	/* XXX: Only one message can be outstanding. */
417 	if (hdr.sadb_msg_seq == sadb_msg_seq &&
418 	    hdr.sadb_msg_pid == pid) {
419 		if (h)
420 			bcopy(&hdr, h, sizeof(hdr));
421 		return (0);
422 	}
423 
424 	/* not ours, discard */
425 	if (read(sd, &hdr, sizeof(hdr)) == -1) {
426 		if (errno == EAGAIN || errno == EINTR)
427 			return (0);
428 		log_warn("pfkey read");
429 		return (-1);
430 	}
431 
432 	return (1);
433 }
434 
435 int
436 pfkey_reply(int sd, u_int32_t *spip)
437 {
438 	struct sadb_msg hdr, *msg;
439 	struct sadb_ext *ext;
440 	struct sadb_sa *sa;
441 	u_int8_t *data;
442 	ssize_t len;
443 	int rv;
444 
445 	do {
446 		rv = pfkey_read(sd, &hdr);
447 		if (rv == -1)
448 			return (-1);
449 	} while (rv);
450 
451 	if (hdr.sadb_msg_errno != 0) {
452 		errno = hdr.sadb_msg_errno;
453 		if (errno == ESRCH)
454 			return (0);
455 		else {
456 			log_warn("pfkey");
457 			return (-1);
458 		}
459 	}
460 	if ((data = reallocarray(NULL, hdr.sadb_msg_len, PFKEY2_CHUNK)) == NULL) {
461 		log_warn("pfkey malloc");
462 		return (-1);
463 	}
464 	len = hdr.sadb_msg_len * PFKEY2_CHUNK;
465 	if (read(sd, data, len) != len) {
466 		log_warn("pfkey read");
467 		explicit_bzero(data, len);
468 		free(data);
469 		return (-1);
470 	}
471 
472 	if (hdr.sadb_msg_type == SADB_GETSPI) {
473 		if (spip == NULL) {
474 			explicit_bzero(data, len);
475 			free(data);
476 			return (0);
477 		}
478 
479 		msg = (struct sadb_msg *)data;
480 		for (ext = (struct sadb_ext *)(msg + 1);
481 		    (size_t)((u_int8_t *)ext - (u_int8_t *)msg) <
482 		    msg->sadb_msg_len * PFKEY2_CHUNK;
483 		    ext = (struct sadb_ext *)((u_int8_t *)ext +
484 		    ext->sadb_ext_len * PFKEY2_CHUNK)) {
485 			if (ext->sadb_ext_type == SADB_EXT_SA) {
486 				sa = (struct sadb_sa *) ext;
487 				*spip = sa->sadb_sa_spi;
488 				break;
489 			}
490 		}
491 	}
492 	explicit_bzero(data, len);
493 	free(data);
494 	return (0);
495 }
496 
497 int
498 pfkey_sa_add(struct bgpd_addr *src, struct bgpd_addr *dst, u_int8_t keylen,
499     char *key, u_int32_t *spi)
500 {
501 	if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_GETSPI, 0,
502 	    src, dst, 0, 0, 0, NULL, 0, 0, NULL, 0, 0) < 0)
503 		return (-1);
504 	if (pfkey_reply(fd, spi) < 0)
505 		return (-1);
506 	if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_UPDATE, 0,
507 		src, dst, *spi, 0, keylen, key, 0, 0, NULL, 0, 0) < 0)
508 		return (-1);
509 	if (pfkey_reply(fd, NULL) < 0)
510 		return (-1);
511 	return (0);
512 }
513 
514 int
515 pfkey_sa_remove(struct bgpd_addr *src, struct bgpd_addr *dst, u_int32_t *spi)
516 {
517 	if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_DELETE, 0,
518 	    src, dst, *spi, 0, 0, NULL, 0, 0, NULL, 0, 0) < 0)
519 		return (-1);
520 	if (pfkey_reply(fd, NULL) < 0)
521 		return (-1);
522 	*spi = 0;
523 	return (0);
524 }
525 
526 int
527 pfkey_md5sig_establish(struct peer *p)
528 {
529 	sleep(1);
530 
531 	if (!p->auth.spi_out)
532 		if (pfkey_sa_add(&p->auth.local_addr, &p->conf.remote_addr,
533 		    p->conf.auth.md5key_len, p->conf.auth.md5key,
534 		    &p->auth.spi_out) == -1)
535 			return (-1);
536 	if (!p->auth.spi_in)
537 		if (pfkey_sa_add(&p->conf.remote_addr, &p->auth.local_addr,
538 		    p->conf.auth.md5key_len, p->conf.auth.md5key,
539 		    &p->auth.spi_in) == -1)
540 			return (-1);
541 
542 	p->auth.established = 1;
543 	return (0);
544 }
545 
546 int
547 pfkey_md5sig_remove(struct peer *p)
548 {
549 	if (p->auth.spi_out)
550 		if (pfkey_sa_remove(&p->auth.local_addr, &p->conf.remote_addr,
551 		    &p->auth.spi_out) == -1)
552 			return (-1);
553 	if (p->auth.spi_in)
554 		if (pfkey_sa_remove(&p->conf.remote_addr, &p->auth.local_addr,
555 		    &p->auth.spi_in) == -1)
556 			return (-1);
557 
558 	p->auth.established = 0;
559 	return (0);
560 }
561 
562 int
563 pfkey_ipsec_establish(struct peer *p)
564 {
565 	uint8_t satype = SADB_SATYPE_ESP;
566 
567 	switch (p->auth.method) {
568 	case AUTH_IPSEC_IKE_ESP:
569 		satype = SADB_SATYPE_ESP;
570 		break;
571 	case AUTH_IPSEC_IKE_AH:
572 		satype = SADB_SATYPE_AH;
573 		break;
574 	case AUTH_IPSEC_MANUAL_ESP:
575 	case AUTH_IPSEC_MANUAL_AH:
576 		satype = p->auth.method == AUTH_IPSEC_MANUAL_ESP ?
577 		    SADB_SATYPE_ESP : SADB_SATYPE_AH;
578 		if (pfkey_send(fd, satype, SADB_ADD, 0,
579 		    &p->auth.local_addr, &p->conf.remote_addr,
580 		    p->auth.spi_out,
581 		    p->conf.auth.auth_alg_out,
582 		    p->conf.auth.auth_keylen_out,
583 		    p->conf.auth.auth_key_out,
584 		    p->conf.auth.enc_alg_out,
585 		    p->conf.auth.enc_keylen_out,
586 		    p->conf.auth.enc_key_out,
587 		    0, 0) < 0)
588 			return (-1);
589 		if (pfkey_reply(fd, NULL) < 0)
590 			return (-1);
591 		if (pfkey_send(fd, satype, SADB_ADD, 0,
592 		    &p->conf.remote_addr, &p->auth.local_addr,
593 		    p->auth.spi_in,
594 		    p->conf.auth.auth_alg_in,
595 		    p->conf.auth.auth_keylen_in,
596 		    p->conf.auth.auth_key_in,
597 		    p->conf.auth.enc_alg_in,
598 		    p->conf.auth.enc_keylen_in,
599 		    p->conf.auth.enc_key_in,
600 		    0, 0) < 0)
601 			return (-1);
602 		if (pfkey_reply(fd, NULL) < 0)
603 			return (-1);
604 		break;
605 	default:
606 		return (-1);
607 		break;
608 	}
609 
610 	if (pfkey_flow(fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_OUT,
611 	    &p->auth.local_addr, &p->conf.remote_addr, 0, BGP_PORT) < 0)
612 		return (-1);
613 	if (pfkey_reply(fd, NULL) < 0)
614 		return (-1);
615 
616 	if (pfkey_flow(fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_OUT,
617 	    &p->auth.local_addr, &p->conf.remote_addr, BGP_PORT, 0) < 0)
618 		return (-1);
619 	if (pfkey_reply(fd, NULL) < 0)
620 		return (-1);
621 
622 	if (pfkey_flow(fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_IN,
623 	    &p->conf.remote_addr, &p->auth.local_addr, 0, BGP_PORT) < 0)
624 		return (-1);
625 	if (pfkey_reply(fd, NULL) < 0)
626 		return (-1);
627 
628 	if (pfkey_flow(fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_IN,
629 	    &p->conf.remote_addr, &p->auth.local_addr, BGP_PORT, 0) < 0)
630 		return (-1);
631 	if (pfkey_reply(fd, NULL) < 0)
632 		return (-1);
633 
634 	p->auth.established = 1;
635 	return (0);
636 }
637 
638 int
639 pfkey_ipsec_remove(struct peer *p)
640 {
641 	uint8_t satype;
642 
643 	switch (p->auth.method) {
644 	case AUTH_IPSEC_IKE_ESP:
645 		satype = SADB_SATYPE_ESP;
646 		break;
647 	case AUTH_IPSEC_IKE_AH:
648 		satype = SADB_SATYPE_AH;
649 		break;
650 	case AUTH_IPSEC_MANUAL_ESP:
651 	case AUTH_IPSEC_MANUAL_AH:
652 		satype = p->auth.method == AUTH_IPSEC_MANUAL_ESP ?
653 		    SADB_SATYPE_ESP : SADB_SATYPE_AH;
654 		if (pfkey_send(fd, satype, SADB_DELETE, 0,
655 		    &p->auth.local_addr, &p->conf.remote_addr,
656 		    p->auth.spi_out, 0, 0, NULL, 0, 0, NULL,
657 		    0, 0) < 0)
658 			return (-1);
659 		if (pfkey_reply(fd, NULL) < 0)
660 			return (-1);
661 
662 		if (pfkey_send(fd, satype, SADB_DELETE, 0,
663 		    &p->conf.remote_addr, &p->auth.local_addr,
664 		    p->auth.spi_in, 0, 0, NULL, 0, 0, NULL,
665 		    0, 0) < 0)
666 			return (-1);
667 		if (pfkey_reply(fd, NULL) < 0)
668 			return (-1);
669 		break;
670 	default:
671 		return (-1);
672 		break;
673 	}
674 
675 	if (pfkey_flow(fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_OUT,
676 	    &p->auth.local_addr, &p->conf.remote_addr, 0, BGP_PORT) < 0)
677 		return (-1);
678 	if (pfkey_reply(fd, NULL) < 0)
679 		return (-1);
680 
681 	if (pfkey_flow(fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_OUT,
682 	    &p->auth.local_addr, &p->conf.remote_addr, BGP_PORT, 0) < 0)
683 		return (-1);
684 	if (pfkey_reply(fd, NULL) < 0)
685 		return (-1);
686 
687 	if (pfkey_flow(fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_IN,
688 	    &p->conf.remote_addr, &p->auth.local_addr, 0, BGP_PORT) < 0)
689 		return (-1);
690 	if (pfkey_reply(fd, NULL) < 0)
691 		return (-1);
692 
693 	if (pfkey_flow(fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_IN,
694 	    &p->conf.remote_addr, &p->auth.local_addr, BGP_PORT, 0) < 0)
695 		return (-1);
696 	if (pfkey_reply(fd, NULL) < 0)
697 		return (-1);
698 
699 	p->auth.established = 0;
700 	return (0);
701 }
702 
703 int
704 pfkey_establish(struct peer *p)
705 {
706 	/*
707 	 * make sure we keep copies of everything we need to
708 	 * remove SAs and flows later again, even if the
709 	 * info in p->conf changed due to reload.
710 	 * We need: SPIs, method, local_addr, remote_addr.
711 	 * remote_addr cannot change, so no copy.
712 	 */
713 	memcpy(&p->auth.local_addr, &p->conf.local_addr,
714 	    sizeof(p->auth.local_addr));
715 	p->auth.method = p->conf.auth.method;
716 	p->auth.spi_in = p->conf.auth.spi_in;
717 	p->auth.spi_out = p->conf.auth.spi_out;
718 
719 	if (!p->auth.method)
720 		return (0);
721 	else if (p->auth.method == AUTH_MD5SIG)
722 		return (pfkey_md5sig_establish(p));
723 	else
724 		return (pfkey_ipsec_establish(p));
725 }
726 
727 int
728 pfkey_remove(struct peer *p)
729 {
730 	if (!p->auth.established)
731 		return (0);
732 	else if (p->auth.method == AUTH_MD5SIG)
733 		return (pfkey_md5sig_remove(p));
734 	else
735 		return (pfkey_ipsec_remove(p));
736 }
737 
738 int
739 pfkey_init(struct bgpd_sysdep *sysdep)
740 {
741 	if ((fd = socket(PF_KEY, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK,
742 	    PF_KEY_V2)) == -1) {
743 		if (errno == EPROTONOSUPPORT) {
744 			log_warnx("PF_KEY not available, disabling ipsec");
745 			sysdep->no_pfkey = 1;
746 			return (-1);
747 		} else
748 			fatal("pfkey setup failed");
749 	}
750 	return (fd);
751 }
752