GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/bgpd/pfkey.c Lines: 0 430 0.0 %
Date: 2017-11-07 Branches: 0 199 0.0 %

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