mirror of
https://github.com/bgp/bgpq4
synced 2025-02-28 08:53:11 +00:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30110bad46 | ||
|
|
5507267c63 | ||
|
|
ab683d75d5 | ||
|
|
fb955c0521 | ||
|
|
4661fab181 | ||
|
|
6484a9a40c | ||
|
|
3ec83e255a | ||
|
|
c01ebfc3cb | ||
|
|
8dfcfb3173 | ||
|
|
c2126343cf | ||
|
|
96079b8901 | ||
|
|
58521eb687 | ||
|
|
8b804f83fd | ||
|
|
f26a04e8dd | ||
|
|
392a44a536 | ||
|
|
2aed3f9e67 | ||
|
|
d285db3c81 | ||
|
|
5d27a24659 | ||
|
|
97d1f2acda | ||
|
|
61a7bcf671 | ||
|
|
e920d74007 |
17
.github/images/alpine.Dockerfile
vendored
Normal file
17
.github/images/alpine.Dockerfile
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
ARG image=alpine:latest
|
||||
FROM $image
|
||||
|
||||
# Install dependencies
|
||||
RUN apk upgrade
|
||||
RUN apk add autoconf automake file gcc gzip libtool make musl-dev
|
||||
|
||||
# Add source code
|
||||
ADD . /src
|
||||
WORKDIR /src
|
||||
|
||||
# Run steps
|
||||
RUN ./bootstrap
|
||||
RUN ./configure
|
||||
RUN make
|
||||
RUN make check
|
||||
RUN make distcheck
|
||||
1
.github/images/alpine:3.16.Dockerfile
vendored
Symbolic link
1
.github/images/alpine:3.16.Dockerfile
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
alpine.Dockerfile
|
||||
1
.github/images/alpine:edge.Dockerfile
vendored
Symbolic link
1
.github/images/alpine:edge.Dockerfile
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
alpine.Dockerfile
|
||||
8
.github/images/centos.Dockerfile
vendored
8
.github/images/centos.Dockerfile
vendored
@@ -1,10 +1,9 @@
|
||||
ARG image=centos:8
|
||||
FROM $image
|
||||
ARG image=centos/centos:latest
|
||||
FROM quay.io/$image
|
||||
|
||||
# Install dependencies
|
||||
RUN yum update -y
|
||||
RUN yum groupinstall -y 'Development Tools'
|
||||
RUN yum install -y autoconf automake findutils libtool
|
||||
RUN yum install -y autoconf automake gcc libtool make diffutils file
|
||||
|
||||
# Add source code
|
||||
ADD . /src
|
||||
@@ -16,4 +15,3 @@ RUN ./configure
|
||||
RUN make
|
||||
RUN make check
|
||||
RUN make distcheck
|
||||
|
||||
|
||||
1
.github/images/centos/centos:7.Dockerfile
vendored
Symbolic link
1
.github/images/centos/centos:7.Dockerfile
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../centos.Dockerfile
|
||||
1
.github/images/centos/centos:stream8.Dockerfile
vendored
Symbolic link
1
.github/images/centos/centos:stream8.Dockerfile
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../centos.Dockerfile
|
||||
1
.github/images/centos/centos:stream9.Dockerfile
vendored
Symbolic link
1
.github/images/centos/centos:stream9.Dockerfile
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../centos.Dockerfile
|
||||
1
.github/images/centos:7.Dockerfile
vendored
1
.github/images/centos:7.Dockerfile
vendored
@@ -1 +0,0 @@
|
||||
centos.Dockerfile
|
||||
1
.github/images/centos:8.Dockerfile
vendored
1
.github/images/centos:8.Dockerfile
vendored
@@ -1 +0,0 @@
|
||||
centos.Dockerfile
|
||||
1
.github/images/fedora/fedora:35.Dockerfile
vendored
Symbolic link
1
.github/images/fedora/fedora:35.Dockerfile
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../centos.Dockerfile
|
||||
1
.github/images/fedora/fedora:36.Dockerfile
vendored
Symbolic link
1
.github/images/fedora/fedora:36.Dockerfile
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../centos.Dockerfile
|
||||
1
.github/images/fedora/fedora:37.Dockerfile
vendored
Symbolic link
1
.github/images/fedora/fedora:37.Dockerfile
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../centos.Dockerfile
|
||||
1
.github/images/fedora:30.Dockerfile
vendored
1
.github/images/fedora:30.Dockerfile
vendored
@@ -1 +0,0 @@
|
||||
centos.Dockerfile
|
||||
1
.github/images/fedora:31.Dockerfile
vendored
1
.github/images/fedora:31.Dockerfile
vendored
@@ -1 +0,0 @@
|
||||
centos.Dockerfile
|
||||
1
.github/images/rockylinux/rockylinux:8.Dockerfile
vendored
Symbolic link
1
.github/images/rockylinux/rockylinux:8.Dockerfile
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../centos.Dockerfile
|
||||
1
.github/images/rockylinux/rockylinux:9.Dockerfile
vendored
Symbolic link
1
.github/images/rockylinux/rockylinux:9.Dockerfile
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../centos.Dockerfile
|
||||
1
.github/images/ubuntu:focal.Dockerfile
vendored
Symbolic link
1
.github/images/ubuntu:focal.Dockerfile
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
debian.Dockerfile
|
||||
1
.github/images/ubuntu:jammy.Dockerfile
vendored
Symbolic link
1
.github/images/ubuntu:jammy.Dockerfile
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
debian.Dockerfile
|
||||
20
.github/workflows/matrixbuild.yml
vendored
20
.github/workflows/matrixbuild.yml
vendored
@@ -9,14 +9,22 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
dockerenv:
|
||||
- debian:bookworm
|
||||
- debian:bullseye
|
||||
- debian:buster
|
||||
- debian:stretch
|
||||
- ubuntu:jammy
|
||||
- ubuntu:focal
|
||||
- ubuntu:bionic
|
||||
- ubuntu:xenial
|
||||
- centos:8
|
||||
- centos:7
|
||||
- fedora:31
|
||||
- fedora:30
|
||||
- fedora/fedora:37
|
||||
- fedora/fedora:36
|
||||
- fedora/fedora:35
|
||||
- centos/centos:stream9
|
||||
- centos/centos:stream8
|
||||
- centos/centos:7
|
||||
- rockylinux/rockylinux:9
|
||||
- rockylinux/rockylinux:8
|
||||
- alpine:edge
|
||||
- alpine:3.16
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Run build on ${{matrix.dockerenv}}
|
||||
|
||||
6
CHANGES
6
CHANGES
@@ -1,3 +1,9 @@
|
||||
1.6 (2022-09-07)
|
||||
- Fix a bug in address prefix range parsing
|
||||
|
||||
1.5 (2022-07-25)
|
||||
- Add support for the new Junos as-path-origins feature
|
||||
|
||||
1.4 (2021-08-20)
|
||||
- Fix BIRD aspath output
|
||||
|
||||
|
||||
13
README.md
13
README.md
@@ -11,6 +11,7 @@
|
||||
\[**-f** *asn* |
|
||||
**-F** *fmt* |
|
||||
**-G** *asn*
|
||||
**-H** *asn*
|
||||
**-t**]
|
||||
\[**-46ABbDdJjNnsXU**]
|
||||
\[**-a** *asn*]
|
||||
@@ -27,7 +28,7 @@
|
||||
The
|
||||
**bgpq4**
|
||||
utility used to generate configurations (prefix-lists, extended
|
||||
access-lists, policy-statement terms and as-path lists) based on RADB data.
|
||||
access-lists, policy-statement terms and as-path lists) based on IRR data.
|
||||
|
||||
The options are as follows:
|
||||
|
||||
@@ -82,6 +83,10 @@ The options are as follows:
|
||||
|
||||
> generate output as-path access-list.
|
||||
|
||||
**-H** *number*
|
||||
|
||||
> generate output as-list for JunOS 21.3R1+ `as-path-origin` filter (JunOS only)
|
||||
|
||||
**-h** *host\[:port]*
|
||||
|
||||
> host running IRRD database (default: rr.ntt.net).
|
||||
@@ -145,7 +150,7 @@ The options are as follows:
|
||||
|
||||
**-S** *sources*
|
||||
|
||||
> use specified sources only (recommended: RADB,RIPE,APNIC).
|
||||
> use specified sources only (recommended: RPKI,AFRINIC,ARIN,APNIC,LACNIC,RIPE).
|
||||
|
||||
**-t**
|
||||
|
||||
@@ -163,6 +168,10 @@ The options are as follows:
|
||||
|
||||
> generate config for Huawei devices (Cisco IOS by default)
|
||||
|
||||
**-u**
|
||||
|
||||
> generate output in Huawei XPL format.
|
||||
|
||||
**-X**
|
||||
|
||||
> generate config for Cisco IOS XR devices (plain IOS by default).
|
||||
|
||||
44
bgpq4.8
44
bgpq4.8
@@ -37,6 +37,7 @@
|
||||
.Fl f Ar asn |
|
||||
.Fl F Ar fmt |
|
||||
.Fl G Ar asn
|
||||
.Fl H Ar asn
|
||||
.Fl t
|
||||
.Oc
|
||||
.Op Fl 46ABbDdJjNnsXU
|
||||
@@ -52,7 +53,7 @@
|
||||
The
|
||||
.Nm
|
||||
utility used to generate configurations (prefix-lists, extended
|
||||
access-lists, policy-statement terms and as-path lists) based on RADB data.
|
||||
access-lists, policy-statement terms and as-path lists) based on IRR data.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
@@ -83,6 +84,10 @@ generate input as-path access-list.
|
||||
generate output in user-defined format.
|
||||
.It Fl G Ar number
|
||||
generate output as-path access-list.
|
||||
.It Fl H Ar number
|
||||
generate output as-list for
|
||||
.Em as-path-origin
|
||||
filter (JunOS 21.3R1+)
|
||||
.It Fl h Ar host[:port]
|
||||
host running IRRD database (default: rr.ntt.net).
|
||||
.It Fl J
|
||||
@@ -115,7 +120,7 @@ allow more specific routes up to specified masklen too.
|
||||
.It Fl s
|
||||
generate sequence numbers in IOS-style prefix-lists.
|
||||
.It Fl S Ar sources
|
||||
use specified sources only (recommended: RADB,RIPE,APNIC).
|
||||
use specified sources only (recommended: RPKI,AFRINIC,APNIC,ARIN,LACNIC,RIPE).
|
||||
.It Fl t
|
||||
generate as-sets for OpenBGPd, BIRD and JSON formats.
|
||||
.It Fl T
|
||||
@@ -124,6 +129,8 @@ disable pipelining (not recommended).
|
||||
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 u
|
||||
generate config for Huawei devices in XPL format (Cisco IOS by default)
|
||||
.It Fl X
|
||||
generate config for Cisco IOS XR devices (plain IOS by default).
|
||||
.It Fl z
|
||||
@@ -275,9 +282,9 @@ new line
|
||||
tabulation
|
||||
.El
|
||||
.Pp
|
||||
Please note that no new lines inserted automatically after each sentence,
|
||||
you have to add them into format string manually, elsewhere output will
|
||||
be in one line (sometimes it makes sense):
|
||||
Please note that no new lines are inserted automatically after each sentence.
|
||||
You have to add them into format string manually, otherwise the output will
|
||||
be in one single line (sometimes it makes sense):
|
||||
.nf
|
||||
.Bd -literal
|
||||
$ bgpq4 -6F "%n/%l; " as-eltel
|
||||
@@ -287,29 +294,29 @@ $ bgpq4 -6F "%n/%l; " as-eltel
|
||||
.Sh NOTES ON SOURCES
|
||||
By default
|
||||
.Em bgpq4
|
||||
trusts to data from all databases mirrored into NTT's IRR service.
|
||||
Unfortunately, not all these databases are equal in how much can we
|
||||
trusts data from all the databases mirrored into NTT's IRR service.
|
||||
Unfortunately, not all these databases are equal in how much we can
|
||||
trust their data.
|
||||
RIR maintained databases (AFRINIC, ARIN, APNIC, LACNIC and RIPE)
|
||||
shall be trusted more than the others because they are indeed have the
|
||||
knowledge about which address space allocated to this or that ASn,
|
||||
other databases lack this knowledge and can (and, actually, do) contain
|
||||
some stale data: noone but RIRs care to remove outdated route-objects
|
||||
when address space revoked from one ASn and allocated to another.
|
||||
shall be trusted more than the others because they have the
|
||||
knowledge about who the rightful holders of resources are, while
|
||||
other databases lack this knowledge and can (and, actually do) contain
|
||||
stale data: no one but the RIRs care to remove outdated route-objects
|
||||
when address space is de-allocated or transferred.
|
||||
In order to keep their filters both compact and actual,
|
||||
.Em bgpq4 users
|
||||
are encouraged to use '-S' flag to limit database sources to only
|
||||
ones they trust.
|
||||
the ones they trust.
|
||||
.Pp
|
||||
General recommendations:
|
||||
.Pp
|
||||
Use minimal set of RIR databases (only those in which you and your
|
||||
Use a minimal set of RIR databases (only those in which you and your
|
||||
customers have registered route-objects).
|
||||
.Pp
|
||||
Avoid using ARIN-NONAUTH and RIPE-NONAUTH as trusted source: these records
|
||||
were created in database but for address space allocated to different RIR,
|
||||
so the NONAUTH databases have no chance to confirm validity of this route
|
||||
object.
|
||||
Avoid using ARIN-NONAUTH and RIPE-NONAUTH as trusted sources: these records
|
||||
were created in the database, but for address space allocated to different RIRs,
|
||||
so the NONAUTH databases have no chance to confirm validity of the route
|
||||
objects they contain.
|
||||
.Bd -literal
|
||||
$ bgpq4 -S RIPE,RADB as-space
|
||||
no ip prefix-list NN
|
||||
@@ -322,6 +329,7 @@ ip prefix-list NN permit 45.4.132.0/22
|
||||
ip prefix-list NN permit 45.6.128.0/22
|
||||
ip prefix-list NN permit 45.65.184.0/22
|
||||
[...]
|
||||
.Ed
|
||||
.Sh PERFORMANCE
|
||||
To improve `bgpq4` performance when expanding extra-large AS-SETs you
|
||||
shall tune OS settings to enlarge TCP send buffer.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
bsd_environment() {
|
||||
# Based on https://github.com/rvm/rvm/blob/59fe3b39f0fb5ae01ed5b9aa187201080815ac16/scripts/functions/build_config_system#L123
|
||||
if [[ -z "${AUTOCONF_VERSION:-}" ]]
|
||||
if [ -z "${AUTOCONF_VERSION}" ]
|
||||
then
|
||||
export AUTOCONF_VERSION
|
||||
AUTOCONF_VERSION="$(
|
||||
@@ -17,7 +17,7 @@ bsd_environment() {
|
||||
echo "Using autoconf version: $AUTOCONF_VERSION"
|
||||
fi
|
||||
|
||||
if [[ -z "${AUTOMAKE_VERSION:-}" ]]
|
||||
if [ -z "${AUTOMAKE_VERSION}" ]
|
||||
then
|
||||
export AUTOMAKE_VERSION
|
||||
# FreeBSD might have automake-wrapper
|
||||
|
||||
@@ -229,7 +229,7 @@ bgpq_expander_add_prefix(struct bgpq_expander *b, char *prefix)
|
||||
sx_radix_tree_insert(b->tree, p);
|
||||
|
||||
if (p)
|
||||
sx_prefix_destroy(p);
|
||||
sx_prefix_free(p);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -1113,7 +1113,7 @@ sx_radix_node_freeall(struct sx_radix_node *n) {
|
||||
if (n->payload)
|
||||
free(n->payload);
|
||||
|
||||
sx_prefix_destroy(n->prefix);
|
||||
sx_prefix_free(n->prefix);
|
||||
|
||||
free(n);
|
||||
}
|
||||
|
||||
3
extern.h
3
extern.h
@@ -58,6 +58,7 @@ typedef enum {
|
||||
V_FORMAT,
|
||||
V_NOKIA,
|
||||
V_HUAWEI,
|
||||
V_HUAWEI_XPL,
|
||||
V_MIKROTIK,
|
||||
V_NOKIA_MD,
|
||||
V_ARISTA
|
||||
@@ -67,6 +68,7 @@ typedef enum {
|
||||
T_NONE = 0,
|
||||
T_ASPATH,
|
||||
T_OASPATH,
|
||||
T_ASLIST,
|
||||
T_ASSET,
|
||||
T_PREFIXLIST,
|
||||
T_EACL,
|
||||
@@ -131,6 +133,7 @@ void bgpq4_print_eacl(FILE *f, struct bgpq_expander *b);
|
||||
void bgpq4_print_aspath(FILE *f, struct bgpq_expander *b);
|
||||
void bgpq4_print_asset(FILE *f, struct bgpq_expander *b);
|
||||
void bgpq4_print_oaspath(FILE *f, struct bgpq_expander *b);
|
||||
void bgpq4_print_aslist(FILE *f, struct bgpq_expander *b);
|
||||
void bgpq4_print_route_filter_list(FILE *f, struct bgpq_expander *b);
|
||||
|
||||
void sx_radix_node_freeall(struct sx_radix_node *n);
|
||||
|
||||
438
main.c
438
main.c
@@ -31,8 +31,6 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
@@ -52,13 +50,14 @@ extern int expand_special_asn;
|
||||
static int
|
||||
usage(int ecode)
|
||||
{
|
||||
printf("\nUsage: bgpq4 [-h host[:port]] [-S sources] [-E|G <num>"
|
||||
printf("\nUsage: bgpq4 [-h host[:port]] [-S sources] [-E|G|H <num>"
|
||||
"|f <num>|t] [-46ABbdJjKNnwXz] [-R len] <OBJECTS> ... "
|
||||
"[EXCEPT <OBJECTS> ...]\n");
|
||||
printf("\nVendor targets:\n");
|
||||
printf(" no option : Cisco IOS Classic (default)\n");
|
||||
printf(" -X : Cisco IOS XR\n");
|
||||
printf(" -U : Huawei\n");
|
||||
printf(" -u : Huawei XPL\n");
|
||||
printf(" -j : JSON\n");
|
||||
printf(" -J : Juniper Junos\n");
|
||||
printf(" -K : MikroTik RouterOS\n");
|
||||
@@ -88,6 +87,7 @@ usage(int ecode)
|
||||
"(OpenBGPD)\n");
|
||||
printf(" -f number : generate input as-path access-list\n");
|
||||
printf(" -G number : generate output as-path access-list\n");
|
||||
printf(" -H number : generate origin as-lists (JunOS only)\n");
|
||||
printf(" -M match : extra match conditions for JunOS route-filters\n");
|
||||
printf(" -l name : use specified name for generated access/prefix/.."
|
||||
" list\n");
|
||||
@@ -97,7 +97,7 @@ usage(int ecode)
|
||||
printf(" -t : generate as-sets for OpenBGPD (OpenBGPD 6.4+), BIRD "
|
||||
"and JSON formats\n");
|
||||
printf(" -z : generate route-filter-list (Junos only)\n");
|
||||
printf(" -W len : specify max-entries on as-path line (use 0 for "
|
||||
printf(" -W len : specify max-entries on as-path/as-list line (use 0 for "
|
||||
"infinity)\n");
|
||||
|
||||
printf("\nUtility operations:\n");
|
||||
@@ -134,8 +134,8 @@ vendor_exclusive(void)
|
||||
{
|
||||
fprintf(stderr, "-b (BIRD), -B (OpenBGPD), -F (formatted), -J (Junos),"
|
||||
" -j (JSON), -N (Nokia SR OS Classic), -n (Nokia SR OS MD-CLI),"
|
||||
" -U (Huawei), -e (Arista) and -X (IOS XR) options are mutually"
|
||||
" exclusive\n");
|
||||
" -U (Huawei), -u (Huawei XPL), -e (Arista) and -X (IOS XR) options "
|
||||
" are mutually exclusive\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -197,149 +197,149 @@ main(int argc, char* argv[])
|
||||
expander.sources=getenv("IRRD_SOURCES");
|
||||
|
||||
while ((c = getopt(argc, argv,
|
||||
"346a:AbBdDEeF:S:jJKf:l:L:m:M:NnW:pr:R:G:tTh:UwXsvz"))
|
||||
!=EOF) {
|
||||
"46a:AbBdDEeF:S:jJKf:l:L:m:M:NnW:pr:R:G:H:tTh:UuwXsvz")) != EOF) {
|
||||
switch (c) {
|
||||
case '3':
|
||||
/*
|
||||
* No-op, left for backwards compatibility with bgpq3
|
||||
*/
|
||||
break;
|
||||
case '4':
|
||||
/* do nothing, expander already configured for IPv4 */
|
||||
if (expander.family == AF_INET6) {
|
||||
sx_report(SX_FATAL, "-4 and -6 are mutually "
|
||||
"exclusive\n");
|
||||
exit(1);
|
||||
case '4':
|
||||
/* do nothing, expander already configured for IPv4 */
|
||||
if (expander.family == AF_INET6) {
|
||||
sx_report(SX_FATAL, "-4 and -6 are mutually "
|
||||
"exclusive\n");
|
||||
exit(1);
|
||||
}
|
||||
selectedipv4 = 1;
|
||||
break;
|
||||
case '6':
|
||||
if (selectedipv4) {
|
||||
sx_report(SX_FATAL, "-4 and -6 are mutually "
|
||||
"exclusive\n");
|
||||
exit(1);
|
||||
}
|
||||
af = AF_INET6;
|
||||
expander.family = AF_INET6;
|
||||
expander.tree->family = AF_INET6;
|
||||
break;
|
||||
case 'a':
|
||||
parseasnumber(&expander, optarg);
|
||||
break;
|
||||
case 'A':
|
||||
if (aggregate)
|
||||
debug_aggregation++;
|
||||
aggregate = 1;
|
||||
break;
|
||||
case 'b':
|
||||
if (expander.vendor)
|
||||
vendor_exclusive();
|
||||
expander.vendor = V_BIRD;
|
||||
break;
|
||||
case 'B':
|
||||
if (expander.vendor)
|
||||
vendor_exclusive();
|
||||
expander.vendor = V_OPENBGPD;
|
||||
break;
|
||||
case 'd':
|
||||
debug_expander++;
|
||||
break;
|
||||
case 'E':
|
||||
if (expander.generation)
|
||||
exclusive();
|
||||
expander.generation = T_EACL;
|
||||
break;
|
||||
case 'e':
|
||||
if (expander.vendor)
|
||||
vendor_exclusive();
|
||||
expander.vendor = V_ARISTA;
|
||||
expander.sequence = 1;
|
||||
break;
|
||||
case 'F':
|
||||
if (expander.vendor)
|
||||
exclusive();
|
||||
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':
|
||||
if (expander.generation)
|
||||
exclusive();
|
||||
expander.generation = T_ASLIST;
|
||||
parseasnumber(&expander, optarg);
|
||||
break;
|
||||
case 'h':
|
||||
{
|
||||
char *d = strchr(optarg, ':');
|
||||
expander.server = optarg;
|
||||
if (d) {
|
||||
*d = 0;
|
||||
expander.port = d + 1;
|
||||
}
|
||||
selectedipv4=1;
|
||||
break;
|
||||
case '6':
|
||||
if (selectedipv4) {
|
||||
sx_report(SX_FATAL, "-4 and -6 are mutually "
|
||||
"exclusive\n");
|
||||
exit(1);
|
||||
}
|
||||
af = AF_INET6;
|
||||
expander.family = AF_INET6;
|
||||
expander.tree->family = AF_INET6;
|
||||
break;
|
||||
case 'a':
|
||||
parseasnumber(&expander, optarg);
|
||||
break;
|
||||
case 'A':
|
||||
if (aggregate)
|
||||
debug_aggregation++;
|
||||
aggregate = 1;
|
||||
break;
|
||||
case 'b':
|
||||
if (expander.vendor)
|
||||
vendor_exclusive();
|
||||
expander.vendor = V_BIRD;
|
||||
break;
|
||||
case 'B':
|
||||
if (expander.vendor)
|
||||
vendor_exclusive();
|
||||
expander.vendor = V_OPENBGPD;
|
||||
break;
|
||||
case 'd':
|
||||
debug_expander++;
|
||||
break;
|
||||
case 'E':
|
||||
if (expander.generation)
|
||||
exclusive();
|
||||
expander.generation = T_EACL;
|
||||
break;
|
||||
case 'e':
|
||||
if (expander.vendor)
|
||||
vendor_exclusive();
|
||||
expander.vendor = V_ARISTA;
|
||||
expander.sequence = 1;
|
||||
break;
|
||||
case 'F':
|
||||
if (expander.vendor)
|
||||
exclusive();
|
||||
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;
|
||||
if (d) {
|
||||
*d = 0;
|
||||
expander.port = d + 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'J':
|
||||
if (expander.vendor)
|
||||
vendor_exclusive();
|
||||
expander.vendor = V_JUNIPER;
|
||||
break;
|
||||
case 'j':
|
||||
if (expander.vendor)
|
||||
vendor_exclusive();
|
||||
expander.vendor = V_JSON;
|
||||
break;
|
||||
case 'K':
|
||||
if (expander.vendor)
|
||||
vendor_exclusive();
|
||||
expander.vendor = V_MIKROTIK;
|
||||
break;
|
||||
case 'p':
|
||||
expand_special_asn = 1;
|
||||
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) {
|
||||
sx_report(SX_FATAL,"Invalid refine length:"
|
||||
" %s\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
expander.name = optarg;
|
||||
break;
|
||||
case 'L':
|
||||
expander.maxdepth = strtol(optarg, NULL, 10);
|
||||
if (expander.maxdepth < 1) {
|
||||
sx_report(SX_FATAL, "Invalid maximum recursion"
|
||||
" (-L): %s\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
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 *mc, *md;
|
||||
}
|
||||
break;
|
||||
case 'J':
|
||||
if (expander.vendor)
|
||||
vendor_exclusive();
|
||||
expander.vendor = V_JUNIPER;
|
||||
break;
|
||||
case 'j':
|
||||
if (expander.vendor)
|
||||
vendor_exclusive();
|
||||
expander.vendor = V_JSON;
|
||||
break;
|
||||
case 'K':
|
||||
if (expander.vendor)
|
||||
vendor_exclusive();
|
||||
expander.vendor = V_MIKROTIK;
|
||||
break;
|
||||
case 'p':
|
||||
expand_special_asn = 1;
|
||||
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) {
|
||||
sx_report(SX_FATAL,"Invalid refine length:"
|
||||
" %s\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
expander.name = optarg;
|
||||
break;
|
||||
case 'L':
|
||||
expander.maxdepth = strtol(optarg, NULL, 10);
|
||||
if (expander.maxdepth < 1) {
|
||||
sx_report(SX_FATAL, "Invalid maximum recursion"
|
||||
" (-L): %s\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
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 *mc, *md;
|
||||
expander.match = strdup(optarg);
|
||||
mc = md = expander.match;
|
||||
while (*mc) {
|
||||
@@ -377,64 +377,68 @@ main(int argc, char* argv[])
|
||||
}
|
||||
}
|
||||
*md = 0;
|
||||
}
|
||||
break;
|
||||
case 'N':
|
||||
if (expander.vendor)
|
||||
vendor_exclusive();
|
||||
expander.vendor = V_NOKIA;
|
||||
break;
|
||||
case 'n':
|
||||
if (expander.vendor)
|
||||
vendor_exclusive();
|
||||
expander.vendor = V_NOKIA_MD;
|
||||
break;
|
||||
case 't':
|
||||
if (expander.generation)
|
||||
exclusive();
|
||||
expander.generation = T_ASSET;
|
||||
break;
|
||||
case 'T':
|
||||
pipelining = 0;
|
||||
break;
|
||||
case 's':
|
||||
expander.sequence = 1;
|
||||
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);
|
||||
exit(1);
|
||||
}
|
||||
widthSet = 1;
|
||||
break;
|
||||
case 'w':
|
||||
expander.validate_asns = 1;
|
||||
break;
|
||||
case 'X':
|
||||
if (expander.vendor)
|
||||
vendor_exclusive();
|
||||
expander.vendor = V_CISCO_XR;
|
||||
break;
|
||||
case 'v':
|
||||
version();
|
||||
break;
|
||||
case 'z':
|
||||
if (expander.generation)
|
||||
exclusive();
|
||||
expander.generation = T_ROUTE_FILTER_LIST;
|
||||
break;
|
||||
default:
|
||||
usage(1);
|
||||
}
|
||||
break;
|
||||
case 'N':
|
||||
if (expander.vendor)
|
||||
vendor_exclusive();
|
||||
expander.vendor = V_NOKIA;
|
||||
break;
|
||||
case 'n':
|
||||
if (expander.vendor)
|
||||
vendor_exclusive();
|
||||
expander.vendor = V_NOKIA_MD;
|
||||
break;
|
||||
case 't':
|
||||
if (expander.generation)
|
||||
exclusive();
|
||||
expander.generation = T_ASSET;
|
||||
break;
|
||||
case 'T':
|
||||
pipelining = 0;
|
||||
break;
|
||||
case 's':
|
||||
expander.sequence = 1;
|
||||
break;
|
||||
case 'S':
|
||||
expander.sources = optarg;
|
||||
break;
|
||||
case 'U':
|
||||
if (expander.vendor)
|
||||
exclusive();
|
||||
expander.vendor = V_HUAWEI;
|
||||
break;
|
||||
case 'u':
|
||||
if (expander.vendor)
|
||||
exclusive();
|
||||
expander.vendor = V_HUAWEI_XPL;
|
||||
break;
|
||||
case 'W':
|
||||
expander.aswidth = atoi(optarg);
|
||||
if (expander.aswidth < 0) {
|
||||
sx_report(SX_FATAL,"Invalid as-width: %s\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
widthSet = 1;
|
||||
break;
|
||||
case 'w':
|
||||
expander.validate_asns = 1;
|
||||
break;
|
||||
case 'X':
|
||||
if (expander.vendor)
|
||||
vendor_exclusive();
|
||||
expander.vendor = V_CISCO_XR;
|
||||
break;
|
||||
case 'v':
|
||||
version();
|
||||
break;
|
||||
case 'z':
|
||||
if (expander.generation)
|
||||
exclusive();
|
||||
expander.generation = T_ROUTE_FILTER_LIST;
|
||||
break;
|
||||
default:
|
||||
usage(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -478,6 +482,13 @@ main(int argc, char* argv[])
|
||||
expander.aswidth = 8;
|
||||
break;
|
||||
}
|
||||
} else if (expander.generation == T_ASLIST) {
|
||||
int vendor = expander.vendor;
|
||||
switch (vendor) {
|
||||
case V_JUNIPER:
|
||||
expander.aswidth = 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -663,14 +674,18 @@ main(int argc, char* argv[])
|
||||
"only with Juniper route-filters\n");
|
||||
}
|
||||
|
||||
if ((expander.generation == T_ASPATH || expander.generation == T_OASPATH)
|
||||
if ((expander.generation == T_ASPATH
|
||||
|| expander.generation == T_OASPATH
|
||||
|| expander.generation == T_ASLIST)
|
||||
&& af != AF_INET && !expander.validate_asns) {
|
||||
sx_report(SX_FATAL, "Sorry, -6 makes no sense with as-path (-f/-G) "
|
||||
sx_report(SX_FATAL, "Sorry, -6 makes no sense with as-path (-f/-G) or as-list (-H) "
|
||||
"generation\n");
|
||||
}
|
||||
|
||||
if (expander.validate_asns && expander.generation != T_ASPATH
|
||||
&& expander.generation != T_OASPATH) {
|
||||
if (expander.validate_asns
|
||||
&& expander.generation != T_ASPATH
|
||||
&& expander.generation != T_OASPATH
|
||||
&& expander.generation != T_ASLIST) {
|
||||
sx_report(SX_FATAL, "Sorry, -w makes sense only for as-path "
|
||||
"(-f/-G) generation\n");
|
||||
}
|
||||
@@ -733,7 +748,7 @@ main(int argc, char* argv[])
|
||||
|
||||
switch (expander.generation) {
|
||||
case T_NONE:
|
||||
sx_report(SX_FATAL,"Unreachable point... call snar\n");
|
||||
sx_report(SX_FATAL,"Unreachable point");
|
||||
exit(1);
|
||||
case T_ASPATH:
|
||||
bgpq4_print_aspath(stdout, &expander);
|
||||
@@ -741,6 +756,9 @@ main(int argc, char* argv[])
|
||||
case T_OASPATH:
|
||||
bgpq4_print_oaspath(stdout, &expander);
|
||||
break;
|
||||
case T_ASLIST:
|
||||
bgpq4_print_aslist(stdout, &expander);
|
||||
break;
|
||||
case T_ASSET:
|
||||
bgpq4_print_asset(stdout, &expander);
|
||||
break;
|
||||
|
||||
194
printer.c
194
printer.c
@@ -274,6 +274,45 @@ bgpq4_print_juniper_oaspath(FILE *f, struct bgpq_expander *b)
|
||||
fprintf(f, " }\n}\n");
|
||||
}
|
||||
|
||||
static void
|
||||
bgpq4_print_juniper_aslist(FILE *f, struct bgpq_expander *b)
|
||||
{
|
||||
int nc = 0, lineNo = 0;
|
||||
struct asn_entry *asne, find, *res;
|
||||
|
||||
fprintf(f,"policy-options {\nreplace:\n as-list-group %s {\n",
|
||||
b->name);
|
||||
|
||||
find.asn = b->asnumber;
|
||||
if ((res = RB_FIND(asn_tree, &b->asnlist, &find)) != NULL) {
|
||||
fprintf(f, " as-list a0 members %u;\n", res->asn);
|
||||
RB_REMOVE(asn_tree, &b->asnlist, res);
|
||||
lineNo++;
|
||||
}
|
||||
|
||||
RB_FOREACH(asne, asn_tree, &b->asnlist) {
|
||||
if (!nc) {
|
||||
fprintf(f, " as-list a%u members [ %u",
|
||||
lineNo, asne->asn);
|
||||
} else {
|
||||
fprintf(f," %u", asne->asn);
|
||||
}
|
||||
|
||||
nc++;
|
||||
|
||||
if (nc == b->aswidth) {
|
||||
fprintf(f, " ];\n");
|
||||
nc = 0;
|
||||
lineNo++;
|
||||
}
|
||||
}
|
||||
|
||||
if (nc)
|
||||
fprintf(f, " ];\n");
|
||||
|
||||
fprintf(f, " }\n}\n");
|
||||
}
|
||||
|
||||
static void
|
||||
bgpq4_print_openbgpd_oaspath(FILE *f, struct bgpq_expander *b)
|
||||
{
|
||||
@@ -406,6 +445,43 @@ bgpq4_print_huawei_aspath(FILE *f, struct bgpq_expander *b)
|
||||
fprintf(f, ")$\n");
|
||||
}
|
||||
|
||||
static void
|
||||
bgpq4_print_huawei_xpl_aspath(FILE *f, struct bgpq_expander *b)
|
||||
{
|
||||
int nc = 0, comma = 1;
|
||||
struct asn_entry *asne, find, *res;
|
||||
|
||||
fprintf(f, "xpl as-path-list %s", b->name);
|
||||
|
||||
find.asn = b->asnumber;
|
||||
if ((res = RB_FIND(asn_tree, &b->asnlist, &find)) != NULL) {
|
||||
fprintf(f, "\n regular ^%u(_%u)*$", res->asn, res->asn);
|
||||
RB_REMOVE(asn_tree, &b->asnlist, res);
|
||||
}
|
||||
|
||||
RB_FOREACH(asne, asn_tree, &b->asnlist) {
|
||||
if (!nc) {
|
||||
fprintf(f, "%s\n regular ^%u(_[0-9]+)*_(%u",
|
||||
comma ? "," : "",
|
||||
b->asnumber,
|
||||
asne->asn);
|
||||
comma = 1;
|
||||
} else
|
||||
fprintf(f, "|%u", asne->asn);
|
||||
|
||||
nc++;
|
||||
if (nc == b->aswidth) {
|
||||
fprintf(f, ")$");
|
||||
nc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (nc)
|
||||
fprintf(f, ")$");
|
||||
|
||||
fprintf(f, "\nend-list\n");
|
||||
}
|
||||
|
||||
static void
|
||||
bgpq4_print_huawei_oaspath(FILE *f, struct bgpq_expander *b)
|
||||
{
|
||||
@@ -445,6 +521,42 @@ bgpq4_print_huawei_oaspath(FILE *f, struct bgpq_expander *b)
|
||||
fprintf(f, ")$\n");
|
||||
}
|
||||
|
||||
static void
|
||||
bgpq4_print_huawei_xpl_oaspath(FILE *f, struct bgpq_expander *b)
|
||||
{
|
||||
int nc = 0, comma = 0;
|
||||
struct asn_entry *asne, find, *res;
|
||||
|
||||
fprintf(f, "xpl as-path-list %s", b->name);
|
||||
|
||||
find.asn = b->asnumber;
|
||||
if ((res = RB_FIND(asn_tree, &b->asnlist, &find)) != NULL) {
|
||||
fprintf(f, "\n regular ^(_%u)*$", res->asn);
|
||||
RB_REMOVE(asn_tree, &b->asnlist, res);
|
||||
comma = 1;
|
||||
}
|
||||
|
||||
RB_FOREACH(asne, asn_tree, &b->asnlist) {
|
||||
if (!nc) {
|
||||
fprintf(f,"%s\n regular ^(_[0-9]+)*_(%u",
|
||||
comma ? "," : "", asne->asn);
|
||||
comma = 1;
|
||||
} else
|
||||
fprintf(f,"|%u",asne->asn);
|
||||
|
||||
nc++;
|
||||
if (nc == b->aswidth) {
|
||||
fprintf(f,")$");
|
||||
nc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (nc)
|
||||
fprintf(f,")$");
|
||||
|
||||
fprintf(f,"\nend-list\n");
|
||||
}
|
||||
|
||||
static void
|
||||
bgpq4_print_nokia_oaspath(FILE *f, struct bgpq_expander *b)
|
||||
{
|
||||
@@ -664,7 +776,7 @@ bgpq4_print_bird_aspath(FILE* f, struct bgpq_expander* b)
|
||||
nc = 0;
|
||||
}
|
||||
|
||||
fprintf(f, "];\n");
|
||||
fprintf(f, "\n];\n");
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -763,6 +875,9 @@ bgpq4_print_aspath(FILE *f, struct bgpq_expander *b)
|
||||
case V_HUAWEI:
|
||||
bgpq4_print_huawei_aspath(f, b);
|
||||
break;
|
||||
case V_HUAWEI_XPL:
|
||||
bgpq4_print_huawei_xpl_aspath(f, b);
|
||||
break;
|
||||
default:
|
||||
sx_report(SX_FATAL,"Unknown vendor %i\n", b->vendor);
|
||||
}
|
||||
@@ -794,6 +909,21 @@ bgpq4_print_oaspath(FILE *f, struct bgpq_expander *b)
|
||||
case V_HUAWEI:
|
||||
bgpq4_print_huawei_oaspath(f, b);
|
||||
break;
|
||||
case V_HUAWEI_XPL:
|
||||
bgpq4_print_huawei_xpl_oaspath(f, b);
|
||||
break;
|
||||
default:
|
||||
sx_report(SX_FATAL,"Unknown vendor %i\n", b->vendor);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bgpq4_print_aslist(FILE *f, struct bgpq_expander *b)
|
||||
{
|
||||
switch (b->vendor) {
|
||||
case V_JUNIPER:
|
||||
bgpq4_print_juniper_aslist(f, b);
|
||||
break;
|
||||
default:
|
||||
sx_report(SX_FATAL,"Unknown vendor %i\n", b->vendor);
|
||||
}
|
||||
@@ -973,6 +1103,43 @@ checkSon:
|
||||
bgpq4_print_hprefix(n->son, ff);
|
||||
}
|
||||
|
||||
static void
|
||||
bgpq4_print_hprefixxpl(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,"%s %s ge %u le %u",
|
||||
needscomma ? ",\n " : " ",
|
||||
prefix, n->aggregateLow, n->aggregateHi);
|
||||
} else {
|
||||
fprintf(f,"%s %s le %u",
|
||||
needscomma ? ",\n " : " ",
|
||||
prefix, n->aggregateHi);
|
||||
}
|
||||
} else {
|
||||
fprintf(f, "%s %s",
|
||||
needscomma ? ",\n " : " ",
|
||||
prefix);
|
||||
}
|
||||
|
||||
needscomma = 1;
|
||||
|
||||
checkSon:
|
||||
if (n->son)
|
||||
bgpq4_print_hprefixxpl(n->son, ff);
|
||||
}
|
||||
|
||||
static void
|
||||
bgpq4_print_eprefix(struct sx_radix_node *n, void *ff)
|
||||
{
|
||||
@@ -1070,11 +1237,11 @@ bgpq4_print_ceacl(struct sx_radix_node *n, void *ff)
|
||||
wildmask.s_addr = htonl(wildmask.s_addr);
|
||||
|
||||
if (wildaddr.s_addr) {
|
||||
fprintf(f, "permit ip %s ",
|
||||
fprintf(f, " permit ip %s ",
|
||||
inet_ntoa(n->prefix->addr.addr));
|
||||
fprintf(f, "%s ", inet_ntoa(wildaddr));
|
||||
} else {
|
||||
fprintf(f, "permit ip host %s ",
|
||||
fprintf(f, " permit ip host %s ",
|
||||
inet_ntoa(n->prefix->addr.addr));
|
||||
}
|
||||
|
||||
@@ -1085,7 +1252,7 @@ bgpq4_print_ceacl(struct sx_radix_node *n, void *ff)
|
||||
fprintf(f, "host %s\n", inet_ntoa(mask));
|
||||
}
|
||||
} else {
|
||||
fprintf(f, "permit ip host %s host %s\n", prefix,
|
||||
fprintf(f, " permit ip host %s host %s\n", prefix,
|
||||
inet_ntoa(netmask));
|
||||
}
|
||||
|
||||
@@ -1369,6 +1536,18 @@ bgpq4_print_huawei_prefixlist(FILE *f, struct bgpq_expander *b)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bgpq4_print_huawei_xpl_prefixlist(FILE* f, struct bgpq_expander* b)
|
||||
{
|
||||
bname = b->name ? b->name : "NN";
|
||||
|
||||
fprintf(f, "no xpl %s-prefix-list %s\nxpl %s-prefix-list %s\n", b->family==AF_INET ? "ip" : "ipv6", bname, b->family==AF_INET ? "ip" : "ipv6", bname);
|
||||
|
||||
sx_radix_tree_foreach(b->tree, bgpq4_print_hprefixxpl, f);
|
||||
|
||||
fprintf(f, "\nend-list\n");
|
||||
}
|
||||
|
||||
static void
|
||||
bgpq4_print_arista_prefixlist(FILE *f, struct bgpq_expander *b)
|
||||
{
|
||||
@@ -1615,6 +1794,9 @@ bgpq4_print_prefixlist(FILE *f, struct bgpq_expander *b)
|
||||
case V_HUAWEI:
|
||||
bgpq4_print_huawei_prefixlist(f, b);
|
||||
break;
|
||||
case V_HUAWEI_XPL:
|
||||
bgpq4_print_huawei_xpl_prefixlist(f, b);
|
||||
break;
|
||||
case V_MIKROTIK:
|
||||
bgpq4_print_mikrotik_prefixlist(f, b);
|
||||
break;
|
||||
@@ -1632,6 +1814,7 @@ bgpq4_print_eacl(FILE *f, struct bgpq_expander *b)
|
||||
bgpq4_print_juniper_routefilter(f, b);
|
||||
break;
|
||||
case V_CISCO:
|
||||
case V_ARISTA:
|
||||
bgpq4_print_cisco_eacl(f, b);
|
||||
break;
|
||||
case V_OPENBGPD:
|
||||
@@ -1643,9 +1826,6 @@ bgpq4_print_eacl(FILE *f, struct bgpq_expander *b)
|
||||
case V_NOKIA_MD:
|
||||
bgpq4_print_nokia_md_prefixlist(f, b);
|
||||
break;
|
||||
case V_ARISTA:
|
||||
bgpq4_print_cisco_eacl(f, b);
|
||||
break;
|
||||
default:
|
||||
sx_report(SX_FATAL, "unreachable point\n");
|
||||
}
|
||||
|
||||
121
sx_prefix.c
121
sx_prefix.c
@@ -26,6 +26,7 @@
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -38,13 +39,13 @@
|
||||
int debug_aggregation = 0;
|
||||
extern int debug_expander;
|
||||
|
||||
struct sx_prefix*
|
||||
struct sx_prefix *
|
||||
sx_prefix_alloc(struct sx_prefix *p)
|
||||
{
|
||||
struct sx_prefix *sp = malloc(sizeof(struct sx_prefix));
|
||||
struct sx_prefix *sp;
|
||||
|
||||
if (!sp)
|
||||
return NULL;
|
||||
if ((sp = malloc(sizeof(struct sx_prefix))) == NULL)
|
||||
err(1, NULL);
|
||||
|
||||
if (p)
|
||||
memcpy(sp, p, sizeof(struct sx_prefix));
|
||||
@@ -55,7 +56,7 @@ sx_prefix_alloc(struct sx_prefix *p)
|
||||
}
|
||||
|
||||
void
|
||||
sx_prefix_destroy(struct sx_prefix *p)
|
||||
sx_prefix_free(struct sx_prefix *p)
|
||||
{
|
||||
if (p)
|
||||
free(p);
|
||||
@@ -64,15 +65,16 @@ sx_prefix_destroy(struct sx_prefix *p)
|
||||
void
|
||||
sx_radix_node_destroy(struct sx_radix_node *n)
|
||||
{
|
||||
if (n) {
|
||||
if (n->payload)
|
||||
free(n->payload);
|
||||
if (!n)
|
||||
return;
|
||||
|
||||
if (n->prefix)
|
||||
free(n->prefix);
|
||||
if (n->payload)
|
||||
free(n->payload);
|
||||
|
||||
free(n);
|
||||
}
|
||||
if (n->prefix)
|
||||
free(n->prefix);
|
||||
|
||||
free(n);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -140,7 +142,7 @@ sx_prefix_parse(struct sx_prefix *p, int af, char *text)
|
||||
c = strchr(mtext,'/');
|
||||
|
||||
if (c) {
|
||||
char* eod;
|
||||
char *eod;
|
||||
*c = 0;
|
||||
masklen = strtol(c + 1, &eod, 10);
|
||||
if (eod && eod[0] && !isspace(eod[0])) {
|
||||
@@ -257,25 +259,19 @@ sx_prefix_setbit(struct sx_prefix *p, int n)
|
||||
|
||||
|
||||
static int
|
||||
sx_radix_tree_insert_specifics(struct sx_radix_tree *t, struct sx_prefix *p,
|
||||
sx_radix_tree_insert_specifics(struct sx_radix_tree *t, struct sx_prefix p,
|
||||
unsigned min, unsigned max)
|
||||
{
|
||||
struct sx_prefix *np;
|
||||
np = sx_prefix_alloc(p);
|
||||
if (p.masklen >= min)
|
||||
sx_radix_tree_insert(t, &p);
|
||||
|
||||
if (np->masklen >= min) {
|
||||
struct sx_radix_node *nn = sx_radix_tree_insert(t, np);
|
||||
sx_prefix_destroy(np);
|
||||
np = nn->prefix;
|
||||
}
|
||||
|
||||
if (np->masklen + 1 > max)
|
||||
if (p.masklen + 1 > max)
|
||||
return 1;
|
||||
|
||||
np->masklen += 1;
|
||||
sx_radix_tree_insert_specifics(t, np, min, max);
|
||||
sx_prefix_setbit(np, np->masklen);
|
||||
sx_radix_tree_insert_specifics(t, np, min, max);
|
||||
p.masklen += 1;
|
||||
sx_radix_tree_insert_specifics(t, p, min, max);
|
||||
sx_prefix_setbit(&p, p.masklen);
|
||||
sx_radix_tree_insert_specifics(t, p, min, max);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -284,18 +280,16 @@ int
|
||||
sx_prefix_range_parse(struct sx_radix_tree *tree, int af, unsigned int maxlen,
|
||||
char *text)
|
||||
{
|
||||
char *d = strchr(text, '^');
|
||||
struct sx_prefix *p;
|
||||
struct sx_prefix p;
|
||||
unsigned long min, max = 0;
|
||||
|
||||
p = sx_prefix_alloc(NULL);
|
||||
char *d = strchr(text, '^');
|
||||
|
||||
if (!d || !d[1])
|
||||
return 0;
|
||||
|
||||
*d = 0;
|
||||
|
||||
if (!sx_prefix_parse(p, 0, text)) {
|
||||
if (!sx_prefix_parse(&p, 0, text)) {
|
||||
sx_report(SX_ERROR, "Unable to parse prefix %s^%s\n", text,
|
||||
d + 1);
|
||||
return 0;
|
||||
@@ -303,23 +297,23 @@ sx_prefix_range_parse(struct sx_radix_tree *tree, int af, unsigned int maxlen,
|
||||
|
||||
*d = '^';
|
||||
|
||||
if (af && p->family != af) {
|
||||
if (af && p.family != af) {
|
||||
sx_report(SX_ERROR, "Ignoring prefix %s, wrong af %i\n", text,
|
||||
p->family);
|
||||
p.family);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (maxlen && p->masklen > maxlen) {
|
||||
if (maxlen && p.masklen > maxlen) {
|
||||
SX_DEBUG(debug_expander, "Ignoring prefix %s, masklen %i > max"
|
||||
" masklen %u\n", text, p->masklen, maxlen);
|
||||
" masklen %u\n", text, p.masklen, maxlen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (d[1] == '-') {
|
||||
min = p->masklen + 1;
|
||||
min = p.masklen + 1;
|
||||
max = maxlen;
|
||||
} else if (d[1] == '+') {
|
||||
min = p->masklen;
|
||||
min = p.masklen;
|
||||
max = maxlen;
|
||||
} else if (isdigit(d[1])) {
|
||||
char *dm = NULL;
|
||||
@@ -336,9 +330,9 @@ sx_prefix_range_parse(struct sx_radix_tree *tree, int af, unsigned int maxlen,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (min < p->masklen) {
|
||||
if (min < p.masklen) {
|
||||
sx_report(SX_ERROR, "Invalid prefix-range %s: min %lu < "
|
||||
"masklen %u\n", text, min, p->masklen);
|
||||
"masklen %u\n", text, min, p.masklen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -377,7 +371,7 @@ sx_prefix_new(int af, char *text)
|
||||
return NULL;
|
||||
|
||||
if (!sx_prefix_parse(p, af, text)) {
|
||||
sx_prefix_destroy(p);
|
||||
sx_prefix_free(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -519,13 +513,13 @@ sx_prefix_jsnprintf(struct sx_prefix *p, char *rbuffer, int srb)
|
||||
return snprintf(rbuffer, srb, "%s\\/%i", buffer, p->masklen);
|
||||
}
|
||||
|
||||
struct sx_radix_tree*
|
||||
struct sx_radix_tree *
|
||||
sx_radix_tree_new(int af)
|
||||
{
|
||||
struct sx_radix_tree *rt = malloc(sizeof(struct sx_radix_tree));
|
||||
struct sx_radix_tree *rt;
|
||||
|
||||
if (!rt)
|
||||
return NULL;
|
||||
if ((rt = malloc(sizeof(struct sx_radix_tree))) == NULL)
|
||||
err(1, NULL);
|
||||
|
||||
memset(rt, 0, sizeof(struct sx_radix_tree));
|
||||
rt->family = af;
|
||||
@@ -539,13 +533,13 @@ sx_radix_tree_empty(struct sx_radix_tree *t)
|
||||
return t->head == NULL;
|
||||
}
|
||||
|
||||
struct sx_radix_node*
|
||||
struct sx_radix_node *
|
||||
sx_radix_node_new(struct sx_prefix *prefix)
|
||||
{
|
||||
struct sx_radix_node *rn = malloc(sizeof(struct sx_radix_node));
|
||||
struct sx_radix_node *rn;
|
||||
|
||||
if (!rn)
|
||||
return NULL;
|
||||
if ((rn = malloc(sizeof(struct sx_radix_node))) == NULL)
|
||||
err(1, NULL);
|
||||
|
||||
memset(rn, 0, sizeof(struct sx_radix_node));
|
||||
|
||||
@@ -582,7 +576,7 @@ sx_prefix_eqbits(struct sx_prefix *a, struct sx_prefix *b)
|
||||
return b->masklen;
|
||||
}
|
||||
|
||||
struct sx_prefix*
|
||||
struct sx_prefix *
|
||||
sx_prefix_overlay(struct sx_prefix *p, int n)
|
||||
{
|
||||
struct sx_prefix *sp = sx_prefix_alloc(p);
|
||||
@@ -668,7 +662,7 @@ next:
|
||||
}
|
||||
|
||||
|
||||
struct sx_radix_node*
|
||||
struct sx_radix_node *
|
||||
sx_radix_tree_lookup(struct sx_radix_tree *tree, struct sx_prefix *prefix)
|
||||
{
|
||||
unsigned int eb;
|
||||
@@ -725,18 +719,18 @@ next:
|
||||
char pbuffer[128], cbuffer[128];
|
||||
sx_prefix_snprintf(prefix, pbuffer, sizeof(pbuffer));
|
||||
sx_prefix_snprintf(chead->prefix, cbuffer, sizeof(cbuffer));
|
||||
printf("Unreachible point... eb=%i, prefix=%s, chead=%s\n",
|
||||
printf("Unreachable point... eb=%i, prefix=%s, chead=%s\n",
|
||||
eb, pbuffer, cbuffer);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct sx_radix_node*
|
||||
struct sx_radix_node *
|
||||
sx_radix_tree_insert(struct sx_radix_tree *tree, struct sx_prefix *prefix)
|
||||
{
|
||||
unsigned int eb;
|
||||
struct sx_radix_node **candidate=NULL, *chead;
|
||||
unsigned int eb;
|
||||
struct sx_radix_node *chead, **candidate = NULL;
|
||||
|
||||
if (!tree || !prefix)
|
||||
return NULL;
|
||||
@@ -752,7 +746,7 @@ sx_radix_tree_insert(struct sx_radix_tree *tree, struct sx_prefix *prefix)
|
||||
candidate = &tree->head;
|
||||
chead = tree->head;
|
||||
|
||||
next:
|
||||
next:
|
||||
eb = sx_prefix_eqbits(prefix, chead->prefix);
|
||||
if (eb < prefix->masklen && eb < chead->prefix->masklen) {
|
||||
struct sx_prefix *neoRoot = sx_prefix_alloc(prefix);
|
||||
@@ -761,7 +755,7 @@ next:
|
||||
neoRoot->masklen = eb;
|
||||
sx_prefix_adjust_masklen(neoRoot);
|
||||
rn=sx_radix_node_new(neoRoot);
|
||||
sx_prefix_destroy(neoRoot);
|
||||
sx_prefix_free(neoRoot);
|
||||
neoRoot = rn->prefix;
|
||||
if (!rn) {
|
||||
sx_report(SX_ERROR,"Unable to create node: %s\n",
|
||||
@@ -785,11 +779,10 @@ next:
|
||||
return ret;
|
||||
} else if (eb == prefix->masklen && eb < chead->prefix->masklen) {
|
||||
struct sx_radix_node *ret = sx_radix_node_new(prefix);
|
||||
if (sx_prefix_isbitset(chead->prefix, eb + 1)) {
|
||||
if (sx_prefix_isbitset(chead->prefix, eb + 1))
|
||||
ret->r = chead;
|
||||
} else {
|
||||
else
|
||||
ret->l = chead;
|
||||
}
|
||||
ret->parent = chead->parent;
|
||||
chead->parent = ret;
|
||||
*candidate = ret;
|
||||
@@ -826,7 +819,7 @@ next:
|
||||
char pbuffer[128], cbuffer[128];
|
||||
sx_prefix_snprintf(prefix, pbuffer, sizeof(pbuffer));
|
||||
sx_prefix_snprintf(chead->prefix, cbuffer, sizeof(cbuffer));
|
||||
printf("Unreachible point... eb=%i, prefix=%s, chead=%s\n", eb,
|
||||
printf("Unreachable point... eb=%i, prefix=%s, chead=%s\n", eb,
|
||||
pbuffer, cbuffer);
|
||||
abort();
|
||||
}
|
||||
@@ -848,7 +841,7 @@ sx_radix_node_fprintf(struct sx_radix_node *node, void *udata)
|
||||
|
||||
int
|
||||
sx_radix_node_foreach(struct sx_radix_node *node,
|
||||
void (*func)(struct sx_radix_node*, void*), void *udata)
|
||||
void (*func)(struct sx_radix_node *, void *), void *udata)
|
||||
{
|
||||
func(node, udata);
|
||||
|
||||
@@ -1055,7 +1048,7 @@ sx_radix_tree_aggregate(struct sx_radix_tree *tree)
|
||||
static void
|
||||
setGlueUpTo(struct sx_radix_node *node, void *udata)
|
||||
{
|
||||
unsigned refine = *(unsigned*)udata;
|
||||
unsigned refine = *(unsigned *)udata;
|
||||
|
||||
if (node && node->prefix->masklen <= refine)
|
||||
node->isGlue = 1;
|
||||
@@ -1115,7 +1108,7 @@ sx_radix_tree_refine(struct sx_radix_tree *tree, unsigned refine)
|
||||
static void
|
||||
setGlueFrom(struct sx_radix_node *node, void *udata)
|
||||
{
|
||||
unsigned refine = *(unsigned*)udata;
|
||||
unsigned refine = *(unsigned *)udata;
|
||||
|
||||
if (node && node->prefix->masklen <= refine)
|
||||
node->isGlue = 1;
|
||||
|
||||
@@ -68,7 +68,7 @@ struct sx_radix_node *sx_radix_tree_lookup_exact(struct sx_radix_tree *tree,
|
||||
struct sx_prefix *prefix);
|
||||
|
||||
struct sx_prefix *sx_prefix_alloc(struct sx_prefix *p);
|
||||
void sx_prefix_destroy(struct sx_prefix *p);
|
||||
void sx_prefix_free(struct sx_prefix *p);
|
||||
void sx_radix_node_destroy(struct sx_radix_node *p);
|
||||
void sx_prefix_adjust_masklen(struct sx_prefix *p);
|
||||
struct sx_prefix *sx_prefix_new(int af, char *text);
|
||||
|
||||
Reference in New Issue
Block a user