diff --git a/CHANGES b/CHANGES index f8748a9..b2f74e7 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +0.1.20-todo2 (2014-05-01) + - new flag -r , allowing bgpq to generate limited set of more-specific + routes - only routes with prefix-length >= are accepted. + Thanks to Pavel Gulchouck for suggesion. + 0.1.20-todo (2013-10-07) - socket close code fixed. Thanks to Martin J. Levy. - new flag -4, "force ipv4". Actually does a little more than allowing diff --git a/COPYRIGHT b/COPYRIGHT index ca85ca0..0b0a6f9 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2007-2013 Alexandre Snarskii + * Copyright (c) 2007-2014 Alexandre Snarskii * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/README.md b/README.md index 86024aa..9d9a590 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,3 @@ - - - NAME ---- @@ -19,7 +6,7 @@ NAME SYNOPSIS -------- - bgpq3 [-h host] [-S sources] [-EP] [-f asn | -G asn] [-36ADdJjX] [-R len] [-m max] OBJECTS [...] + bgpq3 [-h host] [-S sources] [-EP] [-f asn | -G asn] [-346ADdJjX] [-r len] [-R len] [-m max] OBJECTS [...] DESCRIPTION ----------- @@ -97,6 +84,11 @@ The options are as follows: > generate prefix-list (default behaviour, flag added for backward compatibility only). +- -r len + + > allow more-specific routes with masklen starting with specified + length. + - -R len > allow more-specific routes up to specified masklen too. @@ -115,7 +107,8 @@ The options are as follows: > generate config for Cisco IOS XR devices (plain IOS by default). -`OBJECTS` means networks (in prefix format), autonomous systems and as-macros. +`OBJECTS` means networks (in prefix format), autonomous systems, as-sets +and route-sets. EXAMPLES -------- @@ -165,33 +158,34 @@ into single entry ip prefix-list eltel permit 89.112.0.0/18 ge 19 le 19. Well, for Juniper we can generate even more interesting policy-statement, -using `-M `, `-R ` and hierarchical names: +using `-M `, `-r `, `-R ` and hierarchical +names: - user@host:~>bgpq3 -AJEl eltel/specifics -R 32 -M "community blackhole" AS20597 - policy-options { - policy-statement eltel { - term specifics { - replace: - from { - community blackhole; - route-filter 81.9.0.0/20 upto /32; - route-filter 81.9.32.0/20 upto /32; - route-filter 81.9.96.0/20 upto /32; - route-filter 81.222.128.0/20 upto /32; - route-filter 81.222.192.0/18 upto /32; - route-filter 85.249.8.0/21 upto /32; - route-filter 85.249.224.0/19 upto /32; - route-filter 89.112.0.0/18 prefix-length-range /19-/32; - route-filter 89.112.64.0/19 upto /32; - route-filter 217.170.64.0/19 prefix-length-range /20-/32; - } - } - } - } + user@host:~>bgpq3 -AJEl eltel/specifics -r 29 -R 32 -M "community blackhole" AS20597 + policy-options { + policy-statement eltel { + term specifics { + replace: + from { + community blackhole; + route-filter 81.9.0.0/20 prefix-length-range /29-/32; + route-filter 81.9.32.0/20 prefix-length-range /29-/32; + route-filter 81.9.96.0/20 prefix-length-range /29-/32; + route-filter 81.222.128.0/20 prefix-length-range /29-/32; + route-filter 81.222.192.0/18 prefix-length-range /29-/32; + route-filter 85.249.8.0/21 prefix-length-range /29-/32; + route-filter 85.249.224.0/19 prefix-length-range /29-/32; + route-filter 89.112.0.0/17 prefix-length-range /29-/32; + route-filter 217.170.64.0/19 prefix-length-range /29-/32; + } + } + } + } -generated policy-option term now allows all more-specific routes -for eltel networks if they marked with community 'blackhole' (defined -elsewhere in configuration). + +generated policy-option term now allows more-specific routes in range +/29 - /32 for eltel networks if they marked with community 'blackhole' +(defined elsewhere in configuration). Of course, `bgpq3` supports IPv6 (-6): diff --git a/bgpq3.8 b/bgpq3.8 index e59961c..cca6624 100644 --- a/bgpq3.8 +++ b/bgpq3.8 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2007-2013 Alexandre Snarskii +.\" Copyright (c) 2007-2014 Alexandre Snarskii .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -21,7 +21,6 @@ .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. -.\" "$Id: bgpq3.8,v 1.10 2013/10/08 10:50:34 snar Exp $ .\" .Dd Oct 27, 2008 .Dt BGPQ3 8 @@ -39,6 +38,7 @@ .Fl G Ar asn .Oc .Op Fl 346ADdJjX +.Op Fl r Ar len .Op Fl R Ar len .Op Fl m Ar max .Ar OBJECTS @@ -86,8 +86,10 @@ extra match conditions for Juniper route-filters. name of generated entry. .It Fl P generate prefix-list (default, backward compatibility). +.It Fl r Ar len +allow more specific routes starting with specified masklen too. .It Fl R Ar len -allow specific routes up to specified masklen too. +allow more specific routes up to specified masklen too. .It Fl S Ar sources use specified sources only (default: RADB,RIPE,APNIC). .It Fl T @@ -95,7 +97,7 @@ disable pipelining. .It Fl X generate config for Cisco IOS XR devices (plain IOS by default). .It Ar OBJECTS -means networks (in prefix format), autonomous systems and as-macros. +means networks (in prefix format), autonomous systems, as-sets and route-sets. .El .Sh EXAMPLES Generating named juniper prefix-filter for AS20597: @@ -149,31 +151,31 @@ Well, for Juniper we can generate even more interesting policy-options, using -M , -R and hierarchical names: .nf .RS -~>bgpq3 -AJEl eltel/specifics -R 32 -M "community blackhole" AS20597 +./bgpq3 -AJEl eltel/specifics -r 29 -R 32 -M "community blackhole" AS20597 policy-options { policy-statement eltel { term specifics { replace: from { community blackhole; - route-filter 81.9.0.0/20 upto /32; - route-filter 81.9.32.0/20 upto /32; - route-filter 81.9.96.0/20 upto /32; - route-filter 81.222.128.0/20 upto /32; - route-filter 81.222.192.0/18 upto /32; - route-filter 85.249.8.0/21 upto /32; - route-filter 85.249.224.0/19 upto /32; - route-filter 89.112.0.0/18 prefix-length-range /19-/32; - route-filter 89.112.64.0/19 upto /32; - route-filter 217.170.64.0/19 prefix-length-range /20-/32; + route-filter 81.9.0.0/20 prefix-length-range /29-/32; + route-filter 81.9.32.0/20 prefix-length-range /29-/32; + route-filter 81.9.96.0/20 prefix-length-range /29-/32; + route-filter 81.222.128.0/20 prefix-length-range /29-/32; + route-filter 81.222.192.0/18 prefix-length-range /29-/32; + route-filter 85.249.8.0/21 prefix-length-range /29-/32; + route-filter 85.249.224.0/19 prefix-length-range /29-/32; + route-filter 89.112.0.0/17 prefix-length-range /29-/32; + route-filter 217.170.64.0/19 prefix-length-range /29-/32; } } } } .RE .fi -generated policy-option term now allows all specifics for eltel networks -if they match with special community 'blackhole'. +generated policy-option term now allows all specifics with prefix-length +between /29 and /32 for eltel networks if they match with special community +'blackhole' (defined elsewhere in configuration). .Pp Of course, this version supports IPv6 (-6): .nf diff --git a/bgpq3.c b/bgpq3.c index a4d3799..34eccd8 100644 --- a/bgpq3.c +++ b/bgpq3.c @@ -47,13 +47,14 @@ usage(int ecode) " list\n"); printf(" -P : generate prefix-list (default, just for backward" " compatibility)\n"); - printf(" -R len : allow specific routes up to masklen specified\n"); + printf(" -r len : allow more specific routes from masklen specified\n"); + printf(" -R len : allow more specific routes up to specified masklen\n"); printf(" -S sources: use only specified sources (default:" " RADB,RIPE,APNIC)\n"); printf(" -T : disable pipelining (experimental, faster mode)\n"); printf(" -X : generate config for IOS XR (Cisco IOS by default)\n"); printf("\n" PACKAGE_NAME " version: " PACKAGE_VERSION "\n"); - printf("Copyright(c) Alexandre Snarskii 2007-2013\n\n"); + printf("Copyright(c) Alexandre Snarskii 2007-2014\n\n"); exit(ecode); }; @@ -114,13 +115,13 @@ main(int argc, char* argv[]) int c; struct bgpq_expander expander; int af=AF_INET, selectedipv4 = 0; - int widthSet=0, aggregate=0, refine=0; + int widthSet=0, aggregate=0, refine=0, refineLow=0; unsigned long maxlen=0; bgpq_expander_init(&expander,af); expander.sources=getenv("IRRD_SOURCES"); - while((c=getopt(argc,argv,"346AdDES:jJf:l:m:M:W:PR:G:Th:X"))!=EOF) { + while((c=getopt(argc,argv,"346AdDES:jJf:l:m:M:W:Pr:R:G:Th:X"))!=EOF) { switch(c) { case '3': expander.asn32=1; @@ -175,6 +176,13 @@ main(int argc, char* argv[]) if(expander.generation) exclusive(); expander.generation=T_PREFIXLIST; break; + case 'r': + refineLow=strtoul(optarg,NULL,10); + if(!refineLow) { + sx_report(SX_FATAL,"Invalid refineLow value: %s\n", optarg); + exit(1); + }; + break; case 'R': refine=strtoul(optarg,NULL,10); if(!refine) { @@ -260,12 +268,6 @@ main(int argc, char* argv[]) expander.generation=T_PREFIXLIST; }; - /* - if(expander.vendor==V_CISCO && expander.asn32 && - expander.generation128)) { - sx_report(SX_FATAL, "Invalid value for refinement: %u (1-128 for" + if(refineLow && !refine) { + if(expander.family == AF_INET) + refine = 32; + else + refine = 128; + }; + + if (refineLow && refineLow > refine) { + sx_report(SX_FATAL, "Incompatible values for -r %u and -R %u\n", + refineLow, refine); + }; + + if(refine || refineLow) { + if(expander.family==AF_INET6 && refine>128) { + sx_report(SX_FATAL, "Invalid value for refine(-R): %u (1-128 for" " IPv6)\n", refine); + } else if(expander.family==AF_INET6 && refineLow>128) { + sx_report(SX_FATAL, "Invalid value for refineLow(-r): %u (1-128 for" + " IPv6)\n", refineLow); } else if(expander.family==AF_INET && refine>32) { - sx_report(SX_FATAL, "Invalid value for refinement: %u (1-32 for" + sx_report(SX_FATAL, "Invalid value for refine(-R): %u (1-32 for" " IPv4)\n", refine); + } else if(expander.family==AF_INET && refineLow>32) { + sx_report(SX_FATAL, "Invalid value for refineLow(-r): %u (1-32 for" + " IPv4)\n", refineLow); }; + if(expander.vendor==V_JUNIPER && expander.generation==T_PREFIXLIST) { - sx_report(SX_FATAL, "Sorry, more-specific filter (-R %u) " - "is not supported for Juniper prefix-lists\n", refine); + if(refine) { + sx_report(SX_FATAL, "Sorry, more-specific filters (-R %u) " + "is not supported for Juniper prefix-lists.\n" + "Use router-filters (-E) instead\n", refine); + } else { + sx_report(SX_FATAL, "Sorry, more-specific filters (-r %u) " + "is not supported for Juniper prefix-lists.\n" + "Use route-filters (-E) instead\n", refineLow); + }; }; if(expander.generationhead) return sx_radix_node_refine(tree->head, refine); return 0; }; + +static void +setGlueFrom(struct sx_radix_node* node, void* udata) +{ + unsigned refine=*(unsigned*)udata; + if(node && node->prefix.masklen <= refine) { + node->isGlue=1; + }; +}; + +static int +sx_radix_node_refineLow(struct sx_radix_node* node, unsigned refineLow) +{ + if(!node->isGlue && node->prefix.masklen<=refineLow) { + if(!node->isAggregate) { + node->isAggregate=1; + node->aggregateLow=refineLow; + if(node->prefix.family == AF_INET) { + node->aggregateHi=32; + } else { + node->aggregateHi=128; + } + } else { + node->aggregateLow=refineLow; + }; + if(node->l) { + sx_radix_node_foreach(node->l, setGlueFrom, &refineLow); + sx_radix_node_refineLow(node->l, refineLow); + }; + if(node->r) { + sx_radix_node_foreach(node->r, setGlueFrom, &refineLow); + sx_radix_node_refineLow(node->r, refineLow); + }; + } else if(!node->isGlue && node->prefix.masklen==refineLow) { + /* not setting aggregate in this case */ + if(node->l) sx_radix_node_refineLow(node->l, refineLow); + if(node->r) sx_radix_node_refineLow(node->r, refineLow); + } else if(node->isGlue) { + if(node->r) sx_radix_node_refineLow(node->r, refineLow); + if(node->l) sx_radix_node_refineLow(node->l, refineLow); + } else { + /* node->prefix.masklen > refine */ + /* do nothing, should pass specifics 'as is'. Also, do not + process any embedded routes, their masklen is bigger, too... + node->isGlue=1; + if(node->l) sx_radix_node_foreach(node->l, setGlue, NULL); + if(node->r) sx_radix_node_foreach(node->r, setGlue, NULL); + */ + }; + return 0; +}; +int +sx_radix_tree_refineLow(struct sx_radix_tree* tree, unsigned refineLow) +{ + if(tree && tree->head) + return sx_radix_node_refineLow(tree->head, refineLow); + return 0; +}; + #if SX_PTREE_TEST int diff --git a/sx_prefix.h b/sx_prefix.h index cc306fd..36bc909 100644 --- a/sx_prefix.h +++ b/sx_prefix.h @@ -59,6 +59,7 @@ int sx_radix_tree_foreach(struct sx_radix_tree* tree, void (*func)(struct sx_radix_node*, void*), void* udata); int sx_radix_tree_aggregate(struct sx_radix_tree* tree); int sx_radix_tree_refine(struct sx_radix_tree* tree, unsigned refine); +int sx_radix_tree_refineLow(struct sx_radix_tree* tree, unsigned refineLow); #endif