Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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