Bug Summary

File:src/usr.sbin/bgpctl/bgpctl.c
Warning:line 1066, column 10
Although the value stored to 'linelen' is used in the enclosing expression, the value is never actually read from 'linelen'

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 bgpctl.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/bgpctl/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/bgpctl -I /usr/src/usr.sbin/bgpctl/../bgpd -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/bgpctl/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/bgpctl/bgpctl.c
1/* $OpenBSD: bgpctl.c,v 1.273 2021/08/09 08:24:36 claudio Exp $ */
2
3/*
4 * Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
5 * Copyright (c) 2004-2019 Claudio Jeker <claudio@openbsd.org>
6 * Copyright (c) 2016 Job Snijders <job@instituut.net>
7 * Copyright (c) 2016 Peter Hessler <phessler@openbsd.org>
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 */
21
22#include <sys/types.h>
23#include <sys/socket.h>
24#include <sys/stat.h>
25#include <sys/un.h>
26
27#include <endian.h>
28#include <err.h>
29#include <errno(*__errno()).h>
30#include <fcntl.h>
31#include <math.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <time.h>
36#include <unistd.h>
37#include <util.h>
38
39#include "bgpd.h"
40#include "session.h"
41#include "rde.h"
42#include "version.h"
43
44#include "bgpctl.h"
45#include "parser.h"
46#include "mrtparser.h"
47
48int main(int, char *[]);
49int show(struct imsg *, struct parse_result *);
50void send_filterset(struct imsgbuf *, struct filter_set_head *);
51void show_mrt_dump_neighbors(struct mrt_rib *, struct mrt_peer *,
52 void *);
53void show_mrt_dump(struct mrt_rib *, struct mrt_peer *, void *);
54void network_mrt_dump(struct mrt_rib *, struct mrt_peer *, void *);
55void show_mrt_state(struct mrt_bgp_state *, void *);
56void show_mrt_msg(struct mrt_bgp_msg *, void *);
57const char *msg_type(u_int8_t);
58void network_bulk(struct parse_result *);
59int match_aspath(void *, u_int16_t, struct filter_as *);
60
61struct imsgbuf *ibuf;
62struct mrt_parser show_mrt = { show_mrt_dump, show_mrt_state, show_mrt_msg };
63struct mrt_parser net_mrt = { network_mrt_dump, NULL((void*)0), NULL((void*)0) };
64const struct output *output = &show_output;
65int tableid;
66int nodescr;
67
68__dead__attribute__((__noreturn__)) void
69usage(void)
70{
71 extern char *__progname;
72
73 fprintf(stderr(&__sF[2]), "usage: %s [-jnV] [-s socket] command [argument ...]\n",
74 __progname);
75 exit(1);
76}
77
78int
79main(int argc, char *argv[])
80{
81 struct sockaddr_un sun;
82 int fd, n, done, ch, verbose = 0;
83 struct imsg imsg;
84 struct network_config net;
85 struct parse_result *res;
86 struct ctl_neighbor neighbor;
87 struct ctl_show_rib_request ribreq;
88 char *sockname;
89 enum imsg_type type;
90
91 if (pledge("stdio rpath wpath cpath unix inet dns", NULL((void*)0)) == -1)
92 err(1, "pledge");
93
94 tableid = getrtable();
95 if (asprintf(&sockname, "%s.%d", SOCKET_NAME"/var/run/bgpd.sock", tableid) == -1)
96 err(1, "asprintf");
97
98 while ((ch = getopt(argc, argv, "jns:V")) != -1) {
99 switch (ch) {
100 case 'n':
101 if (++nodescr > 1)
102 usage();
103 break;
104 case 'j':
105 output = &json_output;
106 break;
107 case 's':
108 sockname = optarg;
109 break;
110 case 'V':
111 fprintf(stderr(&__sF[2]), "OpenBGPD %s\n", BGPD_VERSION"7.2");
112 return 0;
113 default:
114 usage();
115 /* NOTREACHED */
116 }
117 }
118 argc -= optind;
119 argv += optind;
120
121 if ((res = parse(argc, argv)) == NULL((void*)0))
122 exit(1);
123
124 memcpy(&neighbor.addr, &res->peeraddr, sizeof(neighbor.addr));
125 strlcpy(neighbor.descr, res->peerdesc, sizeof(neighbor.descr));
126 neighbor.is_group = res->is_group;
127 strlcpy(neighbor.reason, res->reason, sizeof(neighbor.reason));
128
129 switch (res->action) {
130 case SHOW_MRT:
131 if (pledge("stdio", NULL((void*)0)) == -1)
132 err(1, "pledge");
133
134 bzero(&ribreq, sizeof(ribreq));
135 if (res->as.type != AS_UNDEF)
136 ribreq.as = res->as;
137 if (res->addr.aid) {
138 ribreq.prefix = res->addr;
139 ribreq.prefixlen = res->prefixlen;
140 }
141 /* XXX currently no communities support */
142 ribreq.neighbor = neighbor;
143 ribreq.aid = res->aid;
144 ribreq.flags = res->flags;
145 ribreq.validation_state = res->validation_state;
146 show_mrt.arg = &ribreq;
147 if (res->flags & F_CTL_NEIGHBORS0x400000)
148 show_mrt.dump = show_mrt_dump_neighbors;
149 else
150 output->head(res);
151 mrt_parse(res->mrtfd, &show_mrt, 1);
152 exit(0);
153 default:
154 break;
155 }
156
157 if (pledge("stdio unix", NULL((void*)0)) == -1)
158 err(1, "pledge");
159
160 if ((fd = socket(AF_UNIX1, SOCK_STREAM1, 0)) == -1)
161 err(1, "control_init: socket");
162
163 bzero(&sun, sizeof(sun));
164 sun.sun_family = AF_UNIX1;
165 if (strlcpy(sun.sun_path, sockname, sizeof(sun.sun_path)) >=
166 sizeof(sun.sun_path))
167 errx(1, "socket name too long");
168 if (connect(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1)
169 err(1, "connect: %s", sockname);
170
171 if (pledge("stdio", NULL((void*)0)) == -1)
172 err(1, "pledge");
173
174 if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL((void*)0))
175 err(1, NULL((void*)0));
176 imsg_init(ibuf, fd);
177 done = 0;
178
179 switch (res->action) {
180 case NONE:
181 case SHOW_MRT:
182 usage();
183 /* NOTREACHED */
184 case SHOW:
185 case SHOW_SUMMARY:
186 imsg_compose(ibuf, IMSG_CTL_SHOW_NEIGHBOR, 0, 0, -1, NULL((void*)0), 0);
187 break;
188 case SHOW_SUMMARY_TERSE:
189 imsg_compose(ibuf, IMSG_CTL_SHOW_TERSE, 0, 0, -1, NULL((void*)0), 0);
190 break;
191 case SHOW_FIB:
192 if (!res->addr.aid) {
193 struct ibuf *msg;
194 sa_family_t af;
195
196 af = aid2af(res->aid);
197 if ((msg = imsg_create(ibuf, IMSG_CTL_KROUTE,
198 res->rtableid, 0, sizeof(res->flags) +
199 sizeof(af))) == NULL((void*)0))
200 errx(1, "imsg_create failure");
201 if (imsg_add(msg, &res->flags, sizeof(res->flags)) ==
202 -1 ||
203 imsg_add(msg, &af, sizeof(af)) == -1)
204 errx(1, "imsg_add failure");
205 imsg_close(ibuf, msg);
206 } else
207 imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, res->rtableid,
208 0, -1, &res->addr, sizeof(res->addr));
209 break;
210 case SHOW_FIB_TABLES:
211 imsg_compose(ibuf, IMSG_CTL_SHOW_FIB_TABLES, 0, 0, -1, NULL((void*)0), 0);
212 break;
213 case SHOW_NEXTHOP:
214 imsg_compose(ibuf, IMSG_CTL_SHOW_NEXTHOP, res->rtableid, 0, -1,
215 NULL((void*)0), 0);
216 break;
217 case SHOW_INTERFACE:
218 imsg_compose(ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1, NULL((void*)0), 0);
219 break;
220 case SHOW_SET:
221 imsg_compose(ibuf, IMSG_CTL_SHOW_SET, 0, 0, -1, NULL((void*)0), 0);
222 break;
223 case SHOW_RTR:
224 imsg_compose(ibuf, IMSG_CTL_SHOW_RTR, 0, 0, -1, NULL((void*)0), 0);
225 break;
226 case SHOW_NEIGHBOR:
227 case SHOW_NEIGHBOR_TIMERS:
228 case SHOW_NEIGHBOR_TERSE:
229 neighbor.show_timers = (res->action == SHOW_NEIGHBOR_TIMERS);
230 if (res->peeraddr.aid || res->peerdesc[0])
231 imsg_compose(ibuf, IMSG_CTL_SHOW_NEIGHBOR, 0, 0, -1,
232 &neighbor, sizeof(neighbor));
233 else
234 imsg_compose(ibuf, IMSG_CTL_SHOW_NEIGHBOR, 0, 0, -1,
235 NULL((void*)0), 0);
236 break;
237 case SHOW_RIB:
238 bzero(&ribreq, sizeof(ribreq));
239 type = IMSG_CTL_SHOW_RIB;
240 if (res->addr.aid) {
241 ribreq.prefix = res->addr;
242 ribreq.prefixlen = res->prefixlen;
243 type = IMSG_CTL_SHOW_RIB_PREFIX;
244 }
245 if (res->as.type != AS_UNDEF)
246 ribreq.as = res->as;
247 if (res->community.flags != 0)
248 ribreq.community = res->community;
249 ribreq.neighbor = neighbor;
250 strlcpy(ribreq.rib, res->rib, sizeof(ribreq.rib));
251 ribreq.aid = res->aid;
252 ribreq.path_id = res->pathid;
253 ribreq.flags = res->flags;
254 imsg_compose(ibuf, type, 0, 0, -1, &ribreq, sizeof(ribreq));
255 break;
256 case SHOW_RIB_MEM:
257 imsg_compose(ibuf, IMSG_CTL_SHOW_RIB_MEM, 0, 0, -1, NULL((void*)0), 0);
258 break;
259 case RELOAD:
260 imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1,
261 res->reason, sizeof(res->reason));
262 if (res->reason[0])
263 printf("reload request sent: %s\n", res->reason);
264 else
265 printf("reload request sent.\n");
266 break;
267 case FIB:
268 errx(1, "action==FIB");
269 break;
270 case FIB_COUPLE:
271 imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, res->rtableid, 0, -1,
272 NULL((void*)0), 0);
273 printf("couple request sent.\n");
274 done = 1;
275 break;
276 case FIB_DECOUPLE:
277 imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, res->rtableid, 0, -1,
278 NULL((void*)0), 0);
279 printf("decouple request sent.\n");
280 done = 1;
281 break;
282 case NEIGHBOR:
283 errx(1, "action==NEIGHBOR");
284 break;
285 case NEIGHBOR_UP:
286 imsg_compose(ibuf, IMSG_CTL_NEIGHBOR_UP, 0, 0, -1,
287 &neighbor, sizeof(neighbor));
288 break;
289 case NEIGHBOR_DOWN:
290 imsg_compose(ibuf, IMSG_CTL_NEIGHBOR_DOWN, 0, 0, -1,
291 &neighbor, sizeof(neighbor));
292 break;
293 case NEIGHBOR_CLEAR:
294 imsg_compose(ibuf, IMSG_CTL_NEIGHBOR_CLEAR, 0, 0, -1,
295 &neighbor, sizeof(neighbor));
296 break;
297 case NEIGHBOR_RREFRESH:
298 imsg_compose(ibuf, IMSG_CTL_NEIGHBOR_RREFRESH, 0, 0, -1,
299 &neighbor, sizeof(neighbor));
300 break;
301 case NEIGHBOR_DESTROY:
302 imsg_compose(ibuf, IMSG_CTL_NEIGHBOR_DESTROY, 0, 0, -1,
303 &neighbor, sizeof(neighbor));
304 break;
305 case NETWORK_BULK_ADD:
306 case NETWORK_BULK_REMOVE:
307 network_bulk(res);
308 printf("requests sent.\n");
309 done = 1;
310 break;
311 case NETWORK_ADD:
312 case NETWORK_REMOVE:
313 bzero(&net, sizeof(net));
314 net.prefix = res->addr;
315 net.prefixlen = res->prefixlen;
316 net.rd = res->rd;
317 /* attribute sets are not supported */
318 if (res->action == NETWORK_ADD) {
319 imsg_compose(ibuf, IMSG_NETWORK_ADD, 0, 0, -1,
320 &net, sizeof(net));
321 send_filterset(ibuf, &res->set);
322 imsg_compose(ibuf, IMSG_NETWORK_DONE, 0, 0, -1,
323 NULL((void*)0), 0);
324 } else
325 imsg_compose(ibuf, IMSG_NETWORK_REMOVE, 0, 0, -1,
326 &net, sizeof(net));
327 printf("request sent.\n");
328 done = 1;
329 break;
330 case NETWORK_FLUSH:
331 imsg_compose(ibuf, IMSG_NETWORK_FLUSH, 0, 0, -1, NULL((void*)0), 0);
332 printf("request sent.\n");
333 done = 1;
334 break;
335 case NETWORK_SHOW:
336 bzero(&ribreq, sizeof(ribreq));
337 ribreq.aid = res->aid;
338 strlcpy(ribreq.rib, res->rib, sizeof(ribreq.rib));
339 imsg_compose(ibuf, IMSG_CTL_SHOW_NETWORK, 0, 0, -1,
340 &ribreq, sizeof(ribreq));
341 break;
342 case NETWORK_MRT:
343 bzero(&ribreq, sizeof(ribreq));
344 if (res->as.type != AS_UNDEF)
345 ribreq.as = res->as;
346 if (res->addr.aid) {
347 ribreq.prefix = res->addr;
348 ribreq.prefixlen = res->prefixlen;
349 }
350 /* XXX currently no community support */
351 ribreq.neighbor = neighbor;
352 ribreq.aid = res->aid;
353 ribreq.flags = res->flags;
354 net_mrt.arg = &ribreq;
355 mrt_parse(res->mrtfd, &net_mrt, 1);
356 done = 1;
357 break;
358 case LOG_VERBOSE:
359 verbose = 1;
360 /* FALLTHROUGH */
361 case LOG_BRIEF:
362 imsg_compose(ibuf, IMSG_CTL_LOG_VERBOSE, 0, 0, -1,
363 &verbose, sizeof(verbose));
364 printf("logging request sent.\n");
365 done = 1;
366 break;
367 }
368
369 while (ibuf->w.queued)
370 if (msgbuf_write(&ibuf->w) <= 0 && errno(*__errno()) != EAGAIN35)
371 err(1, "write error");
372
373 output->head(res);
374
375 while (!done) {
376 if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35)
377 err(1, "imsg_read error");
378 if (n == 0)
379 errx(1, "pipe closed");
380
381 while (!done) {
382 if ((n = imsg_get(ibuf, &imsg)) == -1)
383 err(1, "imsg_get error");
384 if (n == 0)
385 break;
386
387 done = show(&imsg, res);
388 imsg_free(&imsg);
389 }
390 }
391
392 output->tail();
393
394 close(fd);
395 free(ibuf);
396
397 exit(0);
398}
399
400int
401show(struct imsg *imsg, struct parse_result *res)
402{
403 struct peer *p;
404 struct ctl_timer t;
405 struct ctl_show_interface *iface;
406 struct ctl_show_nexthop *nh;
407 struct ctl_show_set set;
408 struct ctl_show_rtr rtr;
409 struct kroute_full *kf;
410 struct ktable *kt;
411 struct ctl_show_rib rib;
412 struct rde_memstats stats;
413 struct rde_hashstats hash;
414 u_char *asdata;
415 u_int rescode, ilen;
416 size_t aslen;
417
418 switch (imsg->hdr.type) {
419 case IMSG_CTL_SHOW_NEIGHBOR:
420 p = imsg->data;
421 output->neighbor(p, res);
422 break;
423 case IMSG_CTL_SHOW_TIMER:
424 if (imsg->hdr.len < IMSG_HEADER_SIZEsizeof(struct imsg_hdr) + sizeof(t))
425 errx(1, "wrong imsg len");
426 memcpy(&t, imsg->data, sizeof(t));
427 if (t.type > 0 && t.type < Timer_Max)
428 output->timer(&t);
429 break;
430 case IMSG_CTL_SHOW_INTERFACE:
431 iface = imsg->data;
432 output->interface(iface);
433 break;
434 case IMSG_CTL_SHOW_NEXTHOP:
435 nh = imsg->data;
436 output->nexthop(nh);
437 break;
438 case IMSG_CTL_KROUTE:
439 case IMSG_CTL_SHOW_NETWORK:
440 if (imsg->hdr.len < IMSG_HEADER_SIZEsizeof(struct imsg_hdr) + sizeof(*kf))
441 errx(1, "wrong imsg len");
442 kf = imsg->data;
443 output->fib(kf);
444 break;
445 case IMSG_CTL_SHOW_FIB_TABLES:
446 if (imsg->hdr.len < IMSG_HEADER_SIZEsizeof(struct imsg_hdr) + sizeof(*kt))
447 errx(1, "wrong imsg len");
448 kt = imsg->data;
449 output->fib_table(kt);
450 break;
451 case IMSG_CTL_SHOW_RIB:
452 if (imsg->hdr.len < IMSG_HEADER_SIZEsizeof(struct imsg_hdr) + sizeof(rib))
453 errx(1, "wrong imsg len");
454 memcpy(&rib, imsg->data, sizeof(rib));
455 aslen = imsg->hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr) - sizeof(rib);
456 asdata = imsg->data;
457 asdata += sizeof(rib);
458 output->rib(&rib, asdata, aslen, res);
459 break;
460 case IMSG_CTL_SHOW_RIB_COMMUNITIES:
461 ilen = imsg->hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr);
462 if (ilen % sizeof(struct community)) {
463 warnx("bad IMSG_CTL_SHOW_RIB_COMMUNITIES received");
464 break;
465 }
466 output->communities(imsg->data, ilen, res);
467 break;
468 case IMSG_CTL_SHOW_RIB_ATTR:
469 ilen = imsg->hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr);
470 if (ilen < 3) {
471 warnx("bad IMSG_CTL_SHOW_RIB_ATTR received");
472 break;
473 }
474 output->attr(imsg->data, ilen, res->flags, 0);
475 break;
476 case IMSG_CTL_SHOW_RIB_MEM:
477 if (imsg->hdr.len < IMSG_HEADER_SIZEsizeof(struct imsg_hdr) + sizeof(stats))
478 errx(1, "wrong imsg len");
479 memcpy(&stats, imsg->data, sizeof(stats));
480 output->rib_mem(&stats);
481 break;
482 case IMSG_CTL_SHOW_RIB_HASH:
483 if (imsg->hdr.len < IMSG_HEADER_SIZEsizeof(struct imsg_hdr) + sizeof(hash))
484 errx(1, "wrong imsg len");
485 memcpy(&hash, imsg->data, sizeof(hash));
486 output->rib_hash(&hash);
487 break;
488 case IMSG_CTL_SHOW_SET:
489 if (imsg->hdr.len < IMSG_HEADER_SIZEsizeof(struct imsg_hdr) + sizeof(set))
490 errx(1, "wrong imsg len");
491 memcpy(&set, imsg->data, sizeof(set));
492 output->set(&set);
493 break;
494 case IMSG_CTL_SHOW_RTR:
495 if (imsg->hdr.len < IMSG_HEADER_SIZEsizeof(struct imsg_hdr) + sizeof(rtr))
496 errx(1, "wrong imsg len");
497 memcpy(&rtr, imsg->data, sizeof(rtr));
498 output->rtr(&rtr);
499 break;
500 case IMSG_CTL_RESULT:
501 if (imsg->hdr.len != IMSG_HEADER_SIZEsizeof(struct imsg_hdr) + sizeof(rescode)) {
502 warnx("got IMSG_CTL_RESULT with wrong len");
503 break;
504 }
505 memcpy(&rescode, imsg->data, sizeof(rescode));
506 output->result(rescode);
507 return (1);
508 case IMSG_CTL_END:
509 return (1);
510 default:
511 warnx("unknown imsg %d received", imsg->hdr.type);
512 break;
513 }
514
515 return (0);
516}
517
518time_t
519get_monotime(time_t t)
520{
521 struct timespec ts;
522
523 if (t == 0)
524 return -1;
525 if (clock_gettime(CLOCK_MONOTONIC3, &ts) != 0)
526 err(1, "clock_gettime");
527 if (t > ts.tv_sec) /* time in the future is not possible */
528 t = ts.tv_sec;
529 return (ts.tv_sec - t);
530}
531
532char *
533fmt_peer(const char *descr, const struct bgpd_addr *remote_addr,
534 int masklen)
535{
536 const char *ip;
537 char *p;
538
539 if (descr && descr[0] && !nodescr) {
540 if ((p = strdup(descr)) == NULL((void*)0))
541 err(1, NULL((void*)0));
542 return (p);
543 }
544
545 ip = log_addr(remote_addr);
546 if (masklen != -1 && ((remote_addr->aid == AID_INET1 && masklen != 32) ||
547 (remote_addr->aid == AID_INET62 && masklen != 128))) {
548 if (asprintf(&p, "%s/%u", ip, masklen) == -1)
549 err(1, NULL((void*)0));
550 } else {
551 if ((p = strdup(ip)) == NULL((void*)0))
552 err(1, NULL((void*)0));
553 }
554
555 return (p);
556}
557
558const char *
559fmt_auth_method(enum auth_method method)
560{
561 switch (method) {
562 case AUTH_MD5SIG:
563 return ", using md5sig";
564 case AUTH_IPSEC_MANUAL_ESP:
565 return ", using ipsec manual esp";
566 case AUTH_IPSEC_MANUAL_AH:
567 return ", using ipsec manual ah";
568 case AUTH_IPSEC_IKE_ESP:
569 return ", using ipsec ike esp";
570 case AUTH_IPSEC_IKE_AH:
571 return ", using ipsec ike ah";
572 case AUTH_NONE: /* FALLTHROUGH */
573 default:
574 return "";
575 }
576}
577
578#define TF_BUFS8 8
579#define TF_LEN9 9
580
581const char *
582fmt_timeframe(time_t t)
583{
584 char *buf;
585 static char tfbuf[TF_BUFS8][TF_LEN9]; /* ring buffer */
586 static int idx = 0;
587 unsigned int sec, min, hrs, day;
588 unsigned long long week;
589
590 buf = tfbuf[idx++];
591 if (idx == TF_BUFS8)
592 idx = 0;
593
594 week = t;
595
596 sec = week % 60;
597 week /= 60;
598 min = week % 60;
599 week /= 60;
600 hrs = week % 24;
601 week /= 24;
602 day = week % 7;
603 week /= 7;
604
605 if (week > 0)
606 snprintf(buf, TF_LEN9, "%02lluw%01ud%02uh", week, day, hrs);
607 else if (day > 0)
608 snprintf(buf, TF_LEN9, "%01ud%02uh%02um", day, hrs, min);
609 else
610 snprintf(buf, TF_LEN9, "%02u:%02u:%02u", hrs, min, sec);
611
612 return (buf);
613}
614
615const char *
616fmt_monotime(time_t t)
617{
618 t = get_monotime(t);
619
620 if (t == -1)
621 return ("Never");
622
623 return (fmt_timeframe(t));
624}
625
626const char *
627fmt_fib_flags(u_int16_t flags)
628{
629 static char buf[8];
630
631 if (flags & F_DOWN0x0010)
632 strlcpy(buf, " ", sizeof(buf));
633 else
634 strlcpy(buf, "*", sizeof(buf));
635
636 if (flags & F_BGPD_INSERTED0x0001)
637 strlcat(buf, "B", sizeof(buf));
638 else if (flags & F_CONNECTED0x0004)
639 strlcat(buf, "C", sizeof(buf));
640 else if (flags & F_STATIC0x0020)
641 strlcat(buf, "S", sizeof(buf));
642 else if (flags & F_DYNAMIC0x0040)
643 strlcat(buf, "D", sizeof(buf));
644 else
645 strlcat(buf, " ", sizeof(buf));
646
647 if (flags & F_NEXTHOP0x0008)
648 strlcat(buf, "N", sizeof(buf));
649 else
650 strlcat(buf, " ", sizeof(buf));
651
652 if (flags & F_REJECT0x0080 && flags & F_BLACKHOLE0x0100)
653 strlcat(buf, "f", sizeof(buf));
654 else if (flags & F_REJECT0x0080)
655 strlcat(buf, "r", sizeof(buf));
656 else if (flags & F_BLACKHOLE0x0100)
657 strlcat(buf, "b", sizeof(buf));
658 else
659 strlcat(buf, " ", sizeof(buf));
660
661 if (strlcat(buf, " ", sizeof(buf)) >= sizeof(buf))
662 errx(1, "%s buffer too small", __func__);
663
664 return buf;
665}
666
667const char *
668fmt_origin(u_int8_t origin, int sum)
669{
670 switch (origin) {
671 case ORIGIN_IGP0:
672 return (sum ? "i" : "IGP");
673 case ORIGIN_EGP1:
674 return (sum ? "e" : "EGP");
675 case ORIGIN_INCOMPLETE2:
676 return (sum ? "?" : "incomplete");
677 default:
678 return (sum ? "X" : "bad origin");
679 }
680}
681
682const char *
683fmt_flags(u_int8_t flags, int sum)
684{
685 static char buf[80];
686 char flagstr[5];
687 char *p = flagstr;
688
689 if (sum) {
690 if (flags & F_PREF_INVALID0x20)
691 *p++ = 'E';
692 if (flags & F_PREF_ANNOUNCE0x08)
693 *p++ = 'A';
694 if (flags & F_PREF_INTERNAL0x04)
695 *p++ = 'I';
696 if (flags & F_PREF_STALE0x10)
697 *p++ = 'S';
698 if (flags & F_PREF_ELIGIBLE0x01)
699 *p++ = '*';
700 if (flags & F_PREF_ACTIVE0x02)
701 *p++ = '>';
702 *p = '\0';
703 snprintf(buf, sizeof(buf), "%-5s", flagstr);
704 } else {
705 if (flags & F_PREF_INTERNAL0x04)
706 strlcpy(buf, "internal", sizeof(buf));
707 else
708 strlcpy(buf, "external", sizeof(buf));
709
710 if (flags & F_PREF_STALE0x10)
711 strlcat(buf, ", stale", sizeof(buf));
712 if (flags & F_PREF_ELIGIBLE0x01)
713 strlcat(buf, ", valid", sizeof(buf));
714 if (flags & F_PREF_ACTIVE0x02)
715 strlcat(buf, ", best", sizeof(buf));
716 if (flags & F_PREF_ANNOUNCE0x08)
717 strlcat(buf, ", announced", sizeof(buf));
718 if (strlen(buf) >= sizeof(buf) - 1)
719 errx(1, "%s buffer too small", __func__);
720 }
721
722 return buf;
723}
724
725const char *
726fmt_ovs(u_int8_t validation_state, int sum)
727{
728 switch (validation_state) {
729 case ROA_INVALID0x1:
730 return (sum ? "!" : "invalid");
731 case ROA_VALID0x2:
732 return (sum ? "V" : "valid");
733 default:
734 return (sum ? "N" : "not-found");
735 }
736}
737
738const char *
739fmt_mem(long long num)
740{
741 static char buf[16];
742
743 if (fmt_scaled(num, buf) == -1)
744 snprintf(buf, sizeof(buf), "%lldB", num);
745
746 return (buf);
747}
748
749const char *
750fmt_errstr(u_int8_t errcode, u_int8_t subcode)
751{
752 static char errbuf[256];
753 const char *errstr = NULL((void*)0);
754 const char *suberr = NULL((void*)0);
755 int uk = 0;
756
757 if (errcode == 0) /* no error */
758 return NULL((void*)0);
759
760 if (errcode < sizeof(errnames)/sizeof(char *))
761 errstr = errnames[errcode];
762
763 switch (errcode) {
764 case ERR_HEADER:
765 if (subcode < sizeof(suberr_header_names)/sizeof(char *))
766 suberr = suberr_header_names[subcode];
767 else
768 uk = 1;
769 break;
770 case ERR_OPEN:
771 if (subcode < sizeof(suberr_open_names)/sizeof(char *))
772 suberr = suberr_open_names[subcode];
773 else
774 uk = 1;
775 break;
776 case ERR_UPDATE:
777 if (subcode < sizeof(suberr_update_names)/sizeof(char *))
778 suberr = suberr_update_names[subcode];
779 else
780 uk = 1;
781 break;
782 case ERR_HOLDTIMEREXPIRED:
783 if (subcode != 0)
784 uk = 1;
785 break;
786 case ERR_FSM:
787 if (subcode < sizeof(suberr_fsm_names)/sizeof(char *))
788 suberr = suberr_fsm_names[subcode];
789 else
790 uk = 1;
791 break;
792 case ERR_CEASE:
793 if (subcode < sizeof(suberr_cease_names)/sizeof(char *))
794 suberr = suberr_cease_names[subcode];
795 else
796 uk = 1;
797 break;
798 default:
799 snprintf(errbuf, sizeof(errbuf),
800 "unknown error code %u subcode %u", errcode, subcode);
801 return (errbuf);
802 }
803
804 if (uk)
805 snprintf(errbuf, sizeof(errbuf),
806 "%s, unknown subcode %u", errstr, subcode);
807 else if (suberr == NULL((void*)0))
808 return (errstr);
809 else
810 snprintf(errbuf, sizeof(errbuf),
811 "%s, %s", errstr, suberr);
812
813 return (errbuf);
814}
815
816const char *
817fmt_attr(u_int8_t type, int flags)
818{
819#define CHECK_FLAGS(s, t, m) \
820 if (((s) & ~(ATTR_DEFMASK(0x0f | 0x10) | (m))) != (t)) pflags = 1
821
822 static char cstr[48];
823 int pflags = 0;
824
825 switch (type) {
826 case ATTR_ORIGIN:
827 CHECK_FLAGS(flags, ATTR_WELL_KNOWN0x40, 0);
828 strlcpy(cstr, "Origin", sizeof(cstr));
829 break;
830 case ATTR_ASPATH:
831 CHECK_FLAGS(flags, ATTR_WELL_KNOWN0x40, 0);
832 strlcpy(cstr, "AS-Path", sizeof(cstr));
833 break;
834 case ATTR_AS4_PATH:
835 CHECK_FLAGS(flags, ATTR_WELL_KNOWN0x40, 0);
836 strlcpy(cstr, "AS4-Path", sizeof(cstr));
837 break;
838 case ATTR_NEXTHOP:
839 CHECK_FLAGS(flags, ATTR_WELL_KNOWN0x40, 0);
840 strlcpy(cstr, "Nexthop", sizeof(cstr));
841 break;
842 case ATTR_MED:
843 CHECK_FLAGS(flags, ATTR_OPTIONAL0x80, 0);
844 strlcpy(cstr, "Med", sizeof(cstr));
845 break;
846 case ATTR_LOCALPREF:
847 CHECK_FLAGS(flags, ATTR_WELL_KNOWN0x40, 0);
848 strlcpy(cstr, "Localpref", sizeof(cstr));
849 break;
850 case ATTR_ATOMIC_AGGREGATE:
851 CHECK_FLAGS(flags, ATTR_WELL_KNOWN0x40, 0);
852 strlcpy(cstr, "Atomic Aggregate", sizeof(cstr));
853 break;
854 case ATTR_AGGREGATOR:
855 CHECK_FLAGS(flags, ATTR_OPTIONAL0x80|ATTR_TRANSITIVE0x40, ATTR_PARTIAL0x20);
856 strlcpy(cstr, "Aggregator", sizeof(cstr));
857 break;
858 case ATTR_AS4_AGGREGATOR:
859 CHECK_FLAGS(flags, ATTR_OPTIONAL0x80|ATTR_TRANSITIVE0x40, ATTR_PARTIAL0x20);
860 strlcpy(cstr, "AS4-Aggregator", sizeof(cstr));
861 break;
862 case ATTR_COMMUNITIES:
863 CHECK_FLAGS(flags, ATTR_OPTIONAL0x80|ATTR_TRANSITIVE0x40, ATTR_PARTIAL0x20);
864 strlcpy(cstr, "Communities", sizeof(cstr));
865 break;
866 case ATTR_ORIGINATOR_ID:
867 CHECK_FLAGS(flags, ATTR_OPTIONAL0x80, 0);
868 strlcpy(cstr, "Originator Id", sizeof(cstr));
869 break;
870 case ATTR_CLUSTER_LIST:
871 CHECK_FLAGS(flags, ATTR_OPTIONAL0x80, 0);
872 strlcpy(cstr, "Cluster Id List", sizeof(cstr));
873 break;
874 case ATTR_MP_REACH_NLRI:
875 CHECK_FLAGS(flags, ATTR_OPTIONAL0x80, 0);
876 strlcpy(cstr, "MP Reach NLRI", sizeof(cstr));
877 break;
878 case ATTR_MP_UNREACH_NLRI:
879 CHECK_FLAGS(flags, ATTR_OPTIONAL0x80, 0);
880 strlcpy(cstr, "MP Unreach NLRI", sizeof(cstr));
881 break;
882 case ATTR_EXT_COMMUNITIES:
883 CHECK_FLAGS(flags, ATTR_OPTIONAL0x80|ATTR_TRANSITIVE0x40, ATTR_PARTIAL0x20);
884 strlcpy(cstr, "Ext. Communities", sizeof(cstr));
885 break;
886 case ATTR_LARGE_COMMUNITIES:
887 CHECK_FLAGS(flags, ATTR_OPTIONAL0x80|ATTR_TRANSITIVE0x40, ATTR_PARTIAL0x20);
888 strlcpy(cstr, "Large Communities", sizeof(cstr));
889 break;
890 default:
891 /* ignore unknown attributes */
892 snprintf(cstr, sizeof(cstr), "Unknown Attribute #%u", type);
893 pflags = 1;
894 break;
895 }
896 if (flags != -1 && pflags) {
897 strlcat(cstr, " flags [", sizeof(cstr));
898 if (flags & ATTR_OPTIONAL0x80)
899 strlcat(cstr, "O", sizeof(cstr));
900 if (flags & ATTR_TRANSITIVE0x40)
901 strlcat(cstr, "T", sizeof(cstr));
902 if (flags & ATTR_PARTIAL0x20)
903 strlcat(cstr, "P", sizeof(cstr));
904 strlcat(cstr, "]", sizeof(cstr));
905 }
906 return (cstr);
907
908#undef CHECK_FLAGS
909}
910
911const char *
912fmt_community(u_int16_t a, u_int16_t v)
913{
914 static char buf[12];
915
916 if (a == COMMUNITY_WELLKNOWN0xffff)
917 switch (v) {
918 case COMMUNITY_GRACEFUL_SHUTDOWN0x0000:
919 return "GRACEFUL_SHUTDOWN";
920 case COMMUNITY_NO_EXPORT0xff01:
921 return "NO_EXPORT";
922 case COMMUNITY_NO_ADVERTISE0xff02:
923 return "NO_ADVERTISE";
924 case COMMUNITY_NO_EXPSUBCONFED0xff03:
925 return "NO_EXPORT_SUBCONFED";
926 case COMMUNITY_NO_PEER0xff04:
927 return "NO_PEER";
928 case COMMUNITY_BLACKHOLE0x029A:
929 return "BLACKHOLE";
930 default:
931 break;
932 }
933
934 snprintf(buf, sizeof(buf), "%hu:%hu", a, v);
935 return buf;
936}
937
938const char *
939fmt_large_community(u_int32_t d1, u_int32_t d2, u_int32_t d3)
940{
941 static char buf[33];
942
943 snprintf(buf, sizeof(buf), "%u:%u:%u", d1, d2, d3);
944 return buf;
945}
946
947const char *
948fmt_ext_community(u_int8_t *data)
949{
950 static char buf[32];
951 u_int64_t ext;
952 struct in_addr ip;
953 u_int32_t as4, u32;
954 u_int16_t as2, u16;
955 u_int8_t type, subtype;
956
957 type = data[0];
958 subtype = data[1];
959
960 switch (type) {
961 case EXT_COMMUNITY_TRANS_TWO_AS0x00:
962 memcpy(&as2, data + 2, sizeof(as2));
963 memcpy(&u32, data + 4, sizeof(u32));
964 snprintf(buf, sizeof(buf), "%s %s:%u",
965 log_ext_subtype(type, subtype),
966 log_as(ntohs(as2)(__uint16_t)(__builtin_constant_p(as2) ? (__uint16_t)(((__uint16_t
)(as2) & 0xffU) << 8 | ((__uint16_t)(as2) & 0xff00U
) >> 8) : __swap16md(as2))
), ntohl(u32)(__uint32_t)(__builtin_constant_p(u32) ? (__uint32_t)(((__uint32_t
)(u32) & 0xff) << 24 | ((__uint32_t)(u32) & 0xff00
) << 8 | ((__uint32_t)(u32) & 0xff0000) >> 8 |
((__uint32_t)(u32) & 0xff000000) >> 24) : __swap32md
(u32))
);
967 return buf;
968 case EXT_COMMUNITY_TRANS_IPV40x01:
969 memcpy(&ip, data + 2, sizeof(ip));
970 memcpy(&u16, data + 6, sizeof(u16));
971 snprintf(buf, sizeof(buf), "%s %s:%hu",
972 log_ext_subtype(type, subtype),
973 inet_ntoa(ip), ntohs(u16)(__uint16_t)(__builtin_constant_p(u16) ? (__uint16_t)(((__uint16_t
)(u16) & 0xffU) << 8 | ((__uint16_t)(u16) & 0xff00U
) >> 8) : __swap16md(u16))
);
974 return buf;
975 case EXT_COMMUNITY_TRANS_FOUR_AS0x02:
976 memcpy(&as4, data + 2, sizeof(as4));
977 memcpy(&u16, data + 6, sizeof(u16));
978 snprintf(buf, sizeof(buf), "%s %s:%hu",
979 log_ext_subtype(type, subtype),
980 log_as(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))
), ntohs(u16)(__uint16_t)(__builtin_constant_p(u16) ? (__uint16_t)(((__uint16_t
)(u16) & 0xffU) << 8 | ((__uint16_t)(u16) & 0xff00U
) >> 8) : __swap16md(u16))
);
981 return buf;
982 case EXT_COMMUNITY_TRANS_OPAQUE0x03:
983 case EXT_COMMUNITY_TRANS_EVPN0x06:
984 memcpy(&ext, data, sizeof(ext));
985 ext = be64toh(ext)(__uint64_t)(__builtin_constant_p(ext) ? (__uint64_t)((((__uint64_t
)(ext) & 0xff) << 56) | ((__uint64_t)(ext) & 0xff00ULL
) << 40 | ((__uint64_t)(ext) & 0xff0000ULL) <<
24 | ((__uint64_t)(ext) & 0xff000000ULL) << 8 | ((
__uint64_t)(ext) & 0xff00000000ULL) >> 8 | ((__uint64_t
)(ext) & 0xff0000000000ULL) >> 24 | ((__uint64_t)(ext
) & 0xff000000000000ULL) >> 40 | ((__uint64_t)(ext)
& 0xff00000000000000ULL) >> 56) : __swap64md(ext))
& 0xffffffffffffLL;
986 snprintf(buf, sizeof(buf), "%s 0x%llx",
987 log_ext_subtype(type, subtype), (unsigned long long)ext);
988 return buf;
989 case EXT_COMMUNITY_NON_TRANS_OPAQUE0x43:
990 memcpy(&ext, data, sizeof(ext));
991 ext = be64toh(ext)(__uint64_t)(__builtin_constant_p(ext) ? (__uint64_t)((((__uint64_t
)(ext) & 0xff) << 56) | ((__uint64_t)(ext) & 0xff00ULL
) << 40 | ((__uint64_t)(ext) & 0xff0000ULL) <<
24 | ((__uint64_t)(ext) & 0xff000000ULL) << 8 | ((
__uint64_t)(ext) & 0xff00000000ULL) >> 8 | ((__uint64_t
)(ext) & 0xff0000000000ULL) >> 24 | ((__uint64_t)(ext
) & 0xff000000000000ULL) >> 40 | ((__uint64_t)(ext)
& 0xff00000000000000ULL) >> 56) : __swap64md(ext))
& 0xffffffffffffLL;
992 switch (ext) {
993 case EXT_COMMUNITY_OVS_VALID0:
994 snprintf(buf, sizeof(buf), "%s valid ",
995 log_ext_subtype(type, subtype));
996 return buf;
997 case EXT_COMMUNITY_OVS_NOTFOUND1:
998 snprintf(buf, sizeof(buf), "%s not-found ",
999 log_ext_subtype(type, subtype));
1000 return buf;
1001 case EXT_COMMUNITY_OVS_INVALID2:
1002 snprintf(buf, sizeof(buf), "%s invalid ",
1003 log_ext_subtype(type, subtype));
1004 return buf;
1005 default:
1006 snprintf(buf, sizeof(buf), "%s 0x%llx ",
1007 log_ext_subtype(type, subtype),
1008 (unsigned long long)ext);
1009 return buf;
1010 }
1011 break;
1012 default:
1013 memcpy(&ext, data, sizeof(ext));
1014 snprintf(buf, sizeof(buf), "%s 0x%llx",
1015 log_ext_subtype(type, subtype),
1016 (unsigned long long)be64toh(ext)(__uint64_t)(__builtin_constant_p(ext) ? (__uint64_t)((((__uint64_t
)(ext) & 0xff) << 56) | ((__uint64_t)(ext) & 0xff00ULL
) << 40 | ((__uint64_t)(ext) & 0xff0000ULL) <<
24 | ((__uint64_t)(ext) & 0xff000000ULL) << 8 | ((
__uint64_t)(ext) & 0xff00000000ULL) >> 8 | ((__uint64_t
)(ext) & 0xff0000000000ULL) >> 24 | ((__uint64_t)(ext
) & 0xff000000000000ULL) >> 40 | ((__uint64_t)(ext)
& 0xff00000000000000ULL) >> 56) : __swap64md(ext))
);
1017 return buf;
1018 }
1019}
1020
1021const char *
1022fmt_set_type(struct ctl_show_set *set)
1023{
1024 switch (set->type) {
1025 case ROA_SET:
1026 return "ROA";
1027 case PREFIX_SET:
1028 return "PREFIX";
1029 case ORIGIN_SET:
1030 return "ORIGIN";
1031 case ASNUM_SET:
1032 return "ASNUM";
1033 default:
1034 return "BULA";
1035 }
1036}
1037
1038void
1039send_filterset(struct imsgbuf *i, struct filter_set_head *set)
1040{
1041 struct filter_set *s;
1042
1043 while ((s = TAILQ_FIRST(set)((set)->tqh_first)) != NULL((void*)0)) {
1044 imsg_compose(i, IMSG_FILTER_SET, 0, 0, -1, s,
1045 sizeof(struct filter_set));
1046 TAILQ_REMOVE(set, s, entry)do { if (((s)->entry.tqe_next) != ((void*)0)) (s)->entry
.tqe_next->entry.tqe_prev = (s)->entry.tqe_prev; else (
set)->tqh_last = (s)->entry.tqe_prev; *(s)->entry.tqe_prev
= (s)->entry.tqe_next; ; ; } while (0)
;
1047 free(s);
1048 }
1049}
1050
1051void
1052network_bulk(struct parse_result *res)
1053{
1054 struct network_config net;
1055 struct filter_set *s = NULL((void*)0);
1056 struct bgpd_addr h;
1057 char *line = NULL((void*)0);
1058 size_t linesize = 0;
1059 ssize_t linelen;
1060 u_int8_t len;
1061 FILE *f;
1062
1063 if ((f = fdopen(STDIN_FILENO0, "r")) == NULL((void*)0))
1064 err(1, "Failed to open stdin\n");
1065
1066 while ((linelen = getline(&line, &linesize, f)) != -1) {
Although the value stored to 'linelen' is used in the enclosing expression, the value is never actually read from 'linelen'
1067 char *b, *buf = line;
1068 while ((b = strsep(&buf, " \t\n")) != NULL((void*)0)) {
1069 if (*b == '\0') /* skip empty tokens */
1070 continue;
1071 /* Stop processing after a comment */
1072 if (*b == '#')
1073 break;
1074 bzero(&net, sizeof(net));
1075 if (parse_prefix(b, strlen(b), &h, &len) != 1)
1076 errx(1, "bad prefix: %s", b);
1077 net.prefix = h;
1078 net.prefixlen = len;
1079 net.rd = res->rd;
1080
1081 if (res->action == NETWORK_BULK_ADD) {
1082 imsg_compose(ibuf, IMSG_NETWORK_ADD,
1083 0, 0, -1, &net, sizeof(net));
1084 /*
1085 * can't use send_filterset since that
1086 * would free the set.
1087 */
1088 TAILQ_FOREACH(s, &res->set, entry)for((s) = ((&res->set)->tqh_first); (s) != ((void*)
0); (s) = ((s)->entry.tqe_next))
{
1089 imsg_compose(ibuf,
1090 IMSG_FILTER_SET,
1091 0, 0, -1, s, sizeof(*s));
1092 }
1093 imsg_compose(ibuf, IMSG_NETWORK_DONE,
1094 0, 0, -1, NULL((void*)0), 0);
1095 } else
1096 imsg_compose(ibuf, IMSG_NETWORK_REMOVE,
1097 0, 0, -1, &net, sizeof(net));
1098 }
1099 }
1100 free(line);
1101 if (ferror(f)(!__isthreaded ? (((f)->_flags & 0x0040) != 0) : (ferror
)(f))
)
1102 err(1, "getline");
1103 fclose(f);
1104}
1105
1106void
1107show_mrt_dump_neighbors(struct mrt_rib *mr, struct mrt_peer *mp, void *arg)
1108{
1109 struct mrt_peer_entry *p;
1110 struct in_addr ina;
1111 u_int16_t i;
1112
1113 ina.s_addr = htonl(mp->bgp_id)(__uint32_t)(__builtin_constant_p(mp->bgp_id) ? (__uint32_t
)(((__uint32_t)(mp->bgp_id) & 0xff) << 24 | ((__uint32_t
)(mp->bgp_id) & 0xff00) << 8 | ((__uint32_t)(mp->
bgp_id) & 0xff0000) >> 8 | ((__uint32_t)(mp->bgp_id
) & 0xff000000) >> 24) : __swap32md(mp->bgp_id))
;
1114 printf("view: %s BGP ID: %s Number of peers: %u\n\n",
1115 mp->view, inet_ntoa(ina), mp->npeers);
1116 printf("%-30s %8s %15s\n", "Neighbor", "AS", "BGP ID");
1117 for (i = 0; i < mp->npeers; i++) {
1118 p = &mp->peers[i];
1119 ina.s_addr = htonl(p->bgp_id)(__uint32_t)(__builtin_constant_p(p->bgp_id) ? (__uint32_t
)(((__uint32_t)(p->bgp_id) & 0xff) << 24 | ((__uint32_t
)(p->bgp_id) & 0xff00) << 8 | ((__uint32_t)(p->
bgp_id) & 0xff0000) >> 8 | ((__uint32_t)(p->bgp_id
) & 0xff000000) >> 24) : __swap32md(p->bgp_id))
;
1120 printf("%-30s %8u %15s\n", log_addr(&p->addr), p->asnum,
1121 inet_ntoa(ina));
1122 }
1123 /* we only print the first message */
1124 exit(0);
1125}
1126
1127void
1128show_mrt_dump(struct mrt_rib *mr, struct mrt_peer *mp, void *arg)
1129{
1130 struct ctl_show_rib ctl;
1131 struct parse_result res;
1132 struct ctl_show_rib_request *req = arg;
1133 struct mrt_rib_entry *mre;
1134 time_t now;
1135 u_int16_t i, j;
1136
1137 memset(&res, 0, sizeof(res));
1138 res.flags = req->flags;
1139 now = time(NULL((void*)0));
1140
1141 for (i = 0; i < mr->nentries; i++) {
1142 mre = &mr->entries[i];
1143 bzero(&ctl, sizeof(ctl));
1144 ctl.prefix = mr->prefix;
1145 ctl.prefixlen = mr->prefixlen;
1146 if (mre->originated <= now)
1147 ctl.age = now - mre->originated;
1148 ctl.true_nexthop = mre->nexthop;
1149 ctl.exit_nexthop = mre->nexthop;
1150 ctl.origin = mre->origin;
1151 ctl.local_pref = mre->local_pref;
1152 ctl.med = mre->med;
1153 /* weight is not part of the mrt dump so it can't be set */
1154 if (mr->add_path) {
1155 ctl.flags |= F_PREF_PATH_ID0x40;
1156 ctl.path_id = mre->path_id;
1157 }
1158
1159 if (mre->peer_idx < mp->npeers) {
1160 ctl.remote_addr = mp->peers[mre->peer_idx].addr;
1161 ctl.remote_id = mp->peers[mre->peer_idx].bgp_id;
1162 }
1163
1164 /* filter by neighbor */
1165 if (req->neighbor.addr.aid != AID_UNSPEC0 &&
1166 memcmp(&req->neighbor.addr, &ctl.remote_addr,
1167 sizeof(ctl.remote_addr)) != 0)
1168 continue;
1169 /* filter by AF */
1170 if (req->aid && req->aid != ctl.prefix.aid)
1171 return;
1172 /* filter by prefix */
1173 if (req->prefix.aid != AID_UNSPEC0) {
1174 if (req->flags & F_LONGER0x0200) {
1175 if (req->prefixlen > ctl.prefixlen)
1176 return;
1177 if (prefix_compare(&req->prefix, &ctl.prefix,
1178 req->prefixlen))
1179 return;
1180 } else if (req->flags & F_SHORTER0x0400) {
1181 if (req->prefixlen < ctl.prefixlen)
1182 return;
1183 if (prefix_compare(&req->prefix, &ctl.prefix,
1184 ctl.prefixlen))
1185 return;
1186 } else {
1187 if (req->prefixlen != ctl.prefixlen)
1188 return;
1189 if (prefix_compare(&req->prefix, &ctl.prefix,
1190 req->prefixlen))
1191 return;
1192 }
1193 }
1194 /* filter by AS */
1195 if (req->as.type != AS_UNDEF &&
1196 !match_aspath(mre->aspath, mre->aspath_len, &req->as))
1197 continue;
1198
1199 output->rib(&ctl, mre->aspath, mre->aspath_len, &res);
1200 if (req->flags & F_CTL_DETAIL0x1000) {
1201 for (j = 0; j < mre->nattrs; j++)
1202 output->attr(mre->attrs[j].attr,
1203 mre->attrs[j].attr_len, req->flags, 0);
1204 }
1205 }
1206}
1207
1208void
1209network_mrt_dump(struct mrt_rib *mr, struct mrt_peer *mp, void *arg)
1210{
1211 struct ctl_show_rib ctl;
1212 struct network_config net;
1213 struct ctl_show_rib_request *req = arg;
1214 struct mrt_rib_entry *mre;
1215 struct ibuf *msg;
1216 time_t now;
1217 u_int16_t i, j;
1218
1219 /* can't announce more than one path so ignore add-path */
1220 if (mr->add_path)
1221 return;
1222
1223 now = time(NULL((void*)0));
1224 for (i = 0; i < mr->nentries; i++) {
1225 mre = &mr->entries[i];
1226 bzero(&ctl, sizeof(ctl));
1227 ctl.prefix = mr->prefix;
1228 ctl.prefixlen = mr->prefixlen;
1229 if (mre->originated <= now)
1230 ctl.age = now - mre->originated;
1231 ctl.true_nexthop = mre->nexthop;
1232 ctl.exit_nexthop = mre->nexthop;
1233 ctl.origin = mre->origin;
1234 ctl.local_pref = mre->local_pref;
1235 ctl.med = mre->med;
1236
1237 if (mre->peer_idx < mp->npeers) {
1238 ctl.remote_addr = mp->peers[mre->peer_idx].addr;
1239 ctl.remote_id = mp->peers[mre->peer_idx].bgp_id;
1240 }
1241
1242 /* filter by neighbor */
1243 if (req->neighbor.addr.aid != AID_UNSPEC0 &&
1244 memcmp(&req->neighbor.addr, &ctl.remote_addr,
1245 sizeof(ctl.remote_addr)) != 0)
1246 continue;
1247 /* filter by AF */
1248 if (req->aid && req->aid != ctl.prefix.aid)
1249 return;
1250 /* filter by prefix */
1251 if (req->prefix.aid != AID_UNSPEC0) {
1252 if (!prefix_compare(&req->prefix, &ctl.prefix,
1253 req->prefixlen)) {
1254 if (req->flags & F_LONGER0x0200) {
1255 if (req->prefixlen > ctl.prefixlen)
1256 return;
1257 } else if (req->prefixlen != ctl.prefixlen)
1258 return;
1259 } else
1260 return;
1261 }
1262 /* filter by AS */
1263 if (req->as.type != AS_UNDEF &&
1264 !match_aspath(mre->aspath, mre->aspath_len, &req->as))
1265 continue;
1266
1267 bzero(&net, sizeof(net));
1268 net.prefix = ctl.prefix;
1269 net.prefixlen = ctl.prefixlen;
1270 net.type = NETWORK_MRTCLONE;
1271 /* XXX rd can't be set and will be 0 */
1272
1273 imsg_compose(ibuf, IMSG_NETWORK_ADD, 0, 0, -1,
1274 &net, sizeof(net));
1275 if ((msg = imsg_create(ibuf, IMSG_NETWORK_ASPATH,
1276 0, 0, sizeof(ctl) + mre->aspath_len)) == NULL((void*)0))
1277 errx(1, "imsg_create failure");
1278 if (imsg_add(msg, &ctl, sizeof(ctl)) == -1 ||
1279 imsg_add(msg, mre->aspath, mre->aspath_len) == -1)
1280 errx(1, "imsg_add failure");
1281 imsg_close(ibuf, msg);
1282 for (j = 0; j < mre->nattrs; j++)
1283 imsg_compose(ibuf, IMSG_NETWORK_ATTR, 0, 0, -1,
1284 mre->attrs[j].attr, mre->attrs[j].attr_len);
1285 imsg_compose(ibuf, IMSG_NETWORK_DONE, 0, 0, -1, NULL((void*)0), 0);
1286
1287 while (ibuf->w.queued) {
1288 if (msgbuf_write(&ibuf->w) <= 0 && errno(*__errno()) != EAGAIN35)
1289 err(1, "write error");
1290 }
1291 }
1292}
1293
1294static const char *
1295fmt_time(struct timespec *t)
1296{
1297 static char timebuf[32];
1298 static struct timespec prevtime;
1299 struct timespec temp;
1300
1301 timespecsub(t, &prevtime, &temp)do { (&temp)->tv_sec = (t)->tv_sec - (&prevtime
)->tv_sec; (&temp)->tv_nsec = (t)->tv_nsec - (&
prevtime)->tv_nsec; if ((&temp)->tv_nsec < 0) { (
&temp)->tv_sec--; (&temp)->tv_nsec += 1000000000L
; } } while (0)
;
1302 snprintf(timebuf, sizeof(timebuf), "%lld.%06ld",
1303 (long long)temp.tv_sec, temp.tv_nsec / 1000);
1304 prevtime = *t;
1305 return (timebuf);
1306}
1307
1308void
1309show_mrt_state(struct mrt_bgp_state *ms, void *arg)
1310{
1311 printf("%s %s[%u] -> ", fmt_time(&ms->time),
1312 log_addr(&ms->src), ms->src_as);
1313 printf("%s[%u]: %s -> %s\n", log_addr(&ms->dst), ms->dst_as,
1314 statenames[ms->old_state], statenames[ms->new_state]);
1315}
1316
1317static void
1318print_afi(u_char *p, u_int8_t len)
1319{
1320 u_int16_t afi;
1321 u_int8_t safi, aid;
1322
1323 if (len != 4) {
1324 printf("bad length");
1325 return;
1326 }
1327
1328 /* afi, 2 byte */
1329 memcpy(&afi, p, sizeof(afi));
1330 afi = ntohs(afi)(__uint16_t)(__builtin_constant_p(afi) ? (__uint16_t)(((__uint16_t
)(afi) & 0xffU) << 8 | ((__uint16_t)(afi) & 0xff00U
) >> 8) : __swap16md(afi))
;
1331 p += 2;
1332 /* reserved, 1 byte */
1333 p += 1;
1334 /* safi, 1 byte */
1335 memcpy(&safi, p, sizeof(safi));
1336 if (afi2aid(afi, safi, &aid) == -1)
1337 printf("unkown afi %u safi %u", afi, safi);
1338 else
1339 printf("%s", aid2str(aid));
1340}
1341
1342static void
1343print_capability(u_int8_t capa_code, u_char *p, u_int8_t len)
1344{
1345 switch (capa_code) {
1346 case CAPA_MP:
1347 printf("multiprotocol capability: ");
1348 print_afi(p, len);
1349 break;
1350 case CAPA_REFRESH:
1351 printf("route refresh capability");
1352 break;
1353 case CAPA_RESTART:
1354 printf("graceful restart capability");
1355 /* XXX there is more needed here */
1356 break;
1357 case CAPA_AS4BYTE:
1358 printf("4-byte AS num capability: ");
1359 if (len == 4) {
1360 u_int32_t as;
1361 memcpy(&as, p, sizeof(as));
1362 as = ntohl(as)(__uint32_t)(__builtin_constant_p(as) ? (__uint32_t)(((__uint32_t
)(as) & 0xff) << 24 | ((__uint32_t)(as) & 0xff00
) << 8 | ((__uint32_t)(as) & 0xff0000) >> 8 |
((__uint32_t)(as) & 0xff000000) >> 24) : __swap32md
(as))
;
1363 printf("AS %u", as);
1364 } else
1365 printf("bad length");
1366 break;
1367 case CAPA_ADD_PATH:
1368 printf("add-path capability");
1369 /* XXX there is more needed here */
1370 break;
1371 case CAPA_ENHANCED_RR:
1372 printf("enhanced route refresh capability");
1373 break;
1374 default:
1375 printf("unknown capability %u length %u", capa_code, len);
1376 break;
1377 }
1378}
1379
1380static void
1381print_notification(u_int8_t errcode, u_int8_t subcode)
1382{
1383 const char *suberrname = NULL((void*)0);
1384 int uk = 0;
1385
1386 switch (errcode) {
1387 case ERR_HEADER:
1388 if (subcode >= sizeof(suberr_header_names)/sizeof(char *))
1389 uk = 1;
1390 else
1391 suberrname = suberr_header_names[subcode];
1392 break;
1393 case ERR_OPEN:
1394 if (subcode >= sizeof(suberr_open_names)/sizeof(char *))
1395 uk = 1;
1396 else
1397 suberrname = suberr_open_names[subcode];
1398 break;
1399 case ERR_UPDATE:
1400 if (subcode >= sizeof(suberr_update_names)/sizeof(char *))
1401 uk = 1;
1402 else
1403 suberrname = suberr_update_names[subcode];
1404 break;
1405 case ERR_CEASE:
1406 if (subcode >= sizeof(suberr_cease_names)/sizeof(char *))
1407 uk = 1;
1408 else
1409 suberrname = suberr_cease_names[subcode];
1410 break;
1411 case ERR_HOLDTIMEREXPIRED:
1412 if (subcode != 0)
1413 uk = 1;
1414 break;
1415 case ERR_FSM:
1416 if (subcode >= sizeof(suberr_fsm_names)/sizeof(char *))
1417 uk = 1;
1418 else
1419 suberrname = suberr_fsm_names[subcode];
1420 break;
1421 default:
1422 printf("unknown errcode %u, subcode %u",
1423 errcode, subcode);
1424 return;
1425 }
1426
1427 if (uk)
1428 printf("%s, unknown subcode %u", errnames[errcode], subcode);
1429 else {
1430 if (suberrname == NULL((void*)0))
1431 printf("%s", errnames[errcode]);
1432 else
1433 printf("%s, %s", errnames[errcode], suberrname);
1434 }
1435}
1436
1437static int
1438show_mrt_capabilities(u_char *p, u_int16_t len)
1439{
1440 u_int16_t totlen = len;
1441 u_int8_t capa_code, capa_len;
1442
1443 while (len > 2) {
1444 memcpy(&capa_code, p, sizeof(capa_code));
1445 p += sizeof(capa_code);
1446 len -= sizeof(capa_code);
1447 memcpy(&capa_len, p, sizeof(capa_len));
1448 p += sizeof(capa_len);
1449 len -= sizeof(capa_len);
1450 if (len < capa_len) {
1451 printf("capa_len %u exceeds remaining length",
1452 capa_len);
1453 return (-1);
1454 }
1455 printf("\n ");
1456 print_capability(capa_code, p, capa_len);
1457 p += capa_len;
1458 len -= capa_len;
1459 }
1460 if (len != 0) {
1461 printf("length missmatch while capability parsing");
1462 return (-1);
1463 }
1464 return (totlen);
1465}
1466
1467static void
1468show_mrt_open(u_char *p, u_int16_t len)
1469{
1470 u_int8_t version, optparamlen;
1471 u_int16_t short_as, holdtime;
1472 struct in_addr bgpid;
1473
1474 /* length check up to optparamlen already happened */
1475 memcpy(&version, p, sizeof(version));
1476 p += sizeof(version);
1477 len -= sizeof(version);
1478 memcpy(&short_as, p, sizeof(short_as));
1479 p += sizeof(short_as);
1480 len -= sizeof(short_as);
1481 short_as = ntohs(short_as)(__uint16_t)(__builtin_constant_p(short_as) ? (__uint16_t)(((
__uint16_t)(short_as) & 0xffU) << 8 | ((__uint16_t)
(short_as) & 0xff00U) >> 8) : __swap16md(short_as))
;
1482 memcpy(&holdtime, p, sizeof(holdtime));
1483 holdtime = ntohs(holdtime)(__uint16_t)(__builtin_constant_p(holdtime) ? (__uint16_t)(((
__uint16_t)(holdtime) & 0xffU) << 8 | ((__uint16_t)
(holdtime) & 0xff00U) >> 8) : __swap16md(holdtime))
;
1484 p += sizeof(holdtime);
1485 len -= sizeof(holdtime);
1486 memcpy(&bgpid, p, sizeof(bgpid));
1487 p += sizeof(bgpid);
1488 len -= sizeof(bgpid);
1489 memcpy(&optparamlen, p, sizeof(optparamlen));
1490 p += sizeof(optparamlen);
1491 len -= sizeof(optparamlen);
1492
1493 printf("\n ");
1494 printf("Version: %d AS: %u Holdtime: %u BGP Id: %s Paramlen: %u",
1495 version, short_as, holdtime, inet_ntoa(bgpid), optparamlen);
1496 if (optparamlen != len) {
1497 printf("optional parameter length mismatch");
1498 return;
1499 }
1500 while (len > 2) {
1501 u_int8_t op_type, op_len;
1502 int r;
1503
1504 memcpy(&op_type, p, sizeof(op_type));
1505 p += sizeof(op_type);
1506 len -= sizeof(op_type);
1507 memcpy(&op_len, p, sizeof(op_len));
1508 p += sizeof(op_len);
1509 len -= sizeof(op_len);
1510
1511 printf("\n ");
1512 switch (op_type) {
1513 case OPT_PARAM_CAPABILITIES:
1514 printf("Capabilities: size %u", op_len);
1515 r = show_mrt_capabilities(p, op_len);
1516 if (r == -1)
1517 return;
1518 p += r;
1519 len -= r;
1520 break;
1521 case OPT_PARAM_AUTH:
1522 default:
1523 printf("unsupported optional parameter: type %u",
1524 op_type);
1525 return;
1526 }
1527 }
1528 if (len != 0) {
1529 printf("optional parameter encoding error");
1530 return;
1531 }
1532}
1533
1534static void
1535show_mrt_notification(u_char *p, u_int16_t len)
1536{
1537 u_int16_t i;
1538 u_int8_t errcode, subcode;
1539 size_t reason_len;
1540 char reason[REASON_LEN256];
1541
1542 memcpy(&errcode, p, sizeof(errcode));
1543 p += sizeof(errcode);
1544 len -= sizeof(errcode);
1545
1546 memcpy(&subcode, p, sizeof(subcode));
1547 p += sizeof(subcode);
1548 len -= sizeof(subcode);
1549
1550 printf("\n ");
1551 print_notification(errcode, subcode);
1552
1553 if (errcode == ERR_CEASE && (subcode == ERR_CEASE_ADMIN_DOWN ||
1554 subcode == ERR_CEASE_ADMIN_RESET)) {
1555 if (len > 1) {
1556 reason_len = *p++;
1557 len--;
1558 if (len < reason_len) {
1559 printf("truncated shutdown reason");
1560 return;
1561 }
1562 if (reason_len > REASON_LEN256 - 1) {
1563 printf("overly long shutdown reason");
1564 return;
1565 }
1566 memcpy(reason, p, reason_len);
1567 reason[reason_len] = '\0';
1568 printf("shutdown reason: \"%s\"",
1569 log_reason(reason));
1570 p += reason_len;
1571 len -= reason_len;
1572 }
1573 }
1574 if (errcode == ERR_OPEN && subcode == ERR_OPEN_CAPA) {
1575 int r;
1576
1577 r = show_mrt_capabilities(p, len);
1578 if (r == -1)
1579 return;
1580 p += r;
1581 len -= r;
1582 }
1583
1584 if (len > 0) {
1585 printf("\n additional data %u bytes", len);
1586 for (i = 0; i < len; i++) {
1587 if (i % 16 == 0)
1588 printf("\n ");
1589 if (i % 8 == 0)
1590 printf(" ");
1591 printf(" %02X", *p++);
1592 }
1593 }
1594}
1595
1596/* XXX this function does not handle JSON output */
1597static void
1598show_mrt_update(u_char *p, u_int16_t len, int reqflags, int addpath)
1599{
1600 struct bgpd_addr prefix;
1601 int pos;
1602 u_int32_t pathid;
1603 u_int16_t wlen, alen;
1604 u_int8_t prefixlen;
1605
1606 if (len < sizeof(wlen)) {
1607 printf("bad length");
1608 return;
1609 }
1610 memcpy(&wlen, p, sizeof(wlen));
1611 wlen = ntohs(wlen)(__uint16_t)(__builtin_constant_p(wlen) ? (__uint16_t)(((__uint16_t
)(wlen) & 0xffU) << 8 | ((__uint16_t)(wlen) & 0xff00U
) >> 8) : __swap16md(wlen))
;
1612 p += sizeof(wlen);
1613 len -= sizeof(wlen);
1614
1615 if (len < wlen) {
1616 printf("bad withdraw length");
1617 return;
1618 }
1619 if (wlen > 0) {
1620 printf("\n Withdrawn prefixes:");
1621 while (wlen > 0) {
1622 if (addpath) {
1623 if (wlen <= sizeof(pathid)) {
1624 printf("bad withdraw prefix");
1625 return;
1626 }
1627 memcpy(&pathid, p, sizeof(pathid));
1628 pathid = ntohl(pathid)(__uint32_t)(__builtin_constant_p(pathid) ? (__uint32_t)(((__uint32_t
)(pathid) & 0xff) << 24 | ((__uint32_t)(pathid) &
0xff00) << 8 | ((__uint32_t)(pathid) & 0xff0000) >>
8 | ((__uint32_t)(pathid) & 0xff000000) >> 24) : __swap32md
(pathid))
;
1629 p += sizeof(pathid);
1630 len -= sizeof(pathid);
1631 wlen -= sizeof(pathid);
1632 }
1633 if ((pos = nlri_get_prefix(p, wlen, &prefix,
1634 &prefixlen)) == -1) {
1635 printf("bad withdraw prefix");
1636 return;
1637 }
1638 printf(" %s/%u", log_addr(&prefix), prefixlen);
1639 if (addpath)
1640 printf(" path-id %u", pathid);
1641 p += pos;
1642 len -= pos;
1643 wlen -= pos;
1644 }
1645 }
1646
1647 if (len < sizeof(alen)) {
1648 printf("bad length");
1649 return;
1650 }
1651 memcpy(&alen, p, sizeof(alen));
1652 alen = ntohs(alen)(__uint16_t)(__builtin_constant_p(alen) ? (__uint16_t)(((__uint16_t
)(alen) & 0xffU) << 8 | ((__uint16_t)(alen) & 0xff00U
) >> 8) : __swap16md(alen))
;
1653 p += sizeof(alen);
1654 len -= sizeof(alen);
1655
1656 if (len < alen) {
1657 printf("bad attribute length");
1658 return;
1659 }
1660 printf("\n");
1661 /* alen attributes here */
1662 while (alen > 3) {
1663 u_int8_t flags;
1664 u_int16_t attrlen;
1665
1666 flags = p[0];
1667 /* type = p[1]; */
1668
1669 /* get the attribute length */
1670 if (flags & ATTR_EXTLEN0x10) {
1671 if (len < sizeof(attrlen) + 2)
1672 printf("bad attribute length");
1673 memcpy(&attrlen, &p[2], sizeof(attrlen));
1674 attrlen = ntohs(attrlen)(__uint16_t)(__builtin_constant_p(attrlen) ? (__uint16_t)(((__uint16_t
)(attrlen) & 0xffU) << 8 | ((__uint16_t)(attrlen) &
0xff00U) >> 8) : __swap16md(attrlen))
;
1675 attrlen += sizeof(attrlen) + 2;
1676 } else {
1677 attrlen = p[2];
1678 attrlen += 1 + 2;
1679 }
1680
1681 output->attr(p, attrlen, reqflags, addpath);
1682 p += attrlen;
1683 alen -= attrlen;
1684 len -= attrlen;
1685 }
1686
1687 if (len > 0) {
1688 printf(" NLRI prefixes:");
1689 while (len > 0) {
1690 if (addpath) {
1691 if (len <= sizeof(pathid)) {
1692 printf(" bad nlri prefix: pathid, len %d", len);
1693 return;
1694 }
1695 memcpy(&pathid, p, sizeof(pathid));
1696 pathid = ntohl(pathid)(__uint32_t)(__builtin_constant_p(pathid) ? (__uint32_t)(((__uint32_t
)(pathid) & 0xff) << 24 | ((__uint32_t)(pathid) &
0xff00) << 8 | ((__uint32_t)(pathid) & 0xff0000) >>
8 | ((__uint32_t)(pathid) & 0xff000000) >> 24) : __swap32md
(pathid))
;
1697 p += sizeof(pathid);
1698 len -= sizeof(pathid);
1699 }
1700 if ((pos = nlri_get_prefix(p, len, &prefix,
1701 &prefixlen)) == -1) {
1702 printf(" bad nlri prefix");
1703 return;
1704 }
1705 printf(" %s/%u", log_addr(&prefix), prefixlen);
1706 if (addpath)
1707 printf(" path-id %u", pathid);
1708 p += pos;
1709 len -= pos;
1710 }
1711 }
1712}
1713
1714void
1715show_mrt_msg(struct mrt_bgp_msg *mm, void *arg)
1716{
1717 static const u_int8_t marker[MSGSIZE_HEADER_MARKER16] = {
1718 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1719 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1720 u_char *p;
1721 u_int16_t len;
1722 u_int8_t type;
1723 struct ctl_show_rib_request *req = arg;
1724
1725 printf("%s %s[%u] -> ", fmt_time(&mm->time),
1726 log_addr(&mm->src), mm->src_as);
1727 printf("%s[%u]: size %u%s ", log_addr(&mm->dst), mm->dst_as,
1728 mm->msg_len, mm->add_path ? " addpath" : "");
1729 p = mm->msg;
1730 len = mm->msg_len;
1731
1732 if (len < MSGSIZE_HEADER19) {
1733 printf("illegal header length: %u byte\n", len);
1734 return;
1735 }
1736
1737 /* parse BGP message header */
1738 if (memcmp(p, marker, sizeof(marker))) {
1739 printf("incorrect marker in BGP message\n");
1740 return;
1741 }
1742 p += MSGSIZE_HEADER_MARKER16;
1743
1744 memcpy(&len, p, 2);
1745 len = ntohs(len)(__uint16_t)(__builtin_constant_p(len) ? (__uint16_t)(((__uint16_t
)(len) & 0xffU) << 8 | ((__uint16_t)(len) & 0xff00U
) >> 8) : __swap16md(len))
;
1746 p += 2;
1747 memcpy(&type, p, 1);
1748 p += 1;
1749
1750 if (len < MSGSIZE_HEADER19 || len > MAX_PKTSIZE4096) {
1751 printf("illegal header length: %u byte\n", len);
1752 return;
1753 }
1754
1755 switch (type) {
1756 case OPEN:
1757 printf("%s ", msgtypenames[type]);
1758 if (len < MSGSIZE_OPEN_MIN29) {
1759 printf("illegal length: %u byte\n", len);
1760 return;
1761 }
1762 show_mrt_open(p, len - MSGSIZE_HEADER19);
1763 break;
1764 case NOTIFICATION:
1765 printf("%s ", msgtypenames[type]);
1766 if (len < MSGSIZE_NOTIFICATION_MIN21) {
1767 printf("illegal length: %u byte\n", len);
1768 return;
1769 }
1770 show_mrt_notification(p, len - MSGSIZE_HEADER19);
1771 break;
1772 case UPDATE:
1773 printf("%s ", msgtypenames[type]);
1774 if (len < MSGSIZE_UPDATE_MIN23) {
1775 printf("illegal length: %u byte\n", len);
1776 return;
1777 }
1778 show_mrt_update(p, len - MSGSIZE_HEADER19, req->flags,
1779 mm->add_path);
1780 break;
1781 case KEEPALIVE:
1782 printf("%s ", msgtypenames[type]);
1783 if (len != MSGSIZE_KEEPALIVE19) {
1784 printf("illegal length: %u byte\n", len);
1785 return;
1786 }
1787 /* nothing */
1788 break;
1789 case RREFRESH:
1790 printf("%s ", msgtypenames[type]);
1791 if (len != MSGSIZE_RREFRESH(19 + 4)) {
1792 printf("illegal length: %u byte\n", len);
1793 return;
1794 }
1795 print_afi(p, len);
1796 break;
1797 default:
1798 printf("unknown type %u\n", type);
1799 return;
1800 }
1801 printf("\n");
1802}
1803
1804const char *
1805msg_type(u_int8_t type)
1806{
1807 if (type >= sizeof(msgtypenames)/sizeof(msgtypenames[0]))
1808 return "BAD";
1809 return (msgtypenames[type]);
1810}
1811
1812int
1813match_aspath(void *data, u_int16_t len, struct filter_as *f)
1814{
1815 u_int8_t *seg;
1816 int final;
1817 u_int16_t seg_size;
1818 u_int8_t i, seg_len;
1819 u_int32_t as = 0;
1820
1821 if (f->type == AS_EMPTY) {
1822 if (len == 0)
1823 return (1);
1824 else
1825 return (0);
1826 }
1827
1828 seg = data;
1829
1830 /* just check the leftmost AS */
1831 if (f->type == AS_PEER && len >= 6) {
1832 as = aspath_extract(seg, 0);
1833 if (f->as_min == as)
1834 return (1);
1835 else
1836 return (0);
1837 }
1838
1839 for (; len >= 6; len -= seg_size, seg += seg_size) {
1840 seg_len = seg[1];
1841 seg_size = 2 + sizeof(u_int32_t) * seg_len;
1842
1843 final = (len == seg_size);
1844
1845 if (f->type == AS_SOURCE) {
1846 /*
1847 * Just extract the rightmost AS
1848 * but if that segment is an AS_SET then the rightmost
1849 * AS of a previous AS_SEQUENCE segment should be used.
1850 * Because of that just look at AS_SEQUENCE segments.
1851 */
1852 if (seg[0] == AS_SEQUENCE2)
1853 as = aspath_extract(seg, seg_len - 1);
1854 /* not yet in the final segment */
1855 if (!final)
1856 continue;
1857 if (f->as_min == as)
1858 return (1);
1859 else
1860 return (0);
1861 }
1862 /* AS_TRANSIT or AS_ALL */
1863 for (i = 0; i < seg_len; i++) {
1864 /*
1865 * the source (rightmost) AS is excluded from
1866 * AS_TRANSIT matches.
1867 */
1868 if (final && i == seg_len - 1 && f->type == AS_TRANSIT)
1869 return (0);
1870 as = aspath_extract(seg, i);
1871 if (f->as_min == as)
1872 return (1);
1873 }
1874 }
1875 return (0);
1876}