From 1cc07774cfc15c5accf668633262a2f4b03d9049 Mon Sep 17 00:00:00 2001 From: Michail Litvak Date: Wed, 1 Mar 2017 10:02:04 +0200 Subject: [PATCH 1/4] Support of Nokia (former Alcatel-Lucent) SR OS --- README.md | 6 +- bgpq3.c | 12 +++- bgpq3.h | 3 +- bgpq3_printer.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 181 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e064ac1..937b069 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ Use asdot notation for Cisco as-path access-lists. #### -E Generate extended access-list (Cisco) or policy-statement term using -route-filters (Juniper). +route-filters (Juniper) or [ip|ipv6]-prefix-list (Nokia) #### -f `AS number` @@ -93,6 +93,10 @@ Maximum length of accepted prefixes (default: `32` for IPv4, `128` for IPv6). Extra match conditions for Juniper route-filters. See the examples section. +#### -N + +Generate config for Nokia SR OS (former Alcatel-Lucent) (default: Cisco) + #### -l `name` `Name` of generated configuration stanza. diff --git a/bgpq3.c b/bgpq3.c index 41d51c6..4653672 100644 --- a/bgpq3.c +++ b/bgpq3.c @@ -55,6 +55,7 @@ usage(int ecode) printf(" -L depth : limit recursion depth (default: unlimited)\n"), printf(" -l name : use specified name for generated access/prefix/.." " list\n"); + printf(" -N : generate config for Nokia SR OS (Cisco IOS by default)\n"); printf(" -P : generate prefix-list (default, just for backward" " compatibility)\n"); printf(" -R len : allow more specific routes up to specified masklen\n"); @@ -83,7 +84,7 @@ void vendor_exclusive() { fprintf(stderr, "-b (BIRD), -B (OpenBGPD), -F (formatted), -J (JunOS), " - "-j (JSON) and -X (IOS XR) options are mutually exclusive\n"); + "-j (JSON), -N (NOKIA SR OS) and -X (IOS XR) options are mutually exclusive\n"); exit(1); }; @@ -135,7 +136,7 @@ main(int argc, char* argv[]) if (getenv("IRRD_SOURCES")) expander.sources=getenv("IRRD_SOURCES"); - while((c=getopt(argc,argv,"2346AbBdDEF:S:jJf:l:L:m:M:W:Ppr:R:G:Th:Xs")) + while((c=getopt(argc,argv,"2346AbBdDEF:S:jJf:l:L:m:M:NW:Ppr:R:G:Th:Xs")) !=EOF) { switch(c) { case '2': @@ -284,6 +285,9 @@ main(int argc, char* argv[]) *d=0; }; break; + case 'N': if(expander.vendor) vendor_exclusive(); + expander.vendor=V_NOKIA; + break; case 'T': pipelining=0; break; case 's': expander.sequence=1; @@ -317,6 +321,8 @@ main(int argc, char* argv[]) expander.aswidth=8; } else if(expander.vendor==V_BIRD) { expander.aswidth=10; + } else if(expander.vendor==V_NOKIA) { + expander.aswidth=8; }; } else if(expander.generation==T_OASPATH) { if(expander.vendor==V_CISCO) { @@ -325,6 +331,8 @@ main(int argc, char* argv[]) expander.aswidth=7; } else if(expander.vendor==V_JUNIPER) { expander.aswidth=8; + } else if(expander.vendor==V_NOKIA) { + expander.aswidth=8; }; }; }; diff --git a/bgpq3.h b/bgpq3.h index 9cf143b..1104acd 100644 --- a/bgpq3.h +++ b/bgpq3.h @@ -17,7 +17,8 @@ typedef enum { V_JSON, V_BIRD, V_OPENBGPD, - V_FORMAT + V_FORMAT, + V_NOKIA } bgpq_vendor_t; typedef enum { diff --git a/bgpq3_printer.c b/bgpq3_printer.c index 9307a0d..3e89a74 100644 --- a/bgpq3_printer.c +++ b/bgpq3_printer.c @@ -323,6 +323,97 @@ bgpq3_print_openbgpd_oaspath(FILE* f, struct bgpq_expander* b) return 0; }; +int +bgpq3_print_nokia_aspath(FILE* f, struct bgpq_expander* b) +{ + int nc=0, lineNo=1, i, j, k; + + fprintf(f,"configure router policy-options\nbegin\nno as-path-group \"%s\"\n", + b->name ? b->name : "NN"); + fprintf(f,"as-path-group \"%s\"\n", b->name ? b->name : "NN"); + + if(b->asn32s[b->asnumber/65536] && + b->asn32s[b->asnumber/65535][(b->asnumber%65536)/8]& + (0x80>>(b->asnumber%8))) { + fprintf(f," entry %u expression \"^%u(%u)*$\"\n", lineNo, b->asnumber, + b->asnumber); + lineNo++; + }; + for(k=0;k<65536;k++) { + if(!b->asn32s[k]) continue; + for(i=0;i<8192;i++) { + for(j=0;j<8;j++) { + if(b->asn32s[k][i]&(0x80>>j)) { + if(k*65536+i*8+j==b->asnumber) continue; + if(!nc) { + fprintf(f," entry %u expression \"^%u(.)*(%u", + lineNo,b->asnumber,k*65536+i*8+j); + } else { + fprintf(f,"|%u",k*65536+i*8+j); + }; + nc++; + if(nc==b->aswidth) { + fprintf(f,")$\"\n"); + nc=0; + lineNo++; + }; + }; + }; + }; + }; + if(nc) fprintf(f,")$\"\n"); + else if(lineNo==1) + fprintf(f," entry 1 \"!.*\"\n"); + fprintf(f,"exit\ncommit\n"); + return 0; +}; + +int +bgpq3_print_nokia_oaspath(FILE* f, struct bgpq_expander* b) +{ + int nc=0, lineNo=1, i, j, k; + + fprintf(f,"configure router policy-options\nbegin\nno as-path-group \"%s\"\n", + b->name ? b->name : "NN"); + fprintf(f,"as-path-group \"%s\"\n", b->name ? b->name : "NN"); + + if(b->asn32s[b->asnumber/65536] && + b->asn32s[b->asnumber/65536][(b->asnumber%65536)/8]& + (0x80>>(b->asnumber%8))) { + fprintf(f," entry %u expression \"^%u(%u)*$\"\n", lineNo, b->asnumber, + b->asnumber); + lineNo++; + }; + for(k=0;k<65536;k++) { + if(!b->asn32s[k]) continue; + + for(i=0;i<8192;i++) { + for(j=0;j<8;j++) { + if(b->asn32s[k][i]&(0x80>>j)) { + if(k*65536+i*8+j==b->asnumber) continue; + if(!nc) { + fprintf(f," entry %u expression \"^(.)*(%u", + lineNo,k*65536+i*8+j); + } else { + fprintf(f,"|%u",k*65536+i*8+j); + } + nc++; + if(nc==b->aswidth) { + fprintf(f,")$\"\n"); + nc=0; + lineNo++; + }; + }; + }; + }; + }; + if(nc) fprintf(f,")$\"\n"); + else if(lineNo==1) + fprintf(f," entry 1 expression \"!.*\"\n"); + fprintf(f,"exit\ncommit\n"); + return 0; +}; + int bgpq3_print_aspath(FILE* f, struct bgpq_expander* b) { @@ -338,6 +429,8 @@ bgpq3_print_aspath(FILE* f, struct bgpq_expander* b) return bgpq3_print_bird_aspath(f,b); } else if(b->vendor==V_OPENBGPD) { return bgpq3_print_openbgpd_aspath(f,b); + } else if(b->vendor==V_NOKIA) { + return bgpq3_print_nokia_aspath(f,b); } else { sx_report(SX_FATAL,"Unknown vendor %i\n", b->vendor); }; @@ -355,6 +448,8 @@ bgpq3_print_oaspath(FILE* f, struct bgpq_expander* b) return bgpq3_print_cisco_xr_oaspath(f,b); } else if(b->vendor==V_OPENBGPD) { return bgpq3_print_openbgpd_oaspath(f,b); + } else if(b->vendor==V_NOKIA) { + return bgpq3_print_nokia_oaspath(f,b); } else { sx_report(SX_FATAL,"Unknown vendor %i\n", b->vendor); }; @@ -689,6 +784,45 @@ checkSon: bgpq3_print_ceacl(n->son,ff); }; +void +bgpq3_print_nokia_ipfilter(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)); + fprintf(f," prefix %s\n", prefix); +checkSon: + if(n->son) + bgpq3_print_nokia_ipfilter(n->son, ff); +}; + +void +bgpq3_print_nokia_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," prefix %s exact\n", prefix); + } else { + if(n->aggregateLow>n->prefix.masklen) { + fprintf(f," prefix %s prefix-length-range %u-%u\n", + prefix,n->aggregateLow,n->aggregateHi); + } else { + fprintf(f," prefix %s prefix-length-range %u-%u\n", + prefix, n->prefix.masklen, n->aggregateHi); + }; + }; +checkSon: + if(n->son) + bgpq3_print_nokia_prefix(n->son, ff); + +}; + int bgpq3_print_juniper_prefixlist(FILE* f, struct bgpq_expander* b) { @@ -840,6 +974,18 @@ bgpq3_print_format_prefixlist(FILE* f, struct bgpq_expander* b) return 0; }; +int +bgpq3_print_nokia_prefixlist(FILE* f, struct bgpq_expander* b) +{ + bname=b->name ? b->name : "NN"; + fprintf(f,"configure router policy-options\nbegin\nno prefix-list \"%s\"\n", + bname); + fprintf(f,"prefix-list \"%s\"\n", bname); + sx_radix_tree_foreach(b->tree,bgpq3_print_nokia_prefix,f); + fprintf(f,"exit\ncommit\n"); + return 0; +}; + int bgpq3_print_cisco_eacl(FILE* f, struct bgpq_expander* b) { @@ -855,6 +1001,22 @@ bgpq3_print_cisco_eacl(FILE* f, struct bgpq_expander* b) return 0; }; +int +bgpq3_print_nokia_ipprefixlist(FILE* f, struct bgpq_expander* b) +{ + bname=b->name ? b->name : "NN"; + fprintf(f,"configure filter match-list\nno %s-prefix-list \"%s\"\n", + b->tree->family==AF_INET?"ip":"ipv6", bname); + fprintf(f,"%s-prefix-list \"%s\" create\n", b->tree->family==AF_INET?"ip":"ipv6", bname); + if (!sx_radix_tree_empty(b->tree)) { + sx_radix_tree_foreach(b->tree,bgpq3_print_nokia_ipfilter,f); + } else { + fprintf(f,"# generated ip-prefix-list %s is empty\n", bname); + }; + fprintf(f,"exit\n"); + return 0; +}; + int bgpq3_print_prefixlist(FILE* f, struct bgpq_expander* b) { @@ -866,6 +1028,7 @@ bgpq3_print_prefixlist(FILE* f, struct bgpq_expander* b) case V_BIRD: return bgpq3_print_bird_prefixlist(f,b); case V_OPENBGPD: return bgpq3_print_openbgpd_prefixlist(f,b); case V_FORMAT: return bgpq3_print_format_prefixlist(f,b); + case V_NOKIA: return bgpq3_print_nokia_prefixlist(f,b); }; return 0; }; @@ -881,6 +1044,7 @@ bgpq3_print_eacl(FILE* f, struct bgpq_expander* b) case V_BIRD: sx_report(SX_FATAL, "unreachable point\n"); case V_OPENBGPD: return bgpq3_print_openbgpd_prefixlist(f,b); case V_FORMAT: sx_report(SX_FATAL, "unreachable point\n"); + case V_NOKIA: return bgpq3_print_nokia_ipprefixlist(f,b); }; return 0; }; From 7aed731cbaeb9a7c0ae929a58ce22e468116ed78 Mon Sep 17 00:00:00 2001 From: Michail Litvak Date: Wed, 1 Mar 2017 19:54:52 +0200 Subject: [PATCH 2/4] Nokia AS path filter generation improvements --- bgpq3_printer.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/bgpq3_printer.c b/bgpq3_printer.c index 3e89a74..8e0e988 100644 --- a/bgpq3_printer.c +++ b/bgpq3_printer.c @@ -335,8 +335,7 @@ bgpq3_print_nokia_aspath(FILE* f, struct bgpq_expander* b) if(b->asn32s[b->asnumber/65536] && b->asn32s[b->asnumber/65535][(b->asnumber%65536)/8]& (0x80>>(b->asnumber%8))) { - fprintf(f," entry %u expression \"^%u(%u)*$\"\n", lineNo, b->asnumber, - b->asnumber); + fprintf(f," entry %u expression \"%u+\"\n", lineNo, b->asnumber); lineNo++; }; for(k=0;k<65536;k++) { @@ -346,14 +345,14 @@ bgpq3_print_nokia_aspath(FILE* f, struct bgpq_expander* b) if(b->asn32s[k][i]&(0x80>>j)) { if(k*65536+i*8+j==b->asnumber) continue; if(!nc) { - fprintf(f," entry %u expression \"^%u(.)*(%u", + fprintf(f," entry %u expression \"%u.*[%u", lineNo,b->asnumber,k*65536+i*8+j); } else { - fprintf(f,"|%u",k*65536+i*8+j); + fprintf(f," %u",k*65536+i*8+j); }; nc++; if(nc==b->aswidth) { - fprintf(f,")$\"\n"); + fprintf(f,"]\"\n"); nc=0; lineNo++; }; @@ -361,9 +360,9 @@ bgpq3_print_nokia_aspath(FILE* f, struct bgpq_expander* b) }; }; }; - if(nc) fprintf(f,")$\"\n"); + if(nc) fprintf(f,"]\"\n"); else if(lineNo==1) - fprintf(f," entry 1 \"!.*\"\n"); + fprintf(f," entry 1 \"\"\n"); fprintf(f,"exit\ncommit\n"); return 0; }; @@ -380,8 +379,7 @@ bgpq3_print_nokia_oaspath(FILE* f, struct bgpq_expander* b) if(b->asn32s[b->asnumber/65536] && b->asn32s[b->asnumber/65536][(b->asnumber%65536)/8]& (0x80>>(b->asnumber%8))) { - fprintf(f," entry %u expression \"^%u(%u)*$\"\n", lineNo, b->asnumber, - b->asnumber); + fprintf(f," entry %u expression \"%u+\"\n", lineNo, b->asnumber); lineNo++; }; for(k=0;k<65536;k++) { @@ -392,14 +390,14 @@ bgpq3_print_nokia_oaspath(FILE* f, struct bgpq_expander* b) if(b->asn32s[k][i]&(0x80>>j)) { if(k*65536+i*8+j==b->asnumber) continue; if(!nc) { - fprintf(f," entry %u expression \"^(.)*(%u", + fprintf(f," entry %u expression \".*[%u", lineNo,k*65536+i*8+j); } else { - fprintf(f,"|%u",k*65536+i*8+j); + fprintf(f," %u",k*65536+i*8+j); } nc++; if(nc==b->aswidth) { - fprintf(f,")$\"\n"); + fprintf(f,"]\"\n"); nc=0; lineNo++; }; @@ -407,9 +405,9 @@ bgpq3_print_nokia_oaspath(FILE* f, struct bgpq_expander* b) }; }; }; - if(nc) fprintf(f,")$\"\n"); + if(nc) fprintf(f,"]\"\n"); else if(lineNo==1) - fprintf(f," entry 1 expression \"!.*\"\n"); + fprintf(f," entry 1 expression \"\"\n"); fprintf(f,"exit\ncommit\n"); return 0; }; From 4082f23bf088a42b2b5d0f6d8f79dad353b4d411 Mon Sep 17 00:00:00 2001 From: Michail Litvak Date: Wed, 1 Mar 2017 22:24:14 +0200 Subject: [PATCH 3/4] Nokia as-path filter: no explicit deny regexp possible --- bgpq3_printer.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/bgpq3_printer.c b/bgpq3_printer.c index 8e0e988..806a7f2 100644 --- a/bgpq3_printer.c +++ b/bgpq3_printer.c @@ -361,8 +361,6 @@ bgpq3_print_nokia_aspath(FILE* f, struct bgpq_expander* b) }; }; if(nc) fprintf(f,"]\"\n"); - else if(lineNo==1) - fprintf(f," entry 1 \"\"\n"); fprintf(f,"exit\ncommit\n"); return 0; }; @@ -406,8 +404,6 @@ bgpq3_print_nokia_oaspath(FILE* f, struct bgpq_expander* b) }; }; if(nc) fprintf(f,"]\"\n"); - else if(lineNo==1) - fprintf(f," entry 1 expression \"\"\n"); fprintf(f,"exit\ncommit\n"); return 0; }; From 765996f26c729ffdc1ceaac884be0397fb94a97d Mon Sep 17 00:00:00 2001 From: Alexandre Snarskii Date: Sun, 5 Mar 2017 20:30:55 +0300 Subject: [PATCH 4/4] adjust manpage, make -ARr incompatible with Nokia --- bgpq3.8 | 16 +++++++++------- bgpq3.c | 22 ++++++++++++++++++++-- configure | 18 +++++++++--------- configure.in | 2 +- 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/bgpq3.8 b/bgpq3.8 index f7410e0..af30243 100644 --- a/bgpq3.8 +++ b/bgpq3.8 @@ -38,7 +38,7 @@ .Fl F Ar fmt | .Fl G Ar asn .Oc -.Op Fl 2346ABbDdJjsX +.Op Fl 2346ABbDdJjNsX .Op Fl r Ar len .Op Fl R Ar len .Op Fl m Ar max @@ -74,8 +74,8 @@ enable some debugging output. .It Fl D use asdot notation for Cisco as-path access-lists. .It Fl E -generate extended access-list (Cisco) or policy-statement term using -route-filters (Juniper). +generate extended access-list (Cisco), policy-statement term using +route-filters (Juniper) or [ip|ipv6]-prefix-list (Nokia). .It Fl f Ar number generate input as-path access-list. .It Fl F Ar fmt @@ -88,15 +88,17 @@ host running IRRD database (default: whois.radb.net). generate config for Juniper (default: Cisco). .It Fl j generate output in JSON format (default: Cisco). +.It Fl l Ar name +name of generated entry. +.It Fl L Ar limit +limit recursion depth when expanding as-sets. .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 -name of generated entry. -.It Fl L Ar limit -limit recursion depth when expanding as-sets. +.It Fl N +generate config for Nokia SR OS (Cisco IOS by default). .It Fl p accept routes registered for private ASNs (default: disabled) .It Fl P diff --git a/bgpq3.c b/bgpq3.c index 84e10d8..fb3e879 100644 --- a/bgpq3.c +++ b/bgpq3.c @@ -39,8 +39,9 @@ usage(int ecode) 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 (Cisco only)\n"); - printf(" -E : generate extended access-list(Cisco) or " - "route-filter(Juniper)\n"); + printf(" -E : generate extended access-list(Cisco), " + "route-filter(Juniper) or\n" + " [ip|ipv6]-prefix-list (Nokia)\n"); printf(" -f number : generate input as-path access-list\n"); printf(" -F fmt : generate output in user-defined format\n"); printf(" -G number : generate output as-path access-list\n"); @@ -388,6 +389,12 @@ main(int argc, char* argv[]) exit(1); }; + if(aggregate && expander.vendor==V_NOKIA) { + sx_report(SX_FATAL, "Sorry, aggregation (-A) is not supported on " + "Nokia equipment (-N)\n"); + exit(1); + }; + if(aggregate && expander.generation. # @@ -580,8 +580,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='bgpq3' PACKAGE_TARNAME='bgpq3' -PACKAGE_VERSION='0.1.33' -PACKAGE_STRING='bgpq3 0.1.33' +PACKAGE_VERSION='0.1.34' +PACKAGE_STRING='bgpq3 0.1.34' PACKAGE_BUGREPORT='snar@snar.spb.ru' PACKAGE_URL='' @@ -1228,7 +1228,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures bgpq3 0.1.33 to adapt to many kinds of systems. +\`configure' configures bgpq3 0.1.34 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1289,7 +1289,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of bgpq3 0.1.33:";; + short | recursive ) echo "Configuration of bgpq3 0.1.34:";; esac cat <<\_ACEOF @@ -1369,7 +1369,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -bgpq3 configure 0.1.33 +bgpq3 configure 0.1.34 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1738,7 +1738,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by bgpq3 $as_me 0.1.33, which was +It was created by bgpq3 $as_me 0.1.34, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -4102,7 +4102,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by bgpq3 $as_me 0.1.33, which was +This file was extended by bgpq3 $as_me 0.1.34, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -4164,7 +4164,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -bgpq3 config.status 0.1.33 +bgpq3 config.status 0.1.34 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.in b/configure.in index 014722a..50abda6 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,4 @@ -AC_INIT(bgpq3,0.1.33,snar@snar.spb.ru) +AC_INIT(bgpq3,0.1.34,snar@snar.spb.ru) AC_CONFIG_HEADER(config.h) AC_PROG_CC AC_PROG_INSTALL