GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/bgplg/bgpctl/../../../usr.sbin/bgpctl/mrtparser.c Lines: 0 645 0.0 %
Date: 2017-11-07 Branches: 0 363 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: mrtparser.c,v 1.8 2015/12/23 20:42:20 mmcc Exp $ */
2
/*
3
 * Copyright (c) 2011 Claudio Jeker <claudio@openbsd.org>
4
 *
5
 * Permission to use, copy, modify, and distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 */
17
#include <sys/types.h>
18
#include <sys/socket.h>
19
#include <netinet/in.h>
20
#include <err.h>
21
#include <errno.h>
22
#include <limits.h>
23
#include <stdlib.h>
24
#include <stdio.h>
25
#include <string.h>
26
#include <unistd.h>
27
28
#include "mrt.h"
29
#include "mrtparser.h"
30
31
void	*mrt_read_msg(int, struct mrt_hdr *);
32
size_t	 mrt_read_buf(int, void *, size_t);
33
34
struct mrt_peer	*mrt_parse_v2_peer(struct mrt_hdr *, void *);
35
struct mrt_rib	*mrt_parse_v2_rib(struct mrt_hdr *, void *);
36
int	mrt_parse_dump(struct mrt_hdr *, void *, struct mrt_peer **,
37
	    struct mrt_rib **);
38
int	mrt_parse_dump_mp(struct mrt_hdr *, void *, struct mrt_peer **,
39
	    struct mrt_rib **);
40
int	mrt_extract_attr(struct mrt_rib_entry *, u_char *, int, sa_family_t,
41
	    int);
42
43
void	mrt_free_peers(struct mrt_peer *);
44
void	mrt_free_rib(struct mrt_rib *);
45
void	mrt_free_bgp_state(struct mrt_bgp_state *);
46
void	mrt_free_bgp_msg(struct mrt_bgp_msg *);
47
48
u_char *mrt_aspath_inflate(void *, u_int16_t, u_int16_t *);
49
int	mrt_extract_addr(void *, u_int, union mrt_addr *, sa_family_t);
50
51
struct mrt_bgp_state	*mrt_parse_state(struct mrt_hdr *, void *);
52
struct mrt_bgp_msg	*mrt_parse_msg(struct mrt_hdr *, void *);
53
54
void *
55
mrt_read_msg(int fd, struct mrt_hdr *hdr)
56
{
57
	void *buf;
58
59
	bzero(hdr, sizeof(*hdr));
60
	if (mrt_read_buf(fd, hdr, sizeof(*hdr)) != sizeof(*hdr))
61
		return (NULL);
62
63
	if ((buf = malloc(ntohl(hdr->length))) == NULL)
64
		err(1, "malloc(%d)", hdr->length);
65
66
	if (mrt_read_buf(fd, buf, ntohl(hdr->length)) != ntohl(hdr->length)) {
67
		free(buf);
68
		return (NULL);
69
	}
70
	return (buf);
71
}
72
73
size_t
74
mrt_read_buf(int fd, void *buf, size_t len)
75
{
76
	char *b = buf;
77
	ssize_t n;
78
79
	while (len > 0) {
80
		if ((n = read(fd, b, len)) == -1) {
81
			if (errno == EINTR)
82
				continue;
83
			err(1, "read");
84
		}
85
		if (n == 0)
86
			break;
87
		b += n;
88
		len -= n;
89
	}
90
91
	return (b - (char *)buf);
92
}
93
94
void
95
mrt_parse(int fd, struct mrt_parser *p, int verbose)
96
{
97
	struct mrt_hdr		h;
98
	struct mrt_peer		*pctx = NULL;
99
	struct mrt_rib		*r;
100
	struct mrt_bgp_state	*s;
101
	struct mrt_bgp_msg	*m;
102
	void			*msg;
103
104
	while ((msg = mrt_read_msg(fd, &h))) {
105
		switch (ntohs(h.type)) {
106
		case MSG_NULL:
107
		case MSG_START:
108
		case MSG_DIE:
109
		case MSG_I_AM_DEAD:
110
		case MSG_PEER_DOWN:
111
		case MSG_PROTOCOL_BGP:
112
		case MSG_PROTOCOL_IDRP:
113
		case MSG_PROTOCOL_BGP4PLUS:
114
		case MSG_PROTOCOL_BGP4PLUS1:
115
			if (verbose)
116
				printf("deprecated MRT type %d\n",
117
				    ntohs(h.type));
118
			break;
119
		case MSG_PROTOCOL_RIP:
120
		case MSG_PROTOCOL_RIPNG:
121
		case MSG_PROTOCOL_OSPF:
122
		case MSG_PROTOCOL_ISIS_ET:
123
		case MSG_PROTOCOL_ISIS:
124
		case MSG_PROTOCOL_OSPFV3_ET:
125
		case MSG_PROTOCOL_OSPFV3:
126
			if (verbose)
127
				printf("unsuported MRT type %d\n",
128
				    ntohs(h.type));
129
			break;
130
		case MSG_TABLE_DUMP:
131
			switch (ntohs(h.subtype)) {
132
			case MRT_DUMP_AFI_IP:
133
			case MRT_DUMP_AFI_IPv6:
134
				if (p->dump == NULL)
135
					break;
136
				if (mrt_parse_dump(&h, msg, &pctx, &r) == 0) {
137
					if (p->dump)
138
						p->dump(r, pctx, p->arg);
139
					mrt_free_rib(r);
140
				}
141
				break;
142
			default:
143
				if (verbose)
144
					printf("unknown AFI %d in table dump\n",
145
					    ntohs(h.subtype));
146
				break;
147
			}
148
			break;
149
		case MSG_TABLE_DUMP_V2:
150
			switch (ntohs(h.subtype)) {
151
			case MRT_DUMP_V2_PEER_INDEX_TABLE:
152
				if (p->dump == NULL)
153
					break;
154
				if (pctx)
155
					mrt_free_peers(pctx);
156
				pctx = mrt_parse_v2_peer(&h, msg);
157
				break;
158
			case MRT_DUMP_V2_RIB_IPV4_UNICAST:
159
			case MRT_DUMP_V2_RIB_IPV4_MULTICAST:
160
			case MRT_DUMP_V2_RIB_IPV6_UNICAST:
161
			case MRT_DUMP_V2_RIB_IPV6_MULTICAST:
162
			case MRT_DUMP_V2_RIB_GENERIC:
163
				if (p->dump == NULL)
164
					break;
165
				r = mrt_parse_v2_rib(&h, msg);
166
				if (r) {
167
					if (p->dump)
168
						p->dump(r, pctx, p->arg);
169
					mrt_free_rib(r);
170
				}
171
				break;
172
			default:
173
				if (verbose)
174
					printf("unhandled BGP4MP subtype %d\n",
175
					    ntohs(h.subtype));
176
				break;
177
			}
178
			break;
179
		case MSG_PROTOCOL_BGP4MP_ET:
180
		case MSG_PROTOCOL_BGP4MP:
181
			switch (ntohs(h.subtype)) {
182
			case BGP4MP_STATE_CHANGE:
183
			case BGP4MP_STATE_CHANGE_AS4:
184
				if ((s = mrt_parse_state(&h, msg))) {
185
					if (p->state)
186
						p->state(s, p->arg);
187
					free(s);
188
				}
189
				break;
190
			case BGP4MP_MESSAGE:
191
			case BGP4MP_MESSAGE_AS4:
192
			case BGP4MP_MESSAGE_LOCAL:
193
			case BGP4MP_MESSAGE_AS4_LOCAL:
194
				if ((m = mrt_parse_msg(&h, msg))) {
195
					if (p->message)
196
						p->message(m, p->arg);
197
					free(m->msg);
198
					free(m);
199
				}
200
				break;
201
			case BGP4MP_ENTRY:
202
				if (p->dump == NULL)
203
					break;
204
				if (mrt_parse_dump_mp(&h, msg, &pctx, &r) ==
205
				    0) {
206
					if (p->dump)
207
						p->dump(r, pctx, p->arg);
208
					mrt_free_rib(r);
209
				}
210
				break;
211
			default:
212
				if (verbose)
213
					printf("unhandled BGP4MP subtype %d\n",
214
					    ntohs(h.subtype));
215
				break;
216
			}
217
			break;
218
		default:
219
			if (verbose)
220
				printf("unknown MRT type %d\n", ntohs(h.type));
221
			break;
222
		}
223
		free(msg);
224
	}
225
	if (pctx)
226
		mrt_free_peers(pctx);
227
}
228
229
struct mrt_peer *
230
mrt_parse_v2_peer(struct mrt_hdr *hdr, void *msg)
231
{
232
	struct mrt_peer_entry	*peers = NULL;
233
	struct mrt_peer	*p;
234
	u_int8_t	*b = msg;
235
	u_int32_t	bid, as4;
236
	u_int16_t	cnt, i, as2;
237
	u_int		len = ntohl(hdr->length);
238
239
	if (len < 8)	/* min msg size */
240
		return NULL;
241
242
	p = calloc(1, sizeof(struct mrt_peer));
243
	if (p == NULL)
244
		err(1, "calloc");
245
246
	/* collector bgp id */
247
	memcpy(&bid, b, sizeof(bid));
248
	b += sizeof(bid);
249
	len -= sizeof(bid);
250
	p->bgp_id = ntohl(bid);
251
252
	/* view name length */
253
	memcpy(&cnt, b, sizeof(cnt));
254
	b += sizeof(cnt);
255
	len -= sizeof(cnt);
256
	cnt = ntohs(cnt);
257
258
	/* view name */
259
	if (cnt > len)
260
		goto fail;
261
	if (cnt != 0) {
262
		if ((p->view = malloc(cnt + 1)) == NULL)
263
			err(1, "malloc");
264
		memcpy(p->view, b, cnt);
265
		p->view[cnt] = 0;
266
	} else
267
		if ((p->view = strdup("")) == NULL)
268
			err(1, "strdup");
269
	b += cnt;
270
	len -= cnt;
271
272
	/* peer_count */
273
	if (len < sizeof(cnt))
274
		goto fail;
275
	memcpy(&cnt, b, sizeof(cnt));
276
	b += sizeof(cnt);
277
	len -= sizeof(cnt);
278
	cnt = ntohs(cnt);
279
280
	/* peer entries */
281
	if ((peers = calloc(cnt, sizeof(struct mrt_peer_entry))) == NULL)
282
		err(1, "calloc");
283
	for (i = 0; i < cnt; i++) {
284
		u_int8_t type;
285
286
		if (len < sizeof(u_int8_t) + sizeof(u_int32_t))
287
			goto fail;
288
		type = *b++;
289
		len -= 1;
290
		memcpy(&bid, b, sizeof(bid));
291
		b += sizeof(bid);
292
		len -= sizeof(bid);
293
		peers[i].bgp_id = ntohl(bid);
294
295
		if (type & MRT_DUMP_V2_PEER_BIT_I) {
296
			if (mrt_extract_addr(b, len, &peers[i].addr,
297
			    AF_INET6) == -1)
298
				goto fail;
299
			b += sizeof(struct in6_addr);
300
			len -= sizeof(struct in6_addr);
301
		} else {
302
			if (mrt_extract_addr(b, len, &peers[i].addr,
303
			    AF_INET) == -1)
304
				goto fail;
305
			b += sizeof(struct in_addr);
306
			len -= sizeof(struct in_addr);
307
		}
308
309
		if (type & MRT_DUMP_V2_PEER_BIT_A) {
310
			memcpy(&as4, b, sizeof(as4));
311
			b += sizeof(as4);
312
			len -= sizeof(as4);
313
			as4 = ntohl(as4);
314
		} else {
315
			memcpy(&as2, b, sizeof(as2));
316
			b += sizeof(as2);
317
			len -= sizeof(as2);
318
			as4 = ntohs(as2);
319
		}
320
		peers[i].asnum = as4;
321
	}
322
	p->peers = peers;
323
	p->npeers = cnt;
324
	return (p);
325
fail:
326
	mrt_free_peers(p);
327
	free(peers);
328
	return (NULL);
329
}
330
331
struct mrt_rib *
332
mrt_parse_v2_rib(struct mrt_hdr *hdr, void *msg)
333
{
334
	struct mrt_rib_entry *entries = NULL;
335
	struct mrt_rib	*r;
336
	u_int8_t	*b = msg;
337
	u_int		len = ntohl(hdr->length);
338
	u_int32_t	snum;
339
	u_int16_t	cnt, i;
340
	u_int8_t	plen;
341
342
	if (len < sizeof(snum) + 1)
343
		return NULL;
344
345
	r = calloc(1, sizeof(struct mrt_rib));
346
	if (r == NULL)
347
		err(1, "calloc");
348
349
	/* seq_num */
350
	memcpy(&snum, b, sizeof(snum));
351
	b += sizeof(snum);
352
	len -= sizeof(snum);
353
	r->seqnum = ntohl(snum);
354
355
	switch (ntohs(hdr->subtype)) {
356
	case MRT_DUMP_V2_RIB_IPV4_UNICAST:
357
	case MRT_DUMP_V2_RIB_IPV4_MULTICAST:
358
		plen = *b++;
359
		len -= 1;
360
		if (len < MRT_PREFIX_LEN(plen))
361
			goto fail;
362
		r->prefix.sin.sin_family = AF_INET;
363
		r->prefix.sin.sin_len = sizeof(struct sockaddr_in);
364
		memcpy(&r->prefix.sin.sin_addr, b, MRT_PREFIX_LEN(plen));
365
		b += MRT_PREFIX_LEN(plen);
366
		len -= MRT_PREFIX_LEN(plen);
367
		r->prefixlen = plen;
368
		break;
369
	case MRT_DUMP_V2_RIB_IPV6_UNICAST:
370
	case MRT_DUMP_V2_RIB_IPV6_MULTICAST:
371
		plen = *b++;
372
		len -= 1;
373
		if (len < MRT_PREFIX_LEN(plen))
374
			goto fail;
375
		r->prefix.sin6.sin6_family = AF_INET6;
376
		r->prefix.sin6.sin6_len = sizeof(struct sockaddr_in6);
377
		memcpy(&r->prefix.sin6.sin6_addr, b, MRT_PREFIX_LEN(plen));
378
		b += MRT_PREFIX_LEN(plen);
379
		len -= MRT_PREFIX_LEN(plen);
380
		r->prefixlen = plen;
381
		break;
382
	case MRT_DUMP_V2_RIB_GENERIC:
383
		/* XXX unhandled */
384
		errx(1, "MRT_DUMP_V2_RIB_GENERIC subtype not yet implemented");
385
		goto fail;
386
	}
387
388
	/* entries count */
389
	if (len < sizeof(cnt))
390
		goto fail;
391
	memcpy(&cnt, b, sizeof(cnt));
392
	b += sizeof(cnt);
393
	len -= sizeof(cnt);
394
	cnt = ntohs(cnt);
395
	r->nentries = cnt;
396
397
	/* entries */
398
	if ((entries = calloc(cnt, sizeof(struct mrt_rib_entry))) == NULL)
399
		err(1, "calloc");
400
	for (i = 0; i < cnt; i++) {
401
		u_int32_t	otm;
402
		u_int16_t	pix, alen;
403
		if (len < 2 * sizeof(u_int16_t) + sizeof(u_int32_t))
404
			goto fail;
405
		/* peer index */
406
		memcpy(&pix, b, sizeof(pix));
407
		b += sizeof(pix);
408
		len -= sizeof(pix);
409
		entries[i].peer_idx = ntohs(pix);
410
411
		/* originated */
412
		memcpy(&otm, b, sizeof(otm));
413
		b += sizeof(otm);
414
		len -= sizeof(otm);
415
		entries[i].originated = ntohl(otm);
416
417
		/* attr_len */
418
		memcpy(&alen, b, sizeof(alen));
419
		b += sizeof(alen);
420
		len -= sizeof(alen);
421
		alen = ntohs(alen);
422
423
		/* attr */
424
		if (len < alen)
425
			goto fail;
426
		if (mrt_extract_attr(&entries[i], b, alen,
427
		    r->prefix.sa.sa_family, 1) == -1)
428
			goto fail;
429
		b += alen;
430
		len -= alen;
431
	}
432
	r->entries = entries;
433
	return (r);
434
fail:
435
	mrt_free_rib(r);
436
	free(entries);
437
	return (NULL);
438
}
439
440
int
441
mrt_parse_dump(struct mrt_hdr *hdr, void *msg, struct mrt_peer **pp,
442
    struct mrt_rib **rp)
443
{
444
	struct mrt_peer		*p;
445
	struct mrt_rib		*r;
446
	struct mrt_rib_entry	*re;
447
	u_int8_t		*b = msg;
448
	u_int			 len = ntohl(hdr->length);
449
	u_int16_t		 asnum, alen;
450
451
	if (*pp == NULL) {
452
		*pp = calloc(1, sizeof(struct mrt_peer));
453
		if (*pp == NULL)
454
			err(1, "calloc");
455
		(*pp)->peers = calloc(1, sizeof(struct mrt_peer_entry));
456
		if ((*pp)->peers == NULL)
457
			err(1, "calloc");
458
		(*pp)->npeers = 1;
459
	}
460
	p = *pp;
461
462
	*rp = r = calloc(1, sizeof(struct mrt_rib));
463
	if (r == NULL)
464
		err(1, "calloc");
465
	re = calloc(1, sizeof(struct mrt_rib_entry));
466
	if (re == NULL)
467
		err(1, "calloc");
468
	r->nentries = 1;
469
	r->entries = re;
470
471
	if (len < 2 * sizeof(u_int16_t))
472
		goto fail;
473
	/* view */
474
	b += sizeof(u_int16_t);
475
	len -= sizeof(u_int16_t);
476
	/* seqnum */
477
	memcpy(&r->seqnum, b, sizeof(u_int16_t));
478
	b += sizeof(u_int16_t);
479
	len -= sizeof(u_int16_t);
480
	r->seqnum = ntohs(r->seqnum);
481
482
	switch (ntohs(hdr->subtype)) {
483
	case MRT_DUMP_AFI_IP:
484
		if (mrt_extract_addr(b, len, &r->prefix, AF_INET) == -1)
485
			goto fail;
486
		b += sizeof(struct in_addr);
487
		len -= sizeof(struct in_addr);
488
		break;
489
	case MRT_DUMP_AFI_IPv6:
490
		if (mrt_extract_addr(b, len, &r->prefix, AF_INET6) == -1)
491
			goto fail;
492
		b += sizeof(struct in6_addr);
493
		len -= sizeof(struct in6_addr);
494
		break;
495
	}
496
	if (len < 2 * sizeof(u_int32_t) + 2 * sizeof(u_int16_t) + 2)
497
		goto fail;
498
	r->prefixlen = *b++;
499
	len -= 1;
500
	/* status */
501
	b += 1;
502
	len -= 1;
503
	/* originated */
504
	memcpy(&re->originated, b, sizeof(u_int32_t));
505
	b += sizeof(u_int32_t);
506
	len -= sizeof(u_int32_t);
507
	re->originated = ntohl(re->originated);
508
	/* peer ip */
509
	switch (ntohs(hdr->subtype)) {
510
	case MRT_DUMP_AFI_IP:
511
		if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET) == -1)
512
			goto fail;
513
		b += sizeof(struct in_addr);
514
		len -= sizeof(struct in_addr);
515
		break;
516
	case MRT_DUMP_AFI_IPv6:
517
		if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET6) == -1)
518
			goto fail;
519
		b += sizeof(struct in6_addr);
520
		len -= sizeof(struct in6_addr);
521
		break;
522
	}
523
	memcpy(&asnum, b, sizeof(asnum));
524
	b += sizeof(asnum);
525
	len -= sizeof(asnum);
526
	p->peers->asnum = ntohs(asnum);
527
528
	memcpy(&alen, b, sizeof(alen));
529
	b += sizeof(alen);
530
	len -= sizeof(alen);
531
	alen = ntohs(alen);
532
533
	/* attr */
534
	if (len < alen)
535
		goto fail;
536
	if (mrt_extract_attr(re, b, alen, r->prefix.sa.sa_family, 0) == -1)
537
		goto fail;
538
	b += alen;
539
	len -= alen;
540
541
	return (0);
542
fail:
543
	mrt_free_rib(r);
544
	return (-1);
545
}
546
547
int
548
mrt_parse_dump_mp(struct mrt_hdr *hdr, void *msg, struct mrt_peer **pp,
549
    struct mrt_rib **rp)
550
{
551
	struct mrt_peer		*p;
552
	struct mrt_rib		*r;
553
	struct mrt_rib_entry	*re;
554
	u_int8_t		*b = msg;
555
	u_int			 len = ntohl(hdr->length);
556
	u_int16_t		 asnum, alen, afi;
557
	u_int8_t		 safi, nhlen;
558
	sa_family_t		 af;
559
560
	/* just ignore the microsec field for _ET header for now */
561
	if (ntohs(hdr->type) == MSG_PROTOCOL_BGP4MP_ET) {
562
		b = (char *)b + sizeof(u_int32_t);
563
		len -= sizeof(u_int32_t);
564
	}
565
566
	if (*pp == NULL) {
567
		*pp = calloc(1, sizeof(struct mrt_peer));
568
		if (*pp == NULL)
569
			err(1, "calloc");
570
		(*pp)->peers = calloc(1, sizeof(struct mrt_peer_entry));
571
		if ((*pp)->peers == NULL)
572
			err(1, "calloc");
573
		(*pp)->npeers = 1;
574
	}
575
	p = *pp;
576
577
	*rp = r = calloc(1, sizeof(struct mrt_rib));
578
	if (r == NULL)
579
		err(1, "calloc");
580
	re = calloc(1, sizeof(struct mrt_rib_entry));
581
	if (re == NULL)
582
		err(1, "calloc");
583
	r->nentries = 1;
584
	r->entries = re;
585
586
	if (len < 4 * sizeof(u_int16_t))
587
		goto fail;
588
	/* source AS */
589
	b += sizeof(u_int16_t);
590
	len -= sizeof(u_int16_t);
591
	/* dest AS */
592
	memcpy(&asnum, b, sizeof(asnum));
593
	b += sizeof(asnum);
594
	len -= sizeof(asnum);
595
	p->peers->asnum = ntohs(asnum);
596
	/* iface index */
597
	b += sizeof(u_int16_t);
598
	len -= sizeof(u_int16_t);
599
	/* afi */
600
	memcpy(&afi, b, sizeof(afi));
601
	b += sizeof(afi);
602
	len -= sizeof(afi);
603
	afi = ntohs(afi);
604
605
	/* source + dest ip */
606
	switch (afi) {
607
	case MRT_DUMP_AFI_IP:
608
		if (len < 2 * sizeof(struct in_addr))
609
			goto fail;
610
		/* source IP */
611
		b += sizeof(struct in_addr);
612
		len -= sizeof(struct in_addr);
613
		/* dest IP */
614
		if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET) == -1)
615
			goto fail;
616
		b += sizeof(struct in_addr);
617
		len -= sizeof(struct in_addr);
618
		break;
619
	case MRT_DUMP_AFI_IPv6:
620
		if (len < 2 * sizeof(struct in6_addr))
621
			goto fail;
622
		/* source IP */
623
		b += sizeof(struct in6_addr);
624
		len -= sizeof(struct in6_addr);
625
		/* dest IP */
626
		if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET6) == -1)
627
			goto fail;
628
		b += sizeof(struct in6_addr);
629
		len -= sizeof(struct in6_addr);
630
		break;
631
	}
632
633
	if (len < 2 * sizeof(u_int16_t) + 2 * sizeof(u_int32_t))
634
		goto fail;
635
	/* view + status */
636
	b += 2 * sizeof(u_int16_t);
637
	len -= 2 * sizeof(u_int16_t);
638
	/* originated */
639
	memcpy(&re->originated, b, sizeof(u_int32_t));
640
	b += sizeof(u_int32_t);
641
	len -= sizeof(u_int32_t);
642
	re->originated = ntohl(re->originated);
643
644
	/* afi */
645
	memcpy(&afi, b, sizeof(afi));
646
	b += sizeof(afi);
647
	len -= sizeof(afi);
648
	afi = ntohs(afi);
649
650
	/* safi */
651
	safi = *b++;
652
	len -= 1;
653
654
	switch (afi) {
655
	case MRT_DUMP_AFI_IP:
656
		if (safi == 1 || safi == 2) {
657
			af = AF_INET;
658
			break;
659
		} else if (safi == 128) {
660
			af = AF_VPNv4;
661
			break;
662
		}
663
		goto fail;
664
	case MRT_DUMP_AFI_IPv6:
665
		if (safi != 1 && safi != 2)
666
			goto fail;
667
		af = AF_INET6;
668
		break;
669
	default:
670
		goto fail;
671
	}
672
673
	/* nhlen */
674
	nhlen = *b++;
675
	len -= 1;
676
677
	/* nexthop */
678
	if (mrt_extract_addr(b, len, &re->nexthop, af) == -1)
679
		goto fail;
680
	if (len < nhlen)
681
		goto fail;
682
	b += nhlen;
683
	len -= nhlen;
684
685
	if (len < 1)
686
		goto fail;
687
	r->prefixlen = *b++;
688
	len -= 1;
689
690
	/* prefix */
691
	switch (af) {
692
	case AF_INET:
693
		if (len < MRT_PREFIX_LEN(r->prefixlen))
694
			goto fail;
695
		r->prefix.sin.sin_family = AF_INET;
696
		r->prefix.sin.sin_len = sizeof(struct sockaddr_in);
697
		memcpy(&r->prefix.sin.sin_addr, b,
698
		    MRT_PREFIX_LEN(r->prefixlen));
699
		b += MRT_PREFIX_LEN(r->prefixlen);
700
		len -= MRT_PREFIX_LEN(r->prefixlen);
701
		break;
702
	case AF_INET6:
703
		if (len < MRT_PREFIX_LEN(r->prefixlen))
704
			goto fail;
705
		r->prefix.sin6.sin6_family = AF_INET6;
706
		r->prefix.sin6.sin6_len = sizeof(struct sockaddr_in6);
707
		memcpy(&r->prefix.sin6.sin6_addr, b,
708
		    MRT_PREFIX_LEN(r->prefixlen));
709
		b += MRT_PREFIX_LEN(r->prefixlen);
710
		len -= MRT_PREFIX_LEN(r->prefixlen);
711
		break;
712
	case AF_VPNv4:
713
		if (len < MRT_PREFIX_LEN(r->prefixlen))
714
			goto fail;
715
		errx(1, "AF_VPNv4 handling not yet implemented");
716
		goto fail;
717
	}
718
719
	memcpy(&alen, b, sizeof(alen));
720
	b += sizeof(alen);
721
	len -= sizeof(alen);
722
	alen = ntohs(alen);
723
724
	/* attr */
725
	if (len < alen)
726
		goto fail;
727
	if (mrt_extract_attr(re, b, alen, r->prefix.sa.sa_family, 0) == -1)
728
		goto fail;
729
	b += alen;
730
	len -= alen;
731
732
	return (0);
733
fail:
734
	mrt_free_rib(r);
735
	return (-1);
736
}
737
738
int
739
mrt_extract_attr(struct mrt_rib_entry *re, u_char *a, int alen, sa_family_t af,
740
    int as4)
741
{
742
	struct mrt_attr	*ap;
743
	u_int32_t	tmp;
744
	u_int16_t	attr_len;
745
	u_int8_t	type, flags, *attr;
746
747
	do {
748
		if (alen < 3)
749
			return (-1);
750
		attr = a;
751
		flags = *a++;
752
		alen -= 1;
753
		type = *a++;
754
		alen -= 1;
755
756
		if (flags & MRT_ATTR_EXTLEN) {
757
			if (alen < 2)
758
				return (-1);
759
			memcpy(&attr_len, a, sizeof(attr_len));
760
			attr_len = ntohs(attr_len);
761
			a += sizeof(attr_len);
762
			alen -= sizeof(attr_len);
763
		} else {
764
			attr_len = *a++;
765
			alen -= 1;
766
		}
767
		switch (type) {
768
		case MRT_ATTR_ORIGIN:
769
			if (attr_len != 1)
770
				return (-1);
771
			re->origin = *a;
772
			break;
773
		case MRT_ATTR_ASPATH:
774
			if (as4) {
775
				re->aspath_len = attr_len;
776
				if ((re->aspath = malloc(attr_len)) == NULL)
777
					err(1, "malloc");
778
				memcpy(re->aspath, a, attr_len);
779
			} else {
780
				re->aspath = mrt_aspath_inflate(a, attr_len,
781
				    &re->aspath_len);
782
				if (re->aspath == NULL)
783
					return (-1);
784
			}
785
			break;
786
		case MRT_ATTR_NEXTHOP:
787
			if (attr_len != 4)
788
				return (-1);
789
			if (af != AF_INET)
790
				break;
791
			memcpy(&tmp, a, sizeof(tmp));
792
			re->nexthop.sin.sin_len = sizeof(struct sockaddr_in);
793
			re->nexthop.sin.sin_family = AF_INET;
794
			re->nexthop.sin.sin_addr.s_addr = tmp;
795
			break;
796
		case MRT_ATTR_MED:
797
			if (attr_len != 4)
798
				return (-1);
799
			memcpy(&tmp, a, sizeof(tmp));
800
			re->med = ntohl(tmp);
801
			break;
802
		case MRT_ATTR_LOCALPREF:
803
			if (attr_len != 4)
804
				return (-1);
805
			memcpy(&tmp, a, sizeof(tmp));
806
			re->local_pref = ntohl(tmp);
807
			break;
808
		case MRT_ATTR_MP_REACH_NLRI:
809
			/*
810
			 * XXX horrible hack:
811
			 * Once again IETF and the real world differ in the
812
			 * implementation. In short the abbreviated MP_NLRI
813
			 * hack in the standard is not used in real life.
814
			 * Detect the two cases by looking at the first byte
815
			 * of the payload (either the nexthop addr length (RFC)
816
			 * or the high byte of the AFI (old form)). If the
817
			 * first byte matches the expected nexthop length it
818
			 * is expected to be the RFC 6396 encoding.
819
			 */
820
			if (*a != attr_len - 1) {
821
				a += 3;
822
				alen -= 3;
823
				attr_len -= 3;
824
			}
825
			switch (af) {
826
			case AF_INET6:
827
				if (attr_len < sizeof(struct in6_addr) + 1)
828
					return (-1);
829
				re->nexthop.sin6.sin6_len =
830
				    sizeof(struct sockaddr_in6);
831
				re->nexthop.sin6.sin6_family = AF_INET6;
832
				memcpy(&re->nexthop.sin6.sin6_addr, a + 1,
833
				    sizeof(struct in6_addr));
834
				break;
835
			case AF_VPNv4:
836
				if (attr_len < sizeof(u_int64_t) +
837
				    sizeof(struct in_addr))
838
					return (-1);
839
				re->nexthop.svpn4.sv_len =
840
				    sizeof(struct sockaddr_vpn4);
841
				re->nexthop.svpn4.sv_family = AF_VPNv4;
842
				memcpy(&tmp, a + 1 + sizeof(u_int64_t),
843
				    sizeof(tmp));
844
				re->nexthop.svpn4.sv_addr.s_addr = tmp;
845
				break;
846
			}
847
			break;
848
		case MRT_ATTR_AS4PATH:
849
			if (!as4) {
850
				free(re->aspath);
851
				re->aspath_len = attr_len;
852
				if ((re->aspath = malloc(attr_len)) == NULL)
853
					err(1, "malloc");
854
				memcpy(re->aspath, a, attr_len);
855
				break;
856
			}
857
			/* FALLTHROUGH */
858
		default:
859
			re->nattrs++;
860
			if (re->nattrs >= UCHAR_MAX)
861
				err(1, "too many attributes");
862
			ap = reallocarray(re->attrs,
863
			    re->nattrs, sizeof(struct mrt_attr));
864
			if (ap == NULL)
865
				err(1, "realloc");
866
			re->attrs = ap;
867
			ap = re->attrs + re->nattrs - 1;
868
			ap->attr_len = a + attr_len - attr;
869
			if ((ap->attr = malloc(ap->attr_len)) == NULL)
870
				err(1, "malloc");
871
			memcpy(ap->attr, attr, ap->attr_len);
872
			break;
873
		}
874
		a += attr_len;
875
		alen -= attr_len;
876
	} while (alen > 0);
877
878
	return (0);
879
}
880
881
void
882
mrt_free_peers(struct mrt_peer *p)
883
{
884
	free(p->peers);
885
	free(p->view);
886
	free(p);
887
}
888
889
void
890
mrt_free_rib(struct mrt_rib *r)
891
{
892
	u_int16_t	i, j;
893
894
	for (i = 0; i < r->nentries && r->entries; i++) {
895
		for (j = 0; j < r->entries[i].nattrs; j++)
896
			 free(r->entries[i].attrs[j].attr);
897
		free(r->entries[i].attrs);
898
		free(r->entries[i].aspath);
899
	}
900
901
	free(r->entries);
902
	free(r);
903
}
904
905
void
906
mrt_free_bgp_state(struct mrt_bgp_state *s)
907
{
908
	free(s);
909
}
910
911
void
912
mrt_free_bgp_msg(struct mrt_bgp_msg *m)
913
{
914
	free(m->msg);
915
	free(m);
916
}
917
918
u_char *
919
mrt_aspath_inflate(void *data, u_int16_t len, u_int16_t *newlen)
920
{
921
	u_int8_t	*seg, *nseg, *ndata;
922
	u_int16_t	 seg_size, olen, nlen;
923
	u_int8_t	 seg_len;
924
925
	/* first calculate the length of the aspath */
926
	seg = data;
927
	nlen = 0;
928
	for (olen = len; olen > 0; olen -= seg_size, seg += seg_size) {
929
		seg_len = seg[1];
930
		seg_size = 2 + sizeof(u_int16_t) * seg_len;
931
		nlen += 2 + sizeof(u_int32_t) * seg_len;
932
933
		if (seg_size > olen)
934
			return NULL;
935
	}
936
937
	*newlen = nlen;
938
	if ((ndata = malloc(nlen)) == NULL)
939
		err(1, "malloc");
940
941
	/* then copy the aspath */
942
	seg = data;
943
	for (nseg = ndata; nseg < ndata + nlen; ) {
944
		*nseg++ = *seg++;
945
		*nseg++ = seg_len = *seg++;
946
		for (; seg_len > 0; seg_len--) {
947
			*nseg++ = 0;
948
			*nseg++ = 0;
949
			*nseg++ = *seg++;
950
			*nseg++ = *seg++;
951
		}
952
	}
953
954
	return (ndata);
955
}
956
957
int
958
mrt_extract_addr(void *msg, u_int len, union mrt_addr *addr, sa_family_t af)
959
{
960
	u_int8_t	*b = msg;
961
962
	switch (af) {
963
	case AF_INET:
964
		if (len < sizeof(struct in_addr))
965
			return (-1);
966
		addr->sin.sin_family = AF_INET;
967
		addr->sin.sin_len = sizeof(struct sockaddr_in);
968
		memcpy(&addr->sin.sin_addr, b, sizeof(struct in_addr));
969
		return sizeof(struct in_addr);
970
	case AF_INET6:
971
		if (len < sizeof(struct in6_addr))
972
			return (-1);
973
		addr->sin6.sin6_family = AF_INET6;
974
		addr->sin6.sin6_len = sizeof(struct sockaddr_in6);
975
		memcpy(&addr->sin6.sin6_addr, b, sizeof(struct in6_addr));
976
		return sizeof(struct in6_addr);
977
	case AF_VPNv4:
978
		if (len < sizeof(u_int64_t) + sizeof(struct in_addr))
979
			return (-1);
980
		addr->svpn4.sv_len = sizeof(struct sockaddr_vpn4);
981
		addr->svpn4.sv_family = AF_VPNv4;
982
		memcpy(&addr->svpn4.sv_addr, b + sizeof(u_int64_t),
983
		    sizeof(struct in_addr));
984
		return (sizeof(u_int64_t) + sizeof(struct in_addr));
985
	default:
986
		return (-1);
987
	}
988
}
989
990
struct mrt_bgp_state *
991
mrt_parse_state(struct mrt_hdr *hdr, void *msg)
992
{
993
	struct mrt_bgp_state	*s;
994
	u_int8_t		*b = msg;
995
	u_int			 len = ntohl(hdr->length);
996
	u_int32_t		 sas, das;
997
	u_int16_t		 tmp16, afi;
998
	int			 r;
999
	sa_family_t		 af;
1000
1001
	switch (ntohs(hdr->subtype)) {
1002
	case BGP4MP_STATE_CHANGE:
1003
		if (len < 8)
1004
			return (0);
1005
		/* source as */
1006
		memcpy(&tmp16, b, sizeof(tmp16));
1007
		b += sizeof(tmp16);
1008
		len -= sizeof(tmp16);
1009
		sas = ntohs(tmp16);
1010
		/* dest as */
1011
		memcpy(&tmp16, b, sizeof(tmp16));
1012
		b += sizeof(tmp16);
1013
		len -= sizeof(tmp16);
1014
		das = ntohs(tmp16);
1015
		/* if_index, ignored */
1016
		b += sizeof(tmp16);
1017
		len -= sizeof(tmp16);
1018
		/* afi */
1019
		memcpy(&tmp16, b, sizeof(tmp16));
1020
		b += sizeof(tmp16);
1021
		len -= sizeof(tmp16);
1022
		afi = ntohs(tmp16);
1023
		break;
1024
	case BGP4MP_STATE_CHANGE_AS4:
1025
		if (len < 12)
1026
			return (0);
1027
		/* source as */
1028
		memcpy(&sas, b, sizeof(sas));
1029
		b += sizeof(sas);
1030
		len -= sizeof(sas);
1031
		sas = ntohl(sas);
1032
		/* dest as */
1033
		memcpy(&das, b, sizeof(das));
1034
		b += sizeof(das);
1035
		len -= sizeof(das);
1036
		das = ntohl(das);
1037
		/* if_index, ignored */
1038
		b += sizeof(tmp16);
1039
		len -= sizeof(tmp16);
1040
		/* afi */
1041
		memcpy(&tmp16, b, sizeof(tmp16));
1042
		b += sizeof(tmp16);
1043
		len -= sizeof(tmp16);
1044
		afi = ntohs(tmp16);
1045
		break;
1046
	default:
1047
		errx(1, "mrt_parse_state: bad subtype");
1048
	}
1049
1050
	/* src & dst addr */
1051
	switch (afi) {
1052
	case MRT_DUMP_AFI_IP:
1053
		af = AF_INET;
1054
		break;
1055
	case MRT_DUMP_AFI_IPv6:
1056
		af = AF_INET6;
1057
		break;
1058
	default:
1059
		 errx(1, "mrt_parse_state: bad afi");
1060
	}
1061
1062
	if ((s = calloc(1, sizeof(struct mrt_bgp_state))) == NULL)
1063
		err(1, "calloc");
1064
	s->src_as = sas;
1065
	s->dst_as = das;
1066
1067
	if ((r = mrt_extract_addr(b, len, &s->src, af)) == -1)
1068
		goto fail;
1069
	b += r;
1070
	len -= r;
1071
	if ((r = mrt_extract_addr(b, len, &s->dst, af)) == -1)
1072
		goto fail;
1073
	b += r;
1074
	len -= r;
1075
1076
	/* states */
1077
	memcpy(&tmp16, b, sizeof(tmp16));
1078
	b += sizeof(tmp16);
1079
	len -= sizeof(tmp16);
1080
	s->old_state = ntohs(tmp16);
1081
	memcpy(&tmp16, b, sizeof(tmp16));
1082
	b += sizeof(tmp16);
1083
	len -= sizeof(tmp16);
1084
	s->new_state = ntohs(tmp16);
1085
1086
	return (s);
1087
1088
fail:
1089
	free(s);
1090
	return (NULL);
1091
}
1092
1093
struct mrt_bgp_msg *
1094
mrt_parse_msg(struct mrt_hdr *hdr, void *msg)
1095
{
1096
	struct mrt_bgp_msg	*m;
1097
	u_int8_t		*b = msg;
1098
	u_int			 len = ntohl(hdr->length);
1099
	u_int32_t		 sas, das;
1100
	u_int16_t		 tmp16, afi;
1101
	int			 r;
1102
	sa_family_t		 af;
1103
1104
	switch (ntohs(hdr->subtype)) {
1105
	case BGP4MP_MESSAGE:
1106
		if (len < 8)
1107
			return (0);
1108
		/* source as */
1109
		memcpy(&tmp16, b, sizeof(tmp16));
1110
		b += sizeof(tmp16);
1111
		len -= sizeof(tmp16);
1112
		sas = ntohs(tmp16);
1113
		/* dest as */
1114
		memcpy(&tmp16, b, sizeof(tmp16));
1115
		b += sizeof(tmp16);
1116
		len -= sizeof(tmp16);
1117
		das = ntohs(tmp16);
1118
		/* if_index, ignored */
1119
		b += sizeof(tmp16);
1120
		len -= sizeof(tmp16);
1121
		/* afi */
1122
		memcpy(&tmp16, b, sizeof(tmp16));
1123
		b += sizeof(tmp16);
1124
		len -= sizeof(tmp16);
1125
		afi = ntohs(tmp16);
1126
		break;
1127
	case BGP4MP_MESSAGE_AS4:
1128
		if (len < 12)
1129
			return (0);
1130
		/* source as */
1131
		memcpy(&sas, b, sizeof(sas));
1132
		b += sizeof(sas);
1133
		len -= sizeof(sas);
1134
		sas = ntohl(sas);
1135
		/* dest as */
1136
		memcpy(&das, b, sizeof(das));
1137
		b += sizeof(das);
1138
		len -= sizeof(das);
1139
		das = ntohl(das);
1140
		/* if_index, ignored */
1141
		b += sizeof(tmp16);
1142
		len -= sizeof(tmp16);
1143
		/* afi */
1144
		memcpy(&tmp16, b, sizeof(tmp16));
1145
		b += sizeof(tmp16);
1146
		len -= sizeof(tmp16);
1147
		afi = ntohs(tmp16);
1148
		break;
1149
	default:
1150
		errx(1, "mrt_parse_msg: bad subtype");
1151
	}
1152
1153
	/* src & dst addr */
1154
	switch (afi) {
1155
	case MRT_DUMP_AFI_IP:
1156
		af = AF_INET;
1157
		break;
1158
	case MRT_DUMP_AFI_IPv6:
1159
		af = AF_INET6;
1160
		break;
1161
	default:
1162
		 errx(1, "mrt_parse_msg: bad afi");
1163
	}
1164
1165
	if ((m = calloc(1, sizeof(struct mrt_bgp_msg))) == NULL)
1166
		err(1, "calloc");
1167
	m->src_as = sas;
1168
	m->dst_as = das;
1169
1170
	if ((r = mrt_extract_addr(b, len, &m->src, af)) == -1)
1171
		goto fail;
1172
	b += r;
1173
	len -= r;
1174
	if ((r = mrt_extract_addr(b, len, &m->dst, af)) == -1)
1175
		goto fail;
1176
	b += r;
1177
	len -= r;
1178
1179
	/* msg */
1180
	if (len > 0) {
1181
		m->msg_len = len;
1182
		if ((m->msg = malloc(len)) == NULL)
1183
			err(1, "malloc");
1184
		memcpy(m->msg, b, len);
1185
	}
1186
1187
	return (m);
1188
1189
fail:
1190
	free(m->msg);
1191
	free(m);
1192
	return (NULL);
1193
}