From 5fed6b04b4eb09af8336577d46b510c7d14e4acf Mon Sep 17 00:00:00 2001 From: claudio Date: Thu, 20 Apr 2023 14:01:50 +0000 Subject: [PATCH] Implement bgpctl show flowspec and bgpctl flowspec flush. This uses the flowspec.c file from bgpd and implements the output for flowspec only for the text printer for now. That code uses a lot of code from printconf.c OK tb@ --- usr.sbin/bgpctl/Makefile | 5 +- usr.sbin/bgpctl/bgpctl.c | 27 +++++++++- usr.sbin/bgpctl/bgpctl.h | 3 +- usr.sbin/bgpctl/output.c | 107 ++++++++++++++++++++++++++++++++++++++- usr.sbin/bgpctl/parser.c | 11 +++- usr.sbin/bgpctl/parser.h | 8 ++- 6 files changed, 153 insertions(+), 8 deletions(-) diff --git a/usr.sbin/bgpctl/Makefile b/usr.sbin/bgpctl/Makefile index 06032dc2f62..ac5bd7e2470 100644 --- a/usr.sbin/bgpctl/Makefile +++ b/usr.sbin/bgpctl/Makefile @@ -1,10 +1,11 @@ -# $OpenBSD: Makefile,v 1.18 2022/10/17 12:01:19 claudio Exp $ +# $OpenBSD: Makefile,v 1.19 2023/04/20 14:01:50 claudio Exp $ .PATH: ${.CURDIR}/../bgpd PROG= bgpctl SRCS= bgpctl.c output.c output_json.c output_ometric.c parser.c \ - mrtparser.c util.c json.c ometric.c + mrtparser.c json.c ometric.c +SRCS+= util.c flowspec.c CFLAGS+= -Wall CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes CFLAGS+= -Wmissing-declarations diff --git a/usr.sbin/bgpctl/bgpctl.c b/usr.sbin/bgpctl/bgpctl.c index 6f2a79f91b8..8f607a1a519 100644 --- a/usr.sbin/bgpctl/bgpctl.c +++ b/usr.sbin/bgpctl/bgpctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpctl.c,v 1.290 2023/03/13 16:59:22 claudio Exp $ */ +/* $OpenBSD: bgpctl.c,v 1.291 2023/04/20 14:01:50 claudio Exp $ */ /* * Copyright (c) 2003 Henning Brauer @@ -361,6 +361,22 @@ main(int argc, char *argv[]) mrt_parse(res->mrtfd, &net_mrt, 1); done = 1; break; + case FLOWSPEC_ADD: + case FLOWSPEC_REMOVE: + done = 1; + break; + case FLOWSPEC_FLUSH: + imsg_compose(ibuf, IMSG_FLOWSPEC_FLUSH, 0, 0, -1, NULL, 0); + printf("request sent.\n"); + done = 1; + break; + case FLOWSPEC_SHOW: + memset(&ribreq, 0, sizeof(ribreq)); + ribreq.aid = res->aid; + strlcpy(ribreq.rib, res->rib, sizeof(ribreq.rib)); + imsg_compose(ibuf, IMSG_CTL_SHOW_FLOWSPEC, 0, 0, -1, + &ribreq, sizeof(ribreq)); + break; case LOG_VERBOSE: verbose = 1; /* FALLTHROUGH */ @@ -424,6 +440,7 @@ show(struct imsg *imsg, struct parse_result *res) struct ctl_show_rtr rtr; struct kroute_full *kf; struct ktable *kt; + struct flowspec *f; struct ctl_show_rib rib; struct rde_memstats stats; u_char *asdata; @@ -467,6 +484,14 @@ show(struct imsg *imsg, struct parse_result *res) kf = imsg->data; output->fib(kf); break; + case IMSG_CTL_SHOW_FLOWSPEC: + if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(*f)) + errx(1, "wrong imsg len"); + if (output->flowspec == NULL) + break; + f = imsg->data; + output->flowspec(f); + break; case IMSG_CTL_SHOW_FIB_TABLES: if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(*kt)) errx(1, "wrong imsg len"); diff --git a/usr.sbin/bgpctl/bgpctl.h b/usr.sbin/bgpctl/bgpctl.h index 2eab06f2611..cd15723e156 100644 --- a/usr.sbin/bgpctl/bgpctl.h +++ b/usr.sbin/bgpctl/bgpctl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpctl.h,v 1.20 2023/03/28 12:07:09 claudio Exp $ */ +/* $OpenBSD: bgpctl.h,v 1.21 2023/04/20 14:01:50 claudio Exp $ */ /* * Copyright (c) 2019 Claudio Jeker @@ -24,6 +24,7 @@ struct output { void (*timer)(struct ctl_timer *); void (*fib)(struct kroute_full *); void (*fib_table)(struct ktable *); + void (*flowspec)(struct flowspec *); void (*nexthop)(struct ctl_show_nexthop *); void (*interface)(struct ctl_show_interface *); void (*attr)(u_char *, size_t, int, int); diff --git a/usr.sbin/bgpctl/output.c b/usr.sbin/bgpctl/output.c index 28b47dc5202..a1bcb31e32f 100644 --- a/usr.sbin/bgpctl/output.c +++ b/usr.sbin/bgpctl/output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: output.c,v 1.38 2023/03/28 12:07:09 claudio Exp $ */ +/* $OpenBSD: output.c,v 1.39 2023/04/20 14:01:50 claudio Exp $ */ /* * Copyright (c) 2003 Henning Brauer @@ -85,6 +85,8 @@ show_head(struct parse_result *res) printf("%-5s %-4s %-32s %-32s\n", "flags", "prio", "destination", "gateway"); break; + case FLOWSPEC_SHOW: + printf("flags: S = Static\n"); default: break; } @@ -492,6 +494,108 @@ show_fib_table(struct ktable *kt) kt->fib_sync != kt->fib_conf ? "*" : ""); } +static void +print_flowspec_list(struct flowspec *f, int type, int is_v6) +{ + const uint8_t *comp; + const char *fmt; + int complen, off = 0; + + if (flowspec_get_component(f->data, f->len, type, is_v6, + &comp, &complen) != 1) + return; + + printf("%s ", flowspec_fmt_label(type)); + fmt = flowspec_fmt_num_op(comp, complen, &off); + if (off == -1) { + printf("%s ", fmt); + } else { + printf("{ %s ", fmt); + do { + fmt = flowspec_fmt_num_op(comp, complen, &off); + printf("%s ", fmt); + } while (off != -1); + printf("} "); + } +} + +static void +print_flowspec_flags(struct flowspec *f, int type, int is_v6) +{ + const uint8_t *comp; + const char *fmt, *flags; + int complen, off = 0; + + if (flowspec_get_component(f->data, f->len, type, is_v6, + &comp, &complen) != 1) + return; + + printf("%s ", flowspec_fmt_label(type)); + + switch (type) { + case FLOWSPEC_TYPE_TCP_FLAGS: + flags = FLOWSPEC_TCP_FLAG_STRING; + break; + case FLOWSPEC_TYPE_FRAG: + if (!is_v6) + flags = FLOWSPEC_FRAG_STRING4; + else + flags = FLOWSPEC_FRAG_STRING6; + break; + } + + fmt = flowspec_fmt_bin_op(comp, complen, &off, flags); + if (off == -1) { + printf("%s ", fmt); + } else { + printf("{ %s ", fmt); + do { + fmt = flowspec_fmt_bin_op(comp, complen, &off, flags); + printf("%s ", fmt); + } while (off != -1); + printf("} "); + } +} + +static void +print_flowspec_addr(struct flowspec *f, int type, int is_v6) +{ + struct bgpd_addr addr; + uint8_t plen; + + flowspec_get_addr(f->data, f->len, type, is_v6, &addr, &plen, NULL); + if (plen == 0) + printf("%s any ", flowspec_fmt_label(type)); + else + printf("%s %s/%u ", flowspec_fmt_label(type), + log_addr(&addr), plen); +} + +static void +show_flowspec(struct flowspec *f) +{ + int is_v6 = (f->aid == AID_FLOWSPECv6); + + printf("%-5s ", fmt_fib_flags(f->flags)); + print_flowspec_list(f, FLOWSPEC_TYPE_PROTO, is_v6); + + print_flowspec_addr(f, FLOWSPEC_TYPE_SOURCE, is_v6); + print_flowspec_list(f, FLOWSPEC_TYPE_SRC_PORT, is_v6); + + print_flowspec_addr(f, FLOWSPEC_TYPE_DEST, is_v6); + print_flowspec_list(f, FLOWSPEC_TYPE_DST_PORT, is_v6); + + print_flowspec_list(f, FLOWSPEC_TYPE_DSCP, is_v6); + print_flowspec_list(f, FLOWSPEC_TYPE_PKT_LEN, is_v6); + print_flowspec_flags(f, FLOWSPEC_TYPE_TCP_FLAGS, is_v6); + print_flowspec_flags(f, FLOWSPEC_TYPE_FRAG, is_v6); + /* TODO: fixup the code handling to be like in the parser */ + print_flowspec_list(f, FLOWSPEC_TYPE_ICMP_TYPE, is_v6); + print_flowspec_list(f, FLOWSPEC_TYPE_ICMP_CODE, is_v6); + + printf("\n"); +} + static void show_nexthop(struct ctl_show_nexthop *nh) { @@ -1117,6 +1221,7 @@ const struct output show_output = { .timer = show_timer, .fib = show_fib, .fib_table = show_fib_table, + .flowspec = show_flowspec, .nexthop = show_nexthop, .interface = show_interface, .communities = show_communities, diff --git a/usr.sbin/bgpctl/parser.c b/usr.sbin/bgpctl/parser.c index 85688d236a3..3f039e97c05 100644 --- a/usr.sbin/bgpctl/parser.c +++ b/usr.sbin/bgpctl/parser.c @@ -1,4 +1,4 @@ -/* $OpenBSD: parser.c,v 1.129 2023/04/17 13:48:31 claudio Exp $ */ +/* $OpenBSD: parser.c,v 1.130 2023/04/20 14:01:50 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -96,6 +96,7 @@ static const struct token t_show_mrt_as[]; static const struct token t_show_prefix[]; static const struct token t_show_ip[]; static const struct token t_network[]; +static const struct token t_flowspec[]; static const struct token t_bulk[]; static const struct token t_network_show[]; static const struct token t_prefix[]; @@ -107,6 +108,7 @@ static const struct token t_communication[]; static const struct token t_main[] = { { KEYWORD, "fib", FIB, t_fib}, + { KEYWORD, "flowspec", NONE, t_flowspec}, { KEYWORD, "log", NONE, t_log}, { KEYWORD, "neighbor", NEIGHBOR, t_neighbor}, { KEYWORD, "network", NONE, t_network}, @@ -118,6 +120,7 @@ static const struct token t_main[] = { static const struct token t_show[] = { { NOTOKEN, "", NONE, NULL}, { KEYWORD, "fib", SHOW_FIB, t_show_fib}, + { KEYWORD, "flowspec", FLOWSPEC_SHOW, t_network_show}, { KEYWORD, "interfaces", SHOW_INTERFACE, NULL}, { KEYWORD, "ip", NONE, t_show_ip}, { KEYWORD, "metrics", SHOW_METRICS, NULL}, @@ -329,6 +332,12 @@ static const struct token t_network[] = { { ENDTOKEN, "", NONE, NULL} }; +static const struct token t_flowspec[] = { + { KEYWORD, "flush", FLOWSPEC_FLUSH, NULL}, + { KEYWORD, "show", FLOWSPEC_SHOW, t_network_show}, + { ENDTOKEN, "", NONE, NULL} +}; + static const struct token t_bulk[] = { { KEYWORD, "add", NETWORK_BULK_ADD, t_set}, { KEYWORD, "delete", NETWORK_BULK_REMOVE, NULL}, diff --git a/usr.sbin/bgpctl/parser.h b/usr.sbin/bgpctl/parser.h index 9f1ae95e9e5..c0adf93e538 100644 --- a/usr.sbin/bgpctl/parser.h +++ b/usr.sbin/bgpctl/parser.h @@ -1,4 +1,4 @@ -/* $OpenBSD: parser.h,v 1.44 2022/10/17 16:51:36 claudio Exp $ */ +/* $OpenBSD: parser.h,v 1.45 2023/04/20 14:01:50 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -56,7 +56,11 @@ enum actions { NETWORK_SHOW, NETWORK_MRT, NETWORK_BULK_ADD, - NETWORK_BULK_REMOVE + NETWORK_BULK_REMOVE, + FLOWSPEC_ADD, + FLOWSPEC_REMOVE, + FLOWSPEC_FLUSH, + FLOWSPEC_SHOW, }; struct parse_result { -- 2.20.1