diff --git a/CHANGES b/CHANGES index 5d88c61..61fa5b1 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,11 @@ +0.1.16 (2012-01-19) + - new option -m : maximum length of accepted prefixes. + Suggested by Eugene Demidov, used to discard 'too long prefixes' + (like /30-/32) even if they are registered in IRR. By default + limit is not set and all prefixes accepted. + - documentation redesigned into text/markdown and text/html (manpage + supported still). + 0.1.15 (2011-07-15) - prefix-set's for Cisco IOS XR now supported too. diff --git a/COPYRIGHT b/COPYRIGHT index b798590..9789901 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2007-2011 Alexandre Snarskii + * Copyright (c) 2007-2012 Alexandre Snarskii * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/Makefile.in b/Makefile.in index 8ecab4f..9250225 100644 --- a/Makefile.in +++ b/Makefile.in @@ -16,7 +16,6 @@ OBJECTS=bgpq3.o sx_report.o bgpq_expander.o sx_slentry.o bgpq3_printer.o \ SRCS=bgpq3.c sx_report.c bgpq_expander.c sx_slentry.c bgpq3_printer.c \ sx_prefix.c strlcpy.c sx_maxsockbuf.c - all: bgpq3 bgpq3: ${OBJECTS} @@ -34,4 +33,7 @@ install: bgpq3 ${INSTALL} -m 644 bgpq3.8 @prefix@/man/man8 depend: - makedepend -- $(CFLAGS) -- $(SRCS) + makedepend -- $(CFLAGS) -- $(SRCS) + +bgpq3.html: bgpq3.txt + markdown2 bgpq3.txt > bgpq3.html diff --git a/bgpq3.8 b/bgpq3.8 index eff0190..ea325a5 100644 --- a/bgpq3.8 +++ b/bgpq3.8 @@ -21,7 +21,7 @@ .\" 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.6 2011/07/15 12:16:16 snar Exp $ +.\" "$Id: bgpq3.8,v 1.7 2012/05/18 15:52:06 snar Exp $ .\" .Dd Oct 27, 2008 .Dt BGPQ3 8 @@ -40,6 +40,7 @@ .Oc .Op Fl 36ADd .Op Fl R Ar len +.Op Fl m Ar max .Ar OBJECTS .Op "..." .Sh DESCRIPTION @@ -72,6 +73,9 @@ generate output as-path access-list. host running IRRD database (default: whois.radb.net) .It Fl J generate config for Juniper (Cisco by default). +.It Fl m Ar len +maximum prefix-length of accepted prefixes (default: 32 for IPv4 and +128 for IPv6) .It Fl M Ar match extra match conditions for Juniper route-filters. .It Fl l Ar name @@ -177,10 +181,7 @@ ipv6 prefix-list as-retn-6 permit 2001:7fb:fe01::/48 [....] .RE .fi -and initial support for ASN 32 is also here (for a limited subset -of router's OS'es: if you run JunOS it MUST be 9.1 or higher, -Cisco IOS has even more restrictive list of IOS'es - ASN32 supported -only on GSR/PRP and only in IOS 12.0(32)S12): +and support for ASN 32 is also here .nf .RS ~>bgpq3 -J3f 112 AS-SPACENET @@ -223,8 +224,7 @@ non-zero status. .Sh SEE ALSO .Sy http://www.radb.net/ Routing Arbiter project -.Sy http://www.ietf.org/internet-drafts/ -.Sy draft-michaelson-4byte-as-representation-05.txt +.Sy http://tools.ietf.org/html/draft-michaelson-4byte-as-representation-05 for information on 'asdot' and 'asplain' notations. .Sy http://www.cisco.com/en/US/docs/ios/12_0s/release/ntes/120SNEWF.html#wp3521658 for information on Cisco implementation of ASN32. diff --git a/bgpq3.c b/bgpq3.c index 91d4562..28828e7 100644 --- a/bgpq3.c +++ b/bgpq3.c @@ -39,6 +39,8 @@ usage(int ecode) "default)\n"); printf(" -J : generate config for JunOS (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"); printf(" -l name : use specified name for generated access/prefix/.." " list\n"); printf(" -P : generate prefix-list (default, just for backward" @@ -111,11 +113,12 @@ main(int argc, char* argv[]) struct bgpq_expander expander; int af=AF_INET; int widthSet=0, aggregate=0, refine=0; + unsigned long maxlen=0; bgpq_expander_init(&expander,af); expander.sources=getenv("IRRD_SOURCES"); - while((c=getopt(argc,argv,"36AdDES:Jf:l:M:W:PR:G:Th:X"))!=EOF) { + while((c=getopt(argc,argv,"36AdDES:Jf:l:m:M:W:PR:G:Th:X"))!=EOF) { switch(c) { case '3': expander.asn32=1; @@ -163,6 +166,12 @@ main(int argc, char* argv[]) break; case 'l': expander.name=optarg; break; + case 'm': maxlen=strtoul(optarg, NULL, 10); + if (!maxlen) { + sx_report(SX_FATAL, "Invalid maxlen (-m): %s\n", optarg); + exit(1); + }; + break; case 'M': { char* c, *d; expander.match=strdup(optarg); @@ -282,6 +291,19 @@ main(int argc, char* argv[]) "supported only with prefix-list generation\n", refine); }; }; + if(maxlen) { + if((expander.family==AF_INET6 && maxlen>128) || + (expander.family==AF_INET && maxlen>32)) { + sx_report(SX_FATAL, "Invalid value for max-prefixlen: %lu (1-128 " + "for IPv6, 1-32 for IPv4)\n", maxlen); + exit(1); + } else if((expander.family==AF_INET6 && maxlen<128) || + (expander.family==AF_INET && maxlen<32)) { + /* inet6/128 and inet4/32 does not make sense - all routes will + * be accepted, so save some CPU cycles :) */ + expander.maxlen = maxlen; + }; + }; if(expander.generation==T_EACL && expander.vendor==V_CISCO && expander.family==AF_INET6) { diff --git a/bgpq3.h b/bgpq3.h index 7453dd2..12304cb 100644 --- a/bgpq3.h +++ b/bgpq3.h @@ -43,6 +43,7 @@ struct bgpq_expander { int piped; char* match; char* server; + unsigned maxlen; }; diff --git a/bgpq3.html b/bgpq3.html new file mode 100644 index 0000000..9fbe1fb --- /dev/null +++ b/bgpq3.html @@ -0,0 +1,273 @@ +

+

+ +

NAME

+ +

bgpq3 - bgp filtering automation for Cisco and Juniper routers

+ +

SYNOPSIS

+ +
bgpq3 [-h host] [-S sources] [-EP] [-f asn | -G asn] [-36ADd] [-R len] [-m max] OBJECTS [...]
+
+ +

DESCRIPTION

+ +

The bgpq3 utility used to generate Cisco and Juniper prefix-lists, +extended access-lists, policy-statement terms and as-path lists based on +RADB data.

+ +

The options are as follows:

+ +
    +
  • -3

    + +
    +

    assume that your device is asn32-capable.

    +
  • +
  • -6

    + +
    +

    generate IPv6 prefix/access-lists (IPv4 by default).

    +
  • +
  • -A

    + +
    +

    try to aggregate generated filters as much as possible (Cisco + prefix-lists and Juniper route-filters only supported).

    +
  • +
  • -d

    + +
    +

    enable some debugging output.

    +
  • +
  • -D

    + +
    +

    use asdot notation for Cisco as-path access-lists.

    +
  • +
  • -E

    + +
    +

    generate extended access-list (Cisco) or policy-statement term using + route-filters (Juniper).

    +
  • +
  • -f number

    + +
    +

    generate input as-path access-list.

    +
  • +
  • -G number

    + +
    +

    generate output as-path access-list.

    +
  • +
  • -h host

    + +
    +

    host running IRRD database (default: whois.radb.net)

    +
  • +
  • -J

    + +
    +

    generate config for Juniper (Cisco by default).

    +
  • +
  • -m len

    + +
    +

    maximum length of accepted prefixes

    +
  • +
  • -M match

    + +
    +

    extra match conditions for Juniper route-filters.

    +
  • +
  • -l name

    + +
    +

    name of generated entry.

    +
  • +
  • -P

    + +
    +

    generate prefix-list (default behaviour, flag added for backward + compatibility only).

    +
  • +
  • -R len

    + +
    +

    allow more-specific routes up to specified masklen too. + (Please, note: objects with prefix-length greater than specified length + will be always allowed.)

    +
  • +
  • -S sources

    + +
    +

    use specified sources only (default: RADB,RIPE,APNIC).

    +
  • +
  • -T

    + +
    +

    disable pipelining.

    +
  • +
  • -X

    + +
    +

    generate config for Cisco IOS XR devices (plain IOS by default).

    +
  • +
+ +

OBJECTS means networks (in prefix format), autonomous systems and as-macros.

+ +

EXAMPLES

+ +

Generating named Juniper prefix-filter for AS20597:

+ +
 user@host:~>bgpq3 -Jl eltel AS20597
+ policy-options {
+ replace:
+  prefix-list eltel {
+     81.9.0.0/20;
+     81.9.32.0/20;
+     81.9.96.0/20;
+     81.222.128.0/20;
+     81.222.192.0/18;
+     85.249.8.0/21;
+     85.249.224.0/19;
+     89.112.0.0/19;
+     89.112.4.0/22;
+     89.112.32.0/19;
+     89.112.64.0/19;
+     217.170.64.0/20;
+     217.170.80.0/20;
+  }
+ }
+
+ +

For Cisco we can use aggregation (-A) flag to make this prefix-filter +more compact:

+ +
 user@host:~>bgpq3 -Al eltel AS20597
+ no ip prefix-list eltel
+ ip prefix-list eltel permit 81.9.0.0/20
+ ip prefix-list eltel permit 81.9.32.0/20
+ ip prefix-list eltel permit 81.9.96.0/20
+ ip prefix-list eltel permit 81.222.128.0/20
+ ip prefix-list eltel permit 81.222.192.0/18
+ ip prefix-list eltel permit 85.249.8.0/21
+ ip prefix-list eltel permit 85.249.224.0/19
+ ip prefix-list eltel permit 89.112.0.0/18 ge 19 le 19
+ ip prefix-list eltel permit 89.112.4.0/22
+ ip prefix-list eltel permit 89.112.64.0/19
+ ip prefix-list eltel permit 217.170.64.0/19 ge 20 le 20
+
+ +

and, as you see, prefixes 89.112.32.0/19 and 89.112.64.0/19 now aggregated +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 <extra match conditions>, -R <len> 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;
+    }
+   }
+  }
+ }
+
+ +

generated policy-option term now allows all more-specific routes +for eltel networks if they marked with community 'blackhole' (defined +elsewhere in configuration).

+ +

Of course, bgpq3 supports IPv6 (-6):

+ +
 user@host:~>bgpq3 -6l as-retn-6 AS-RETN6
+ no ipv6 prefix-list as-retn-6
+ ipv6 prefix-list as-retn-6 permit 2001:7fb:fe00::/48
+ ipv6 prefix-list as-retn-6 permit 2001:7fb:fe01::/48
+ [....]
+
+ +

and ASN32

+ +
 user@host:~>bgpq3 -J3f 112 AS-SPACENET
+ policy-options {
+ replace:
+  as-path-group NN {
+   as-path a0 "^112(112)*$";
+   as-path a1 "^112(.)*(1898|5539|8495|8763|8878|12136|12931|15909)$";
+   as-path a2 "^112(.)*(21358|23456|23600|24151|25152|31529|34127|34906)$";
+   as-path a3 "^112(.)*(35052|41720|43628|44450|196611)$";
+  }
+ }
+
+ +

see AS196611 in the end of the list ? That's AS3.3 in 'asplain' notation.

+ +

If your router does not support ASN32 (yet) you should not use switch -3, +and the result will be next:

+ +
 user@host:~>bgpq3 -f 112 AS-SPACENET
+ no ip as-path access-list NN
+ ip as-path access-list NN permit ^112( 112)*$
+ ip as-path access-list NN permit ^112( [0-9]+)* (1898|5539|8495|8763)$
+ ip as-path access-list NN permit ^112( [0-9]+)* (8878|12136|12931|15909)$
+ ip as-path access-list NN permit ^112( [0-9]+)* (21358|23456|23600|24151)$
+ ip as-path access-list NN permit ^112( [0-9]+)* (25152|31529|34127|34906)$
+ ip as-path access-list NN permit ^112( [0-9]+)* (35052|41720|43628|44450)$
+
+ +

AS196611 is no more in the list, however, AS23456 (transition AS) would +have been added to list if it were not present.

+ +

DIAGNOSTICS

+ +

When everything is OK, bgpq3 generates result to standard output and +exits with status == 0. In case of errors they are printed to stderr and +program exits with non-zero status.

+ +

SEE ALSO

+ +
    +
  1. Routing Arbiter
  2. +
  3. draft-michaelson-4byte-as-representation-05.txt + for information on 'asdot' and 'asplain' notations.
  4. +
  5. Cisco documentation + for information on Cisco implementation of ASN32.
  6. +
+ +

AUTHOR

+ +

Alexandre Snarskii snar@snar.spb.ru

+ +

Program Homepage

+ +

http://snar.spb.ru/prog/bgpq3/

diff --git a/bgpq3.txt b/bgpq3.txt new file mode 100644 index 0000000..baac6b1 --- /dev/null +++ b/bgpq3.txt @@ -0,0 +1,251 @@ + + + +NAME +---- + +`bgpq3` - bgp filtering automation for Cisco and Juniper routers + +SYNOPSIS +-------- + + bgpq3 [-h host] [-S sources] [-EP] [-f asn | -G asn] [-36ADd] [-R len] [-m max] OBJECTS [...] + +DESCRIPTION +----------- + +The bgpq3 utility used to generate Cisco and Juniper prefix-lists, +extended access-lists, policy-statement terms and as-path lists based on +RADB data. + +The options are as follows: + +- -3 + + > assume that your device is asn32-capable. + +- -6 + + > generate IPv6 prefix/access-lists (IPv4 by default). + +- -A + + > try to aggregate generated filters as much as possible (Cisco + prefix-lists and Juniper route-filters only supported). + +- -d + + > enable some debugging output. + +- -D + + > use asdot notation for Cisco as-path access-lists. + +- -E + + > generate extended access-list (Cisco) or policy-statement term using + route-filters (Juniper). + +- -f number + + > generate input as-path access-list. + +- -G number + + > generate output as-path access-list. + +- -h host + + > host running IRRD database (default: whois.radb.net) + +- -J + + > generate config for Juniper (Cisco by default). + +- -m len + + > maximum length of accepted prefixes + +- -M match + + > extra match conditions for Juniper route-filters. + +- -l name + + > name of generated entry. + +- -P + + > generate prefix-list (default behaviour, flag added for backward + compatibility only). + +- -R len + + > allow more-specific routes up to specified masklen too. + (Please, note: objects with prefix-length greater than specified length + will be always allowed.) + +- -S sources + + > use specified sources only (default: RADB,RIPE,APNIC). + +- -T + + > disable pipelining. + +- -X + + > generate config for Cisco IOS XR devices (plain IOS by default). + +`OBJECTS` means networks (in prefix format), autonomous systems and as-macros. + +EXAMPLES +-------- + +Generating named Juniper prefix-filter for `AS20597`: + + user@host:~>bgpq3 -Jl eltel AS20597 + policy-options { + replace: + prefix-list eltel { + 81.9.0.0/20; + 81.9.32.0/20; + 81.9.96.0/20; + 81.222.128.0/20; + 81.222.192.0/18; + 85.249.8.0/21; + 85.249.224.0/19; + 89.112.0.0/19; + 89.112.4.0/22; + 89.112.32.0/19; + 89.112.64.0/19; + 217.170.64.0/20; + 217.170.80.0/20; + } + } + +For Cisco we can use aggregation (-A) flag to make this prefix-filter +more compact: + + user@host:~>bgpq3 -Al eltel AS20597 + no ip prefix-list eltel + ip prefix-list eltel permit 81.9.0.0/20 + ip prefix-list eltel permit 81.9.32.0/20 + ip prefix-list eltel permit 81.9.96.0/20 + ip prefix-list eltel permit 81.222.128.0/20 + ip prefix-list eltel permit 81.222.192.0/18 + ip prefix-list eltel permit 85.249.8.0/21 + ip prefix-list eltel permit 85.249.224.0/19 + ip prefix-list eltel permit 89.112.0.0/18 ge 19 le 19 + ip prefix-list eltel permit 89.112.4.0/22 + ip prefix-list eltel permit 89.112.64.0/19 + ip prefix-list eltel permit 217.170.64.0/19 ge 20 le 20 + +and, as you see, prefixes `89.112.32.0/19` and `89.112.64.0/19` now aggregated +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: + + 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; + } + } + } + } + +generated policy-option term now allows all more-specific routes +for eltel networks if they marked with community 'blackhole' (defined +elsewhere in configuration). + +Of course, `bgpq3` supports IPv6 (-6): + + user@host:~>bgpq3 -6l as-retn-6 AS-RETN6 + no ipv6 prefix-list as-retn-6 + ipv6 prefix-list as-retn-6 permit 2001:7fb:fe00::/48 + ipv6 prefix-list as-retn-6 permit 2001:7fb:fe01::/48 + [....] + +and ASN32 + + user@host:~>bgpq3 -J3f 112 AS-SPACENET + policy-options { + replace: + as-path-group NN { + as-path a0 "^112(112)*$"; + as-path a1 "^112(.)*(1898|5539|8495|8763|8878|12136|12931|15909)$"; + as-path a2 "^112(.)*(21358|23456|23600|24151|25152|31529|34127|34906)$"; + as-path a3 "^112(.)*(35052|41720|43628|44450|196611)$"; + } + } + +see `AS196611` in the end of the list ? That's `AS3.3` in 'asplain' notation. + +If your router does not support ASN32 (yet) you should not use switch -3, +and the result will be next: + + user@host:~>bgpq3 -f 112 AS-SPACENET + no ip as-path access-list NN + ip as-path access-list NN permit ^112( 112)*$ + ip as-path access-list NN permit ^112( [0-9]+)* (1898|5539|8495|8763)$ + ip as-path access-list NN permit ^112( [0-9]+)* (8878|12136|12931|15909)$ + ip as-path access-list NN permit ^112( [0-9]+)* (21358|23456|23600|24151)$ + ip as-path access-list NN permit ^112( [0-9]+)* (25152|31529|34127|34906)$ + ip as-path access-list NN permit ^112( [0-9]+)* (35052|41720|43628|44450)$ + +`AS196611` is no more in the list, however, `AS23456` (transition AS) would +have been added to list if it were not present. + +DIAGNOSTICS +----------- + +When everything is OK, `bgpq3` generates result to standard output and +exits with status == 0. In case of errors they are printed to stderr and +program exits with non-zero status. + +SEE ALSO +-------- + +1. [Routing Arbiter](http://www.radb.net/) +2. [draft-michaelson-4byte-as-representation-05.txt](http://www.ietf.org/internet-drafts/draft-michaelson-4byte-as-representation-05.txt) + for information on 'asdot' and 'asplain' notations. +3. [Cisco documentation](http://www.cisco.com/en/US/prod/collateral/iosswrel/ps6537/ps6554/ps6599/data_sheet_C78-521821.html) + for information on Cisco implementation of ASN32. + +AUTHOR +------ + +Alexandre Snarskii [snar@snar.spb.ru](mailto:snar@snar.spb.ru) + +Program Homepage +---------------- + +[http://snar.spb.ru/prog/bgpq3/](http://snar.spb.ru/prog/bgpq3/) + diff --git a/bgpq_expander.c b/bgpq_expander.c index 7a9439c..885008f 100644 --- a/bgpq_expander.c +++ b/bgpq_expander.c @@ -161,6 +161,11 @@ bgpq_expander_add_prefix(struct bgpq_expander* b, char* prefix) ,prefix); return 0; }; + if(b->maxlen && p.masklen>b->maxlen) { + SX_DEBUG(debug_expander, "Ignoring prefix %s: masklen %i > max " + "masklen %u\n", prefix, p.masklen, b->maxlen); + return 0; + }; sx_radix_tree_insert(b->tree,&p); return 1; };