Implement bgpctl show flowspec and bgpctl flowspec flush.
authorclaudio <claudio@openbsd.org>
Thu, 20 Apr 2023 14:01:50 +0000 (14:01 +0000)
committerclaudio <claudio@openbsd.org>
Thu, 20 Apr 2023 14:01:50 +0000 (14:01 +0000)
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
usr.sbin/bgpctl/bgpctl.c
usr.sbin/bgpctl/bgpctl.h
usr.sbin/bgpctl/output.c
usr.sbin/bgpctl/parser.c
usr.sbin/bgpctl/parser.h

index 06032dc..ac5bd7e 100644 (file)
@@ -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
index 6f2a79f..8f607a1 100644 (file)
@@ -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 <henning@openbsd.org>
@@ -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");
index 2eab06f..cd15723 100644 (file)
@@ -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 <claudio@openbsd.org>
@@ -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);
index 28b47dc..a1bcb31 100644 (file)
@@ -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 <henning@openbsd.org>
@@ -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,
index 85688d2..3f039e9 100644 (file)
@@ -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 <henning@openbsd.org>
@@ -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},
index 9f1ae95..c0adf93 100644 (file)
@@ -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 <henning@openbsd.org>
@@ -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 {