GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/bgpd/pfkey.c Lines: 0 384 0.0 %
Date: 2016-12-06 Branches: 0 202 0.0 %

Line Branch Exec Source
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
}