File: | src/usr.sbin/bgpctl/mrtparser.c |
Warning: | line 574, column 15 Assigned value is garbage or undefined |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
32 | void *mrt_read_msg(int, struct mrt_hdr *); | |||
33 | size_t mrt_read_buf(int, void *, size_t); | |||
34 | ||||
35 | struct mrt_peer *mrt_parse_v2_peer(struct mrt_hdr *, void *); | |||
36 | struct mrt_rib *mrt_parse_v2_rib(struct mrt_hdr *, void *, int); | |||
37 | int mrt_parse_dump(struct mrt_hdr *, void *, struct mrt_peer **, | |||
38 | struct mrt_rib **); | |||
39 | int mrt_parse_dump_mp(struct mrt_hdr *, void *, struct mrt_peer **, | |||
40 | struct mrt_rib **, int); | |||
41 | int mrt_extract_attr(struct mrt_rib_entry *, u_char *, int, u_int8_t, | |||
42 | int); | |||
43 | ||||
44 | void mrt_free_peers(struct mrt_peer *); | |||
45 | void mrt_free_rib(struct mrt_rib *); | |||
46 | void mrt_free_bgp_state(struct mrt_bgp_state *); | |||
47 | void mrt_free_bgp_msg(struct mrt_bgp_msg *); | |||
48 | ||||
49 | u_char *mrt_aspath_inflate(void *, u_int16_t, u_int16_t *); | |||
50 | int mrt_extract_addr(void *, u_int, struct bgpd_addr *, u_int8_t); | |||
51 | int mrt_extract_prefix(void *, u_int, u_int8_t, struct bgpd_addr *, | |||
52 | u_int8_t *, int); | |||
53 | ||||
54 | struct mrt_bgp_state *mrt_parse_state(struct mrt_hdr *, void *, int); | |||
55 | struct mrt_bgp_msg *mrt_parse_msg(struct mrt_hdr *, void *, int); | |||
56 | ||||
57 | void * | |||
58 | mrt_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)) | |||
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)) | |||
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 ))) { | |||
70 | free(buf); | |||
71 | return (NULL((void *)0)); | |||
72 | } | |||
73 | return (buf); | |||
74 | } | |||
75 | ||||
76 | size_t | |||
77 | mrt_read_buf(int fd, void *buf, size_t len) | |||
78 | { | |||
79 | char *b = buf; | |||
80 | ssize_t n; | |||
81 | ||||
82 | while (len > 0) { | |||
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 | ||||
97 | void | |||
98 | mrt_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))) { | |||
| ||||
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))) { | |||
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 ))) { | |||
154 | case MRT_DUMP_V2_PEER_INDEX_TABLE: | |||
155 | if (p->dump == NULL((void *)0)) | |||
156 | break; | |||
157 | if (pctx) | |||
158 | mrt_free_peers(pctx); | |||
159 | pctx = mrt_parse_v2_peer(&h, msg); | |||
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 | ||||
241 | static int | |||
242 | mrt_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 | ||||
265 | struct mrt_peer * | |||
266 | mrt_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 )); | |||
274 | ||||
275 | if (len < 8) /* min msg size */ | |||
276 | return NULL((void *)0); | |||
277 | ||||
278 | p = calloc(1, sizeof(struct mrt_peer)); | |||
279 | if (p == NULL((void *)0)) | |||
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)); | |||
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)); | |||
293 | ||||
294 | /* view name */ | |||
295 | if (cnt > len) | |||
296 | goto fail; | |||
297 | if (cnt != 0) { | |||
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)) | |||
304 | err(1, "strdup"); | |||
305 | b += cnt; | |||
306 | len -= cnt; | |||
307 | ||||
308 | /* peer_count */ | |||
309 | if (len < sizeof(cnt)) | |||
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)); | |||
315 | ||||
316 | /* peer entries */ | |||
317 | if ((peers = calloc(cnt, sizeof(struct mrt_peer_entry))) == NULL((void *)0)) | |||
318 | err(1, "calloc"); | |||
319 | for (i = 0; i < cnt; i++) { | |||
320 | u_int8_t type; | |||
321 | ||||
322 | if (len < sizeof(u_int8_t) + sizeof(u_int32_t)) | |||
323 | goto fail; | |||
324 | type = *b++; | |||
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); | |||
361 | fail: | |||
362 | mrt_free_peers(p); | |||
363 | free(peers); | |||
364 | return (NULL((void *)0)); | |||
365 | } | |||
366 | ||||
367 | struct mrt_rib * | |||
368 | mrt_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); | |||
510 | fail: | |||
511 | mrt_free_rib(r); | |||
512 | free(entries); | |||
513 | return (NULL((void *)0)); | |||
514 | } | |||
515 | ||||
516 | int | |||
517 | mrt_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); | |||
618 | fail: | |||
619 | mrt_free_rib(r); | |||
620 | return (-1); | |||
621 | } | |||
622 | ||||
623 | int | |||
624 | mrt_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); | |||
767 | fail: | |||
768 | mrt_free_rib(r); | |||
769 | return (-1); | |||
770 | } | |||
771 | ||||
772 | int | |||
773 | mrt_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 | ||||
919 | void | |||
920 | mrt_free_peers(struct mrt_peer *p) | |||
921 | { | |||
922 | free(p->peers); | |||
923 | free(p->view); | |||
924 | free(p); | |||
925 | } | |||
926 | ||||
927 | void | |||
928 | mrt_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 | ||||
943 | void | |||
944 | mrt_free_bgp_state(struct mrt_bgp_state *s) | |||
945 | { | |||
946 | free(s); | |||
947 | } | |||
948 | ||||
949 | void | |||
950 | mrt_free_bgp_msg(struct mrt_bgp_msg *m) | |||
951 | { | |||
952 | free(m->msg); | |||
953 | free(m); | |||
954 | } | |||
955 | ||||
956 | u_char * | |||
957 | mrt_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 | ||||
995 | int | |||
996 | mrt_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 | ||||
1035 | int | |||
1036 | mrt_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 | ||||
1064 | struct mrt_bgp_state * | |||
1065 | mrt_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 | ||||
1167 | fail: | |||
1168 | free(s); | |||
1169 | return (NULL((void *)0)); | |||
1170 | } | |||
1171 | ||||
1172 | struct mrt_bgp_msg * | |||
1173 | mrt_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 | ||||
1284 | fail: | |||
1285 | free(m->msg); | |||
1286 | free(m); | |||
1287 | return (NULL((void *)0)); | |||
1288 | } |