Bug Summary

File:src/usr.sbin/bgpd/mrt.c
Warning:line 1229, column 14
Result of 'malloc' is converted to a pointer of type 'struct mrt', which is incompatible with sizeof operand type 'struct mrt_config'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name mrt.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/bgpd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/bgpd -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/bgpd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/bgpd/mrt.c
1/* $OpenBSD: mrt.c,v 1.105 2021/09/03 07:48:24 claudio Exp $ */
2
3/*
4 * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/types.h>
20#include <sys/queue.h>
21
22#include <errno(*__errno()).h>
23#include <fcntl.h>
24#include <limits.h>
25#include <stdlib.h>
26#include <string.h>
27#include <time.h>
28#include <unistd.h>
29
30#include "bgpd.h"
31#include "rde.h"
32#include "session.h"
33
34#include "mrt.h"
35#include "log.h"
36
37int mrt_attr_dump(struct ibuf *, struct rde_aspath *, struct rde_community *,
38 struct bgpd_addr *, int);
39int mrt_dump_entry_mp(struct mrt *, struct prefix *, u_int16_t,
40 struct rde_peer*);
41int mrt_dump_entry(struct mrt *, struct prefix *, u_int16_t, struct rde_peer*);
42int mrt_dump_entry_v2(struct mrt *, struct rib_entry *, u_int32_t);
43int mrt_dump_peer(struct ibuf *, struct rde_peer *);
44int mrt_dump_hdr_se(struct ibuf **, struct peer *, u_int16_t, u_int16_t,
45 u_int32_t, int);
46int mrt_dump_hdr_rde(struct ibuf **, u_int16_t type, u_int16_t, u_int32_t);
47int mrt_open(struct mrt *, time_t);
48
49#define DUMP_BYTE(x, b)do { u_char t = (b); if (ibuf_add((x), &t, sizeof(t)) == -
1) { log_warn("mrt_dump1: ibuf_add error"); goto fail; } } while
(0)
\
50 do { \
51 u_char t = (b); \
52 if (ibuf_add((x), &t, sizeof(t)) == -1) { \
53 log_warn("mrt_dump1: ibuf_add error"); \
54 goto fail; \
55 } \
56 } while (0)
57
58#define DUMP_SHORT(x, s)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((s)) ?
(__uint16_t)(((__uint16_t)((s)) & 0xffU) << 8 | ((
__uint16_t)((s)) & 0xff00U) >> 8) : __swap16md((s))
); if (ibuf_add((x), &t, sizeof(t)) == -1) { log_warn("mrt_dump2: ibuf_add error"
); goto fail; } } while (0)
\
59 do { \
60 u_int16_t t; \
61 t = htons((s))(__uint16_t)(__builtin_constant_p((s)) ? (__uint16_t)(((__uint16_t
)((s)) & 0xffU) << 8 | ((__uint16_t)((s)) & 0xff00U
) >> 8) : __swap16md((s)))
; \
62 if (ibuf_add((x), &t, sizeof(t)) == -1) { \
63 log_warn("mrt_dump2: ibuf_add error"); \
64 goto fail; \
65 } \
66 } while (0)
67
68#define DUMP_LONG(x, l)do { u_int32_t t; t = (__uint32_t)(__builtin_constant_p((l)) ?
(__uint32_t)(((__uint32_t)((l)) & 0xff) << 24 | ((
__uint32_t)((l)) & 0xff00) << 8 | ((__uint32_t)((l)
) & 0xff0000) >> 8 | ((__uint32_t)((l)) & 0xff000000
) >> 24) : __swap32md((l))); if (ibuf_add((x), &t, sizeof
(t)) == -1) { log_warn("mrt_dump3: ibuf_add error"); goto fail
; } } while (0)
\
69 do { \
70 u_int32_t t; \
71 t = htonl((l))(__uint32_t)(__builtin_constant_p((l)) ? (__uint32_t)(((__uint32_t
)((l)) & 0xff) << 24 | ((__uint32_t)((l)) & 0xff00
) << 8 | ((__uint32_t)((l)) & 0xff0000) >> 8 |
((__uint32_t)((l)) & 0xff000000) >> 24) : __swap32md
((l)))
; \
72 if (ibuf_add((x), &t, sizeof(t)) == -1) { \
73 log_warn("mrt_dump3: ibuf_add error"); \
74 goto fail; \
75 } \
76 } while (0)
77
78#define DUMP_NLONG(x, l)do { u_int32_t t = (l); if (ibuf_add((x), &t, sizeof(t)) ==
-1) { log_warn("mrt_dump4: ibuf_add error"); goto fail; } } while
(0)
\
79 do { \
80 u_int32_t t = (l); \
81 if (ibuf_add((x), &t, sizeof(t)) == -1) { \
82 log_warn("mrt_dump4: ibuf_add error"); \
83 goto fail; \
84 } \
85 } while (0)
86
87#define RDEIDX0 0
88#define SEIDX1 1
89#define TYPE2IDX(x)((x == MRT_TABLE_DUMP || x == MRT_TABLE_DUMP_MP || x == MRT_TABLE_DUMP_V2
) ? 0 : 1 )
((x == MRT_TABLE_DUMP || \
90 x == MRT_TABLE_DUMP_MP || \
91 x == MRT_TABLE_DUMP_V2) ? RDEIDX0 : SEIDX1 \
92 )
93
94static u_int8_t
95mrt_update_msg_guess_aid(u_int8_t *pkg, u_int16_t pkglen)
96{
97 u_int16_t wlen, alen, len, afi;
98 u_int8_t type, aid;
99
100 pkg += MSGSIZE_HEADER19;
101 pkglen -= MSGSIZE_HEADER19;
102
103 if (pkglen < 4)
104 goto bad;
105
106 memcpy(&wlen, pkg, 2);
107 wlen = ntohs(wlen)(__uint16_t)(__builtin_constant_p(wlen) ? (__uint16_t)(((__uint16_t
)(wlen) & 0xffU) << 8 | ((__uint16_t)(wlen) & 0xff00U
) >> 8) : __swap16md(wlen))
;
108 pkg += 2;
109 pkglen -= 2;
110
111 if (wlen > 0) {
112 /* UPDATE has withdraw routes, therefor IPv4 */
113 return AID_INET1;
114 }
115
116 memcpy(&alen, pkg, 2);
117 alen = ntohs(alen)(__uint16_t)(__builtin_constant_p(alen) ? (__uint16_t)(((__uint16_t
)(alen) & 0xffU) << 8 | ((__uint16_t)(alen) & 0xff00U
) >> 8) : __swap16md(alen))
;
118 pkg += 2;
119 pkglen -= 2;
120
121 if (alen < pkglen) {
122 /* UPDATE has NLRI prefixes, therefor IPv4 */
123 return AID_INET1;
124 }
125
126 if (wlen == 0 && alen == 0) {
127 /* UPDATE is an IPv4 EoR marker */
128 return AID_INET1;
129 }
130
131 /* bad attribute length */
132 if (alen > pkglen)
133 goto bad;
134
135 /* try to extract AFI/SAFI from the MP attributes */
136 while (alen > 0) {
137 if (alen < 3)
138 goto bad;
139 type = pkg[1];
140 if (pkg[0] & ATTR_EXTLEN0x10) {
141 if (alen < 4)
142 goto bad;
143 memcpy(&len, pkg + 2, 2);
144 len = ntohs(len)(__uint16_t)(__builtin_constant_p(len) ? (__uint16_t)(((__uint16_t
)(len) & 0xffU) << 8 | ((__uint16_t)(len) & 0xff00U
) >> 8) : __swap16md(len))
;
145 pkg += 4;
146 alen -= 4;
147 } else {
148 len = pkg[2];
149 pkg += 3;
150 alen -= 3;
151 }
152 if (len > alen)
153 goto bad;
154
155 if (type == ATTR_MP_REACH_NLRI ||
156 type == ATTR_MP_UNREACH_NLRI) {
157 if (alen < 3)
158 goto bad;
159 memcpy(&afi, pkg, 2);
160 afi = ntohs(afi)(__uint16_t)(__builtin_constant_p(afi) ? (__uint16_t)(((__uint16_t
)(afi) & 0xffU) << 8 | ((__uint16_t)(afi) & 0xff00U
) >> 8) : __swap16md(afi))
;
161 if (afi2aid(afi, pkg[2], &aid) == -1)
162 goto bad;
163 return aid;
164 }
165
166 pkg += len;
167 alen -= len;
168 }
169
170bad:
171 return AID_UNSPEC0;
172}
173
174static u_int16_t
175mrt_bgp_msg_subtype(struct mrt *mrt, void *pkg, u_int16_t pkglen,
176 struct peer *peer, enum msg_type msgtype, int in)
177{
178 u_int16_t subtype = BGP4MP_MESSAGE;
179 u_int8_t aid, mask;
180
181 if (peer->capa.neg.as4byte)
182 subtype = BGP4MP_MESSAGE_AS4;
183
184 if (msgtype != UPDATE)
185 return subtype;
186
187 /*
188 * RFC8050 adjust types for add-path enabled sessions.
189 * It is necessary to extract the AID from UPDATES to decide
190 * if the add-path types are needed or not. The ADDPATH
191 * subtypes only matter for BGP UPDATES.
192 */
193
194 mask = in ? CAPA_AP_RECV0x01 : CAPA_AP_SEND0x02;
195 /* only guess if add-path could be active */
196 if (peer->capa.neg.add_path[0] & mask) {
197 aid = mrt_update_msg_guess_aid(pkg, pkglen);
198 if (aid != AID_UNSPEC0 &&
199 (peer->capa.neg.add_path[aid] & mask)) {
200 if (peer->capa.neg.as4byte)
201 subtype = BGP4MP_MESSAGE_AS4_ADDPATH;
202 else
203 subtype = BGP4MP_MESSAGE_ADDPATH;
204 }
205 }
206
207 return subtype;
208}
209
210void
211mrt_dump_bgp_msg(struct mrt *mrt, void *pkg, u_int16_t pkglen,
212 struct peer *peer, enum msg_type msgtype)
213{
214 struct ibuf *buf;
215 int in = 0;
216 u_int16_t subtype = BGP4MP_MESSAGE;
217
218 /* get the direction of the message to swap address and AS fields */
219 if (mrt->type == MRT_ALL_IN || mrt->type == MRT_UPDATE_IN)
220 in = 1;
221
222 subtype = mrt_bgp_msg_subtype(mrt, pkg, pkglen, peer, msgtype, in);
223
224 if (mrt_dump_hdr_se(&buf, peer, MSG_PROTOCOL_BGP4MP_ET, subtype,
225 pkglen, in) == -1)
226 return;
227
228 if (ibuf_add(buf, pkg, pkglen) == -1) {
229 log_warn("mrt_dump_bgp_msg: ibuf_add error");
230 ibuf_free(buf);
231 return;
232 }
233
234 ibuf_close(&mrt->wbuf, buf);
235}
236
237void
238mrt_dump_state(struct mrt *mrt, u_int16_t old_state, u_int16_t new_state,
239 struct peer *peer)
240{
241 struct ibuf *buf;
242 u_int16_t subtype = BGP4MP_STATE_CHANGE;
243
244 if (peer->capa.neg.as4byte)
245 subtype = BGP4MP_STATE_CHANGE_AS4;
246
247 if (mrt_dump_hdr_se(&buf, peer, MSG_PROTOCOL_BGP4MP_ET, subtype,
248 2 * sizeof(short), 0) == -1)
249 return;
250
251 DUMP_SHORT(buf, old_state)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((old_state
)) ? (__uint16_t)(((__uint16_t)((old_state)) & 0xffU) <<
8 | ((__uint16_t)((old_state)) & 0xff00U) >> 8) : __swap16md
((old_state))); if (ibuf_add((buf), &t, sizeof(t)) == -1)
{ log_warn("mrt_dump2: ibuf_add error"); goto fail; } } while
(0)
;
252 DUMP_SHORT(buf, new_state)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((new_state
)) ? (__uint16_t)(((__uint16_t)((new_state)) & 0xffU) <<
8 | ((__uint16_t)((new_state)) & 0xff00U) >> 8) : __swap16md
((new_state))); if (ibuf_add((buf), &t, sizeof(t)) == -1)
{ log_warn("mrt_dump2: ibuf_add error"); goto fail; } } while
(0)
;
253
254 ibuf_close(&mrt->wbuf, buf);
255 return;
256
257fail:
258 ibuf_free(buf);
259}
260
261int
262mrt_attr_dump(struct ibuf *buf, struct rde_aspath *a, struct rde_community *c,
263 struct bgpd_addr *nexthop, int v2)
264{
265 struct attr *oa;
266 u_char *pdata;
267 u_int32_t tmp;
268 int neednewpath = 0;
269 u_int16_t plen, afi;
270 u_int8_t l, safi;
271
272 /* origin */
273 if (attr_writebuf(buf, ATTR_WELL_KNOWN0x40, ATTR_ORIGIN,
274 &a->origin, 1) == -1)
275 return (-1);
276
277 /* aspath */
278 plen = aspath_length(a->aspath);
279 pdata = aspath_dump(a->aspath);
280
281 if (!v2)
282 pdata = aspath_deflate(pdata, &plen, &neednewpath);
283 if (attr_writebuf(buf, ATTR_WELL_KNOWN0x40, ATTR_ASPATH, pdata,
284 plen) == -1) {
285 if (!v2)
286 free(pdata);
287 return (-1);
288 }
289 if (!v2)
290 free(pdata);
291
292 if (nexthop && nexthop->aid == AID_INET1) {
293 /* nexthop, already network byte order */
294 if (attr_writebuf(buf, ATTR_WELL_KNOWN0x40, ATTR_NEXTHOP,
295 &nexthop->v4ba.v4.s_addr, 4) == -1)
296 return (-1);
297 }
298
299 /* MED, non transitive */
300 if (a->med != 0) {
301 tmp = htonl(a->med)(__uint32_t)(__builtin_constant_p(a->med) ? (__uint32_t)((
(__uint32_t)(a->med) & 0xff) << 24 | ((__uint32_t
)(a->med) & 0xff00) << 8 | ((__uint32_t)(a->med
) & 0xff0000) >> 8 | ((__uint32_t)(a->med) &
0xff000000) >> 24) : __swap32md(a->med))
;
302 if (attr_writebuf(buf, ATTR_OPTIONAL0x80, ATTR_MED, &tmp, 4) == -1)
303 return (-1);
304 }
305
306 /* local preference */
307 tmp = htonl(a->lpref)(__uint32_t)(__builtin_constant_p(a->lpref) ? (__uint32_t)
(((__uint32_t)(a->lpref) & 0xff) << 24 | ((__uint32_t
)(a->lpref) & 0xff00) << 8 | ((__uint32_t)(a->
lpref) & 0xff0000) >> 8 | ((__uint32_t)(a->lpref
) & 0xff000000) >> 24) : __swap32md(a->lpref))
;
308 if (attr_writebuf(buf, ATTR_WELL_KNOWN0x40, ATTR_LOCALPREF, &tmp, 4) == -1)
309 return (-1);
310
311 /* communities */
312 if (community_writebuf(buf, c) == -1)
313 return (-1);
314
315 /* dump all other path attributes without modification */
316 for (l = 0; l < a->others_len; l++) {
317 if ((oa = a->others[l]) == NULL((void*)0))
318 break;
319 if (attr_writebuf(buf, oa->flags, oa->type,
320 oa->data, oa->len) == -1)
321 return (-1);
322 }
323
324 if (nexthop && nexthop->aid != AID_INET1) {
325 struct ibuf *nhbuf;
326
327 if ((nhbuf = ibuf_dynamic(0, UCHAR_MAX(127*2 +1))) == NULL((void*)0))
328 return (-1);
329 if (!v2) {
330 if (aid2afi(nexthop->aid, &afi, &safi))
331 return (-1);
332 DUMP_SHORT(nhbuf, afi)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((afi)
) ? (__uint16_t)(((__uint16_t)((afi)) & 0xffU) << 8
| ((__uint16_t)((afi)) & 0xff00U) >> 8) : __swap16md
((afi))); if (ibuf_add((nhbuf), &t, sizeof(t)) == -1) { log_warn
("mrt_dump2: ibuf_add error"); goto fail; } } while (0)
;
333 DUMP_BYTE(nhbuf, safi)do { u_char t = (safi); if (ibuf_add((nhbuf), &t, sizeof(
t)) == -1) { log_warn("mrt_dump1: ibuf_add error"); goto fail
; } } while (0)
;
334 }
335 switch (nexthop->aid) {
336 case AID_INET62:
337 DUMP_BYTE(nhbuf, sizeof(struct in6_addr))do { u_char t = (sizeof(struct in6_addr)); if (ibuf_add((nhbuf
), &t, sizeof(t)) == -1) { log_warn("mrt_dump1: ibuf_add error"
); goto fail; } } while (0)
;
338 if (ibuf_add(nhbuf, &nexthop->v6ba.v6,
339 sizeof(struct in6_addr)) == -1)
340 goto fail;
341 break;
342 case AID_VPN_IPv43:
343 DUMP_BYTE(nhbuf, sizeof(u_int64_t) +do { u_char t = (sizeof(u_int64_t) + sizeof(struct in_addr));
if (ibuf_add((nhbuf), &t, sizeof(t)) == -1) { log_warn("mrt_dump1: ibuf_add error"
); goto fail; } } while (0)
344 sizeof(struct in_addr))do { u_char t = (sizeof(u_int64_t) + sizeof(struct in_addr));
if (ibuf_add((nhbuf), &t, sizeof(t)) == -1) { log_warn("mrt_dump1: ibuf_add error"
); goto fail; } } while (0)
;
345 DUMP_NLONG(nhbuf, 0)do { u_int32_t t = (0); if (ibuf_add((nhbuf), &t, sizeof(
t)) == -1) { log_warn("mrt_dump4: ibuf_add error"); goto fail
; } } while (0)
; /* set RD to 0 */
346 DUMP_NLONG(nhbuf, 0)do { u_int32_t t = (0); if (ibuf_add((nhbuf), &t, sizeof(
t)) == -1) { log_warn("mrt_dump4: ibuf_add error"); goto fail
; } } while (0)
;
347 DUMP_NLONG(nhbuf, nexthop->v4.s_addr)do { u_int32_t t = (nexthop->ba.v4.s_addr); if (ibuf_add((
nhbuf), &t, sizeof(t)) == -1) { log_warn("mrt_dump4: ibuf_add error"
); goto fail; } } while (0)
;
348 break;
349 case AID_VPN_IPv64:
350 DUMP_BYTE(nhbuf, sizeof(u_int64_t) +do { u_char t = (sizeof(u_int64_t) + sizeof(struct in6_addr))
; if (ibuf_add((nhbuf), &t, sizeof(t)) == -1) { log_warn(
"mrt_dump1: ibuf_add error"); goto fail; } } while (0)
351 sizeof(struct in6_addr))do { u_char t = (sizeof(u_int64_t) + sizeof(struct in6_addr))
; if (ibuf_add((nhbuf), &t, sizeof(t)) == -1) { log_warn(
"mrt_dump1: ibuf_add error"); goto fail; } } while (0)
;
352 DUMP_NLONG(nhbuf, 0)do { u_int32_t t = (0); if (ibuf_add((nhbuf), &t, sizeof(
t)) == -1) { log_warn("mrt_dump4: ibuf_add error"); goto fail
; } } while (0)
; /* set RD to 0 */
353 DUMP_NLONG(nhbuf, 0)do { u_int32_t t = (0); if (ibuf_add((nhbuf), &t, sizeof(
t)) == -1) { log_warn("mrt_dump4: ibuf_add error"); goto fail
; } } while (0)
;
354 if (ibuf_add(nhbuf, &nexthop->v6ba.v6,
355 sizeof(struct in6_addr)) == -1)
356 goto fail;
357 break;
358 }
359 if (!v2)
360 DUMP_BYTE(nhbuf, 0)do { u_char t = (0); if (ibuf_add((nhbuf), &t, sizeof(t))
== -1) { log_warn("mrt_dump1: ibuf_add error"); goto fail; }
} while (0)
;
361 if (attr_writebuf(buf, ATTR_OPTIONAL0x80, ATTR_MP_REACH_NLRI,
362 nhbuf->buf, ibuf_size(nhbuf)) == -1) {
363fail:
364 ibuf_free(nhbuf);
365 return (-1);
366 }
367 ibuf_free(nhbuf);
368 }
369
370 if (neednewpath) {
371 pdata = aspath_prepend(a->aspath, rde_local_as(), 0, &plen);
372 if (plen != 0)
373 if (attr_writebuf(buf, ATTR_OPTIONAL0x80|ATTR_TRANSITIVE0x40,
374 ATTR_AS4_PATH, pdata, plen) == -1) {
375 free(pdata);
376 return (-1);
377 }
378 free(pdata);
379 }
380
381 return (0);
382}
383
384int
385mrt_dump_entry_mp(struct mrt *mrt, struct prefix *p, u_int16_t snum,
386 struct rde_peer *peer)
387{
388 struct ibuf *buf, *hbuf = NULL((void*)0), *h2buf = NULL((void*)0);
389 struct nexthop *n;
390 struct bgpd_addr addr, nexthop, *nh;
391 u_int16_t len;
392 u_int8_t aid;
393
394 if ((buf = ibuf_dynamic(0, MAX_PKTSIZE4096)) == NULL((void*)0)) {
395 log_warn("mrt_dump_entry_mp: ibuf_dynamic");
396 return (-1);
397 }
398
399 if (mrt_attr_dump(buf, prefix_aspath(p), prefix_communities(p),
400 NULL((void*)0), 0) == -1) {
401 log_warnx("mrt_dump_entry_mp: mrt_attr_dump error");
402 goto fail;
403 }
404 len = ibuf_size(buf);
405
406 if ((h2buf = ibuf_dynamic(MRT_BGP4MP_IPv4_HEADER_SIZE16 +
407 MRT_BGP4MP_IPv4_ENTRY_SIZE18, MRT_BGP4MP_IPv6_HEADER_SIZE40 +
408 MRT_BGP4MP_IPv6_ENTRY_SIZE30 + MRT_BGP4MP_MAX_PREFIXLEN256)) == NULL((void*)0)) {
409 log_warn("mrt_dump_entry_mp: ibuf_dynamic");
410 goto fail;
411 }
412
413 DUMP_SHORT(h2buf, peer->conf.local_short_as)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((peer
->conf.local_short_as)) ? (__uint16_t)(((__uint16_t)((peer
->conf.local_short_as)) & 0xffU) << 8 | ((__uint16_t
)((peer->conf.local_short_as)) & 0xff00U) >> 8) :
__swap16md((peer->conf.local_short_as))); if (ibuf_add((h2buf
), &t, sizeof(t)) == -1) { log_warn("mrt_dump2: ibuf_add error"
); goto fail; } } while (0)
;
414 DUMP_SHORT(h2buf, peer->short_as)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((peer
->short_as)) ? (__uint16_t)(((__uint16_t)((peer->short_as
)) & 0xffU) << 8 | ((__uint16_t)((peer->short_as
)) & 0xff00U) >> 8) : __swap16md((peer->short_as
))); if (ibuf_add((h2buf), &t, sizeof(t)) == -1) { log_warn
("mrt_dump2: ibuf_add error"); goto fail; } } while (0)
;
415 DUMP_SHORT(h2buf, /* ifindex */ 0)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((0)) ?
(__uint16_t)(((__uint16_t)((0)) & 0xffU) << 8 | ((
__uint16_t)((0)) & 0xff00U) >> 8) : __swap16md((0))
); if (ibuf_add((h2buf), &t, sizeof(t)) == -1) { log_warn
("mrt_dump2: ibuf_add error"); goto fail; } } while (0)
;
416
417 /* XXX is this for peer self? */
418 aid = peer->remote_addr.aid == AID_UNSPEC0 ? p->pt->aid :
419 peer->remote_addr.aid;
420 switch (aid) {
421 case AID_INET1:
422 case AID_VPN_IPv43:
423 DUMP_SHORT(h2buf, AFI_IPv4)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((1)) ?
(__uint16_t)(((__uint16_t)((1)) & 0xffU) << 8 | ((
__uint16_t)((1)) & 0xff00U) >> 8) : __swap16md((1))
); if (ibuf_add((h2buf), &t, sizeof(t)) == -1) { log_warn
("mrt_dump2: ibuf_add error"); goto fail; } } while (0)
;
424 DUMP_NLONG(h2buf, peer->local_v4_addr.v4.s_addr)do { u_int32_t t = (peer->local_v4_addr.ba.v4.s_addr); if (
ibuf_add((h2buf), &t, sizeof(t)) == -1) { log_warn("mrt_dump4: ibuf_add error"
); goto fail; } } while (0)
;
425 DUMP_NLONG(h2buf, peer->remote_addr.v4.s_addr)do { u_int32_t t = (peer->remote_addr.ba.v4.s_addr); if (ibuf_add
((h2buf), &t, sizeof(t)) == -1) { log_warn("mrt_dump4: ibuf_add error"
); goto fail; } } while (0)
;
426 break;
427 case AID_INET62:
428 case AID_VPN_IPv64:
429 DUMP_SHORT(h2buf, AFI_IPv6)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((2)) ?
(__uint16_t)(((__uint16_t)((2)) & 0xffU) << 8 | ((
__uint16_t)((2)) & 0xff00U) >> 8) : __swap16md((2))
); if (ibuf_add((h2buf), &t, sizeof(t)) == -1) { log_warn
("mrt_dump2: ibuf_add error"); goto fail; } } while (0)
;
430 if (ibuf_add(h2buf, &peer->local_v6_addr.v6ba.v6,
431 sizeof(struct in6_addr)) == -1 ||
432 ibuf_add(h2buf, &peer->remote_addr.v6ba.v6,
433 sizeof(struct in6_addr)) == -1) {
434 log_warn("mrt_dump_entry_mp: ibuf_add error");
435 goto fail;
436 }
437 break;
438 default:
439 log_warnx("king bula found new AF %d in %s", aid, __func__);
440 goto fail;
441 }
442
443 DUMP_SHORT(h2buf, 0)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((0)) ?
(__uint16_t)(((__uint16_t)((0)) & 0xffU) << 8 | ((
__uint16_t)((0)) & 0xff00U) >> 8) : __swap16md((0))
); if (ibuf_add((h2buf), &t, sizeof(t)) == -1) { log_warn
("mrt_dump2: ibuf_add error"); goto fail; } } while (0)
; /* view */
444 DUMP_SHORT(h2buf, 1)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((1)) ?
(__uint16_t)(((__uint16_t)((1)) & 0xffU) << 8 | ((
__uint16_t)((1)) & 0xff00U) >> 8) : __swap16md((1))
); if (ibuf_add((h2buf), &t, sizeof(t)) == -1) { log_warn
("mrt_dump2: ibuf_add error"); goto fail; } } while (0)
; /* status */
445 /* originated timestamp */
446 DUMP_LONG(h2buf, time(NULL) - (getmonotime() - p->lastchange))do { u_int32_t t; t = (__uint32_t)(__builtin_constant_p((time
(((void*)0)) - (getmonotime() - p->lastchange))) ? (__uint32_t
)(((__uint32_t)((time(((void*)0)) - (getmonotime() - p->lastchange
))) & 0xff) << 24 | ((__uint32_t)((time(((void*)0))
- (getmonotime() - p->lastchange))) & 0xff00) <<
8 | ((__uint32_t)((time(((void*)0)) - (getmonotime() - p->
lastchange))) & 0xff0000) >> 8 | ((__uint32_t)((time
(((void*)0)) - (getmonotime() - p->lastchange))) & 0xff000000
) >> 24) : __swap32md((time(((void*)0)) - (getmonotime(
) - p->lastchange)))); if (ibuf_add((h2buf), &t, sizeof
(t)) == -1) { log_warn("mrt_dump3: ibuf_add error"); goto fail
; } } while (0)
;
447
448 pt_getaddr(p->pt, &addr);
449
450 n = prefix_nexthop(p);
451 if (n == NULL((void*)0)) {
452 bzero(&nexthop, sizeof(struct bgpd_addr));
453 nexthop.aid = addr.aid;
454 nh = &nexthop;
455 } else
456 nh = &n->exit_nexthop;
457
458 switch (addr.aid) {
459 case AID_INET1:
460 DUMP_SHORT(h2buf, AFI_IPv4)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((1)) ?
(__uint16_t)(((__uint16_t)((1)) & 0xffU) << 8 | ((
__uint16_t)((1)) & 0xff00U) >> 8) : __swap16md((1))
); if (ibuf_add((h2buf), &t, sizeof(t)) == -1) { log_warn
("mrt_dump2: ibuf_add error"); goto fail; } } while (0)
; /* afi */
461 DUMP_BYTE(h2buf, SAFI_UNICAST)do { u_char t = (1); if (ibuf_add((h2buf), &t, sizeof(t))
== -1) { log_warn("mrt_dump1: ibuf_add error"); goto fail; }
} while (0)
; /* safi */
462 DUMP_BYTE(h2buf, 4)do { u_char t = (4); if (ibuf_add((h2buf), &t, sizeof(t))
== -1) { log_warn("mrt_dump1: ibuf_add error"); goto fail; }
} while (0)
; /* nhlen */
463 DUMP_NLONG(h2buf, nh->v4.s_addr)do { u_int32_t t = (nh->ba.v4.s_addr); if (ibuf_add((h2buf
), &t, sizeof(t)) == -1) { log_warn("mrt_dump4: ibuf_add error"
); goto fail; } } while (0)
; /* nexthop */
464 break;
465 case AID_INET62:
466 DUMP_SHORT(h2buf, AFI_IPv6)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((2)) ?
(__uint16_t)(((__uint16_t)((2)) & 0xffU) << 8 | ((
__uint16_t)((2)) & 0xff00U) >> 8) : __swap16md((2))
); if (ibuf_add((h2buf), &t, sizeof(t)) == -1) { log_warn
("mrt_dump2: ibuf_add error"); goto fail; } } while (0)
; /* afi */
467 DUMP_BYTE(h2buf, SAFI_UNICAST)do { u_char t = (1); if (ibuf_add((h2buf), &t, sizeof(t))
== -1) { log_warn("mrt_dump1: ibuf_add error"); goto fail; }
} while (0)
; /* safi */
468 DUMP_BYTE(h2buf, 16)do { u_char t = (16); if (ibuf_add((h2buf), &t, sizeof(t)
) == -1) { log_warn("mrt_dump1: ibuf_add error"); goto fail; }
} while (0)
; /* nhlen */
469 if (ibuf_add(h2buf, &nh->v6ba.v6, sizeof(struct in6_addr)) == -1) {
470 log_warn("mrt_dump_entry_mp: ibuf_add error");
471 goto fail;
472 }
473 break;
474 case AID_VPN_IPv43:
475 DUMP_SHORT(h2buf, AFI_IPv4)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((1)) ?
(__uint16_t)(((__uint16_t)((1)) & 0xffU) << 8 | ((
__uint16_t)((1)) & 0xff00U) >> 8) : __swap16md((1))
); if (ibuf_add((h2buf), &t, sizeof(t)) == -1) { log_warn
("mrt_dump2: ibuf_add error"); goto fail; } } while (0)
; /* afi */
476 DUMP_BYTE(h2buf, SAFI_MPLSVPN)do { u_char t = (128); if (ibuf_add((h2buf), &t, sizeof(t
)) == -1) { log_warn("mrt_dump1: ibuf_add error"); goto fail;
} } while (0)
; /* safi */
477 DUMP_BYTE(h2buf, sizeof(u_int64_t) + sizeof(struct in_addr))do { u_char t = (sizeof(u_int64_t) + sizeof(struct in_addr));
if (ibuf_add((h2buf), &t, sizeof(t)) == -1) { log_warn("mrt_dump1: ibuf_add error"
); goto fail; } } while (0)
;
478 DUMP_NLONG(h2buf, 0)do { u_int32_t t = (0); if (ibuf_add((h2buf), &t, sizeof(
t)) == -1) { log_warn("mrt_dump4: ibuf_add error"); goto fail
; } } while (0)
; /* set RD to 0 */
479 DUMP_NLONG(h2buf, 0)do { u_int32_t t = (0); if (ibuf_add((h2buf), &t, sizeof(
t)) == -1) { log_warn("mrt_dump4: ibuf_add error"); goto fail
; } } while (0)
;
480 DUMP_NLONG(h2buf, nh->v4.s_addr)do { u_int32_t t = (nh->ba.v4.s_addr); if (ibuf_add((h2buf
), &t, sizeof(t)) == -1) { log_warn("mrt_dump4: ibuf_add error"
); goto fail; } } while (0)
; /* nexthop */
481 break;
482 case AID_VPN_IPv64:
483 DUMP_SHORT(h2buf, AFI_IPv6)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((2)) ?
(__uint16_t)(((__uint16_t)((2)) & 0xffU) << 8 | ((
__uint16_t)((2)) & 0xff00U) >> 8) : __swap16md((2))
); if (ibuf_add((h2buf), &t, sizeof(t)) == -1) { log_warn
("mrt_dump2: ibuf_add error"); goto fail; } } while (0)
; /* afi */
484 DUMP_BYTE(h2buf, SAFI_MPLSVPN)do { u_char t = (128); if (ibuf_add((h2buf), &t, sizeof(t
)) == -1) { log_warn("mrt_dump1: ibuf_add error"); goto fail;
} } while (0)
; /* safi */
485 DUMP_BYTE(h2buf, sizeof(u_int64_t) + sizeof(struct in6_addr))do { u_char t = (sizeof(u_int64_t) + sizeof(struct in6_addr))
; if (ibuf_add((h2buf), &t, sizeof(t)) == -1) { log_warn(
"mrt_dump1: ibuf_add error"); goto fail; } } while (0)
;
486 DUMP_NLONG(h2buf, 0)do { u_int32_t t = (0); if (ibuf_add((h2buf), &t, sizeof(
t)) == -1) { log_warn("mrt_dump4: ibuf_add error"); goto fail
; } } while (0)
; /* set RD to 0 */
487 DUMP_NLONG(h2buf, 0)do { u_int32_t t = (0); if (ibuf_add((h2buf), &t, sizeof(
t)) == -1) { log_warn("mrt_dump4: ibuf_add error"); goto fail
; } } while (0)
;
488 if (ibuf_add(h2buf, &nh->v6ba.v6, sizeof(struct in6_addr)) == -1) {
489 log_warn("mrt_dump_entry_mp: ibuf_add error");
490 goto fail;
491 }
492 break;
493 default:
494 log_warnx("king bula found new AF in %s", __func__);
495 goto fail;
496 }
497
498 if (prefix_writebuf(h2buf, &addr, p->pt->prefixlen) == -1) {
499 log_warnx("%s: prefix_writebuf error", __func__);
500 goto fail;
501 }
502
503 DUMP_SHORT(h2buf, len)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((len)
) ? (__uint16_t)(((__uint16_t)((len)) & 0xffU) << 8
| ((__uint16_t)((len)) & 0xff00U) >> 8) : __swap16md
((len))); if (ibuf_add((h2buf), &t, sizeof(t)) == -1) { log_warn
("mrt_dump2: ibuf_add error"); goto fail; } } while (0)
;
504 len += ibuf_size(h2buf);
505
506 if (mrt_dump_hdr_rde(&hbuf, MSG_PROTOCOL_BGP4MP, BGP4MP_ENTRY,
507 len) == -1)
508 goto fail;
509
510 ibuf_close(&mrt->wbuf, hbuf);
511 ibuf_close(&mrt->wbuf, h2buf);
512 ibuf_close(&mrt->wbuf, buf);
513
514 return (len + MRT_HEADER_SIZE12);
515
516fail:
517 ibuf_free(hbuf);
518 ibuf_free(h2buf);
519 ibuf_free(buf);
520 return (-1);
521}
522
523int
524mrt_dump_entry(struct mrt *mrt, struct prefix *p, u_int16_t snum,
525 struct rde_peer *peer)
526{
527 struct ibuf *buf, *hbuf;
528 struct nexthop *nexthop;
529 struct bgpd_addr addr, *nh;
530 size_t len;
531 u_int16_t subtype;
532 u_int8_t dummy;
533
534 if (p->pt->aid != peer->remote_addr.aid &&
535 p->pt->aid != AID_INET1 && p->pt->aid != AID_INET62)
536 /* only able to dump pure IPv4/IPv6 */
537 return (0);
538
539 if ((buf = ibuf_dynamic(0, MAX_PKTSIZE4096)) == NULL((void*)0)) {
540 log_warn("mrt_dump_entry: ibuf_dynamic");
541 return (-1);
542 }
543
544 nexthop = prefix_nexthop(p);
545 if (nexthop == NULL((void*)0)) {
546 bzero(&addr, sizeof(struct bgpd_addr));
547 addr.aid = p->pt->aid;
548 nh = &addr;
549 } else
550 nh = &nexthop->exit_nexthop;
551 if (mrt_attr_dump(buf, prefix_aspath(p), prefix_communities(p),
552 nh, 0) == -1) {
553 log_warnx("mrt_dump_entry: mrt_attr_dump error");
554 ibuf_free(buf);
555 return (-1);
556 }
557 len = ibuf_size(buf);
558 aid2afi(p->pt->aid, &subtype, &dummy);
559 if (mrt_dump_hdr_rde(&hbuf, MSG_TABLE_DUMP, subtype, len) == -1) {
560 ibuf_free(buf);
561 return (-1);
562 }
563
564 DUMP_SHORT(hbuf, 0)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((0)) ?
(__uint16_t)(((__uint16_t)((0)) & 0xffU) << 8 | ((
__uint16_t)((0)) & 0xff00U) >> 8) : __swap16md((0))
); if (ibuf_add((hbuf), &t, sizeof(t)) == -1) { log_warn(
"mrt_dump2: ibuf_add error"); goto fail; } } while (0)
;
565 DUMP_SHORT(hbuf, snum)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((snum
)) ? (__uint16_t)(((__uint16_t)((snum)) & 0xffU) <<
8 | ((__uint16_t)((snum)) & 0xff00U) >> 8) : __swap16md
((snum))); if (ibuf_add((hbuf), &t, sizeof(t)) == -1) { log_warn
("mrt_dump2: ibuf_add error"); goto fail; } } while (0)
;
566
567 pt_getaddr(p->pt, &addr);
568 switch (p->pt->aid) {
569 case AID_INET1:
570 DUMP_NLONG(hbuf, addr.v4.s_addr)do { u_int32_t t = (addr.ba.v4.s_addr); if (ibuf_add((hbuf), &
t, sizeof(t)) == -1) { log_warn("mrt_dump4: ibuf_add error");
goto fail; } } while (0)
;
571 break;
572 case AID_INET62:
573 if (ibuf_add(hbuf, &addr.v6ba.v6, sizeof(struct in6_addr)) == -1) {
574 log_warn("mrt_dump_entry: ibuf_add error");
575 goto fail;
576 }
577 break;
578 }
579 DUMP_BYTE(hbuf, p->pt->prefixlen)do { u_char t = (p->pt->prefixlen); if (ibuf_add((hbuf)
, &t, sizeof(t)) == -1) { log_warn("mrt_dump1: ibuf_add error"
); goto fail; } } while (0)
;
580
581 DUMP_BYTE(hbuf, 1)do { u_char t = (1); if (ibuf_add((hbuf), &t, sizeof(t)) ==
-1) { log_warn("mrt_dump1: ibuf_add error"); goto fail; } } while
(0)
; /* state */
582 /* originated timestamp */
583 DUMP_LONG(hbuf, time(NULL) - (getmonotime() - p->lastchange))do { u_int32_t t; t = (__uint32_t)(__builtin_constant_p((time
(((void*)0)) - (getmonotime() - p->lastchange))) ? (__uint32_t
)(((__uint32_t)((time(((void*)0)) - (getmonotime() - p->lastchange
))) & 0xff) << 24 | ((__uint32_t)((time(((void*)0))
- (getmonotime() - p->lastchange))) & 0xff00) <<
8 | ((__uint32_t)((time(((void*)0)) - (getmonotime() - p->
lastchange))) & 0xff0000) >> 8 | ((__uint32_t)((time
(((void*)0)) - (getmonotime() - p->lastchange))) & 0xff000000
) >> 24) : __swap32md((time(((void*)0)) - (getmonotime(
) - p->lastchange)))); if (ibuf_add((hbuf), &t, sizeof
(t)) == -1) { log_warn("mrt_dump3: ibuf_add error"); goto fail
; } } while (0)
;
584 switch (p->pt->aid) {
585 case AID_INET1:
586 DUMP_NLONG(hbuf, peer->remote_addr.v4.s_addr)do { u_int32_t t = (peer->remote_addr.ba.v4.s_addr); if (ibuf_add
((hbuf), &t, sizeof(t)) == -1) { log_warn("mrt_dump4: ibuf_add error"
); goto fail; } } while (0)
;
587 break;
588 case AID_INET62:
589 if (ibuf_add(hbuf, &peer->remote_addr.v6ba.v6,
590 sizeof(struct in6_addr)) == -1) {
591 log_warn("mrt_dump_entry: ibuf_add error");
592 goto fail;
593 }
594 break;
595 }
596 DUMP_SHORT(hbuf, peer->short_as)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((peer
->short_as)) ? (__uint16_t)(((__uint16_t)((peer->short_as
)) & 0xffU) << 8 | ((__uint16_t)((peer->short_as
)) & 0xff00U) >> 8) : __swap16md((peer->short_as
))); if (ibuf_add((hbuf), &t, sizeof(t)) == -1) { log_warn
("mrt_dump2: ibuf_add error"); goto fail; } } while (0)
;
597 DUMP_SHORT(hbuf, len)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((len)
) ? (__uint16_t)(((__uint16_t)((len)) & 0xffU) << 8
| ((__uint16_t)((len)) & 0xff00U) >> 8) : __swap16md
((len))); if (ibuf_add((hbuf), &t, sizeof(t)) == -1) { log_warn
("mrt_dump2: ibuf_add error"); goto fail; } } while (0)
;
598
599 ibuf_close(&mrt->wbuf, hbuf);
600 ibuf_close(&mrt->wbuf, buf);
601
602 return (len + MRT_HEADER_SIZE12);
603
604fail:
605 ibuf_free(hbuf);
606 ibuf_free(buf);
607 return (-1);
608}
609
610static int
611mrt_dump_entry_v2_rib(struct rib_entry *re, struct ibuf **nb, struct ibuf **apb,
612 uint16_t *np, uint16_t *app)
613{
614 struct bgpd_addr addr;
615 struct ibuf *buf, **bp;
616 struct prefix *p;
617 size_t len;
618 int addpath;
619
620 *np = 0;
621 *app = 0;
622
623 LIST_FOREACH(p, &re->prefix_h, entry.list.rib)for((p) = ((&re->prefix_h)->lh_first); (p)!= ((void
*)0); (p) = ((p)->entry.list.rib.le_next))
{
624 struct nexthop *nexthop;
625 struct bgpd_addr *nh;
626 struct ibuf *tbuf;
627
628 addpath = peer_has_add_path(prefix_peer(p), re->prefix->aid,
629 CAPA_AP_RECV0x01);
630
631 if (addpath) {
632 bp = apb;
633 *app += 1;
634 } else {
635 bp = nb;
636 *np += 1;
637 }
638 if ((buf = *bp) == NULL((void*)0)) {
639 if ((buf = ibuf_dynamic(0, UINT_MAX(2147483647 *2U +1U))) == NULL((void*)0)) {
640 log_warn("%s: ibuf_dynamic", __func__);
641 goto fail;
642 }
643 *bp = buf;
644 }
645
646 nexthop = prefix_nexthop(p);
647 if (nexthop == NULL((void*)0)) {
648 bzero(&addr, sizeof(struct bgpd_addr));
649 addr.aid = re->prefix->aid;
650 nh = &addr;
651 } else
652 nh = &nexthop->exit_nexthop;
653
654 DUMP_SHORT(buf, prefix_peer(p)->mrt_idx)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((prefix_peer
(p)->mrt_idx)) ? (__uint16_t)(((__uint16_t)((prefix_peer(p
)->mrt_idx)) & 0xffU) << 8 | ((__uint16_t)((prefix_peer
(p)->mrt_idx)) & 0xff00U) >> 8) : __swap16md((prefix_peer
(p)->mrt_idx))); if (ibuf_add((buf), &t, sizeof(t)) ==
-1) { log_warn("mrt_dump2: ibuf_add error"); goto fail; } } while
(0)
;
655 /* originated timestamp */
656 DUMP_LONG(buf, time(NULL) - (getmonotime() - p->lastchange))do { u_int32_t t; t = (__uint32_t)(__builtin_constant_p((time
(((void*)0)) - (getmonotime() - p->lastchange))) ? (__uint32_t
)(((__uint32_t)((time(((void*)0)) - (getmonotime() - p->lastchange
))) & 0xff) << 24 | ((__uint32_t)((time(((void*)0))
- (getmonotime() - p->lastchange))) & 0xff00) <<
8 | ((__uint32_t)((time(((void*)0)) - (getmonotime() - p->
lastchange))) & 0xff0000) >> 8 | ((__uint32_t)((time
(((void*)0)) - (getmonotime() - p->lastchange))) & 0xff000000
) >> 24) : __swap32md((time(((void*)0)) - (getmonotime(
) - p->lastchange)))); if (ibuf_add((buf), &t, sizeof(
t)) == -1) { log_warn("mrt_dump3: ibuf_add error"); goto fail
; } } while (0)
;
657
658 /* RFC8050: path-id if add-path is used */
659 if (addpath)
660 DUMP_LONG(buf, p->path_id)do { u_int32_t t; t = (__uint32_t)(__builtin_constant_p((p->
path_id)) ? (__uint32_t)(((__uint32_t)((p->path_id)) &
0xff) << 24 | ((__uint32_t)((p->path_id)) & 0xff00
) << 8 | ((__uint32_t)((p->path_id)) & 0xff0000)
>> 8 | ((__uint32_t)((p->path_id)) & 0xff000000
) >> 24) : __swap32md((p->path_id))); if (ibuf_add((
buf), &t, sizeof(t)) == -1) { log_warn("mrt_dump3: ibuf_add error"
); goto fail; } } while (0)
;
661
662 if ((tbuf = ibuf_dynamic(0, MAX_PKTSIZE4096)) == NULL((void*)0)) {
663 log_warn("%s: ibuf_dynamic", __func__);
664 goto fail;
665 }
666 if (mrt_attr_dump(tbuf, prefix_aspath(p), prefix_communities(p),
667 nh, 1) == -1) {
668 log_warnx("%s: mrt_attr_dump error", __func__);
669 ibuf_free(tbuf);
670 goto fail;
671 }
672 len = ibuf_size(tbuf);
673 DUMP_SHORT(buf, (u_int16_t)len)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p(((u_int16_t
)len)) ? (__uint16_t)(((__uint16_t)(((u_int16_t)len)) & 0xffU
) << 8 | ((__uint16_t)(((u_int16_t)len)) & 0xff00U)
>> 8) : __swap16md(((u_int16_t)len))); if (ibuf_add((buf
), &t, sizeof(t)) == -1) { log_warn("mrt_dump2: ibuf_add error"
); goto fail; } } while (0)
;
674 if (ibuf_add(buf, tbuf->buf, len) == -1) {
675 log_warn("%s: ibuf_add error", __func__);
676 ibuf_free(tbuf);
677 goto fail;
678 }
679 ibuf_free(tbuf);
680 }
681
682 return 0;
683
684fail:
685 return -1;
686}
687
688int
689mrt_dump_entry_v2(struct mrt *mrt, struct rib_entry *re, u_int32_t snum)
690{
691 char pbuf[260];
692 struct ibuf *hbuf = NULL((void*)0), *nbuf = NULL((void*)0), *apbuf = NULL((void*)0);
693 struct bgpd_addr addr;
694 size_t hlen, len;
695 u_int16_t subtype, apsubtype, nump, apnump, afi;
696 u_int8_t safi;
697 int plen;
698
699 pt_getaddr(re->prefix, &addr);
700 plen = prefix_write(pbuf, sizeof(pbuf), &addr, re->prefix->prefixlen,
701 0);
702 if (plen == -1) {
703 log_warnx("%s: prefix_write error", __func__);
704 return -1;
705 }
706
707 switch (re->prefix->aid) {
708 case AID_INET1:
709 subtype = MRT_DUMP_V2_RIB_IPV4_UNICAST;
710 apsubtype = MRT_DUMP_V2_RIB_IPV4_UNICAST_ADDPATH;
711 break;
712 case AID_INET62:
713 subtype = MRT_DUMP_V2_RIB_IPV6_UNICAST;
714 apsubtype = MRT_DUMP_V2_RIB_IPV6_UNICAST_ADDPATH;
715 break;
716 default:
717 /*
718 * XXX The RFC defined the format for this type differently
719 * and it is prohibitly expensive to implement that format.
720 * Instead do what gobgp does and encode it like the other
721 * types.
722 */
723 subtype = MRT_DUMP_V2_RIB_GENERIC;
724 apsubtype = MRT_DUMP_V2_RIB_GENERIC_ADDPATH;
725 aid2afi(re->prefix->aid, &afi, &safi);
726
727 /* prepend 3-bytes AFI/SAFI */
728 memmove(pbuf + 3, pbuf, plen);
729 plen += 3;
730 afi = ntohs(afi)(__uint16_t)(__builtin_constant_p(afi) ? (__uint16_t)(((__uint16_t
)(afi) & 0xffU) << 8 | ((__uint16_t)(afi) & 0xff00U
) >> 8) : __swap16md(afi))
;
731 memcpy(pbuf, &afi, sizeof(afi));
732 pbuf[2] = safi;
733 break;
734 }
735 hlen = sizeof(snum) + sizeof(nump) + plen;
736
737 if (mrt_dump_entry_v2_rib(re, &nbuf, &apbuf, &nump, &apnump))
738 goto fail;
739
740 if (nump > 0) {
741 len = ibuf_size(nbuf) + hlen;
742 if (mrt_dump_hdr_rde(&hbuf, MSG_TABLE_DUMP_V2, subtype,
743 len) == -1)
744 goto fail;
745
746 DUMP_LONG(hbuf, snum)do { u_int32_t t; t = (__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))); if (ibuf_add
((hbuf), &t, sizeof(t)) == -1) { log_warn("mrt_dump3: ibuf_add error"
); goto fail; } } while (0)
;
747 if (ibuf_add(hbuf, pbuf, plen) == -1) {
748 log_warn("%s: ibuf_add error", __func__);
749 goto fail;
750 }
751 DUMP_SHORT(hbuf, nump)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((nump
)) ? (__uint16_t)(((__uint16_t)((nump)) & 0xffU) <<
8 | ((__uint16_t)((nump)) & 0xff00U) >> 8) : __swap16md
((nump))); if (ibuf_add((hbuf), &t, sizeof(t)) == -1) { log_warn
("mrt_dump2: ibuf_add error"); goto fail; } } while (0)
;
752
753 ibuf_close(&mrt->wbuf, hbuf);
754 ibuf_close(&mrt->wbuf, nbuf);
755 hbuf = NULL((void*)0);
756 nbuf = NULL((void*)0);
757 }
758
759 if (apnump > 0) {
760 len = ibuf_size(apbuf) + hlen;
761 if (mrt_dump_hdr_rde(&hbuf, MSG_TABLE_DUMP_V2, apsubtype,
762 len) == -1)
763 goto fail;
764
765 DUMP_LONG(hbuf, snum)do { u_int32_t t; t = (__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))); if (ibuf_add
((hbuf), &t, sizeof(t)) == -1) { log_warn("mrt_dump3: ibuf_add error"
); goto fail; } } while (0)
;
766 if (ibuf_add(hbuf, pbuf, plen) == -1) {
767 log_warn("%s: ibuf_add error", __func__);
768 goto fail;
769 }
770 DUMP_SHORT(hbuf, apnump)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((apnump
)) ? (__uint16_t)(((__uint16_t)((apnump)) & 0xffU) <<
8 | ((__uint16_t)((apnump)) & 0xff00U) >> 8) : __swap16md
((apnump))); if (ibuf_add((hbuf), &t, sizeof(t)) == -1) {
log_warn("mrt_dump2: ibuf_add error"); goto fail; } } while (
0)
;
771
772 ibuf_close(&mrt->wbuf, hbuf);
773 ibuf_close(&mrt->wbuf, apbuf);
774 hbuf = NULL((void*)0);
775 apbuf = NULL((void*)0);
776 }
777
778 return (0);
779fail:
780 ibuf_free(apbuf);
781 ibuf_free(nbuf);
782 ibuf_free(hbuf);
783 return (-1);
784}
785
786int
787mrt_dump_v2_hdr(struct mrt *mrt, struct bgpd_config *conf,
788 struct rde_peer_head *ph)
789{
790 struct rde_peer *peer;
791 struct ibuf *buf, *hbuf = NULL((void*)0);
792 size_t len, off;
793 u_int16_t nlen, nump;
794
795 if ((buf = ibuf_dynamic(0, UINT_MAX(2147483647 *2U +1U))) == NULL((void*)0)) {
796 log_warn("%s: ibuf_dynamic", __func__);
797 return (-1);
798 }
799
800 DUMP_NLONG(buf, conf->bgpid)do { u_int32_t t = (conf->bgpid); if (ibuf_add((buf), &
t, sizeof(t)) == -1) { log_warn("mrt_dump4: ibuf_add error");
goto fail; } } while (0)
;
801 nlen = strlen(mrt->rib);
802 if (nlen > 0)
803 nlen += 1;
804 DUMP_SHORT(buf, nlen)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((nlen
)) ? (__uint16_t)(((__uint16_t)((nlen)) & 0xffU) <<
8 | ((__uint16_t)((nlen)) & 0xff00U) >> 8) : __swap16md
((nlen))); if (ibuf_add((buf), &t, sizeof(t)) == -1) { log_warn
("mrt_dump2: ibuf_add error"); goto fail; } } while (0)
;
805 if (ibuf_add(buf, mrt->rib, nlen) == -1) {
806 log_warn("%s: ibuf_add error", __func__);
807 goto fail;
808 }
809
810 off = ibuf_size(buf);
811 if (ibuf_reserve(buf, sizeof(nump)) == NULL((void*)0)) {
812 log_warn("%s: ibuf_reserve error", __func__);
813 goto fail;
814 }
815 nump = 0;
816 LIST_FOREACH(peer, ph, peer_l)for((peer) = ((ph)->lh_first); (peer)!= ((void*)0); (peer)
= ((peer)->peer_l.le_next))
{
817 peer->mrt_idx = nump;
818 if (mrt_dump_peer(buf, peer) == -1)
819 goto fail;
820 nump++;
821 }
822 nump = htons(nump)(__uint16_t)(__builtin_constant_p(nump) ? (__uint16_t)(((__uint16_t
)(nump) & 0xffU) << 8 | ((__uint16_t)(nump) & 0xff00U
) >> 8) : __swap16md(nump))
;
823 memcpy(ibuf_seek(buf, off, sizeof(nump)), &nump, sizeof(nump));
824
825 len = ibuf_size(buf);
826 if (mrt_dump_hdr_rde(&hbuf, MSG_TABLE_DUMP_V2,
827 MRT_DUMP_V2_PEER_INDEX_TABLE, len) == -1)
828 goto fail;
829
830 ibuf_close(&mrt->wbuf, hbuf);
831 ibuf_close(&mrt->wbuf, buf);
832
833 return (0);
834fail:
835 ibuf_free(hbuf);
836 ibuf_free(buf);
837 return (-1);
838}
839
840int
841mrt_dump_peer(struct ibuf *buf, struct rde_peer *peer)
842{
843 u_int8_t type = 0;
844
845 if (peer->capa.as4byte)
846 type |= MRT_DUMP_V2_PEER_BIT_A0x2;
847 if (peer->remote_addr.aid == AID_INET62)
848 type |= MRT_DUMP_V2_PEER_BIT_I0x1;
849
850 DUMP_BYTE(buf, type)do { u_char t = (type); if (ibuf_add((buf), &t, sizeof(t)
) == -1) { log_warn("mrt_dump1: ibuf_add error"); goto fail; }
} while (0)
;
851 DUMP_LONG(buf, peer->remote_bgpid)do { u_int32_t t; t = (__uint32_t)(__builtin_constant_p((peer
->remote_bgpid)) ? (__uint32_t)(((__uint32_t)((peer->remote_bgpid
)) & 0xff) << 24 | ((__uint32_t)((peer->remote_bgpid
)) & 0xff00) << 8 | ((__uint32_t)((peer->remote_bgpid
)) & 0xff0000) >> 8 | ((__uint32_t)((peer->remote_bgpid
)) & 0xff000000) >> 24) : __swap32md((peer->remote_bgpid
))); if (ibuf_add((buf), &t, sizeof(t)) == -1) { log_warn
("mrt_dump3: ibuf_add error"); goto fail; } } while (0)
;
852
853 switch (peer->remote_addr.aid) {
854 case AID_INET1:
855 DUMP_NLONG(buf, peer->remote_addr.v4.s_addr)do { u_int32_t t = (peer->remote_addr.ba.v4.s_addr); if (ibuf_add
((buf), &t, sizeof(t)) == -1) { log_warn("mrt_dump4: ibuf_add error"
); goto fail; } } while (0)
;
856 break;
857 case AID_INET62:
858 if (ibuf_add(buf, &peer->remote_addr.v6ba.v6,
859 sizeof(struct in6_addr)) == -1) {
860 log_warn("mrt_dump_peer: ibuf_add error");
861 goto fail;
862 }
863 break;
864 case AID_UNSPEC0: /* XXX special handling for peerself? */
865 DUMP_NLONG(buf, 0)do { u_int32_t t = (0); if (ibuf_add((buf), &t, sizeof(t)
) == -1) { log_warn("mrt_dump4: ibuf_add error"); goto fail; }
} while (0)
;
866 break;
867 default:
868 log_warnx("king bula found new AF in %s", __func__);
869 goto fail;
870 }
871
872 if (peer->capa.as4byte)
873 DUMP_LONG(buf, peer->conf.remote_as)do { u_int32_t t; t = (__uint32_t)(__builtin_constant_p((peer
->conf.remote_as)) ? (__uint32_t)(((__uint32_t)((peer->
conf.remote_as)) & 0xff) << 24 | ((__uint32_t)((peer
->conf.remote_as)) & 0xff00) << 8 | ((__uint32_t
)((peer->conf.remote_as)) & 0xff0000) >> 8 | ((__uint32_t
)((peer->conf.remote_as)) & 0xff000000) >> 24) :
__swap32md((peer->conf.remote_as))); if (ibuf_add((buf), &
t, sizeof(t)) == -1) { log_warn("mrt_dump3: ibuf_add error");
goto fail; } } while (0)
;
874 else
875 DUMP_SHORT(buf, peer->short_as)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((peer
->short_as)) ? (__uint16_t)(((__uint16_t)((peer->short_as
)) & 0xffU) << 8 | ((__uint16_t)((peer->short_as
)) & 0xff00U) >> 8) : __swap16md((peer->short_as
))); if (ibuf_add((buf), &t, sizeof(t)) == -1) { log_warn
("mrt_dump2: ibuf_add error"); goto fail; } } while (0)
;
876
877 return (0);
878fail:
879 return (-1);
880}
881
882void
883mrt_dump_upcall(struct rib_entry *re, void *ptr)
884{
885 struct mrt *mrtbuf = ptr;
886 struct prefix *p;
887
888 if (mrtbuf->type == MRT_TABLE_DUMP_V2) {
889 mrt_dump_entry_v2(mrtbuf, re, mrtbuf->seqnum++);
890 return;
891 }
892
893 /*
894 * dump all prefixes even the inactive ones. That is the way zebra
895 * dumps the table so we do the same. If only the active route should
896 * be dumped p should be set to p = pt->active.
897 */
898 LIST_FOREACH(p, &re->prefix_h, entry.list.rib)for((p) = ((&re->prefix_h)->lh_first); (p)!= ((void
*)0); (p) = ((p)->entry.list.rib.le_next))
{
899 if (mrtbuf->type == MRT_TABLE_DUMP)
900 mrt_dump_entry(mrtbuf, p, mrtbuf->seqnum++,
901 prefix_peer(p));
902 else
903 mrt_dump_entry_mp(mrtbuf, p, mrtbuf->seqnum++,
904 prefix_peer(p));
905 }
906}
907
908void
909mrt_done(struct mrt *mrtbuf)
910{
911 mrtbuf->state = MRT_STATE_REMOVE;
912}
913
914int
915mrt_dump_hdr_se(struct ibuf ** bp, struct peer *peer, u_int16_t type,
916 u_int16_t subtype, u_int32_t len, int swap)
917{
918 struct timespec time;
919
920 if ((*bp = ibuf_dynamic(MRT_ET_HEADER_SIZE16, MRT_ET_HEADER_SIZE16 +
921 MRT_BGP4MP_AS4_IPv6_HEADER_SIZE44 + len)) == NULL((void*)0)) {
922 log_warn("mrt_dump_hdr_se: ibuf_dynamic error");
923 return (-1);
924 }
925
926 clock_gettime(CLOCK_REALTIME0, &time);
927
928 DUMP_LONG(*bp, time.tv_sec)do { u_int32_t t; t = (__uint32_t)(__builtin_constant_p((time
.tv_sec)) ? (__uint32_t)(((__uint32_t)((time.tv_sec)) & 0xff
) << 24 | ((__uint32_t)((time.tv_sec)) & 0xff00) <<
8 | ((__uint32_t)((time.tv_sec)) & 0xff0000) >> 8 |
((__uint32_t)((time.tv_sec)) & 0xff000000) >> 24) :
__swap32md((time.tv_sec))); if (ibuf_add((*bp), &t, sizeof
(t)) == -1) { log_warn("mrt_dump3: ibuf_add error"); goto fail
; } } while (0)
;
929 DUMP_SHORT(*bp, type)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((type
)) ? (__uint16_t)(((__uint16_t)((type)) & 0xffU) <<
8 | ((__uint16_t)((type)) & 0xff00U) >> 8) : __swap16md
((type))); if (ibuf_add((*bp), &t, sizeof(t)) == -1) { log_warn
("mrt_dump2: ibuf_add error"); goto fail; } } while (0)
;
930 DUMP_SHORT(*bp, subtype)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((subtype
)) ? (__uint16_t)(((__uint16_t)((subtype)) & 0xffU) <<
8 | ((__uint16_t)((subtype)) & 0xff00U) >> 8) : __swap16md
((subtype))); if (ibuf_add((*bp), &t, sizeof(t)) == -1) {
log_warn("mrt_dump2: ibuf_add error"); goto fail; } } while (
0)
;
931
932 switch (peer->local.aid) {
933 case AID_INET1:
934 if (subtype == BGP4MP_STATE_CHANGE_AS4 ||
935 subtype == BGP4MP_MESSAGE_AS4 ||
936 subtype == BGP4MP_MESSAGE_AS4_ADDPATH)
937 len += MRT_BGP4MP_ET_AS4_IPv4_HEADER_SIZE24;
938 else
939 len += MRT_BGP4MP_ET_IPv4_HEADER_SIZE20;
940 break;
941 case AID_INET62:
942 if (subtype == BGP4MP_STATE_CHANGE_AS4 ||
943 subtype == BGP4MP_MESSAGE_AS4 ||
944 subtype == BGP4MP_MESSAGE_AS4_ADDPATH)
945 len += MRT_BGP4MP_ET_AS4_IPv6_HEADER_SIZE48;
946 else
947 len += MRT_BGP4MP_ET_IPv6_HEADER_SIZE44;
948 break;
949 case 0:
950 goto fail;
951 default:
952 log_warnx("king bula found new AF in %s", __func__);
953 goto fail;
954 }
955
956 DUMP_LONG(*bp, len)do { u_int32_t t; t = (__uint32_t)(__builtin_constant_p((len)
) ? (__uint32_t)(((__uint32_t)((len)) & 0xff) << 24
| ((__uint32_t)((len)) & 0xff00) << 8 | ((__uint32_t
)((len)) & 0xff0000) >> 8 | ((__uint32_t)((len)) &
0xff000000) >> 24) : __swap32md((len))); if (ibuf_add(
(*bp), &t, sizeof(t)) == -1) { log_warn("mrt_dump3: ibuf_add error"
); goto fail; } } while (0)
;
957 /* milisecond field use by the _ET format */
958 DUMP_LONG(*bp, time.tv_nsec / 1000)do { u_int32_t t; t = (__uint32_t)(__builtin_constant_p((time
.tv_nsec / 1000)) ? (__uint32_t)(((__uint32_t)((time.tv_nsec /
1000)) & 0xff) << 24 | ((__uint32_t)((time.tv_nsec
/ 1000)) & 0xff00) << 8 | ((__uint32_t)((time.tv_nsec
/ 1000)) & 0xff0000) >> 8 | ((__uint32_t)((time.tv_nsec
/ 1000)) & 0xff000000) >> 24) : __swap32md((time.tv_nsec
/ 1000))); if (ibuf_add((*bp), &t, sizeof(t)) == -1) { log_warn
("mrt_dump3: ibuf_add error"); goto fail; } } while (0)
;
959
960 if (subtype == BGP4MP_STATE_CHANGE_AS4 ||
961 subtype == BGP4MP_MESSAGE_AS4 ||
962 subtype == BGP4MP_MESSAGE_AS4_ADDPATH) {
963 if (!swap)
964 DUMP_LONG(*bp, peer->conf.local_as)do { u_int32_t t; t = (__uint32_t)(__builtin_constant_p((peer
->conf.local_as)) ? (__uint32_t)(((__uint32_t)((peer->conf
.local_as)) & 0xff) << 24 | ((__uint32_t)((peer->
conf.local_as)) & 0xff00) << 8 | ((__uint32_t)((peer
->conf.local_as)) & 0xff0000) >> 8 | ((__uint32_t
)((peer->conf.local_as)) & 0xff000000) >> 24) : __swap32md
((peer->conf.local_as))); if (ibuf_add((*bp), &t, sizeof
(t)) == -1) { log_warn("mrt_dump3: ibuf_add error"); goto fail
; } } while (0)
;
965 DUMP_LONG(*bp, peer->conf.remote_as)do { u_int32_t t; t = (__uint32_t)(__builtin_constant_p((peer
->conf.remote_as)) ? (__uint32_t)(((__uint32_t)((peer->
conf.remote_as)) & 0xff) << 24 | ((__uint32_t)((peer
->conf.remote_as)) & 0xff00) << 8 | ((__uint32_t
)((peer->conf.remote_as)) & 0xff0000) >> 8 | ((__uint32_t
)((peer->conf.remote_as)) & 0xff000000) >> 24) :
__swap32md((peer->conf.remote_as))); if (ibuf_add((*bp), &
t, sizeof(t)) == -1) { log_warn("mrt_dump3: ibuf_add error");
goto fail; } } while (0)
;
966 if (swap)
967 DUMP_LONG(*bp, peer->conf.local_as)do { u_int32_t t; t = (__uint32_t)(__builtin_constant_p((peer
->conf.local_as)) ? (__uint32_t)(((__uint32_t)((peer->conf
.local_as)) & 0xff) << 24 | ((__uint32_t)((peer->
conf.local_as)) & 0xff00) << 8 | ((__uint32_t)((peer
->conf.local_as)) & 0xff0000) >> 8 | ((__uint32_t
)((peer->conf.local_as)) & 0xff000000) >> 24) : __swap32md
((peer->conf.local_as))); if (ibuf_add((*bp), &t, sizeof
(t)) == -1) { log_warn("mrt_dump3: ibuf_add error"); goto fail
; } } while (0)
;
968 } else {
969 if (!swap)
970 DUMP_SHORT(*bp, peer->conf.local_short_as)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((peer
->conf.local_short_as)) ? (__uint16_t)(((__uint16_t)((peer
->conf.local_short_as)) & 0xffU) << 8 | ((__uint16_t
)((peer->conf.local_short_as)) & 0xff00U) >> 8) :
__swap16md((peer->conf.local_short_as))); if (ibuf_add((*
bp), &t, sizeof(t)) == -1) { log_warn("mrt_dump2: ibuf_add error"
); goto fail; } } while (0)
;
971 DUMP_SHORT(*bp, peer->short_as)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((peer
->short_as)) ? (__uint16_t)(((__uint16_t)((peer->short_as
)) & 0xffU) << 8 | ((__uint16_t)((peer->short_as
)) & 0xff00U) >> 8) : __swap16md((peer->short_as
))); if (ibuf_add((*bp), &t, sizeof(t)) == -1) { log_warn
("mrt_dump2: ibuf_add error"); goto fail; } } while (0)
;
972 if (swap)
973 DUMP_SHORT(*bp, peer->conf.local_short_as)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((peer
->conf.local_short_as)) ? (__uint16_t)(((__uint16_t)((peer
->conf.local_short_as)) & 0xffU) << 8 | ((__uint16_t
)((peer->conf.local_short_as)) & 0xff00U) >> 8) :
__swap16md((peer->conf.local_short_as))); if (ibuf_add((*
bp), &t, sizeof(t)) == -1) { log_warn("mrt_dump2: ibuf_add error"
); goto fail; } } while (0)
;
974 }
975
976 DUMP_SHORT(*bp, /* ifindex */ 0)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((0)) ?
(__uint16_t)(((__uint16_t)((0)) & 0xffU) << 8 | ((
__uint16_t)((0)) & 0xff00U) >> 8) : __swap16md((0))
); if (ibuf_add((*bp), &t, sizeof(t)) == -1) { log_warn("mrt_dump2: ibuf_add error"
); goto fail; } } while (0)
;
977
978 switch (peer->local.aid) {
979 case AID_INET1:
980 DUMP_SHORT(*bp, AFI_IPv4)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((1)) ?
(__uint16_t)(((__uint16_t)((1)) & 0xffU) << 8 | ((
__uint16_t)((1)) & 0xff00U) >> 8) : __swap16md((1))
); if (ibuf_add((*bp), &t, sizeof(t)) == -1) { log_warn("mrt_dump2: ibuf_add error"
); goto fail; } } while (0)
;
981 if (!swap)
982 DUMP_NLONG(*bp, peer->local.v4.s_addr)do { u_int32_t t = (peer->local.ba.v4.s_addr); if (ibuf_add
((*bp), &t, sizeof(t)) == -1) { log_warn("mrt_dump4: ibuf_add error"
); goto fail; } } while (0)
;
983 DUMP_NLONG(*bp, peer->remote.v4.s_addr)do { u_int32_t t = (peer->remote.ba.v4.s_addr); if (ibuf_add
((*bp), &t, sizeof(t)) == -1) { log_warn("mrt_dump4: ibuf_add error"
); goto fail; } } while (0)
;
984 if (swap)
985 DUMP_NLONG(*bp, peer->local.v4.s_addr)do { u_int32_t t = (peer->local.ba.v4.s_addr); if (ibuf_add
((*bp), &t, sizeof(t)) == -1) { log_warn("mrt_dump4: ibuf_add error"
); goto fail; } } while (0)
;
986 break;
987 case AID_INET62:
988 DUMP_SHORT(*bp, AFI_IPv6)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((2)) ?
(__uint16_t)(((__uint16_t)((2)) & 0xffU) << 8 | ((
__uint16_t)((2)) & 0xff00U) >> 8) : __swap16md((2))
); if (ibuf_add((*bp), &t, sizeof(t)) == -1) { log_warn("mrt_dump2: ibuf_add error"
); goto fail; } } while (0)
;
989 if (!swap)
990 if (ibuf_add(*bp, &peer->local.v6ba.v6,
991 sizeof(struct in6_addr)) == -1) {
992 log_warn("mrt_dump_hdr_se: ibuf_add error");
993 goto fail;
994 }
995 if (ibuf_add(*bp, &peer->remote.v6ba.v6,
996 sizeof(struct in6_addr)) == -1) {
997 log_warn("mrt_dump_hdr_se: ibuf_add error");
998 goto fail;
999 }
1000 if (swap)
1001 if (ibuf_add(*bp, &peer->local.v6ba.v6,
1002 sizeof(struct in6_addr)) == -1) {
1003 log_warn("mrt_dump_hdr_se: ibuf_add error");
1004 goto fail;
1005 }
1006 break;
1007 }
1008
1009 return (0);
1010
1011fail:
1012 ibuf_free(*bp);
1013 return (-1);
1014}
1015
1016int
1017mrt_dump_hdr_rde(struct ibuf **bp, u_int16_t type, u_int16_t subtype,
1018 u_int32_t len)
1019{
1020 struct timespec time;
1021
1022 if ((*bp = ibuf_dynamic(MRT_HEADER_SIZE12, MRT_HEADER_SIZE12 +
1023 MRT_BGP4MP_AS4_IPv6_HEADER_SIZE44 + MRT_BGP4MP_IPv6_ENTRY_SIZE30)) ==
1024 NULL((void*)0)) {
1025 log_warn("mrt_dump_hdr_rde: ibuf_dynamic error");
1026 return (-1);
1027 }
1028
1029 clock_gettime(CLOCK_REALTIME0, &time);
1030
1031 DUMP_LONG(*bp, time.tv_sec)do { u_int32_t t; t = (__uint32_t)(__builtin_constant_p((time
.tv_sec)) ? (__uint32_t)(((__uint32_t)((time.tv_sec)) & 0xff
) << 24 | ((__uint32_t)((time.tv_sec)) & 0xff00) <<
8 | ((__uint32_t)((time.tv_sec)) & 0xff0000) >> 8 |
((__uint32_t)((time.tv_sec)) & 0xff000000) >> 24) :
__swap32md((time.tv_sec))); if (ibuf_add((*bp), &t, sizeof
(t)) == -1) { log_warn("mrt_dump3: ibuf_add error"); goto fail
; } } while (0)
;
1032 DUMP_SHORT(*bp, type)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((type
)) ? (__uint16_t)(((__uint16_t)((type)) & 0xffU) <<
8 | ((__uint16_t)((type)) & 0xff00U) >> 8) : __swap16md
((type))); if (ibuf_add((*bp), &t, sizeof(t)) == -1) { log_warn
("mrt_dump2: ibuf_add error"); goto fail; } } while (0)
;
1033 DUMP_SHORT(*bp, subtype)do { u_int16_t t; t = (__uint16_t)(__builtin_constant_p((subtype
)) ? (__uint16_t)(((__uint16_t)((subtype)) & 0xffU) <<
8 | ((__uint16_t)((subtype)) & 0xff00U) >> 8) : __swap16md
((subtype))); if (ibuf_add((*bp), &t, sizeof(t)) == -1) {
log_warn("mrt_dump2: ibuf_add error"); goto fail; } } while (
0)
;
1034
1035 switch (type) {
1036 case MSG_TABLE_DUMP:
1037 switch (subtype) {
1038 case AFI_IPv41:
1039 len += MRT_DUMP_HEADER_SIZE22;
1040 break;
1041 case AFI_IPv62:
1042 len += MRT_DUMP_HEADER_SIZE_V646;
1043 break;
1044 }
1045 DUMP_LONG(*bp, len)do { u_int32_t t; t = (__uint32_t)(__builtin_constant_p((len)
) ? (__uint32_t)(((__uint32_t)((len)) & 0xff) << 24
| ((__uint32_t)((len)) & 0xff00) << 8 | ((__uint32_t
)((len)) & 0xff0000) >> 8 | ((__uint32_t)((len)) &
0xff000000) >> 24) : __swap32md((len))); if (ibuf_add(
(*bp), &t, sizeof(t)) == -1) { log_warn("mrt_dump3: ibuf_add error"
); goto fail; } } while (0)
;
1046 break;
1047 case MSG_PROTOCOL_BGP4MP:
1048 case MSG_TABLE_DUMP_V2:
1049 DUMP_LONG(*bp, len)do { u_int32_t t; t = (__uint32_t)(__builtin_constant_p((len)
) ? (__uint32_t)(((__uint32_t)((len)) & 0xff) << 24
| ((__uint32_t)((len)) & 0xff00) << 8 | ((__uint32_t
)((len)) & 0xff0000) >> 8 | ((__uint32_t)((len)) &
0xff000000) >> 24) : __swap32md((len))); if (ibuf_add(
(*bp), &t, sizeof(t)) == -1) { log_warn("mrt_dump3: ibuf_add error"
); goto fail; } } while (0)
;
1050 break;
1051 default:
1052 log_warnx("mrt_dump_hdr_rde: unsupported type");
1053 goto fail;
1054 }
1055 return (0);
1056
1057fail:
1058 ibuf_free(*bp);
1059 *bp = NULL((void*)0);
1060 return (-1);
1061}
1062
1063void
1064mrt_write(struct mrt *mrt)
1065{
1066 int r;
1067
1068 if ((r = ibuf_write(&mrt->wbuf)) == -1 && errno(*__errno()) != EAGAIN35) {
1069 log_warn("mrt dump aborted, mrt_write");
1070 mrt_clean(mrt);
1071 mrt_done(mrt);
1072 }
1073}
1074
1075void
1076mrt_clean(struct mrt *mrt)
1077{
1078 struct ibuf *b;
1079
1080 close(mrt->wbuf.fd);
1081 while ((b = TAILQ_FIRST(&mrt->wbuf.bufs)((&mrt->wbuf.bufs)->tqh_first))) {
1082 TAILQ_REMOVE(&mrt->wbuf.bufs, b, entry)do { if (((b)->entry.tqe_next) != ((void*)0)) (b)->entry
.tqe_next->entry.tqe_prev = (b)->entry.tqe_prev; else (
&mrt->wbuf.bufs)->tqh_last = (b)->entry.tqe_prev
; *(b)->entry.tqe_prev = (b)->entry.tqe_next; ; ; } while
(0)
;
1083 ibuf_free(b);
1084 }
1085 mrt->wbuf.queued = 0;
1086}
1087
1088static struct imsgbuf *mrt_imsgbuf[2];
1089
1090void
1091mrt_init(struct imsgbuf *rde, struct imsgbuf *se)
1092{
1093 mrt_imsgbuf[RDEIDX0] = rde;
1094 mrt_imsgbuf[SEIDX1] = se;
1095}
1096
1097int
1098mrt_open(struct mrt *mrt, time_t now)
1099{
1100 enum imsg_type type;
1101 int fd;
1102
1103 if (strftime(MRT2MC(mrt)((struct mrt_config *)(mrt))->file, sizeof(MRT2MC(mrt)((struct mrt_config *)(mrt))->file),
1104 MRT2MC(mrt)((struct mrt_config *)(mrt))->name, localtime(&now)) == 0) {
1105 log_warnx("mrt_open: strftime conversion failed");
1106 return (-1);
1107 }
1108
1109 fd = open(MRT2MC(mrt)((struct mrt_config *)(mrt))->file,
1110 O_WRONLY0x0001|O_NONBLOCK0x0004|O_CREAT0x0200|O_TRUNC0x0400|O_CLOEXEC0x10000, 0644);
1111 if (fd == -1) {
1112 log_warn("mrt_open %s", MRT2MC(mrt)((struct mrt_config *)(mrt))->file);
1113 return (1);
1114 }
1115
1116 if (mrt->state == MRT_STATE_OPEN)
1117 type = IMSG_MRT_OPEN;
1118 else
1119 type = IMSG_MRT_REOPEN;
1120
1121 if (imsg_compose(mrt_imsgbuf[TYPE2IDX(mrt->type)((mrt->type == MRT_TABLE_DUMP || mrt->type == MRT_TABLE_DUMP_MP
|| mrt->type == MRT_TABLE_DUMP_V2) ? 0 : 1 )
], type, 0, 0, fd,
1122 mrt, sizeof(struct mrt)) == -1)
1123 log_warn("mrt_open");
1124
1125 return (1);
1126}
1127
1128time_t
1129mrt_timeout(struct mrt_head *mrt)
1130{
1131 struct mrt *m;
1132 time_t now;
1133 time_t timeout = -1;
1134
1135 now = time(NULL((void*)0));
1136 LIST_FOREACH(m, mrt, entry)for((m) = ((mrt)->lh_first); (m)!= ((void*)0); (m) = ((m)->
entry.le_next))
{
1137 if (m->state == MRT_STATE_RUNNING &&
1138 MRT2MC(m)((struct mrt_config *)(m))->ReopenTimerInterval != 0) {
1139 if (MRT2MC(m)((struct mrt_config *)(m))->ReopenTimer <= now) {
1140 mrt_open(m, now);
1141 MRT2MC(m)((struct mrt_config *)(m))->ReopenTimer =
1142 now + MRT2MC(m)((struct mrt_config *)(m))->ReopenTimerInterval;
1143 }
1144 if (timeout == -1 ||
1145 MRT2MC(m)((struct mrt_config *)(m))->ReopenTimer - now < timeout)
1146 timeout = MRT2MC(m)((struct mrt_config *)(m))->ReopenTimer - now;
1147 }
1148 }
1149 return (timeout);
1150}
1151
1152void
1153mrt_reconfigure(struct mrt_head *mrt)
1154{
1155 struct mrt *m, *xm;
1156 time_t now;
1157
1158 now = time(NULL((void*)0));
1159 for (m = LIST_FIRST(mrt)((mrt)->lh_first); m != NULL((void*)0); m = xm) {
1160 xm = LIST_NEXT(m, entry)((m)->entry.le_next);
1161 if (m->state == MRT_STATE_OPEN ||
1162 m->state == MRT_STATE_REOPEN) {
1163 if (mrt_open(m, now) == -1)
1164 continue;
1165 if (MRT2MC(m)((struct mrt_config *)(m))->ReopenTimerInterval != 0)
1166 MRT2MC(m)((struct mrt_config *)(m))->ReopenTimer =
1167 now + MRT2MC(m)((struct mrt_config *)(m))->ReopenTimerInterval;
1168 m->state = MRT_STATE_RUNNING;
1169 }
1170 if (m->state == MRT_STATE_REMOVE) {
1171 if (imsg_compose(mrt_imsgbuf[TYPE2IDX(m->type)((m->type == MRT_TABLE_DUMP || m->type == MRT_TABLE_DUMP_MP
|| m->type == MRT_TABLE_DUMP_V2) ? 0 : 1 )
],
1172 IMSG_MRT_CLOSE, 0, 0, -1, m, sizeof(struct mrt)) ==
1173 -1)
1174 log_warn("mrt_reconfigure");
1175 LIST_REMOVE(m, entry)do { if ((m)->entry.le_next != ((void*)0)) (m)->entry.le_next
->entry.le_prev = (m)->entry.le_prev; *(m)->entry.le_prev
= (m)->entry.le_next; ; ; } while (0)
;
1176 free(m);
1177 continue;
1178 }
1179 }
1180}
1181
1182void
1183mrt_handler(struct mrt_head *mrt)
1184{
1185 struct mrt *m;
1186 time_t now;
1187
1188 now = time(NULL((void*)0));
1189 LIST_FOREACH(m, mrt, entry)for((m) = ((mrt)->lh_first); (m)!= ((void*)0); (m) = ((m)->
entry.le_next))
{
1190 if (m->state == MRT_STATE_RUNNING &&
1191 (MRT2MC(m)((struct mrt_config *)(m))->ReopenTimerInterval != 0 ||
1192 m->type == MRT_TABLE_DUMP ||
1193 m->type == MRT_TABLE_DUMP_MP ||
1194 m->type == MRT_TABLE_DUMP_V2)) {
1195 if (mrt_open(m, now) == -1)
1196 continue;
1197 MRT2MC(m)((struct mrt_config *)(m))->ReopenTimer =
1198 now + MRT2MC(m)((struct mrt_config *)(m))->ReopenTimerInterval;
1199 }
1200 }
1201}
1202
1203struct mrt *
1204mrt_get(struct mrt_head *c, struct mrt *m)
1205{
1206 struct mrt *t;
1207
1208 LIST_FOREACH(t, c, entry)for((t) = ((c)->lh_first); (t)!= ((void*)0); (t) = ((t)->
entry.le_next))
{
1209 if (t->type != m->type)
1210 continue;
1211 if (strcmp(t->rib, m->rib))
1212 continue;
1213 if (t->peer_id == m->peer_id &&
1214 t->group_id == m->group_id)
1215 return (t);
1216 }
1217 return (NULL((void*)0));
1218}
1219
1220void
1221mrt_mergeconfig(struct mrt_head *xconf, struct mrt_head *nconf)
1222{
1223 struct mrt *m, *xm;
1224
1225 /* both lists here are actually struct mrt_conifg nodes */
1226 LIST_FOREACH(m, nconf, entry)for((m) = ((nconf)->lh_first); (m)!= ((void*)0); (m) = ((m
)->entry.le_next))
{
1227 if ((xm = mrt_get(xconf, m)) == NULL((void*)0)) {
1228 /* NEW */
1229 if ((xm = malloc(sizeof(struct mrt_config))) == NULL((void*)0))
Result of 'malloc' is converted to a pointer of type 'struct mrt', which is incompatible with sizeof operand type 'struct mrt_config'
1230 fatal("mrt_mergeconfig");
1231 memcpy(xm, m, sizeof(struct mrt_config));
1232 xm->state = MRT_STATE_OPEN;
1233 LIST_INSERT_HEAD(xconf, xm, entry)do { if (((xm)->entry.le_next = (xconf)->lh_first) != (
(void*)0)) (xconf)->lh_first->entry.le_prev = &(xm)
->entry.le_next; (xconf)->lh_first = (xm); (xm)->entry
.le_prev = &(xconf)->lh_first; } while (0)
;
1234 } else {
1235 /* MERGE */
1236 if (strlcpy(MRT2MC(xm)((struct mrt_config *)(xm))->name, MRT2MC(m)((struct mrt_config *)(m))->name,
1237 sizeof(MRT2MC(xm)((struct mrt_config *)(xm))->name)) >=
1238 sizeof(MRT2MC(xm)((struct mrt_config *)(xm))->name))
1239 fatalx("mrt_mergeconfig: strlcpy");
1240 MRT2MC(xm)((struct mrt_config *)(xm))->ReopenTimerInterval =
1241 MRT2MC(m)((struct mrt_config *)(m))->ReopenTimerInterval;
1242 xm->state = MRT_STATE_REOPEN;
1243 }
1244 }
1245
1246 LIST_FOREACH(xm, xconf, entry)for((xm) = ((xconf)->lh_first); (xm)!= ((void*)0); (xm) = (
(xm)->entry.le_next))
1247 if (mrt_get(nconf, xm) == NULL((void*)0))
1248 /* REMOVE */
1249 xm->state = MRT_STATE_REMOVE;
1250
1251 /* free config */
1252 while ((m = LIST_FIRST(nconf)((nconf)->lh_first)) != NULL((void*)0)) {
1253 LIST_REMOVE(m, entry)do { if ((m)->entry.le_next != ((void*)0)) (m)->entry.le_next
->entry.le_prev = (m)->entry.le_prev; *(m)->entry.le_prev
= (m)->entry.le_next; ; ; } while (0)
;
1254 free(m);
1255 }
1256}