Bug Summary

File:src/usr.bin/bgplg/bgpctl/../../../usr.sbin/bgpctl/mrtparser.c
Warning:line 324, column 8
Assigned value is garbage or undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name mrtparser.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/bgplg/bgpctl/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.bin/bgplg/bgpctl/../../../usr.sbin/bgpctl -I /usr/src/usr.bin/bgplg/bgpctl/../../../usr.sbin/bgpctl/../bgpd -I /usr/src/usr.bin/bgplg/bgpctl -I /usr/src/usr.bin/bgplg/bgpctl/../bgpd -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/bgplg/bgpctl/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/bgplg/bgpctl/../../../usr.sbin/bgpctl/mrtparser.c
1/* $OpenBSD: mrtparser.c,v 1.16 2021/09/22 18:17:49 claudio 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(*__errno()).h>
22#include <limits.h>
23#include <stdlib.h>
24#include <stdio.h>
25#include <string.h>
26#include <time.h>
27#include <unistd.h>
28
29#include "mrt.h"
30#include "mrtparser.h"
31
32void *mrt_read_msg(int, struct mrt_hdr *);
33size_t mrt_read_buf(int, void *, size_t);
34
35struct mrt_peer *mrt_parse_v2_peer(struct mrt_hdr *, void *);
36struct mrt_rib *mrt_parse_v2_rib(struct mrt_hdr *, void *, int);
37int mrt_parse_dump(struct mrt_hdr *, void *, struct mrt_peer **,
38 struct mrt_rib **);
39int mrt_parse_dump_mp(struct mrt_hdr *, void *, struct mrt_peer **,
40 struct mrt_rib **, int);
41int mrt_extract_attr(struct mrt_rib_entry *, u_char *, int, u_int8_t,
42 int);
43
44void mrt_free_peers(struct mrt_peer *);
45void mrt_free_rib(struct mrt_rib *);
46void mrt_free_bgp_state(struct mrt_bgp_state *);
47void mrt_free_bgp_msg(struct mrt_bgp_msg *);
48
49u_char *mrt_aspath_inflate(void *, u_int16_t, u_int16_t *);
50int mrt_extract_addr(void *, u_int, struct bgpd_addr *, u_int8_t);
51int mrt_extract_prefix(void *, u_int, u_int8_t, struct bgpd_addr *,
52 u_int8_t *, int);
53
54struct mrt_bgp_state *mrt_parse_state(struct mrt_hdr *, void *, int);
55struct mrt_bgp_msg *mrt_parse_msg(struct mrt_hdr *, void *, int);
56
57void *
58mrt_read_msg(int fd, struct mrt_hdr *hdr)
59{
60 void *buf;
61
62 bzero(hdr, sizeof(*hdr));
63 if (mrt_read_buf(fd, hdr, sizeof(*hdr)) != sizeof(*hdr))
2
Assuming the condition is false
3
Taking false branch
64 return (NULL((void *)0));
65
66 if ((buf = malloc(ntohl(hdr->length)(__uint32_t)(__builtin_constant_p(hdr->length) ? (__uint32_t
)(((__uint32_t)(hdr->length) & 0xff) << 24 | ((__uint32_t
)(hdr->length) & 0xff00) << 8 | ((__uint32_t)(hdr
->length) & 0xff0000) >> 8 | ((__uint32_t)(hdr->
length) & 0xff000000) >> 24) : __swap32md(hdr->length
))
)
) == NULL((void *)0)
)
4
'?' condition is false
5
Storing uninitialized value
6
Assuming the condition is false
7
Taking false branch
67 err(1, "malloc(%d)", hdr->length);
68
69 if (mrt_read_buf(fd, buf, ntohl(hdr->length)(__uint32_t)(__builtin_constant_p(hdr->length) ? (__uint32_t
)(((__uint32_t)(hdr->length) & 0xff) << 24 | ((__uint32_t
)(hdr->length) & 0xff00) << 8 | ((__uint32_t)(hdr
->length) & 0xff0000) >> 8 | ((__uint32_t)(hdr->
length) & 0xff000000) >> 24) : __swap32md(hdr->length
))
)
!= ntohl(hdr->length)(__uint32_t)(__builtin_constant_p(hdr->length) ? (__uint32_t
)(((__uint32_t)(hdr->length) & 0xff) << 24 | ((__uint32_t
)(hdr->length) & 0xff00) << 8 | ((__uint32_t)(hdr
->length) & 0xff0000) >> 8 | ((__uint32_t)(hdr->
length) & 0xff000000) >> 24) : __swap32md(hdr->length
))
) {
8
'?' condition is false
9
Calling 'mrt_read_buf'
12
Returning from 'mrt_read_buf'
13
'?' condition is false
14
Assuming the condition is false
15
Taking false branch
70 free(buf);
71 return (NULL((void *)0));
72 }
73 return (buf);
74}
75
76size_t
77mrt_read_buf(int fd, void *buf, size_t len)
78{
79 char *b = buf;
80 ssize_t n;
81
82 while (len > 0) {
10
Assuming 'len' is <= 0
11
Loop condition is false. Execution continues on line 94
83 if ((n = read(fd, b, len)) == -1) {
84 if (errno(*__errno()) == EINTR4)
85 continue;
86 err(1, "read");
87 }
88 if (n == 0)
89 break;
90 b += n;
91 len -= n;
92 }
93
94 return (b - (char *)buf);
95}
96
97void
98mrt_parse(int fd, struct mrt_parser *p, int verbose)
99{
100 struct mrt_hdr h;
101 struct mrt_peer *pctx = NULL((void *)0);
102 struct mrt_rib *r;
103 struct mrt_bgp_state *s;
104 struct mrt_bgp_msg *m;
105 void *msg;
106
107 while ((msg = mrt_read_msg(fd, &h))) {
1
Calling 'mrt_read_msg'
16
Returning from 'mrt_read_msg'
17
Loop condition is true. Entering loop body
108 switch (ntohs(h.type)(__uint16_t)(__builtin_constant_p(h.type) ? (__uint16_t)(((__uint16_t
)(h.type) & 0xffU) << 8 | ((__uint16_t)(h.type) &
0xff00U) >> 8) : __swap16md(h.type))
) {
18
'?' condition is false
19
Control jumps to 'case MSG_TABLE_DUMP_V2:' at line 152
109 case MSG_NULL:
110 case MSG_START:
111 case MSG_DIE:
112 case MSG_I_AM_DEAD:
113 case MSG_PEER_DOWN:
114 case MSG_PROTOCOL_BGP:
115 case MSG_PROTOCOL_IDRP:
116 case MSG_PROTOCOL_BGP4PLUS:
117 case MSG_PROTOCOL_BGP4PLUS1:
118 if (verbose)
119 printf("deprecated MRT type %d\n",
120 ntohs(h.type)(__uint16_t)(__builtin_constant_p(h.type) ? (__uint16_t)(((__uint16_t
)(h.type) & 0xffU) << 8 | ((__uint16_t)(h.type) &
0xff00U) >> 8) : __swap16md(h.type))
);
121 break;
122 case MSG_PROTOCOL_RIP:
123 case MSG_PROTOCOL_RIPNG:
124 case MSG_PROTOCOL_OSPF:
125 case MSG_PROTOCOL_ISIS_ET:
126 case MSG_PROTOCOL_ISIS:
127 case MSG_PROTOCOL_OSPFV3_ET:
128 case MSG_PROTOCOL_OSPFV3:
129 if (verbose)
130 printf("unsuported MRT type %d\n",
131 ntohs(h.type)(__uint16_t)(__builtin_constant_p(h.type) ? (__uint16_t)(((__uint16_t
)(h.type) & 0xffU) << 8 | ((__uint16_t)(h.type) &
0xff00U) >> 8) : __swap16md(h.type))
);
132 break;
133 case MSG_TABLE_DUMP:
134 switch (ntohs(h.subtype)(__uint16_t)(__builtin_constant_p(h.subtype) ? (__uint16_t)((
(__uint16_t)(h.subtype) & 0xffU) << 8 | ((__uint16_t
)(h.subtype) & 0xff00U) >> 8) : __swap16md(h.subtype
))
) {
135 case MRT_DUMP_AFI_IP:
136 case MRT_DUMP_AFI_IPv6:
137 if (p->dump == NULL((void *)0))
138 break;
139 if (mrt_parse_dump(&h, msg, &pctx, &r) == 0) {
140 if (p->dump)
141 p->dump(r, pctx, p->arg);
142 mrt_free_rib(r);
143 }
144 break;
145 default:
146 if (verbose)
147 printf("unknown AFI %d in table dump\n",
148 ntohs(h.subtype)(__uint16_t)(__builtin_constant_p(h.subtype) ? (__uint16_t)((
(__uint16_t)(h.subtype) & 0xffU) << 8 | ((__uint16_t
)(h.subtype) & 0xff00U) >> 8) : __swap16md(h.subtype
))
);
149 break;
150 }
151 break;
152 case MSG_TABLE_DUMP_V2:
153 switch (ntohs(h.subtype)(__uint16_t)(__builtin_constant_p(h.subtype) ? (__uint16_t)((
(__uint16_t)(h.subtype) & 0xffU) << 8 | ((__uint16_t
)(h.subtype) & 0xff00U) >> 8) : __swap16md(h.subtype
))
) {
20
'?' condition is false
21
Control jumps to 'case MRT_DUMP_V2_PEER_INDEX_TABLE:' at line 154
154 case MRT_DUMP_V2_PEER_INDEX_TABLE:
155 if (p->dump == NULL((void *)0))
22
Assuming field 'dump' is not equal to NULL
23
Taking false branch
156 break;
157 if (pctx
23.1
'pctx' is null
)
24
Taking false branch
158 mrt_free_peers(pctx);
159 pctx = mrt_parse_v2_peer(&h, msg);
25
Calling 'mrt_parse_v2_peer'
160 break;
161 case MRT_DUMP_V2_RIB_IPV4_UNICAST:
162 case MRT_DUMP_V2_RIB_IPV4_MULTICAST:
163 case MRT_DUMP_V2_RIB_IPV6_UNICAST:
164 case MRT_DUMP_V2_RIB_IPV6_MULTICAST:
165 case MRT_DUMP_V2_RIB_GENERIC:
166 case MRT_DUMP_V2_RIB_IPV4_UNICAST_ADDPATH:
167 case MRT_DUMP_V2_RIB_IPV4_MULTICAST_ADDPATH:
168 case MRT_DUMP_V2_RIB_IPV6_UNICAST_ADDPATH:
169 case MRT_DUMP_V2_RIB_IPV6_MULTICAST_ADDPATH:
170 case MRT_DUMP_V2_RIB_GENERIC_ADDPATH:
171 if (p->dump == NULL((void *)0))
172 break;
173 r = mrt_parse_v2_rib(&h, msg, verbose);
174 if (r) {
175 if (p->dump)
176 p->dump(r, pctx, p->arg);
177 mrt_free_rib(r);
178 }
179 break;
180 default:
181 if (verbose)
182 printf("unhandled DUMP_V2 subtype %d\n",
183 ntohs(h.subtype)(__uint16_t)(__builtin_constant_p(h.subtype) ? (__uint16_t)((
(__uint16_t)(h.subtype) & 0xffU) << 8 | ((__uint16_t
)(h.subtype) & 0xff00U) >> 8) : __swap16md(h.subtype
))
);
184 break;
185 }
186 break;
187 case MSG_PROTOCOL_BGP4MP_ET:
188 case MSG_PROTOCOL_BGP4MP:
189 switch (ntohs(h.subtype)(__uint16_t)(__builtin_constant_p(h.subtype) ? (__uint16_t)((
(__uint16_t)(h.subtype) & 0xffU) << 8 | ((__uint16_t
)(h.subtype) & 0xff00U) >> 8) : __swap16md(h.subtype
))
) {
190 case BGP4MP_STATE_CHANGE:
191 case BGP4MP_STATE_CHANGE_AS4:
192 if ((s = mrt_parse_state(&h, msg, verbose))) {
193 if (p->state)
194 p->state(s, p->arg);
195 free(s);
196 }
197 break;
198 case BGP4MP_MESSAGE:
199 case BGP4MP_MESSAGE_AS4:
200 case BGP4MP_MESSAGE_LOCAL:
201 case BGP4MP_MESSAGE_AS4_LOCAL:
202 case BGP4MP_MESSAGE_ADDPATH:
203 case BGP4MP_MESSAGE_AS4_ADDPATH:
204 case BGP4MP_MESSAGE_LOCAL_ADDPATH:
205 case BGP4MP_MESSAGE_AS4_LOCAL_ADDPATH:
206 if ((m = mrt_parse_msg(&h, msg, verbose))) {
207 if (p->message)
208 p->message(m, p->arg);
209 free(m->msg);
210 free(m);
211 }
212 break;
213 case BGP4MP_ENTRY:
214 if (p->dump == NULL((void *)0))
215 break;
216 if (mrt_parse_dump_mp(&h, msg, &pctx, &r,
217 verbose) == 0) {
218 if (p->dump)
219 p->dump(r, pctx, p->arg);
220 mrt_free_rib(r);
221 }
222 break;
223 default:
224 if (verbose)
225 printf("unhandled BGP4MP subtype %d\n",
226 ntohs(h.subtype)(__uint16_t)(__builtin_constant_p(h.subtype) ? (__uint16_t)((
(__uint16_t)(h.subtype) & 0xffU) << 8 | ((__uint16_t
)(h.subtype) & 0xff00U) >> 8) : __swap16md(h.subtype
))
);
227 break;
228 }
229 break;
230 default:
231 if (verbose)
232 printf("unknown MRT type %d\n", ntohs(h.type)(__uint16_t)(__builtin_constant_p(h.type) ? (__uint16_t)(((__uint16_t
)(h.type) & 0xffU) << 8 | ((__uint16_t)(h.type) &
0xff00U) >> 8) : __swap16md(h.type))
);
233 break;
234 }
235 free(msg);
236 }
237 if (pctx)
238 mrt_free_peers(pctx);
239}
240
241static int
242mrt_afi2aid(int afi, int safi, int verbose)
243{
244 switch (afi) {
245 case MRT_DUMP_AFI_IP:
246 if (safi == -1 || safi == 1 || safi == 2)
247 return AID_INET1;
248 else if (safi == 128)
249 return AID_VPN_IPv43;
250 break;
251 case MRT_DUMP_AFI_IPv6:
252 if (safi == -1 || safi == 1 || safi == 2)
253 return AID_INET62;
254 else if (safi == 128)
255 return AID_VPN_IPv64;
256 break;
257 default:
258 break;
259 }
260 if (verbose)
261 printf("unhandled AFI/SAFI %d/%d\n", afi, safi);
262 return AID_UNSPEC0;
263}
264
265struct mrt_peer *
266mrt_parse_v2_peer(struct mrt_hdr *hdr, void *msg)
267{
268 struct mrt_peer_entry *peers = NULL((void *)0);
269 struct mrt_peer *p;
270 u_int8_t *b = msg;
271 u_int32_t bid, as4;
272 u_int16_t cnt, i, as2;
273 u_int len = ntohl(hdr->length)(__uint32_t)(__builtin_constant_p(hdr->length) ? (__uint32_t
)(((__uint32_t)(hdr->length) & 0xff) << 24 | ((__uint32_t
)(hdr->length) & 0xff00) << 8 | ((__uint32_t)(hdr
->length) & 0xff0000) >> 8 | ((__uint32_t)(hdr->
length) & 0xff000000) >> 24) : __swap32md(hdr->length
))
;
26
'?' condition is false
274
275 if (len < 8) /* min msg size */
27
Assuming 'len' is >= 8
28
Taking false branch
276 return NULL((void *)0);
277
278 p = calloc(1, sizeof(struct mrt_peer));
279 if (p == NULL((void *)0))
29
Assuming 'p' is not equal to NULL
30
Taking false branch
280 err(1, "calloc");
281
282 /* collector bgp id */
283 memcpy(&bid, b, sizeof(bid));
284 b += sizeof(bid);
285 len -= sizeof(bid);
286 p->bgp_id = ntohl(bid)(__uint32_t)(__builtin_constant_p(bid) ? (__uint32_t)(((__uint32_t
)(bid) & 0xff) << 24 | ((__uint32_t)(bid) & 0xff00
) << 8 | ((__uint32_t)(bid) & 0xff0000) >> 8 |
((__uint32_t)(bid) & 0xff000000) >> 24) : __swap32md
(bid))
;
31
'?' condition is false
287
288 /* view name length */
289 memcpy(&cnt, b, sizeof(cnt));
290 b += sizeof(cnt);
291 len -= sizeof(cnt);
292 cnt = ntohs(cnt)(__uint16_t)(__builtin_constant_p(cnt) ? (__uint16_t)(((__uint16_t
)(cnt) & 0xffU) << 8 | ((__uint16_t)(cnt) & 0xff00U
) >> 8) : __swap16md(cnt))
;
32
'?' condition is false
293
294 /* view name */
295 if (cnt > len)
33
Assuming 'cnt' is <= 'len'
34
Taking false branch
296 goto fail;
297 if (cnt != 0) {
35
Assuming 'cnt' is equal to 0
36
Taking false branch
298 if ((p->view = malloc(cnt + 1)) == NULL((void *)0))
299 err(1, "malloc");
300 memcpy(p->view, b, cnt);
301 p->view[cnt] = 0;
302 } else
303 if ((p->view = strdup("")) == NULL((void *)0))
37
Assuming the condition is false
38
Taking false branch
304 err(1, "strdup");
305 b += cnt;
306 len -= cnt;
307
308 /* peer_count */
309 if (len < sizeof(cnt))
39
Taking false branch
310 goto fail;
311 memcpy(&cnt, b, sizeof(cnt));
312 b += sizeof(cnt);
313 len -= sizeof(cnt);
314 cnt = ntohs(cnt)(__uint16_t)(__builtin_constant_p(cnt) ? (__uint16_t)(((__uint16_t
)(cnt) & 0xffU) << 8 | ((__uint16_t)(cnt) & 0xff00U
) >> 8) : __swap16md(cnt))
;
40
'?' condition is false
315
316 /* peer entries */
317 if ((peers = calloc(cnt, sizeof(struct mrt_peer_entry))) == NULL((void *)0))
41
Assuming the condition is false
42
Taking false branch
318 err(1, "calloc");
319 for (i = 0; i
42.1
'i' is < 'cnt'
< cnt; i++) {
43
Loop condition is true. Entering loop body
320 u_int8_t type;
321
322 if (len < sizeof(u_int8_t) + sizeof(u_int32_t))
44
Assuming the condition is false
45
Taking false branch
323 goto fail;
324 type = *b++;
46
Assigned value is garbage or undefined
325 len -= 1;
326 memcpy(&bid, b, sizeof(bid));
327 b += sizeof(bid);
328 len -= sizeof(bid);
329 peers[i].bgp_id = ntohl(bid)(__uint32_t)(__builtin_constant_p(bid) ? (__uint32_t)(((__uint32_t
)(bid) & 0xff) << 24 | ((__uint32_t)(bid) & 0xff00
) << 8 | ((__uint32_t)(bid) & 0xff0000) >> 8 |
((__uint32_t)(bid) & 0xff000000) >> 24) : __swap32md
(bid))
;
330
331 if (type & MRT_DUMP_V2_PEER_BIT_I0x1) {
332 if (mrt_extract_addr(b, len, &peers[i].addr,
333 AID_INET62) == -1)
334 goto fail;
335 b += sizeof(struct in6_addr);
336 len -= sizeof(struct in6_addr);
337 } else {
338 if (mrt_extract_addr(b, len, &peers[i].addr,
339 AID_INET1) == -1)
340 goto fail;
341 b += sizeof(struct in_addr);
342 len -= sizeof(struct in_addr);
343 }
344
345 if (type & MRT_DUMP_V2_PEER_BIT_A0x2) {
346 memcpy(&as4, b, sizeof(as4));
347 b += sizeof(as4);
348 len -= sizeof(as4);
349 as4 = ntohl(as4)(__uint32_t)(__builtin_constant_p(as4) ? (__uint32_t)(((__uint32_t
)(as4) & 0xff) << 24 | ((__uint32_t)(as4) & 0xff00
) << 8 | ((__uint32_t)(as4) & 0xff0000) >> 8 |
((__uint32_t)(as4) & 0xff000000) >> 24) : __swap32md
(as4))
;
350 } else {
351 memcpy(&as2, b, sizeof(as2));
352 b += sizeof(as2);
353 len -= sizeof(as2);
354 as4 = ntohs(as2)(__uint16_t)(__builtin_constant_p(as2) ? (__uint16_t)(((__uint16_t
)(as2) & 0xffU) << 8 | ((__uint16_t)(as2) & 0xff00U
) >> 8) : __swap16md(as2))
;
355 }
356 peers[i].asnum = as4;
357 }
358 p->peers = peers;
359 p->npeers = cnt;
360 return (p);
361fail:
362 mrt_free_peers(p);
363 free(peers);
364 return (NULL((void *)0));
365}
366
367struct mrt_rib *
368mrt_parse_v2_rib(struct mrt_hdr *hdr, void *msg, int verbose)
369{
370 struct mrt_rib_entry *entries = NULL((void *)0);
371 struct mrt_rib *r;
372 u_int8_t *b = msg;
373 u_int len = ntohl(hdr->length)(__uint32_t)(__builtin_constant_p(hdr->length) ? (__uint32_t
)(((__uint32_t)(hdr->length) & 0xff) << 24 | ((__uint32_t
)(hdr->length) & 0xff00) << 8 | ((__uint32_t)(hdr
->length) & 0xff0000) >> 8 | ((__uint32_t)(hdr->
length) & 0xff000000) >> 24) : __swap32md(hdr->length
))
;
374 u_int32_t snum, path_id = 0;
375 u_int16_t cnt, i, afi;
376 u_int8_t safi, aid;
377 int ret;
378
379 if (len < sizeof(snum) + 1)
380 return NULL((void *)0);
381
382 r = calloc(1, sizeof(struct mrt_rib));
383 if (r == NULL((void *)0))
384 err(1, "calloc");
385
386 /* seq_num */
387 memcpy(&snum, b, sizeof(snum));
388 b += sizeof(snum);
389 len -= sizeof(snum);
390 r->seqnum = ntohl(snum)(__uint32_t)(__builtin_constant_p(snum) ? (__uint32_t)(((__uint32_t
)(snum) & 0xff) << 24 | ((__uint32_t)(snum) & 0xff00
) << 8 | ((__uint32_t)(snum) & 0xff0000) >> 8
| ((__uint32_t)(snum) & 0xff000000) >> 24) : __swap32md
(snum))
;
391
392 switch (ntohs(hdr->subtype)(__uint16_t)(__builtin_constant_p(hdr->subtype) ? (__uint16_t
)(((__uint16_t)(hdr->subtype) & 0xffU) << 8 | ((
__uint16_t)(hdr->subtype) & 0xff00U) >> 8) : __swap16md
(hdr->subtype))
) {
393 case MRT_DUMP_V2_RIB_IPV4_UNICAST_ADDPATH:
394 case MRT_DUMP_V2_RIB_IPV4_MULTICAST_ADDPATH:
395 r->add_path = 1;
396 /* FALLTHROUGH */
397 case MRT_DUMP_V2_RIB_IPV4_UNICAST:
398 case MRT_DUMP_V2_RIB_IPV4_MULTICAST:
399 /* prefix */
400 ret = mrt_extract_prefix(b, len, AID_INET1, &r->prefix,
401 &r->prefixlen, verbose);
402 if (ret == 1)
403 goto fail;
404 break;
405 case MRT_DUMP_V2_RIB_IPV6_UNICAST_ADDPATH:
406 case MRT_DUMP_V2_RIB_IPV6_MULTICAST_ADDPATH:
407 r->add_path = 1;
408 /* FALLTHROUGH */
409 case MRT_DUMP_V2_RIB_IPV6_UNICAST:
410 case MRT_DUMP_V2_RIB_IPV6_MULTICAST:
411 /* prefix */
412 ret = mrt_extract_prefix(b, len, AID_INET62, &r->prefix,
413 &r->prefixlen, verbose);
414 if (ret == 1)
415 goto fail;
416 break;
417 case MRT_DUMP_V2_RIB_GENERIC_ADDPATH:
418 /*
419 * RFC8050 handling for add-path has special handling for
420 * RIB_GENERIC_ADDPATH but nobody implements it that way.
421 * So just use the same way as for the other _ADDPATH types.
422 */
423 r->add_path = 1;
424 /* FALLTHROUGH */
425 case MRT_DUMP_V2_RIB_GENERIC:
426 /* fetch AFI/SAFI pair */
427 if (len < 3)
428 goto fail;
429 memcpy(&afi, b, sizeof(afi));
430 b += sizeof(afi);
431 len -= sizeof(afi);
432 afi = ntohs(afi)(__uint16_t)(__builtin_constant_p(afi) ? (__uint16_t)(((__uint16_t
)(afi) & 0xffU) << 8 | ((__uint16_t)(afi) & 0xff00U
) >> 8) : __swap16md(afi))
;
433
434 safi = *b++;
435 len -= 1;
436
437 if ((aid = mrt_afi2aid(afi, safi, verbose)) == AID_UNSPEC0)
438 goto fail;
439
440 /* prefix */
441 ret = mrt_extract_prefix(b, len, aid, &r->prefix,
442 &r->prefixlen, verbose);
443 if (ret == 1)
444 goto fail;
445 break;
446 default:
447 errx(1, "unknonw subtype %hd", ntohs(hdr->subtype)(__uint16_t)(__builtin_constant_p(hdr->subtype) ? (__uint16_t
)(((__uint16_t)(hdr->subtype) & 0xffU) << 8 | ((
__uint16_t)(hdr->subtype) & 0xff00U) >> 8) : __swap16md
(hdr->subtype))
);
448 }
449
450 /* adjust length */
451 b += ret;
452 len -= ret;
453
454 /* entries count */
455 if (len < sizeof(cnt))
456 goto fail;
457 memcpy(&cnt, b, sizeof(cnt));
458 b += sizeof(cnt);
459 len -= sizeof(cnt);
460 cnt = ntohs(cnt)(__uint16_t)(__builtin_constant_p(cnt) ? (__uint16_t)(((__uint16_t
)(cnt) & 0xffU) << 8 | ((__uint16_t)(cnt) & 0xff00U
) >> 8) : __swap16md(cnt))
;
461 r->nentries = cnt;
462
463 /* entries */
464 if ((entries = calloc(cnt, sizeof(struct mrt_rib_entry))) == NULL((void *)0))
465 err(1, "calloc");
466 for (i = 0; i < cnt; i++) {
467 u_int32_t otm;
468 u_int16_t pix, alen;
469 if (len < 2 * sizeof(u_int16_t) + sizeof(u_int32_t))
470 goto fail;
471 /* peer index */
472 memcpy(&pix, b, sizeof(pix));
473 b += sizeof(pix);
474 len -= sizeof(pix);
475 entries[i].peer_idx = ntohs(pix)(__uint16_t)(__builtin_constant_p(pix) ? (__uint16_t)(((__uint16_t
)(pix) & 0xffU) << 8 | ((__uint16_t)(pix) & 0xff00U
) >> 8) : __swap16md(pix))
;
476
477 /* originated */
478 memcpy(&otm, b, sizeof(otm));
479 b += sizeof(otm);
480 len -= sizeof(otm);
481 entries[i].originated = ntohl(otm)(__uint32_t)(__builtin_constant_p(otm) ? (__uint32_t)(((__uint32_t
)(otm) & 0xff) << 24 | ((__uint32_t)(otm) & 0xff00
) << 8 | ((__uint32_t)(otm) & 0xff0000) >> 8 |
((__uint32_t)(otm) & 0xff000000) >> 24) : __swap32md
(otm))
;
482
483 if (r->add_path) {
484 if (len < sizeof(path_id) + sizeof(alen))
485 goto fail;
486 memcpy(&path_id, b, sizeof(path_id));
487 b += sizeof(path_id);
488 len -= sizeof(path_id);
489 path_id = ntohl(path_id)(__uint32_t)(__builtin_constant_p(path_id) ? (__uint32_t)(((__uint32_t
)(path_id) & 0xff) << 24 | ((__uint32_t)(path_id) &
0xff00) << 8 | ((__uint32_t)(path_id) & 0xff0000) >>
8 | ((__uint32_t)(path_id) & 0xff000000) >> 24) : __swap32md
(path_id))
;
490 }
491 entries[i].path_id = path_id;
492
493 /* attr_len */
494 memcpy(&alen, b, sizeof(alen));
495 b += sizeof(alen);
496 len -= sizeof(alen);
497 alen = ntohs(alen)(__uint16_t)(__builtin_constant_p(alen) ? (__uint16_t)(((__uint16_t
)(alen) & 0xffU) << 8 | ((__uint16_t)(alen) & 0xff00U
) >> 8) : __swap16md(alen))
;
498
499 /* attr */
500 if (len < alen)
501 goto fail;
502 if (mrt_extract_attr(&entries[i], b, alen,
503 r->prefix.aid, 1) == -1)
504 goto fail;
505 b += alen;
506 len -= alen;
507 }
508 r->entries = entries;
509 return (r);
510fail:
511 mrt_free_rib(r);
512 free(entries);
513 return (NULL((void *)0));
514}
515
516int
517mrt_parse_dump(struct mrt_hdr *hdr, void *msg, struct mrt_peer **pp,
518 struct mrt_rib **rp)
519{
520 struct mrt_peer *p;
521 struct mrt_rib *r;
522 struct mrt_rib_entry *re;
523 u_int8_t *b = msg;
524 u_int len = ntohl(hdr->length)(__uint32_t)(__builtin_constant_p(hdr->length) ? (__uint32_t
)(((__uint32_t)(hdr->length) & 0xff) << 24 | ((__uint32_t
)(hdr->length) & 0xff00) << 8 | ((__uint32_t)(hdr
->length) & 0xff0000) >> 8 | ((__uint32_t)(hdr->
length) & 0xff000000) >> 24) : __swap32md(hdr->length
))
;
525 u_int16_t asnum, alen;
526
527 if (*pp == NULL((void *)0)) {
528 *pp = calloc(1, sizeof(struct mrt_peer));
529 if (*pp == NULL((void *)0))
530 err(1, "calloc");
531 (*pp)->peers = calloc(1, sizeof(struct mrt_peer_entry));
532 if ((*pp)->peers == NULL((void *)0))
533 err(1, "calloc");
534 (*pp)->npeers = 1;
535 }
536 p = *pp;
537
538 *rp = r = calloc(1, sizeof(struct mrt_rib));
539 if (r == NULL((void *)0))
540 err(1, "calloc");
541 re = calloc(1, sizeof(struct mrt_rib_entry));
542 if (re == NULL((void *)0))
543 err(1, "calloc");
544 r->nentries = 1;
545 r->entries = re;
546
547 if (len < 2 * sizeof(u_int16_t))
548 goto fail;
549 /* view */
550 b += sizeof(u_int16_t);
551 len -= sizeof(u_int16_t);
552 /* seqnum */
553 memcpy(&r->seqnum, b, sizeof(u_int16_t));
554 b += sizeof(u_int16_t);
555 len -= sizeof(u_int16_t);
556 r->seqnum = ntohs(r->seqnum)(__uint16_t)(__builtin_constant_p(r->seqnum) ? (__uint16_t
)(((__uint16_t)(r->seqnum) & 0xffU) << 8 | ((__uint16_t
)(r->seqnum) & 0xff00U) >> 8) : __swap16md(r->
seqnum))
;
557
558 switch (ntohs(hdr->subtype)(__uint16_t)(__builtin_constant_p(hdr->subtype) ? (__uint16_t
)(((__uint16_t)(hdr->subtype) & 0xffU) << 8 | ((
__uint16_t)(hdr->subtype) & 0xff00U) >> 8) : __swap16md
(hdr->subtype))
) {
559 case MRT_DUMP_AFI_IP:
560 if (mrt_extract_addr(b, len, &r->prefix, AID_INET1) == -1)
561 goto fail;
562 b += sizeof(struct in_addr);
563 len -= sizeof(struct in_addr);
564 break;
565 case MRT_DUMP_AFI_IPv6:
566 if (mrt_extract_addr(b, len, &r->prefix, AID_INET62) == -1)
567 goto fail;
568 b += sizeof(struct in6_addr);
569 len -= sizeof(struct in6_addr);
570 break;
571 }
572 if (len < 2 * sizeof(u_int32_t) + 2 * sizeof(u_int16_t) + 2)
573 goto fail;
574 r->prefixlen = *b++;
575 len -= 1;
576 /* status */
577 b += 1;
578 len -= 1;
579 /* originated */
580 memcpy(&re->originated, b, sizeof(u_int32_t));
581 b += sizeof(u_int32_t);
582 len -= sizeof(u_int32_t);
583 re->originated = ntohl(re->originated)(__uint32_t)(__builtin_constant_p(re->originated) ? (__uint32_t
)(((__uint32_t)(re->originated) & 0xff) << 24 | (
(__uint32_t)(re->originated) & 0xff00) << 8 | ((
__uint32_t)(re->originated) & 0xff0000) >> 8 | (
(__uint32_t)(re->originated) & 0xff000000) >> 24
) : __swap32md(re->originated))
;
584 /* peer ip */
585 switch (ntohs(hdr->subtype)(__uint16_t)(__builtin_constant_p(hdr->subtype) ? (__uint16_t
)(((__uint16_t)(hdr->subtype) & 0xffU) << 8 | ((
__uint16_t)(hdr->subtype) & 0xff00U) >> 8) : __swap16md
(hdr->subtype))
) {
586 case MRT_DUMP_AFI_IP:
587 if (mrt_extract_addr(b, len, &p->peers->addr, AID_INET1) == -1)
588 goto fail;
589 b += sizeof(struct in_addr);
590 len -= sizeof(struct in_addr);
591 break;
592 case MRT_DUMP_AFI_IPv6:
593 if (mrt_extract_addr(b, len, &p->peers->addr, AID_INET62) == -1)
594 goto fail;
595 b += sizeof(struct in6_addr);
596 len -= sizeof(struct in6_addr);
597 break;
598 }
599 memcpy(&asnum, b, sizeof(asnum));
600 b += sizeof(asnum);
601 len -= sizeof(asnum);
602 p->peers->asnum = ntohs(asnum)(__uint16_t)(__builtin_constant_p(asnum) ? (__uint16_t)(((__uint16_t
)(asnum) & 0xffU) << 8 | ((__uint16_t)(asnum) &
0xff00U) >> 8) : __swap16md(asnum))
;
603
604 memcpy(&alen, b, sizeof(alen));
605 b += sizeof(alen);
606 len -= sizeof(alen);
607 alen = ntohs(alen)(__uint16_t)(__builtin_constant_p(alen) ? (__uint16_t)(((__uint16_t
)(alen) & 0xffU) << 8 | ((__uint16_t)(alen) & 0xff00U
) >> 8) : __swap16md(alen))
;
608
609 /* attr */
610 if (len < alen)
611 goto fail;
612 if (mrt_extract_attr(re, b, alen, r->prefix.aid, 0) == -1)
613 goto fail;
614 b += alen;
615 len -= alen;
616
617 return (0);
618fail:
619 mrt_free_rib(r);
620 return (-1);
621}
622
623int
624mrt_parse_dump_mp(struct mrt_hdr *hdr, void *msg, struct mrt_peer **pp,
625 struct mrt_rib **rp, int verbose)
626{
627 struct mrt_peer *p;
628 struct mrt_rib *r;
629 struct mrt_rib_entry *re;
630 u_int8_t *b = msg;
631 u_int len = ntohl(hdr->length)(__uint32_t)(__builtin_constant_p(hdr->length) ? (__uint32_t
)(((__uint32_t)(hdr->length) & 0xff) << 24 | ((__uint32_t
)(hdr->length) & 0xff00) << 8 | ((__uint32_t)(hdr
->length) & 0xff0000) >> 8 | ((__uint32_t)(hdr->
length) & 0xff000000) >> 24) : __swap32md(hdr->length
))
;
632 u_int16_t asnum, alen, afi;
633 u_int8_t safi, nhlen, aid;
634 int ret;
635
636 /* just ignore the microsec field for _ET header for now */
637 if (ntohs(hdr->type)(__uint16_t)(__builtin_constant_p(hdr->type) ? (__uint16_t
)(((__uint16_t)(hdr->type) & 0xffU) << 8 | ((__uint16_t
)(hdr->type) & 0xff00U) >> 8) : __swap16md(hdr->
type))
== MSG_PROTOCOL_BGP4MP_ET) {
638 b = (char *)b + sizeof(u_int32_t);
639 len -= sizeof(u_int32_t);
640 }
641
642 if (*pp == NULL((void *)0)) {
643 *pp = calloc(1, sizeof(struct mrt_peer));
644 if (*pp == NULL((void *)0))
645 err(1, "calloc");
646 (*pp)->peers = calloc(1, sizeof(struct mrt_peer_entry));
647 if ((*pp)->peers == NULL((void *)0))
648 err(1, "calloc");
649 (*pp)->npeers = 1;
650 }
651 p = *pp;
652
653 *rp = r = calloc(1, sizeof(struct mrt_rib));
654 if (r == NULL((void *)0))
655 err(1, "calloc");
656 re = calloc(1, sizeof(struct mrt_rib_entry));
657 if (re == NULL((void *)0))
658 err(1, "calloc");
659 r->nentries = 1;
660 r->entries = re;
661
662 if (len < 4 * sizeof(u_int16_t))
663 goto fail;
664 /* source AS */
665 b += sizeof(u_int16_t);
666 len -= sizeof(u_int16_t);
667 /* dest AS */
668 memcpy(&asnum, b, sizeof(asnum));
669 b += sizeof(asnum);
670 len -= sizeof(asnum);
671 p->peers->asnum = ntohs(asnum)(__uint16_t)(__builtin_constant_p(asnum) ? (__uint16_t)(((__uint16_t
)(asnum) & 0xffU) << 8 | ((__uint16_t)(asnum) &
0xff00U) >> 8) : __swap16md(asnum))
;
672 /* iface index */
673 b += sizeof(u_int16_t);
674 len -= sizeof(u_int16_t);
675 /* afi */
676 memcpy(&afi, b, sizeof(afi));
677 b += sizeof(afi);
678 len -= sizeof(afi);
679 afi = ntohs(afi)(__uint16_t)(__builtin_constant_p(afi) ? (__uint16_t)(((__uint16_t
)(afi) & 0xffU) << 8 | ((__uint16_t)(afi) & 0xff00U
) >> 8) : __swap16md(afi))
;
680
681 /* source + dest ip */
682 switch (afi) {
683 case MRT_DUMP_AFI_IP:
684 if (len < 2 * sizeof(struct in_addr))
685 goto fail;
686 /* source IP */
687 b += sizeof(struct in_addr);
688 len -= sizeof(struct in_addr);
689 /* dest IP */
690 if (mrt_extract_addr(b, len, &p->peers->addr, AID_INET1) == -1)
691 goto fail;
692 b += sizeof(struct in_addr);
693 len -= sizeof(struct in_addr);
694 break;
695 case MRT_DUMP_AFI_IPv6:
696 if (len < 2 * sizeof(struct in6_addr))
697 goto fail;
698 /* source IP */
699 b += sizeof(struct in6_addr);
700 len -= sizeof(struct in6_addr);
701 /* dest IP */
702 if (mrt_extract_addr(b, len, &p->peers->addr, AID_INET62) == -1)
703 goto fail;
704 b += sizeof(struct in6_addr);
705 len -= sizeof(struct in6_addr);
706 break;
707 }
708
709 if (len < 2 * sizeof(u_int16_t) + 2 * sizeof(u_int32_t))
710 goto fail;
711 /* view + status */
712 b += 2 * sizeof(u_int16_t);
713 len -= 2 * sizeof(u_int16_t);
714 /* originated */
715 memcpy(&re->originated, b, sizeof(u_int32_t));
716 b += sizeof(u_int32_t);
717 len -= sizeof(u_int32_t);
718 re->originated = ntohl(re->originated)(__uint32_t)(__builtin_constant_p(re->originated) ? (__uint32_t
)(((__uint32_t)(re->originated) & 0xff) << 24 | (
(__uint32_t)(re->originated) & 0xff00) << 8 | ((
__uint32_t)(re->originated) & 0xff0000) >> 8 | (
(__uint32_t)(re->originated) & 0xff000000) >> 24
) : __swap32md(re->originated))
;
719
720 /* afi */
721 memcpy(&afi, b, sizeof(afi));
722 b += sizeof(afi);
723 len -= sizeof(afi);
724 afi = ntohs(afi)(__uint16_t)(__builtin_constant_p(afi) ? (__uint16_t)(((__uint16_t
)(afi) & 0xffU) << 8 | ((__uint16_t)(afi) & 0xff00U
) >> 8) : __swap16md(afi))
;
725
726 /* safi */
727 safi = *b++;
728 len -= 1;
729
730 if ((aid = mrt_afi2aid(afi, safi, verbose)) == AID_UNSPEC0)
731 goto fail;
732
733 /* nhlen */
734 nhlen = *b++;
735 len -= 1;
736
737 /* nexthop */
738 if (mrt_extract_addr(b, len, &re->nexthop, aid) == -1)
739 goto fail;
740 if (len < nhlen)
741 goto fail;
742 b += nhlen;
743 len -= nhlen;
744
745 /* prefix */
746 ret = mrt_extract_prefix(b, len, aid, &r->prefix, &r->prefixlen,
747 verbose);
748 if (ret == 1)
749 goto fail;
750 b += ret;
751 len -= ret;
752
753 memcpy(&alen, b, sizeof(alen));
754 b += sizeof(alen);
755 len -= sizeof(alen);
756 alen = ntohs(alen)(__uint16_t)(__builtin_constant_p(alen) ? (__uint16_t)(((__uint16_t
)(alen) & 0xffU) << 8 | ((__uint16_t)(alen) & 0xff00U
) >> 8) : __swap16md(alen))
;
757
758 /* attr */
759 if (len < alen)
760 goto fail;
761 if (mrt_extract_attr(re, b, alen, r->prefix.aid, 0) == -1)
762 goto fail;
763 b += alen;
764 len -= alen;
765
766 return (0);
767fail:
768 mrt_free_rib(r);
769 return (-1);
770}
771
772int
773mrt_extract_attr(struct mrt_rib_entry *re, u_char *a, int alen, u_int8_t aid,
774 int as4)
775{
776 struct mrt_attr *ap;
777 u_int32_t tmp;
778 u_int16_t attr_len;
779 u_int8_t type, flags, *attr;
780
781 do {
782 if (alen < 3)
783 return (-1);
784 attr = a;
785 flags = *a++;
786 alen -= 1;
787 type = *a++;
788 alen -= 1;
789
790 if (flags & MRT_ATTR_EXTLEN0x10) {
791 if (alen < 2)
792 return (-1);
793 memcpy(&attr_len, a, sizeof(attr_len));
794 attr_len = ntohs(attr_len)(__uint16_t)(__builtin_constant_p(attr_len) ? (__uint16_t)(((
__uint16_t)(attr_len) & 0xffU) << 8 | ((__uint16_t)
(attr_len) & 0xff00U) >> 8) : __swap16md(attr_len))
;
795 a += sizeof(attr_len);
796 alen -= sizeof(attr_len);
797 } else {
798 attr_len = *a++;
799 alen -= 1;
800 }
801 switch (type) {
802 case MRT_ATTR_ORIGIN1:
803 if (attr_len != 1)
804 return (-1);
805 re->origin = *a;
806 break;
807 case MRT_ATTR_ASPATH2:
808 if (as4) {
809 re->aspath_len = attr_len;
810 if ((re->aspath = malloc(attr_len)) == NULL((void *)0))
811 err(1, "malloc");
812 memcpy(re->aspath, a, attr_len);
813 } else {
814 re->aspath = mrt_aspath_inflate(a, attr_len,
815 &re->aspath_len);
816 if (re->aspath == NULL((void *)0))
817 return (-1);
818 }
819 break;
820 case MRT_ATTR_NEXTHOP3:
821 if (attr_len != 4)
822 return (-1);
823 if (aid != AID_INET1)
824 break;
825 memcpy(&tmp, a, sizeof(tmp));
826 re->nexthop.aid = AID_INET1;
827 re->nexthop.v4ba.v4.s_addr = tmp;
828 break;
829 case MRT_ATTR_MED4:
830 if (attr_len != 4)
831 return (-1);
832 memcpy(&tmp, a, sizeof(tmp));
833 re->med = ntohl(tmp)(__uint32_t)(__builtin_constant_p(tmp) ? (__uint32_t)(((__uint32_t
)(tmp) & 0xff) << 24 | ((__uint32_t)(tmp) & 0xff00
) << 8 | ((__uint32_t)(tmp) & 0xff0000) >> 8 |
((__uint32_t)(tmp) & 0xff000000) >> 24) : __swap32md
(tmp))
;
834 break;
835 case MRT_ATTR_LOCALPREF5:
836 if (attr_len != 4)
837 return (-1);
838 memcpy(&tmp, a, sizeof(tmp));
839 re->local_pref = ntohl(tmp)(__uint32_t)(__builtin_constant_p(tmp) ? (__uint32_t)(((__uint32_t
)(tmp) & 0xff) << 24 | ((__uint32_t)(tmp) & 0xff00
) << 8 | ((__uint32_t)(tmp) & 0xff0000) >> 8 |
((__uint32_t)(tmp) & 0xff000000) >> 24) : __swap32md
(tmp))
;
840 break;
841 case MRT_ATTR_MP_REACH_NLRI14:
842 /*
843 * XXX horrible hack:
844 * Once again IETF and the real world differ in the
845 * implementation. In short the abbreviated MP_NLRI
846 * hack in the standard is not used in real life.
847 * Detect the two cases by looking at the first byte
848 * of the payload (either the nexthop addr length (RFC)
849 * or the high byte of the AFI (old form)). If the
850 * first byte matches the expected nexthop length it
851 * is expected to be the RFC 6396 encoding.
852 */
853 if (*a != attr_len - 1) {
854 a += 3;
855 alen -= 3;
856 attr_len -= 3;
857 }
858 switch (aid) {
859 case AID_INET62:
860 if (attr_len < sizeof(struct in6_addr) + 1)
861 return (-1);
862 re->nexthop.aid = aid;
863 memcpy(&re->nexthop.v6ba.v6, a + 1,
864 sizeof(struct in6_addr));
865 break;
866 case AID_VPN_IPv43:
867 if (attr_len < sizeof(u_int64_t) +
868 sizeof(struct in_addr))
869 return (-1);
870 re->nexthop.aid = aid;
871 memcpy(&tmp, a + 1 + sizeof(u_int64_t),
872 sizeof(tmp));
873 re->nexthop.v4ba.v4.s_addr = tmp;
874 break;
875 case AID_VPN_IPv64:
876 if (attr_len < sizeof(u_int64_t) +
877 sizeof(struct in6_addr))
878 return (-1);
879 re->nexthop.aid = aid;
880 memcpy(&re->nexthop.v6ba.v6,
881 a + 1 + sizeof(u_int64_t),
882 sizeof(struct in6_addr));
883 break;
884 }
885 break;
886 case MRT_ATTR_AS4PATH17:
887 if (!as4) {
888 free(re->aspath);
889 re->aspath_len = attr_len;
890 if ((re->aspath = malloc(attr_len)) == NULL((void *)0))
891 err(1, "malloc");
892 memcpy(re->aspath, a, attr_len);
893 break;
894 }
895 /* FALLTHROUGH */
896 default:
897 re->nattrs++;
898 if (re->nattrs >= UCHAR_MAX(127*2 +1))
899 err(1, "too many attributes");
900 ap = reallocarray(re->attrs,
901 re->nattrs, sizeof(struct mrt_attr));
902 if (ap == NULL((void *)0))
903 err(1, "realloc");
904 re->attrs = ap;
905 ap = re->attrs + re->nattrs - 1;
906 ap->attr_len = a + attr_len - attr;
907 if ((ap->attr = malloc(ap->attr_len)) == NULL((void *)0))
908 err(1, "malloc");
909 memcpy(ap->attr, attr, ap->attr_len);
910 break;
911 }
912 a += attr_len;
913 alen -= attr_len;
914 } while (alen > 0);
915
916 return (0);
917}
918
919void
920mrt_free_peers(struct mrt_peer *p)
921{
922 free(p->peers);
923 free(p->view);
924 free(p);
925}
926
927void
928mrt_free_rib(struct mrt_rib *r)
929{
930 u_int16_t i, j;
931
932 for (i = 0; i < r->nentries && r->entries; i++) {
933 for (j = 0; j < r->entries[i].nattrs; j++)
934 free(r->entries[i].attrs[j].attr);
935 free(r->entries[i].attrs);
936 free(r->entries[i].aspath);
937 }
938
939 free(r->entries);
940 free(r);
941}
942
943void
944mrt_free_bgp_state(struct mrt_bgp_state *s)
945{
946 free(s);
947}
948
949void
950mrt_free_bgp_msg(struct mrt_bgp_msg *m)
951{
952 free(m->msg);
953 free(m);
954}
955
956u_char *
957mrt_aspath_inflate(void *data, u_int16_t len, u_int16_t *newlen)
958{
959 u_int8_t *seg, *nseg, *ndata;
960 u_int16_t seg_size, olen, nlen;
961 u_int8_t seg_len;
962
963 /* first calculate the length of the aspath */
964 seg = data;
965 nlen = 0;
966 for (olen = len; olen > 0; olen -= seg_size, seg += seg_size) {
967 seg_len = seg[1];
968 seg_size = 2 + sizeof(u_int16_t) * seg_len;
969 nlen += 2 + sizeof(u_int32_t) * seg_len;
970
971 if (seg_size > olen)
972 return NULL((void *)0);
973 }
974
975 *newlen = nlen;
976 if ((ndata = malloc(nlen)) == NULL((void *)0))
977 err(1, "malloc");
978
979 /* then copy the aspath */
980 seg = data;
981 for (nseg = ndata; nseg < ndata + nlen; ) {
982 *nseg++ = *seg++;
983 *nseg++ = seg_len = *seg++;
984 for (; seg_len > 0; seg_len--) {
985 *nseg++ = 0;
986 *nseg++ = 0;
987 *nseg++ = *seg++;
988 *nseg++ = *seg++;
989 }
990 }
991
992 return (ndata);
993}
994
995int
996mrt_extract_addr(void *msg, u_int len, struct bgpd_addr *addr, u_int8_t aid)
997{
998 u_int8_t *b = msg;
999
1000 memset(addr, 0, sizeof(*addr));
1001 switch (aid) {
1002 case AID_INET1:
1003 if (len < sizeof(struct in_addr))
1004 return (-1);
1005 addr->aid = aid;
1006 memcpy(&addr->v4ba.v4, b, sizeof(struct in_addr));
1007 return sizeof(struct in_addr);
1008 case AID_INET62:
1009 if (len < sizeof(struct in6_addr))
1010 return (-1);
1011 addr->aid = aid;
1012 memcpy(&addr->v6ba.v6, b, sizeof(struct in6_addr));
1013 return sizeof(struct in6_addr);
1014 case AID_VPN_IPv43:
1015 if (len < sizeof(u_int64_t) + sizeof(struct in_addr))
1016 return (-1);
1017 addr->aid = aid;
1018 /* XXX labelstack and rd missing */
1019 memcpy(&addr->v4ba.v4, b + sizeof(u_int64_t),
1020 sizeof(struct in_addr));
1021 return (sizeof(u_int64_t) + sizeof(struct in_addr));
1022 case AID_VPN_IPv64:
1023 if (len < sizeof(u_int64_t) + sizeof(struct in6_addr))
1024 return (-1);
1025 addr->aid = aid;
1026 /* XXX labelstack and rd missing */
1027 memcpy(&addr->v6ba.v6, b + sizeof(u_int64_t),
1028 sizeof(struct in6_addr));
1029 return (sizeof(u_int64_t) + sizeof(struct in6_addr));
1030 default:
1031 return (-1);
1032 }
1033}
1034
1035int
1036mrt_extract_prefix(void *msg, u_int len, u_int8_t aid,
1037 struct bgpd_addr *prefix, u_int8_t *prefixlen, int verbose)
1038{
1039 int r;
1040
1041 switch (aid) {
1042 case AID_INET1:
1043 r = nlri_get_prefix(msg, len, prefix, prefixlen);
1044 break;
1045 case AID_INET62:
1046 r = nlri_get_prefix6(msg, len, prefix, prefixlen);
1047 break;
1048 case AID_VPN_IPv43:
1049 r = nlri_get_vpn4(msg, len, prefix, prefixlen, 0);
1050 break;
1051 case AID_VPN_IPv64:
1052 r = nlri_get_vpn6(msg, len, prefix, prefixlen, 0);
1053 break;
1054 default:
1055 if (verbose)
1056 printf("unknown prefix AID %d\n", aid);
1057 return -1;
1058 }
1059 if (r == -1 && verbose)
1060 printf("failed to parse prefix of AID %d\n", aid);
1061 return r;
1062}
1063
1064struct mrt_bgp_state *
1065mrt_parse_state(struct mrt_hdr *hdr, void *msg, int verbose)
1066{
1067 struct timespec t;
1068 struct mrt_bgp_state *s;
1069 u_int8_t *b = msg;
1070 u_int len = ntohl(hdr->length)(__uint32_t)(__builtin_constant_p(hdr->length) ? (__uint32_t
)(((__uint32_t)(hdr->length) & 0xff) << 24 | ((__uint32_t
)(hdr->length) & 0xff00) << 8 | ((__uint32_t)(hdr
->length) & 0xff0000) >> 8 | ((__uint32_t)(hdr->
length) & 0xff000000) >> 24) : __swap32md(hdr->length
))
;
1071 u_int32_t sas, das, usec;
1072 u_int16_t tmp16, afi;
1073 int r;
1074 u_int8_t aid;
1075
1076 t.tv_sec = ntohl(hdr->timestamp)(__uint32_t)(__builtin_constant_p(hdr->timestamp) ? (__uint32_t
)(((__uint32_t)(hdr->timestamp) & 0xff) << 24 | (
(__uint32_t)(hdr->timestamp) & 0xff00) << 8 | ((
__uint32_t)(hdr->timestamp) & 0xff0000) >> 8 | (
(__uint32_t)(hdr->timestamp) & 0xff000000) >> 24
) : __swap32md(hdr->timestamp))
;
1077 t.tv_nsec = 0;
1078
1079 /* handle the microsec field for _ET header */
1080 if (ntohs(hdr->type)(__uint16_t)(__builtin_constant_p(hdr->type) ? (__uint16_t
)(((__uint16_t)(hdr->type) & 0xffU) << 8 | ((__uint16_t
)(hdr->type) & 0xff00U) >> 8) : __swap16md(hdr->
type))
== MSG_PROTOCOL_BGP4MP_ET) {
1081 memcpy(&usec, b, sizeof(usec));
1082 b += sizeof(usec);
1083 len -= sizeof(usec);
1084 t.tv_nsec = ntohl(usec)(__uint32_t)(__builtin_constant_p(usec) ? (__uint32_t)(((__uint32_t
)(usec) & 0xff) << 24 | ((__uint32_t)(usec) & 0xff00
) << 8 | ((__uint32_t)(usec) & 0xff0000) >> 8
| ((__uint32_t)(usec) & 0xff000000) >> 24) : __swap32md
(usec))
* 1000;
1085 }
1086
1087 switch (ntohs(hdr->subtype)(__uint16_t)(__builtin_constant_p(hdr->subtype) ? (__uint16_t
)(((__uint16_t)(hdr->subtype) & 0xffU) << 8 | ((
__uint16_t)(hdr->subtype) & 0xff00U) >> 8) : __swap16md
(hdr->subtype))
) {
1088 case BGP4MP_STATE_CHANGE:
1089 if (len < 8)
1090 return (0);
1091 /* source as */
1092 memcpy(&tmp16, b, sizeof(tmp16));
1093 b += sizeof(tmp16);
1094 len -= sizeof(tmp16);
1095 sas = ntohs(tmp16)(__uint16_t)(__builtin_constant_p(tmp16) ? (__uint16_t)(((__uint16_t
)(tmp16) & 0xffU) << 8 | ((__uint16_t)(tmp16) &
0xff00U) >> 8) : __swap16md(tmp16))
;
1096 /* dest as */
1097 memcpy(&tmp16, b, sizeof(tmp16));
1098 b += sizeof(tmp16);
1099 len -= sizeof(tmp16);
1100 das = ntohs(tmp16)(__uint16_t)(__builtin_constant_p(tmp16) ? (__uint16_t)(((__uint16_t
)(tmp16) & 0xffU) << 8 | ((__uint16_t)(tmp16) &
0xff00U) >> 8) : __swap16md(tmp16))
;
1101 /* if_index, ignored */
1102 b += sizeof(tmp16);
1103 len -= sizeof(tmp16);
1104 /* afi */
1105 memcpy(&tmp16, b, sizeof(tmp16));
1106 b += sizeof(tmp16);
1107 len -= sizeof(tmp16);
1108 afi = ntohs(tmp16)(__uint16_t)(__builtin_constant_p(tmp16) ? (__uint16_t)(((__uint16_t
)(tmp16) & 0xffU) << 8 | ((__uint16_t)(tmp16) &
0xff00U) >> 8) : __swap16md(tmp16))
;
1109 break;
1110 case BGP4MP_STATE_CHANGE_AS4:
1111 if (len < 12)
1112 return (0);
1113 /* source as */
1114 memcpy(&sas, b, sizeof(sas));
1115 b += sizeof(sas);
1116 len -= sizeof(sas);
1117 sas = ntohl(sas)(__uint32_t)(__builtin_constant_p(sas) ? (__uint32_t)(((__uint32_t
)(sas) & 0xff) << 24 | ((__uint32_t)(sas) & 0xff00
) << 8 | ((__uint32_t)(sas) & 0xff0000) >> 8 |
((__uint32_t)(sas) & 0xff000000) >> 24) : __swap32md
(sas))
;
1118 /* dest as */
1119 memcpy(&das, b, sizeof(das));
1120 b += sizeof(das);
1121 len -= sizeof(das);
1122 das = ntohl(das)(__uint32_t)(__builtin_constant_p(das) ? (__uint32_t)(((__uint32_t
)(das) & 0xff) << 24 | ((__uint32_t)(das) & 0xff00
) << 8 | ((__uint32_t)(das) & 0xff0000) >> 8 |
((__uint32_t)(das) & 0xff000000) >> 24) : __swap32md
(das))
;
1123 /* if_index, ignored */
1124 b += sizeof(tmp16);
1125 len -= sizeof(tmp16);
1126 /* afi */
1127 memcpy(&tmp16, b, sizeof(tmp16));
1128 b += sizeof(tmp16);
1129 len -= sizeof(tmp16);
1130 afi = ntohs(tmp16)(__uint16_t)(__builtin_constant_p(tmp16) ? (__uint16_t)(((__uint16_t
)(tmp16) & 0xffU) << 8 | ((__uint16_t)(tmp16) &
0xff00U) >> 8) : __swap16md(tmp16))
;
1131 break;
1132 default:
1133 errx(1, "mrt_parse_state: bad subtype");
1134 }
1135
1136 /* src & dst addr */
1137 if ((aid = mrt_afi2aid(afi, -1, verbose)) == AID_UNSPEC0)
1138 return (NULL((void *)0));
1139
1140 if ((s = calloc(1, sizeof(struct mrt_bgp_state))) == NULL((void *)0))
1141 err(1, "calloc");
1142 s->time = t;
1143 s->src_as = sas;
1144 s->dst_as = das;
1145
1146 if ((r = mrt_extract_addr(b, len, &s->src, aid)) == -1)
1147 goto fail;
1148 b += r;
1149 len -= r;
1150 if ((r = mrt_extract_addr(b, len, &s->dst, aid)) == -1)
1151 goto fail;
1152 b += r;
1153 len -= r;
1154
1155 /* states */
1156 memcpy(&tmp16, b, sizeof(tmp16));
1157 b += sizeof(tmp16);
1158 len -= sizeof(tmp16);
1159 s->old_state = ntohs(tmp16)(__uint16_t)(__builtin_constant_p(tmp16) ? (__uint16_t)(((__uint16_t
)(tmp16) & 0xffU) << 8 | ((__uint16_t)(tmp16) &
0xff00U) >> 8) : __swap16md(tmp16))
;
1160 memcpy(&tmp16, b, sizeof(tmp16));
1161 b += sizeof(tmp16);
1162 len -= sizeof(tmp16);
1163 s->new_state = ntohs(tmp16)(__uint16_t)(__builtin_constant_p(tmp16) ? (__uint16_t)(((__uint16_t
)(tmp16) & 0xffU) << 8 | ((__uint16_t)(tmp16) &
0xff00U) >> 8) : __swap16md(tmp16))
;
1164
1165 return (s);
1166
1167fail:
1168 free(s);
1169 return (NULL((void *)0));
1170}
1171
1172struct mrt_bgp_msg *
1173mrt_parse_msg(struct mrt_hdr *hdr, void *msg, int verbose)
1174{
1175 struct timespec t;
1176 struct mrt_bgp_msg *m;
1177 u_int8_t *b = msg;
1178 u_int len = ntohl(hdr->length)(__uint32_t)(__builtin_constant_p(hdr->length) ? (__uint32_t
)(((__uint32_t)(hdr->length) & 0xff) << 24 | ((__uint32_t
)(hdr->length) & 0xff00) << 8 | ((__uint32_t)(hdr
->length) & 0xff0000) >> 8 | ((__uint32_t)(hdr->
length) & 0xff000000) >> 24) : __swap32md(hdr->length
))
;
1179 u_int32_t sas, das, usec;
1180 u_int16_t tmp16, afi;
1181 int r, addpath = 0;
1182 u_int8_t aid;
1183
1184 t.tv_sec = ntohl(hdr->timestamp)(__uint32_t)(__builtin_constant_p(hdr->timestamp) ? (__uint32_t
)(((__uint32_t)(hdr->timestamp) & 0xff) << 24 | (
(__uint32_t)(hdr->timestamp) & 0xff00) << 8 | ((
__uint32_t)(hdr->timestamp) & 0xff0000) >> 8 | (
(__uint32_t)(hdr->timestamp) & 0xff000000) >> 24
) : __swap32md(hdr->timestamp))
;
1185 t.tv_nsec = 0;
1186
1187 /* handle the microsec field for _ET header */
1188 if (ntohs(hdr->type)(__uint16_t)(__builtin_constant_p(hdr->type) ? (__uint16_t
)(((__uint16_t)(hdr->type) & 0xffU) << 8 | ((__uint16_t
)(hdr->type) & 0xff00U) >> 8) : __swap16md(hdr->
type))
== MSG_PROTOCOL_BGP4MP_ET) {
1189 memcpy(&usec, b, sizeof(usec));
1190 b += sizeof(usec);
1191 len -= sizeof(usec);
1192 t.tv_nsec = ntohl(usec)(__uint32_t)(__builtin_constant_p(usec) ? (__uint32_t)(((__uint32_t
)(usec) & 0xff) << 24 | ((__uint32_t)(usec) & 0xff00
) << 8 | ((__uint32_t)(usec) & 0xff0000) >> 8
| ((__uint32_t)(usec) & 0xff000000) >> 24) : __swap32md
(usec))
* 1000;
1193 }
1194
1195 switch (ntohs(hdr->subtype)(__uint16_t)(__builtin_constant_p(hdr->subtype) ? (__uint16_t
)(((__uint16_t)(hdr->subtype) & 0xffU) << 8 | ((
__uint16_t)(hdr->subtype) & 0xff00U) >> 8) : __swap16md
(hdr->subtype))
) {
1196 case BGP4MP_MESSAGE_ADDPATH:
1197 case BGP4MP_MESSAGE_LOCAL_ADDPATH:
1198 addpath = 1;
1199 /* FALLTHROUGH */
1200 case BGP4MP_MESSAGE:
1201 case BGP4MP_MESSAGE_LOCAL:
1202 if (len < 8)
1203 return (0);
1204 /* source as */
1205 memcpy(&tmp16, b, sizeof(tmp16));
1206 b += sizeof(tmp16);
1207 len -= sizeof(tmp16);
1208 sas = ntohs(tmp16)(__uint16_t)(__builtin_constant_p(tmp16) ? (__uint16_t)(((__uint16_t
)(tmp16) & 0xffU) << 8 | ((__uint16_t)(tmp16) &
0xff00U) >> 8) : __swap16md(tmp16))
;
1209 /* dest as */
1210 memcpy(&tmp16, b, sizeof(tmp16));
1211 b += sizeof(tmp16);
1212 len -= sizeof(tmp16);
1213 das = ntohs(tmp16)(__uint16_t)(__builtin_constant_p(tmp16) ? (__uint16_t)(((__uint16_t
)(tmp16) & 0xffU) << 8 | ((__uint16_t)(tmp16) &
0xff00U) >> 8) : __swap16md(tmp16))
;
1214 /* if_index, ignored */
1215 b += sizeof(tmp16);
1216 len -= sizeof(tmp16);
1217 /* afi */
1218 memcpy(&tmp16, b, sizeof(tmp16));
1219 b += sizeof(tmp16);
1220 len -= sizeof(tmp16);
1221 afi = ntohs(tmp16)(__uint16_t)(__builtin_constant_p(tmp16) ? (__uint16_t)(((__uint16_t
)(tmp16) & 0xffU) << 8 | ((__uint16_t)(tmp16) &
0xff00U) >> 8) : __swap16md(tmp16))
;
1222 break;
1223 case BGP4MP_MESSAGE_AS4_ADDPATH:
1224 case BGP4MP_MESSAGE_AS4_LOCAL_ADDPATH:
1225 addpath = 1;
1226 /* FALLTHROUGH */
1227 case BGP4MP_MESSAGE_AS4:
1228 case BGP4MP_MESSAGE_AS4_LOCAL:
1229 if (len < 12)
1230 return (0);
1231 /* source as */
1232 memcpy(&sas, b, sizeof(sas));
1233 b += sizeof(sas);
1234 len -= sizeof(sas);
1235 sas = ntohl(sas)(__uint32_t)(__builtin_constant_p(sas) ? (__uint32_t)(((__uint32_t
)(sas) & 0xff) << 24 | ((__uint32_t)(sas) & 0xff00
) << 8 | ((__uint32_t)(sas) & 0xff0000) >> 8 |
((__uint32_t)(sas) & 0xff000000) >> 24) : __swap32md
(sas))
;
1236 /* dest as */
1237 memcpy(&das, b, sizeof(das));
1238 b += sizeof(das);
1239 len -= sizeof(das);
1240 das = ntohl(das)(__uint32_t)(__builtin_constant_p(das) ? (__uint32_t)(((__uint32_t
)(das) & 0xff) << 24 | ((__uint32_t)(das) & 0xff00
) << 8 | ((__uint32_t)(das) & 0xff0000) >> 8 |
((__uint32_t)(das) & 0xff000000) >> 24) : __swap32md
(das))
;
1241 /* if_index, ignored */
1242 b += sizeof(tmp16);
1243 len -= sizeof(tmp16);
1244 /* afi */
1245 memcpy(&tmp16, b, sizeof(tmp16));
1246 b += sizeof(tmp16);
1247 len -= sizeof(tmp16);
1248 afi = ntohs(tmp16)(__uint16_t)(__builtin_constant_p(tmp16) ? (__uint16_t)(((__uint16_t
)(tmp16) & 0xffU) << 8 | ((__uint16_t)(tmp16) &
0xff00U) >> 8) : __swap16md(tmp16))
;
1249 break;
1250 default:
1251 errx(1, "mrt_parse_msg: bad subtype");
1252 }
1253
1254 /* src & dst addr */
1255 if ((aid = mrt_afi2aid(afi, -1, verbose)) == AID_UNSPEC0)
1256 return (NULL((void *)0));
1257
1258 if ((m = calloc(1, sizeof(struct mrt_bgp_msg))) == NULL((void *)0))
1259 err(1, "calloc");
1260 m->time = t;
1261 m->src_as = sas;
1262 m->dst_as = das;
1263 m->add_path = addpath;
1264
1265 if ((r = mrt_extract_addr(b, len, &m->src, aid)) == -1)
1266 goto fail;
1267 b += r;
1268 len -= r;
1269 if ((r = mrt_extract_addr(b, len, &m->dst, aid)) == -1)
1270 goto fail;
1271 b += r;
1272 len -= r;
1273
1274 /* msg */
1275 if (len > 0) {
1276 m->msg_len = len;
1277 if ((m->msg = malloc(len)) == NULL((void *)0))
1278 err(1, "malloc");
1279 memcpy(m->msg, b, len);
1280 }
1281
1282 return (m);
1283
1284fail:
1285 free(m->msg);
1286 free(m);
1287 return (NULL((void *)0));
1288}