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