diff --git a/README.md b/README.md index 9d9a590..734ef3a 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,10 @@ The options are as follows: > try to aggregate generated filters as much as possible (not all output formats supported). +- -b + + > generate output in BIRD format (default: Cisco). + - -d > enable some debugging output. diff --git a/bgpq3.8 b/bgpq3.8 index cca6624..bdbcc36 100644 --- a/bgpq3.8 +++ b/bgpq3.8 @@ -60,6 +60,8 @@ generate IPv6 prefix/access-lists (IPv4 by default). .It Fl A try to aggregate prefix-lists as much as possible (not all output formats supported). +.It Fl b +generate output in BIRD format (default: Cisco). .It Fl d enable some debugging output. .It Fl D diff --git a/bgpq3.c b/bgpq3.c index 34eccd8..d27f8fb 100644 --- a/bgpq3.c +++ b/bgpq3.c @@ -24,12 +24,13 @@ int usage(int ecode) { printf("\nUsage: bgpq3 [-h host] [-S sources] [-P|E|G |f ]" - " [-346ADJjXd] [-R len] ...\n"); + " [-346AbDJjXd] [-R len] ...\n"); printf(" -3 : assume that your device is asn32-safe\n"); printf(" -4 : generate IPv4 prefix-lists (default)\n"); printf(" -6 : generate IPv6 prefix-lists (IPv4 by default)\n"); printf(" -A : try to aggregate Cisco prefix-lists or Juniper " "route-filters\n as much as possible\n"); + printf(" -b : generate BIRD output (Cisco IOS by default)\n"); printf(" -d : generate some debugging output\n"); printf(" -D : use asdot notation in as-path\n"); printf(" -E : generate extended access-list(Cisco) or " @@ -69,8 +70,8 @@ exclusive() void vendor_exclusive() { - fprintf(stderr, "-J (JunOS), -j (JSON) and -X (IOS XR) options are mutually" - " exclusive\n"); + fprintf(stderr, "-b (BIRD), -J (JunOS), -j (JSON) and -X (IOS XR) options are " + "mutually exclusive\n"); exit(1); }; @@ -121,7 +122,7 @@ main(int argc, char* argv[]) bgpq_expander_init(&expander,af); expander.sources=getenv("IRRD_SOURCES"); - while((c=getopt(argc,argv,"346AdDES:jJf:l:m:M:W:Pr:R:G:Th:X"))!=EOF) { + while((c=getopt(argc,argv,"346AbdDES:jJf:l:m:M:W:Pr:R:G:Th:X"))!=EOF) { switch(c) { case '3': expander.asn32=1; @@ -147,6 +148,9 @@ main(int argc, char* argv[]) if(aggregate) debug_aggregation++; aggregate=1; break; + case 'b': if(expander.vendor) vendor_exclusive(); + expander.vendor=V_BIRD; + break; case 'd': debug_expander++; break; case 'D': expander.asdot=1; @@ -268,9 +272,13 @@ main(int argc, char* argv[]) expander.generation=T_PREFIXLIST; }; - if(expander.vendor==V_CISCO_XR && expander.generation!=T_PREFIXLIST) { + if(expander.vendor==V_CISCO_XR && expander.generation!=T_PREFIXLIST) { sx_report(SX_FATAL, "Sorry, only prefix-sets supported for IOS XR\n"); }; + if(expander.vendor==V_BIRD && expander.generation!=T_PREFIXLIST) { + sx_report(SX_FATAL, "Sorry, only prefix-lists supported for BIRD " + "output\n"); + }; if(expander.vendor==V_JSON && expander.generation!=T_PREFIXLIST) { sx_report(SX_FATAL, "Sorry, only prefix-lists supported for JSON " "output\n"); diff --git a/bgpq3.h b/bgpq3.h index 2967e55..68d10c4 100644 --- a/bgpq3.h +++ b/bgpq3.h @@ -8,7 +8,8 @@ typedef enum { V_CISCO = 0, V_JUNIPER, V_CISCO_XR, - V_JSON + V_JSON, + V_BIRD } bgpq_vendor_t; typedef enum { diff --git a/bgpq3_printer.c b/bgpq3_printer.c index ebf2720..ea1bd35 100644 --- a/bgpq3_printer.c +++ b/bgpq3_printer.c @@ -270,6 +270,32 @@ checkSon: bgpq3_print_json_prefix(n->son, ff); }; +void +bgpq3_print_bird_prefix(struct sx_radix_node* n, void* ff) +{ + char prefix[128]; + FILE* f=(FILE*)ff; + if(n->isGlue) + goto checkSon; + if(!f) + f=stdout; + sx_prefix_snprintf(&n->prefix, prefix, sizeof(prefix)); + if (!n->isAggregate) { + fprintf(f, "%s\n %s", + needscomma?",":"", prefix); + } else if (n->aggregateLow > n->prefix.masklen) { + fprintf(f, "%s\n %s{%u,%u}", + needscomma?",":"", prefix, n->aggregateLow, n->aggregateHi); + } else { + fprintf(f, "%s\n %s{%u,%u}", + needscomma?",":"", prefix, n->prefix.masklen, n->aggregateHi); + }; + needscomma=1; +checkSon: + if(n->son) + bgpq3_print_bird_prefix(n->son, ff); +}; + void bgpq3_print_jrfilter(struct sx_radix_node* n, void* ff) { @@ -479,6 +505,16 @@ bgpq3_print_json_prefixlist(FILE* f, struct bgpq_expander* b) return 0; }; +int +bgpq3_print_bird_prefixlist(FILE* f, struct bgpq_expander* b) +{ + fprintf(f,"%s = [", + b->name?b->name:"NN"); + sx_radix_tree_foreach(b->tree,bgpq3_print_bird_prefix,f); + fprintf(f,"\n];\n"); + return 0; +}; + int bgpq3_print_cisco_eacl(FILE* f, struct bgpq_expander* b) { @@ -497,6 +533,7 @@ bgpq3_print_prefixlist(FILE* f, struct bgpq_expander* b) case V_CISCO: return bgpq3_print_cisco_prefixlist(f,b); case V_CISCO_XR: return bgpq3_print_ciscoxr_prefixlist(f,b); case V_JSON: return bgpq3_print_json_prefixlist(f,b); + case V_BIRD: return bgpq3_print_bird_prefixlist(f,b); }; return 0; }; @@ -509,6 +546,7 @@ bgpq3_print_eacl(FILE* f, struct bgpq_expander* b) case V_CISCO: return bgpq3_print_cisco_eacl(f,b); case V_CISCO_XR: sx_report(SX_FATAL, "unreachable point\n"); case V_JSON: sx_report(SX_FATAL, "unreachable point\n"); + case V_BIRD: sx_report(SX_FATAL, "unreachable point\n"); }; return 0; };