File: | src/usr.bin/bgplg/bgpctl/../../../usr.sbin/bgpctl/mrtparser.c |
Warning: | line 433, column 8 Assigned value is garbage or undefined |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
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, uint8_t, int); | |||
42 | ||||
43 | void mrt_free_peers(struct mrt_peer *); | |||
44 | void mrt_free_rib(struct mrt_rib *); | |||
45 | void mrt_free_bgp_state(struct mrt_bgp_state *); | |||
46 | void mrt_free_bgp_msg(struct mrt_bgp_msg *); | |||
47 | ||||
48 | u_char *mrt_aspath_inflate(void *, uint16_t, uint16_t *); | |||
49 | int mrt_extract_addr(void *, u_int, struct bgpd_addr *, uint8_t); | |||
50 | int mrt_extract_prefix(void *, u_int, uint8_t, struct bgpd_addr *, | |||
51 | uint8_t *, int); | |||
52 | ||||
53 | struct mrt_bgp_state *mrt_parse_state(struct mrt_hdr *, void *, int); | |||
54 | struct mrt_bgp_msg *mrt_parse_msg(struct mrt_hdr *, void *, int); | |||
55 | ||||
56 | void * | |||
57 | mrt_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)) | |||
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)) | |||
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 ))) { | |||
69 | free(buf); | |||
70 | return (NULL((void *)0)); | |||
71 | } | |||
72 | return (buf); | |||
73 | } | |||
74 | ||||
75 | size_t | |||
76 | mrt_read_buf(int fd, void *buf, size_t len) | |||
77 | { | |||
78 | char *b = buf; | |||
79 | ssize_t n; | |||
80 | ||||
81 | while (len > 0) { | |||
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 | ||||
96 | void | |||
97 | mrt_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))) { | |||
| ||||
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))) { | |||
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 ))) { | |||
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)) | |||
171 | break; | |||
172 | r = mrt_parse_v2_rib(&h, msg, verbose); | |||
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 | ||||
240 | static int | |||
241 | mrt_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 | ||||
264 | struct mrt_peer * | |||
265 | mrt_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); | |||
360 | fail: | |||
361 | mrt_free_peers(p); | |||
362 | free(peers); | |||
363 | return (NULL((void *)0)); | |||
364 | } | |||
365 | ||||
366 | struct mrt_rib * | |||
367 | mrt_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 )); | |||
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) | |||
379 | return NULL((void *)0); | |||
380 | ||||
381 | r = calloc(1, sizeof(struct mrt_rib)); | |||
382 | if (r == NULL((void *)0)) | |||
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)); | |||
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))) { | |||
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) | |||
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)); | |||
432 | ||||
433 | safi = *b++; | |||
| ||||
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); | |||
509 | fail: | |||
510 | mrt_free_rib(r); | |||
511 | free(entries); | |||
512 | return (NULL((void *)0)); | |||
513 | } | |||
514 | ||||
515 | int | |||
516 | mrt_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); | |||
617 | fail: | |||
618 | mrt_free_rib(r); | |||
619 | return (-1); | |||
620 | } | |||
621 | ||||
622 | int | |||
623 | mrt_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); | |||
766 | fail: | |||
767 | mrt_free_rib(r); | |||
768 | return (-1); | |||
769 | } | |||
770 | ||||
771 | int | |||
772 | mrt_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 | ||||
918 | void | |||
919 | mrt_free_peers(struct mrt_peer *p) | |||
920 | { | |||
921 | free(p->peers); | |||
922 | free(p->view); | |||
923 | free(p); | |||
924 | } | |||
925 | ||||
926 | void | |||
927 | mrt_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 | ||||
942 | void | |||
943 | mrt_free_bgp_state(struct mrt_bgp_state *s) | |||
944 | { | |||
945 | free(s); | |||
946 | } | |||
947 | ||||
948 | void | |||
949 | mrt_free_bgp_msg(struct mrt_bgp_msg *m) | |||
950 | { | |||
951 | free(m->msg); | |||
952 | free(m); | |||
953 | } | |||
954 | ||||
955 | u_char * | |||
956 | mrt_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 | ||||
994 | int | |||
995 | mrt_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 | ||||
1034 | int | |||
1035 | mrt_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 | ||||
1063 | struct mrt_bgp_state * | |||
1064 | mrt_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 | ||||
1166 | fail: | |||
1167 | free(s); | |||
1168 | return (NULL((void *)0)); | |||
1169 | } | |||
1170 | ||||
1171 | struct mrt_bgp_msg * | |||
1172 | mrt_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 | ||||
1283 | fail: | |||
1284 | free(m->msg); | |||
1285 | free(m); | |||
1286 | return (NULL((void *)0)); | |||
1287 | } |