File: | src/usr.bin/bgplg/bgpctl/../../../usr.sbin/bgpctl/mrtparser.c |
Warning: | line 615, column 2 Value stored to 'len' is never read |
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; |
Value stored to 'len' is never read | |
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 | } |