Huawei support, copyright year update.

This commit is contained in:
Alexandre Snarskii
2018-08-10 15:02:08 +03:00
parent 1acef0240a
commit 2152ecdb43
11 changed files with 205 additions and 36 deletions

View File

@@ -1,7 +1,9 @@
untagged yet (2017-09-08)
untagged yet (2018-08-10)
- initial support for Juniper route-filter-lists (JunOS 16.2+).
- too large (>124bytes) sources list was not handled correctly.
Reported by Pier Carlo Chiodi.
- initial support for Huawei format (prefix-lists and as-path filters)
New flag -U. Requested by Alexander Wagberg.
0.1.35-rc2 (2017-06-14)
- OpenBSD need <sys/select.h>. Reported by Denis Fondras.

View File

@@ -1,5 +1,5 @@
/*-
* Copyright (c) 2007-2017 Alexandre Snarskii <snar@snar.spb.ru>
* Copyright (c) 2007-2018 Alexandre Snarskii <snar@snar.spb.ru>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -7,7 +7,7 @@ SYNOPSIS
--------
```
bgpq3 [-h host[:port]] [-S sources] [-EPz] [-f asn | -F fmt | -G asn] [-2346ABbDdJjpsX] [-a asn] [-r len] [-R len] [-m max] [-W len] OBJECTS [...] EXCEPT OBJECTS
bgpq3 [-h host[:port]] [-S sources] [-EPz] [-f asn | -F fmt | -G asn] [-2346ABbDdJjpsUX] [-a asn] [-r len] [-R len] [-m max] [-W len] OBJECTS [...] EXCEPT OBJECTS
```
DESCRIPTION
@@ -141,6 +141,10 @@ Use specified sources only (recommended: RADB,RIPE,APNIC).
Disable pipelining. (not recommended)
#### -U
Generate output in Huawei format (default: Cisco).
#### -W `length`
Generate as-path strings of a given length maximum (0 for infinity).

View File

@@ -1,4 +1,4 @@
.\" Copyright (c) 2007-2017 Alexandre Snarskii
.\" Copyright (c) 2007-2018 Alexandre Snarskii
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -38,7 +38,7 @@
.Fl F Ar fmt |
.Fl G Ar asn
.Oc
.Op Fl 2346ABbDdJjNsX
.Op Fl 2346ABbDdJjNsXU
.Op Fl a Ar asn
.Op Fl r Ar len
.Op Fl R Ar len
@@ -118,6 +118,8 @@ use specified sources only (recommended: RADB,RIPE,APNIC).
disable pipelining.
.It Fl W Ar len
generate as-path strings of no more than len items (use 0 for inifinity).
.It Fl U
generate config for Huawei devices (Cisco IOS by default)
.It Fl X
generate config for Cisco IOS XR devices (plain IOS by default).
.It Fl z

45
bgpq3.c
View File

@@ -37,13 +37,13 @@ usage(int ecode)
"route-filters\n as much as possible\n");
printf(" -B : generate OpenBGPD output (Cisco IOS by default)\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 (Cisco only)\n");
printf(" -d : generate some debugging output\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(" -f number : generate input as-path access-list\n");
printf(" -G number : generate output as-path access-list\n");
printf(" -h host : host running IRRD software (whois.radb.net by "
"default)\n"
@@ -65,11 +65,12 @@ usage(int ecode)
" RADB,RIPE,APNIC)\n");
printf(" -s : generate sequence numbers in prefix-lists (IOS only)\n");
printf(" -T : disable pipelining (experimental, faster mode)\n");
printf(" -U : generate config for Huawei (Cisco IOS by default)\n");
printf(" -W len : specify max-entries on as-path line (use 0 for "
"infinity)\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 <snar@snar.spb.ru> 2007-2017\n\n");
printf("Copyright(c) Alexandre Snarskii <snar@snar.spb.ru> 2007-2018\n\n");
exit(ecode);
};
@@ -85,7 +86,8 @@ void
vendor_exclusive()
{
fprintf(stderr, "-b (BIRD), -B (OpenBGPD), -F (formatted), -J (JunOS), "
"-j (JSON), -N (NOKIA SR OS) and -X (IOS XR) options are mutually exclusive\n");
"-j (JSON), -N (NOKIA SR OS), -U (Huawei) and -X (IOS XR) options "
"are mutually exclusive\n");
exit(1);
};
@@ -137,7 +139,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:NW:Ppr:R:G:Th:Xsz"))
while((c=getopt(argc,argv,"2346a:AbBdDEF:S:jJf:l:L:m:M:NW:Ppr:R:G:Th:UXsz"))
!=EOF) {
switch(c) {
case '2':
@@ -179,10 +181,10 @@ main(int argc, char* argv[])
expander.vendor=V_OPENBGPD;
expander.asn32=1;
break;
case 'd': debug_expander++;
break;
case 'D': expander.asdot=1;
break;
case 'd': debug_expander++;
break;
case 'E': if(expander.generation) exclusive();
expander.generation=T_EACL;
break;
@@ -190,6 +192,16 @@ main(int argc, char* argv[])
expander.vendor=V_FORMAT;
expander.format=optarg;
break;
case 'f':
if(expander.generation) exclusive();
expander.generation=T_ASPATH;
parseasnumber(&expander,optarg);
break;
case 'G':
if(expander.generation) exclusive();
expander.generation=T_OASPATH;
parseasnumber(&expander,optarg);
break;
case 'h': {
char* d=strchr(optarg, ':');
expander.server=optarg;
@@ -205,16 +217,6 @@ main(int argc, char* argv[])
case 'j': if(expander.vendor) vendor_exclusive();
expander.vendor=V_JSON;
break;
case 'f':
if(expander.generation) exclusive();
expander.generation=T_ASPATH;
parseasnumber(&expander,optarg);
break;
case 'G':
if(expander.generation) exclusive();
expander.generation=T_OASPATH;
parseasnumber(&expander,optarg);
break;
case 'p':
expand_special_asn=1;
break;
@@ -298,6 +300,10 @@ main(int argc, char* argv[])
break;
case 'S': expander.sources=optarg;
break;
case 'U':
if(expander.vendor) exclusive();
expander.vendor=V_HUAWEI;
break;
case 'W': expander.aswidth=atoi(optarg);
if(expander.aswidth<0) {
sx_report(SX_FATAL,"Invalid as-width: %s\n", optarg);
@@ -372,6 +378,11 @@ main(int argc, char* argv[])
"compatible with -R/-r options\n");
exit(1);
};
if(expander.vendor==V_HUAWEI && expander.generation!=T_ASPATH &&
expander.generation!=T_OASPATH && expander.generation != T_PREFIXLIST)
sx_report(SX_FATAL, "Sorry, only as-paths and prefix-lists supported "
"for Huawei output\n");
if(expander.generation==T_ROUTE_FILTER_LIST && expander.vendor!=V_JUNIPER) {
sx_report(SX_FATAL, "Route-filter-lists (-z) supported for Juniper (-J)"
" output only\n");

View File

@@ -18,7 +18,8 @@ typedef enum {
V_BIRD,
V_OPENBGPD,
V_FORMAT,
V_NOKIA
V_NOKIA,
V_HUAWEI
} bgpq_vendor_t;
typedef enum {
@@ -90,4 +91,3 @@ size_t strlcpy(char* dst, const char* src, size_t size);
#endif
#endif

View File

@@ -369,6 +369,94 @@ bgpq3_print_nokia_aspath(FILE* f, struct bgpq_expander* b)
return 0;
};
int
bgpq3_print_huawei_aspath(FILE* f, struct bgpq_expander* b)
{
int nc=0, i, j, k, empty=1;
fprintf(f,"no ip as-path-filter %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,"ip as-path-filter %s permit ^%u(%u)*$\n",
b->name?b->name:"NN",b->asnumber,b->asnumber);
empty=0;
};
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,"ip as-path-filter %s permit ^%u([0-9]+)*"
"_(%u",
b->name?b->name:"NN",b->asnumber,k*65536+i*8+j);
empty=0;
} else {
fprintf(f,"|%u",k*65536+i*8+j);
};
nc++;
if(nc==b->aswidth) {
fprintf(f,")\n");
nc=0;
};
};
};
};
};
if(nc) fprintf(f,")\n");
if(empty)
fprintf(f,"ip as-path-filter %s deny .*\n", b->name?b->name:"NN");
return 0;
};
int
bgpq3_print_huawei_oaspath(FILE* f, struct bgpq_expander* b)
{
int nc=0, i, j, k, empty=1;
fprintf(f,"no ip as-path-filter %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,"ip as-path-filter %s permit (_%u)*$\n", b->name?b->name:"NN",
b->asnumber);
empty=0;
};
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,"ip as-path-filter %s permit ^(_[0-9]+)*_(%u",
b->name?b->name:"NN",k*65536+i*8+j);
} else {
fprintf(f,"|%u",k*65536+i*8+j);
}
nc++;
empty=0;
if(nc==b->aswidth) {
fprintf(f,")\n");
nc=0;
};
};
};
};
};
if(nc) fprintf(f,")\n");
if(empty)
fprintf(f, "ip as-path-filter %s deny .*\n", b->name?b->name:"NN");
return 0;
};
int
bgpq3_print_nokia_oaspath(FILE* f, struct bgpq_expander* b)
{
@@ -429,6 +517,8 @@ bgpq3_print_aspath(FILE* f, struct bgpq_expander* b)
return bgpq3_print_openbgpd_aspath(f,b);
} else if(b->vendor==V_NOKIA) {
return bgpq3_print_nokia_aspath(f,b);
} else if(b->vendor==V_HUAWEI) {
return bgpq3_print_huawei_aspath(f,b);
} else {
sx_report(SX_FATAL,"Unknown vendor %i\n", b->vendor);
};
@@ -448,6 +538,8 @@ bgpq3_print_oaspath(FILE* f, struct bgpq_expander* b)
return bgpq3_print_openbgpd_oaspath(f,b);
} else if(b->vendor==V_NOKIA) {
return bgpq3_print_nokia_oaspath(f,b);
} else if(b->vendor==V_HUAWEI) {
return bgpq3_print_huawei_oaspath(f,b);
} else {
sx_report(SX_FATAL,"Unknown vendor %i\n", b->vendor);
};
@@ -727,6 +819,36 @@ checkSon:
bgpq3_print_cprefixxr(n->son,ff);
};
void
bgpq3_print_hprefix(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,"ip %s-prefix %s permit %s greater-equal %u "
"less-equal %u\n",
n->prefix.family==AF_INET?"ip":"ipv6",bname?bname:"NN",
prefix,n->aggregateLow,n->aggregateHi);
} else {
fprintf(f,"ip %s-prefix %s permit %s less-equal %u\n",
n->prefix.family==AF_INET?"ip":"ipv6",bname?bname:"NN",
prefix,n->aggregateHi);
};
} else {
fprintf(f,"ip %s-prefix %s permit %s\n",
(n->prefix.family==AF_INET)?"ip":"ipv6",bname?bname:"NN",
prefix);
};
checkSon:
if(n->son)
bgpq3_print_hprefix(n->son,ff);
};
void
bgpq3_print_ceacl(struct sx_radix_node* n, void* ff)
{
@@ -957,6 +1079,24 @@ bgpq3_print_bird_prefixlist(FILE* f, struct bgpq_expander* b)
return 0;
};
int
bgpq3_print_huawei_prefixlist(FILE* f, struct bgpq_expander* b)
{
bname=b->name ? b->name : "NN";
seq=b->sequence;
fprintf(f,"no ip %s-prefix %s\n",
(b->family==AF_INET)?"ip":"ipv6",bname);
if (!sx_radix_tree_empty(b->tree)) {
sx_radix_tree_foreach(b->tree,bgpq3_print_hprefix,f);
} else {
fprintf(f, "ip %s-prefix %s deny %s\n",
(b->family==AF_INET) ? "ip" : "ipv6", bname,
(b->family==AF_INET) ? "0.0.0.0/0" : "::/0");
};
return 0;
};
struct fpcbdata {
FILE* f;
struct bgpq_expander* b;
@@ -1045,6 +1185,7 @@ bgpq3_print_prefixlist(FILE* f, struct bgpq_expander* 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);
case V_HUAWEI: return bgpq3_print_huawei_prefixlist(f,b);
};
return 0;
};
@@ -1061,6 +1202,7 @@ bgpq3_print_eacl(FILE* f, struct bgpq_expander* b)
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);
case V_HUAWEI: return sx_report(SX_FATAL, "unreachable point\n");
};
return 0;
};

18
configure vendored
View File

@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for bgpq3 0.1.35-rc2.
# Generated by GNU Autoconf 2.69 for bgpq3 0.1.35-rc3.
#
# Report bugs to <snar@snar.spb.ru>.
#
@@ -580,8 +580,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='bgpq3'
PACKAGE_TARNAME='bgpq3'
PACKAGE_VERSION='0.1.35-rc2'
PACKAGE_STRING='bgpq3 0.1.35-rc2'
PACKAGE_VERSION='0.1.35-rc3'
PACKAGE_STRING='bgpq3 0.1.35-rc3'
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.35-rc2 to adapt to many kinds of systems.
\`configure' configures bgpq3 0.1.35-rc3 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.35-rc2:";;
short | recursive ) echo "Configuration of bgpq3 0.1.35-rc3:";;
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.35-rc2
bgpq3 configure 0.1.35-rc3
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.35-rc2, which was
It was created by bgpq3 $as_me 0.1.35-rc3, 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.35-rc2, which was
This file was extended by bgpq3 $as_me 0.1.35-rc3, 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.35-rc2
bgpq3 config.status 0.1.35-rc3
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"

View File

@@ -1,4 +1,4 @@
AC_INIT(bgpq3,0.1.35-rc2,snar@snar.spb.ru)
AC_INIT(bgpq3,0.1.35-rc3,snar@snar.spb.ru)
AC_CONFIG_HEADER(config.h)
AC_PROG_CC
AC_PROG_INSTALL

View File

@@ -280,15 +280,22 @@ sx_prefix_fprint(FILE* f, struct sx_prefix* p)
};
int
sx_prefix_snprintf(struct sx_prefix* p, char* rbuffer, int srb)
sx_prefix_snprintf_sep(struct sx_prefix* p, char* rbuffer, int srb, char* sep)
{
char buffer[128];
if(!sep) sep="/";
if(!p) {
snprintf(rbuffer,srb,"(null)");
return 0;
};
inet_ntop(p->family,&p->addr,buffer,sizeof(buffer));
return snprintf(rbuffer,srb,"%s/%i",buffer,p->masklen);
return snprintf(rbuffer,srb,"%s%s%i",buffer,sep,p->masklen);
};
int
sx_prefix_snprintf(struct sx_prefix* p, char* rbuffer, int srb)
{
return sx_prefix_snprintf_sep(p, rbuffer, srb, "/");
};
int

View File

@@ -49,6 +49,7 @@ int sx_prefix_parse(struct sx_prefix* p, int af, char* text);
int sx_prefix_range_parse(struct sx_radix_tree* t, int af, int ml, char* text);
int sx_prefix_fprint(FILE* f, struct sx_prefix* p);
int sx_prefix_snprintf(struct sx_prefix* p, char* rbuffer, int srb);
int sx_prefix_snprintf_sep(struct sx_prefix* p, char* rbuffer, int srb, char*);
int sx_prefix_snprintf_fmt(struct sx_prefix* p, char* rbuffer, int srb,
const char* name, const char* fmt);
int sx_prefix_jsnprintf(struct sx_prefix* p, char* rbuffer, int srb);