From 87966dc1f0fb965a986801ca3421582d533cc74f Mon Sep 17 00:00:00 2001 From: Christian David Date: Sat, 14 Dec 2019 14:48:01 +0100 Subject: [PATCH] Add support for Mikrotik --- CHANGES | 5 +++++ README.md | 17 +++++++++++++++++ bgpq4.8 | 2 ++ bgpq4.c | 8 +++++++- bgpq4.h | 1 + bgpq4_printer.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 80 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index dc8f1b7..daf2f6d 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +======= +0.0.2 (2019-12-14): + - Add Mikrotik support + - remove ASDDOT support + 0.0.1 (2019-12-14): - fork bgpq3 into bgpq4 diff --git a/README.md b/README.md index 06a9061..4b5c911 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,10 @@ Generate config for Juniper (default: Cisco). Generate output in JSON format (default: Cisco). +#### -K + +Generate config for MikroTik (default: Cisco). + #### -m `length` Maximum length of accepted prefixes (default: `32` for IPv4, `128` for IPv6). @@ -178,6 +182,19 @@ expansion from future expansion. EXAMPLES -------- +Generating prefix filter for MikroTik for `AS20597`: + + user@host:~>./bgpq4 -Kl eltel AS20597 + /routing filter add action=accept chain="eltel-V4" prefix=81.9.0.0/20 + /routing filter add action=accept chain="eltel-V4" prefix=81.9.32.0/20 + /routing filter add action=accept chain="eltel-V4" prefix=81.9.96.0/20 + /routing filter add action=accept chain="eltel-V4" prefix=81.222.128.0/20 + /routing filter add action=accept chain="eltel-V4" prefix=81.222.160.0/20 + /routing filter add action=accept chain="eltel-V4" prefix=81.222.192.0/18 + /routing filter add action=accept chain="eltel-V4" prefix=85.249.8.0/21 + /routing filter add action=accept chain="eltel-V4" prefix=85.249.224.0/19 + /routing filter add action=accept chain="eltel-V4" prefix=89.112.0.0/17 + /routing filter add action=accept chain="eltel-V4" prefix=217.170.64.0/19 Generating named Juniper prefix-filter for `AS20597`: diff --git a/bgpq4.8 b/bgpq4.8 index d947c6d..56c9be3 100644 --- a/bgpq4.8 +++ b/bgpq4.8 @@ -93,6 +93,8 @@ host running IRRD database (default: rr.ntt.net). generate config for Juniper (default: Cisco). .It Fl j generate output in JSON format (default: Cisco). +.It Fl K +generate config for Mikrotik (default: Cisco). .It Fl l Ar name name of generated entry. .It Fl L Ar limit diff --git a/bgpq4.c b/bgpq4.c index c3def97..03a0ee2 100644 --- a/bgpq4.c +++ b/bgpq4.c @@ -50,6 +50,7 @@ usage(int ecode) " (use host:port to specify alternate port)\n"); printf(" -J : generate config for JunOS (Cisco IOS by default)\n"); printf(" -j : generate JSON output (Cisco IOS by default)\n"); + printf(" -K : generate config for MikroTik RouterOS (Cisco IOS by default)\n"); printf(" -M match : extra match conditions for JunOS route-filters\n"); printf(" -m len : maximum prefix length (default: 32 for IPv4, " "128 for IPv6)\n"); @@ -145,7 +146,7 @@ main(int argc, char* argv[]) if (getenv("IRRD_SOURCES")) expander.sources=getenv("IRRD_SOURCES"); - while((c=getopt(argc,argv,"2346a:AbBdDEF:S:jJf:l:L:m:M:NnW:Ppr:R:G:tTh:UwXsz")) + while((c=getopt(argc,argv,"2346a:AbBdDEF:S:jJKf:l:L:m:M:NnW:Ppr:R:G:tTh:UwXsz")) !=EOF) { switch(c) { case '2': @@ -223,6 +224,9 @@ main(int argc, char* argv[]) case 'j': if(expander.vendor) vendor_exclusive(); expander.vendor=V_JSON; break; + case 'K': if(expander.vendor) vendor_exclusive(); + expander.vendor=V_MIKROTIK; + break; case 'p': expand_special_asn=1; break; @@ -348,6 +352,8 @@ main(int argc, char* argv[]) expander.aswidth=6; } else if(expander.vendor==V_JUNIPER) { expander.aswidth=8; + } else if(expander.vendor==V_MIKROTIK) { + expander.aswidth=4; } else if(expander.vendor==V_BIRD) { expander.aswidth=10; } else if(expander.vendor==V_NOKIA || expander.vendor==V_NOKIA_MD) { diff --git a/bgpq4.h b/bgpq4.h index 36f74ac..7843711 100644 --- a/bgpq4.h +++ b/bgpq4.h @@ -20,6 +20,7 @@ typedef enum { V_FORMAT, V_NOKIA, V_HUAWEI, + V_MIKROTIK, V_NOKIA_MD } bgpq_vendor_t; diff --git a/bgpq4_printer.c b/bgpq4_printer.c index 529dae1..bec7631 100644 --- a/bgpq4_printer.c +++ b/bgpq4_printer.c @@ -1387,6 +1387,52 @@ bgpq4_print_nokia_md_ipprefixlist(FILE* f, struct bgpq_expander* b) return 0; }; +void +bgpq4_print_kprefix(struct sx_radix_node* n, void* ff) +{ + char prefix[128]; + FILE* f=(FILE*)ff; + if(!f) f=stdout; + if(n->isGlue) goto checkSon; + sx_prefix_snprintf_sep(&n->prefix,prefix,sizeof(prefix),"/"); + if(n->isAggregate) { + if(n->aggregateLow>n->prefix.masklen) { + fprintf(f,"/routing filter add action=accept chain=\"%s-%s\" prefix=%s prefix-length=%d-%d\n", + bname?bname:"NN", + n->prefix.family==AF_INET?"V4":"V6", + prefix, + n->aggregateLow, + n->aggregateHi); + } else { + fprintf(f,"/routing filter add action=accept chain=\"%s-%s\" prefix=%s prefix-length=%d\n", + bname?bname:"NN", + n->prefix.family==AF_INET?"V4":"V6", + prefix, + n->aggregateHi); + }; + } else { + fprintf(f,"/routing filter add action=accept chain=\"%s-%s\" prefix=%s\n", + bname?bname:"NN", + n->prefix.family==AF_INET?"V4":"V6", + prefix); + }; +checkSon: + if(n->son) + bgpq4_print_kprefix(n->son,ff); +}; + +int +bgpq4_print_mikrotik_prefixlist(FILE* f, struct bgpq_expander* b) +{ + bname=b->name ? b->name : "NN"; + if (!sx_radix_tree_empty(b->tree)) { + sx_radix_tree_foreach(b->tree,bgpq4_print_kprefix,f); + } else { + fprintf(f, "# generated prefix-list %s is empty\n", bname); + }; + return 0; +}; + int bgpq4_print_prefixlist(FILE* f, struct bgpq_expander* b) { @@ -1401,6 +1447,7 @@ bgpq4_print_prefixlist(FILE* f, struct bgpq_expander* b) case V_NOKIA: return bgpq4_print_nokia_prefixlist(f,b); case V_NOKIA_MD: return bgpq4_print_nokia_md_ipprefixlist(f,b); case V_HUAWEI: return bgpq4_print_huawei_prefixlist(f,b); + case V_MIKROTIK: return bgpq4_print_mikrotik_prefixlist(f,b); }; return 0; }; @@ -1418,6 +1465,7 @@ bgpq4_print_eacl(FILE* f, struct bgpq_expander* b) case V_FORMAT: sx_report(SX_FATAL, "unreachable point\n"); case V_NOKIA: return bgpq4_print_nokia_ipprefixlist(f,b); case V_NOKIA_MD: return bgpq4_print_nokia_md_prefixlist(f,b); + case V_MIKROTIK: return sx_report(SX_FATAL, "unreachable point\n"); case V_HUAWEI: return sx_report(SX_FATAL, "unreachable point\n"); }; return 0;