128 Commits
0.0.8 ... main

Author SHA1 Message Date
Denis Fondras
20673db180 Remove extraneous space in Arista prefixlist (#124)
Some checks failed
Build and test (latest Ubuntu/macOS) / build (ubuntu-latest) (push) Successful in 30s
Build and test (latest Ubuntu/macOS) / build (macos-latest) (push) Has been cancelled
basic unit tests / output unit tests (push) Has been cancelled
CodeQL analysis / Analyze (cpp) (push) Failing after 2m11s
* Remove extraneous space in Arista prefixlist

When diffing config generated with bgpq4 with config exported from an Arista device, many lines are returned as changed. This is because prefixlist on Arista device use 3 spaces and bgpq4 uses 4 spaces.

* Update eos--4.txt

* Update eos--6.txt
2025-02-21 20:55:15 +01:00
Job Snijders
4cae7d1df5 test if symlink
Some checks failed
Build and test (latest Ubuntu/macOS) / build (ubuntu-latest) (push) Successful in 28s
Build and test (latest Ubuntu/macOS) / build (macos-latest) (push) Has been cancelled
basic unit tests / output unit tests (push) Has been cancelled
CodeQL analysis / Analyze (cpp) (push) Failing after 1m12s
2025-02-08 13:25:31 +00:00
Job Snijders
851d1c6cf1 force cp when not symlink 2025-02-08 13:23:01 +00:00
Job Snijders
f53fbba8b3 only add awk in fedora42
Some checks failed
Build and test (latest Ubuntu/macOS) / build (macos-latest) (push) Waiting to run
basic unit tests / output unit tests (push) Waiting to run
Build and test (latest Ubuntu/macOS) / build (ubuntu-latest) (push) Successful in 27s
CodeQL analysis / Analyze (cpp) (push) Failing after 28s
Build and test (linux matrix) / build (alpine:3.21) (push) Failing after 5s
Build and test (linux matrix) / build (alpine:edge) (push) Failing after 5s
Build and test (linux matrix) / build (centos/centos:stream10) (push) Failing after 5s
Build and test (linux matrix) / build (centos/centos:stream9) (push) Failing after 5s
Build and test (linux matrix) / build (debian:bookworm) (push) Failing after 5s
Build and test (linux matrix) / build (debian:bullseye) (push) Failing after 5s
Build and test (linux matrix) / build (debian:trixie) (push) Failing after 4s
Build and test (linux matrix) / build (fedora/fedora:40) (push) Failing after 4s
Build and test (linux matrix) / build (fedora/fedora:41) (push) Failing after 4s
Build and test (linux matrix) / build (fedora/fedora:42) (push) Failing after 4s
Build and test (linux matrix) / build (rockylinux/rockylinux:8) (push) Failing after 4s
Build and test (linux matrix) / build (rockylinux/rockylinux:9) (push) Failing after 5s
Build and test (linux matrix) / build (ubuntu:focal) (push) Failing after 5s
Build and test (linux matrix) / build (ubuntu:jammy) (push) Failing after 5s
Build and test (linux matrix) / build (ubuntu:noble) (push) Failing after 5s
2025-02-07 15:41:31 +00:00
Job Snijders
282378e673 add awk to fedora42 image
Some checks failed
Build and test (latest Ubuntu/macOS) / build (macos-latest) (push) Waiting to run
basic unit tests / output unit tests (push) Waiting to run
Build and test (latest Ubuntu/macOS) / build (ubuntu-latest) (push) Successful in 28s
CodeQL analysis / Analyze (cpp) (push) Failing after 1m9s
Build and test (linux matrix) / build (alpine:3.21) (push) Failing after 5s
Build and test (linux matrix) / build (alpine:edge) (push) Failing after 5s
Build and test (linux matrix) / build (centos/centos:stream10) (push) Failing after 4s
Build and test (linux matrix) / build (centos/centos:stream9) (push) Failing after 4s
Build and test (linux matrix) / build (debian:bookworm) (push) Failing after 5s
Build and test (linux matrix) / build (debian:bullseye) (push) Failing after 5s
Build and test (linux matrix) / build (debian:trixie) (push) Failing after 5s
Build and test (linux matrix) / build (fedora/fedora:40) (push) Failing after 5s
Build and test (linux matrix) / build (fedora/fedora:41) (push) Failing after 5s
Build and test (linux matrix) / build (fedora/fedora:42) (push) Failing after 4s
Build and test (linux matrix) / build (rockylinux/rockylinux:8) (push) Failing after 4s
Build and test (linux matrix) / build (rockylinux/rockylinux:9) (push) Failing after 5s
Build and test (linux matrix) / build (ubuntu:focal) (push) Failing after 5s
Build and test (linux matrix) / build (ubuntu:jammy) (push) Failing after 5s
Build and test (linux matrix) / build (ubuntu:noble) (push) Failing after 5s
2025-02-07 15:28:14 +00:00
Denis Fondras
60a3b3dabf Forbid -e -E -6 (#123)
The resulting list is a bit weird 😉 

```
 permit ip host 2a05:6340:: host 255.255.255.248
 permit ip host 2a06:19c0:: host 255.255.255.248
 permit ip host 2a07:4b00:: host 255.255.255.248
 permit ip host 2a07:7b40:: host 255.255.255.248
```
2025-02-07 10:08:06 -05:00
Robert Scheck
b769ad9ce6 Update workflow actions and containers (#121) 2024-12-26 02:21:19 +01:00
Robert Scheck
0678439386 Update matrixbuild to current Linux distributions (#120) 2024-12-25 12:21:17 +01:00
Yureka
c51fddefe5 filter out ASN 0 in juniper as-lists (#117)
Fixes error "RPD Policy: Invalid AS 0"
2024-10-16 16:01:36 +00:00
Job Snijders
ad20b71f70 add symlinks, thanks rsc 2024-08-25 13:02:15 +00:00
Job Snijders
983c4f74c2 maybe this one? 2024-08-25 11:19:29 +00:00
Job Snijders
8ed8ae112f Update build targets 2024-08-25 11:07:59 +00:00
Tim de Boer
44e97736ac Remove extra space for MikroTik's RouterOS V7 rules (#115) 2024-08-25 11:01:51 +00:00
Job Snijders
7bd337eac3 Respin release 2024-05-15 11:25:17 +00:00
Job Snijders
4dd3b92b3c Release 1.14 2024-05-15 11:24:02 +00:00
Job Snijders
a97f7eb4ff Update changelog 2024-05-13 12:19:19 +00:00
Robert Scheck
4ab84255a4 Work around broken Docker image by Rocky Linux (until CentOS 7 is EOL) (#114) 2024-05-10 12:16:04 +02:00
Job Snijders
424770be0b Set TCP_NODELAY on the socket
Nagle's algorithm probably serves no purpose with whois queries
often being tiny.
2024-05-10 09:41:28 +00:00
Robert Scheck
4bac9e7e53 Skip online test if no or empty /etc/resolv.conf (#113)
Downstream build systems, e.g. at Linux distributions like Fedora,
might be (sealed) offline (chroot) environments.
2024-05-05 22:33:12 +00:00
Robert Scheck
2ec0ea3fbd Don't try to login and push to GHCR on forks (#112) 2024-05-03 23:55:16 +02:00
Job Snijders
0a83c7598d Fix comma display in ingress IOS XR as-path-set printing 2024-05-01 12:26:30 +00:00
Job Snijders
f44bf47b1f Don't try to maximize the send buffer
Get rid of code that did a binary search to maximize the send buffer
via setsockopt SO_SNDBUF. It caused problems for modern Mac users.
2024-05-01 12:00:17 +00:00
Job Snijders
9ffc4f8ec6 Add missing newline 2024-05-01 12:00:09 +00:00
Job Snijders
a89ac75590 experiment 1 2024-05-01 11:45:59 +00:00
Job Snijders
59f800f31f Do not fiddle with the socket buffer size 2024-05-01 11:20:41 +00:00
Job Snijders
6c8bb871c0 fix path 2024-05-01 11:08:19 +00:00
Job Snijders
26b0827813 Add simple check target 2024-05-01 11:03:05 +00:00
Job Snijders
36a54c9b41 reference correct CI badge 2024-04-30 23:49:23 +00:00
Job Snijders
e743be94b3 add build imagery 2024-04-30 23:46:41 +00:00
Robert Scheck
b631d43755 Modernize usage of autoconf macros (#110) 2024-04-30 23:42:39 +00:00
Robert Scheck
57a70da5a9 Bump GitHub action versions in workflows (#106) 2024-04-30 23:41:45 +00:00
Job Snijders
95d3a4c12b Release 1.12 2024-02-12 16:57:03 +00:00
Robert Scheck
2e06d3c389 Update matrixbuild to current Linux distributions (#99) 2023-12-10 05:08:50 +01:00
Darshan Kowlaser
3d2eed555d fixed - mikrotik routerosv7 output (#103)
* fixed - mikrotik routerosv7 output

* fixed - mikrotik routerosv7 output

---------

Co-authored-by: dkayza-xxx <darshan@darshankowlaser.com>
2023-11-27 19:17:36 +01:00
Job Snijders
a28752247c update changelog 2023-06-20 12:24:28 +00:00
Job Snijders
26d631b257 By default disallow 23456 as origin
Can be bypassed with '-p'
2023-06-20 12:18:41 +00:00
Job Snijders
841840be68 whoops, forgot to bump version 2023-06-17 05:33:11 +00:00
J vanBemmel
8ae08b79b1 Update README.md - document -n2 option (#95) 2023-06-04 00:56:09 +02:00
Roman Dodin
9fa14cc506 Added container build workflow (#94)
* added container build workflow

* remove unneeded env var
2023-06-03 12:13:53 +02:00
J vanBemmel
92561f43af Add a line to usage (#92) 2023-05-26 13:03:59 +00:00
J vanBemmel
aee7adb698 Add support for Nokia SR Linux IP prefix lists / ACL filters (#91)
* Add support for Nokia SR Linux prefix sets

* Update tests

* Update docs

* Fix ACL prefix filter
2023-05-25 18:47:09 +02:00
Richard Laager
3c201684b6 Accept -3 as a no-op for bgpq3 compatibility (#90)
bgpq4 already assumes 32-bit ASN support.

Closes #89
2023-05-15 19:42:25 +02:00
Robert Scheck
b98ecd5d4d Add macOS to CI builds (#88) 2023-04-12 03:35:36 +09:00
James Bensley
d14db9515f Add github workflow for basic unit tests (#87)
Add github workflow for basic unit tests

authored-by: James Bensley <jwbensley@gmail.com>
2023-04-07 07:11:15 +09:00
Job Snijders
8883f13b74 Release 1.9 2023-03-05 12:09:54 +00:00
James Bensley
31ce2e452f Fix issue bgp#83 - fix regression bug which ignored -S CLI option (#1) (#85)
* Fix issue bgp#83 - fix regression bug which ignored -S CLI option (#1)

* Fix issue #83 - fix regression bug which ignored -S CLI option, introduced by commit 08b81f7d19
---------

Co-authored-by: James Bensley <jwbensley@gmail.com>

* Fix off-by-one error

* Swap strlcpy for strdup

---------

Co-authored-by: James Bensley <jwbensley@gmail.com>
2023-03-05 12:08:11 +00:00
Job Snijders
b85bea6324 update CHANGELOG 2023-01-20 15:54:38 +00:00
Job Snijders
6fdae48462 It was argued that upgrading the 'key not found' from DEBUG to ERROR was too verbose 2023-01-20 15:50:25 +00:00
Robert Scheck
89ab54454e Document -p option in README.md again (#81)
Commit 975b577b2e unfortunately misses
the first part of commit dec08b1580.
2023-01-11 00:13:42 +01:00
Robert Scheck
baddc22f15 Update matrixbuild to current Linux distributions (#80) 2023-01-10 00:37:33 +01:00
Job Snijders
0deb7f224c Switch strcpy to strlcpy 2023-01-09 21:08:08 +00:00
Job Snijders
975b577b2e Restore -p functionality 2023-01-09 21:05:39 +00:00
Job Snijders
b785c02e37 KNF 2022-11-07 13:53:01 +00:00
Job Snijders
017bae280f remove trailing spaces 2022-11-07 13:08:02 +00:00
Denis Fondras
2921348a98 add support for Mikrotik ROSv7 filters (#72)
* add support for Mikrotik ROSv7 filters

* Rework Mikrotik ROSv7 option

- Use same option key with a modifier
- avoid some code duplication

* update doc

Co-authored-by: Denis <denis@jig-ai.ledeuns.net>
2022-11-05 12:06:54 +01:00
Robert Scheck
233380d4e9 Remove option to accept routes registered for private ASNs (#77) 2022-11-05 00:40:38 +01:00
Robert Scheck
509e2f0acf Remove non-existing -P option from documentation (#73) 2022-11-05 00:26:13 +01:00
Robert Scheck
a6b41d9352 Fix typo: inifinity -> infinity (#78) 2022-11-05 00:25:50 +01:00
Robert Scheck
7ac2068879 Add CodeQL analysis (#76)
LGTM.com will be shut down in December 2022 and recommend to use GitHub code scanning instead.
See also: https://github.blog/2022-08-15-the-next-step-for-lgtm-com-github-code-scanning/
2022-11-05 00:02:27 +01:00
Robert Scheck
fc79ff9242 Use to GitHub actions/checkout@v3 (#75) 2022-11-05 00:01:30 +01:00
Job Snijders
277126f5ea Release 1.7 2022-11-03 10:17:20 +00:00
James Bensley
08b81f7d19 Parse 'SOURCE::' to only use a specific source for an AS-SET or Route Set
This extension allows operators to specify what IRR source to use when expanding an AS-SET.

For example: `bgpq4 RIPE::AS15562:AS-SNIJDERS`

The notation is also used in databases like PeeringDB.

Authored-by: James Bensley <jwbensley@gmail.com>
2022-11-03 10:09:29 +00:00
Job Snijders
24c3e08f0e alphabetical order 2022-09-13 04:56:21 +00:00
Job Snijders
30110bad46 new release 2022-09-07 12:49:37 +00:00
Job Snijders
5507267c63 Fix prefix address range parsing
This solves #65
2022-09-07 12:48:06 +00:00
Job Snijders
ab683d75d5 rename destroy to free 2022-09-07 12:34:17 +00:00
Job Snijders
fb955c0521 KNF 2022-09-07 10:54:06 +00:00
Robert Scheck
4661fab181 Update matrixbuild to current Linux distributions (#62) 2022-08-03 08:36:45 +00:00
Job Snijders
6484a9a40c fix typo 2022-07-25 14:15:29 +00:00
Jeremiah Millay
3ec83e255a Bump version and change log for 1.5 release (#61) 2022-07-25 16:11:44 +02:00
Job Snijders
c01ebfc3cb cleanup 2022-07-25 09:18:33 +00:00
Job Snijders
8dfcfb3173 add RPKI source (available via most irrd4 instances) 2022-07-25 09:11:23 +00:00
Fiona Weber
c2126343cf Add AS-List Feature for JunOS (#57)
Co-authored-by: Fiona Weber <fiona.weber@wobcom.de>
2022-07-07 09:07:24 +02:00
Massimiliano Stucchi
96079b8901 Improve readability of the manpage (#59) 2022-06-07 11:20:16 -04:00
Job Snijders
58521eb687 Remove a bashism (thanks Marco D'Itri!) 2022-02-11 14:47:48 +00:00
Robert Scheck
8b804f83fd Update matrixbuild to current Linux distributions (#55)
Previously, at the time of #50, broken Fedora Rawhide, 35, CentOS
Stream 9 (development) have been fixed. Switch Alpine 3.14 -> 3.15.
2022-02-06 09:30:05 +01:00
Job Snijders
f26a04e8dd Remove unused header includes.
Thanks Gavin Henry (@ghenry) for reporting.

This fixes #53
2021-10-04 09:50:14 +00:00
Job Snijders
392a44a536 update docs 2021-09-21 20:41:30 +00:00
Stefan Marti
2aed3f9e67 Huawei XPL format support (#45)
Add Huawei XPL format support
2021-09-02 20:45:45 +00:00
Robert Scheck
d285db3c81 Update matrixbuild to current Linux distributions (#50)
Debian 12, 11 and 10, Ubuntu 20.04 and 16.04, Fedora 34 and 33,
CentOS Stream 8 and CentOS Linux 7, Rocky Linux 8, Alpine Edge and
3.14.

Note: Especially CentOS containers are better maintained on Quay.io
rather on Docker Hub (likely because it's a Red Hat service).

CentOS Linux 8 reaches EOL on 2021-12-31 and is superseeded by Rocky
Linux 8 as alternative bug-for-bug compatible RHEL 8 rebuild.

Fedora Rawhide, 35 and CentOS Stream 9 (development) are currently
broken: https://bugzilla.redhat.com/show_bug.cgi?id=1988199#c13
2021-08-30 11:09:29 +00:00
Job Snijders
5d27a24659 reformat main getopt routine 2021-08-22 23:00:51 +00:00
Vincent Bernat
97d1f2acda Add missing .Ed to manual page (#49) 2021-08-20 19:59:07 +02:00
Job Snijders
61a7bcf671 Pretify bird aspath output 2021-08-20 11:19:41 +00:00
Job Snijders
e920d74007 Slightly tweak whitespaces in extended cisco output 2021-08-20 11:14:42 +00:00
Job Snijders
b1074667e8 Add missing closure in bird aspath output 2021-08-20 10:58:07 +00:00
Job Snijders
bdc455d72e Update information on SOURCES 2021-08-20 10:22:19 +00:00
Job Snijders
8cc7ba2751 Bump version 2021-08-20 10:08:59 +00:00
Job Snijders
06b430b420 align bgpq4_print_cisco_aspath and bgpq4_print_cisco_oaspath 2021-08-20 03:51:51 +00:00
Job Snijders
8c51669da9 Clarify what options are mutually exclusive
This fixes #20
2021-08-20 03:06:26 +00:00
Job Snijders
dc1270f10f Improve mikrotik output
This fixes #32
2021-08-20 02:44:37 +00:00
Job Snijders
362f747f0f Let OS decide on buffer size 2021-08-20 02:10:31 +00:00
Job Snijders
6c8c6cfec1 Reduce memory usage 2021-08-20 01:58:38 +00:00
Job Snijders
fb29cd54e1 make local functions static 2021-08-20 01:12:43 +00:00
Job Snijders
903704ef3b Update CHANGES 2021-08-20 01:03:18 +00:00
Job Snijders
b481111cf6 Replace ASN storage facility with Red Black tree macros (RB_) 2021-08-20 00:50:56 +00:00
Job Snijders
80b7dcf4de KNF & renaming 2021-08-19 20:21:25 +00:00
Job Snijders
5ce7d7bfea Untangle function and KNF 2021-08-19 19:59:21 +00:00
Job Snijders
8ec260f03f chop off first and last line 2021-08-19 16:08:37 +00:00
Job Snijders
675155356d Make note of Ben's extra aggregation trick 2021-08-19 16:02:03 +00:00
Job Snijders
da750ed48f KNF 2021-08-19 15:39:19 +00:00
Job Snijders
7fdb481130 bump version 2021-08-19 15:31:25 +00:00
Job Snijders
fa84d146b3 Also put manpage in distribution tarball 2021-08-19 15:30:02 +00:00
Job Snijders
c90c59dba8 Update manpage and readme 2021-08-19 15:20:53 +00:00
Job Snijders
5730525f11 Fix manpage escaping 2021-08-19 15:04:07 +00:00
Job Snijders
78f57867cc Improve manpage 2021-08-19 14:59:58 +00:00
Job Snijders
2391fdb317 Typo 2021-08-19 14:06:01 +00:00
Job Snijders
9f8d82db21 Ensure all queries end with a newline 2021-08-19 13:19:05 +00:00
Job Snijders
a6792d2495 bump version 2021-08-19 08:20:32 +00:00
Caleb Xu
af202a821b compat: don't build when strlcpy is present (#47) 2021-08-19 08:19:44 +00:00
Job Snijders
ed8ee8368d Additionally add copyright file in the root directory. 2021-08-18 20:54:46 +00:00
Job Snijders
bf5f10def9 Rework where newlines are inserted 2021-08-18 16:56:13 +00:00
Job Snijders
1f7572c2f1 KNF 2021-08-18 12:28:57 +00:00
Job Snijders
34cc813446 Remove reference to bgpq4.spec 2021-08-18 10:57:49 +00:00
Job Snijders
5c57bb2bb6 Remove old spec file 2021-08-18 09:49:04 +00:00
Job Snijders
e6bf77058a remove sx_slentry.h 2021-08-18 02:05:40 +00:00
Job Snijders
139e0d972b include stdio 2021-08-18 02:01:03 +00:00
Job Snijders
99f036b186 KNF 2021-08-18 01:58:47 +00:00
Job Snijders
cb98214f0c remove stale comment 2021-08-18 01:38:47 +00:00
Job Snijders
ed28cf6734 Update README 2021-08-18 01:31:25 +00:00
Job Snijders
9ac2087d24 KNF 2021-08-18 01:16:29 +00:00
Job Snijders
58adb550bd KNF 2021-08-18 00:50:22 +00:00
Job Snijders
773849fc3a Release 0.0.9 2021-08-18 00:46:52 +00:00
Job Snijders
40656fbbbf Clean up comments 2021-08-18 00:40:02 +00:00
Job Snijders
4a8dc682fd Add more free() to counter memory errors 2021-08-18 00:38:44 +00:00
Job Snijders
450286a010 plug memory leaks 2021-08-18 00:18:26 +00:00
Job Snijders
a055f6f2ee Adding a free(), KNF 2021-08-17 23:51:18 +00:00
Job Snijders
c4c5866fa3 Fold freeall functions into expander.c 2021-08-17 23:03:29 +00:00
Job Snijders
6074f816e0 rename main program and add AM conditional 2021-08-17 23:00:06 +00:00
92 changed files with 2999 additions and 2089 deletions

17
.github/images/alpine.Dockerfile vendored Normal file
View 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.21.Dockerfile vendored Symbolic link
View File

@@ -0,0 +1 @@
alpine.Dockerfile

24
.github/images/alpine:3.Dockerfile vendored Normal file
View File

@@ -0,0 +1,24 @@
# to build the image locally tagged with the short commit hash:
# docker build -t bgpq4:$(git rev-parse --short HEAD) -f .github/images/alpine:3.Dockerfile .
ARG IMAGE=alpine:3
FROM $IMAGE as builder
# 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
FROM alpine:3
COPY --from=builder /src/bgpq4 /bgp/
WORKDIR /bgp
ENTRYPOINT [ "./bgpq4" ]

1
.github/images/alpine:edge.Dockerfile vendored Symbolic link
View File

@@ -0,0 +1 @@
alpine.Dockerfile

View File

@@ -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 dnf -y update
RUN dnf -y install autoconf automake gcc libtool make diffutils file gzip
# Add source code
ADD . /src
@@ -16,4 +15,3 @@ RUN ./configure
RUN make
RUN make check
RUN make distcheck

View File

@@ -0,0 +1 @@
../centos.Dockerfile

View File

@@ -0,0 +1 @@
../centos.Dockerfile

View File

@@ -1 +0,0 @@
centos.Dockerfile

View File

@@ -1 +0,0 @@
centos.Dockerfile

View File

@@ -0,0 +1 @@
../centos.Dockerfile

View File

@@ -0,0 +1 @@
../centos.Dockerfile

View File

@@ -0,0 +1,17 @@
ARG image=centos/centos:latest
FROM quay.io/$image
# Install dependencies
RUN dnf -y update
RUN dnf -y install autoconf automake gcc libtool make diffutils file gzip awk
# Add source code
ADD . /src
WORKDIR /src
# Run steps
RUN ./bootstrap
RUN ./configure
RUN make
RUN make check
RUN make distcheck

View File

@@ -1 +0,0 @@
centos.Dockerfile

View File

@@ -1 +0,0 @@
centos.Dockerfile

View File

@@ -0,0 +1 @@
../centos.Dockerfile

View File

@@ -0,0 +1 @@
../centos.Dockerfile

1
.github/images/ubuntu:jammy.Dockerfile vendored Symbolic link
View File

@@ -0,0 +1 @@
debian.Dockerfile

1
.github/images/ubuntu:noble.Dockerfile vendored Symbolic link
View File

@@ -0,0 +1 @@
debian.Dockerfile

65
.github/workflows/build-container.yml vendored Normal file
View File

@@ -0,0 +1,65 @@
name: Container build
"on":
push:
tags:
- "*" # Push events to any tag
branches:
- "main"
workflow_dispatch:
inputs:
tag:
description: "Container tag to use for the build"
required: true
default: "test"
jobs:
test:
uses: ./.github/workflows/unit-tests.yml
build:
name: Build container
runs-on: ubuntu-24.04
needs: test
steps:
- name: Checkout
uses: actions/checkout@v4
- # Add support for more platforms with QEMU
# https://github.com/docker/setup-qemu-action
name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository_owner }}/bgpq4
tags: |
# pick up tag provided from workflow_dispatch user's input
type=raw,value=${{ inputs.tag }}
type=ref,event=tag
type=ref,event=branch
# git short commit
type=sha
- name: Login to GitHub Container Registry
if: github.repository_owner == 'bgp'
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v6
with:
file: .github/images/alpine:3.Dockerfile
context: .
platforms: linux/amd64,linux/arm64
push: ${{ github.repository_owner == 'bgp' }}
tags: ${{ steps.meta.outputs.tags }}

View File

@@ -1,12 +1,18 @@
name: Build and test (single linux distro)
name: Build and test (latest Ubuntu/macOS)
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v4
- name: install macOS autogen prerequisites
run: brew install autoconf automake libtool
if: runner.os == 'macOS'
- name: bootstrap
run: ./bootstrap
- name: configure
@@ -17,4 +23,5 @@ jobs:
run: make check
- name: make distcheck
run: make distcheck
if: runner.os == 'Linux'

38
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@@ -0,0 +1,38 @@
name: CodeQL analysis
on:
push:
pull_request:
schedule:
# build the main branch every Tuesday morning
- cron: '15 6 * * 2'
workflow_dispatch:
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'cpp' ]
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
- name: Build Application using script
run: |
./bootstrap
./configure
make
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"

View File

@@ -9,15 +9,25 @@ jobs:
fail-fast: false
matrix:
dockerenv:
- debian:buster
- debian:stretch
- ubuntu:bionic
- ubuntu:xenial
- centos:8
- centos:7
- fedora:31
- fedora:30
- debian:trixie
- debian:bookworm
- debian:bullseye
- ubuntu:noble
- ubuntu:jammy
- ubuntu:focal
- fedora/fedora:42
- fedora/fedora:41
- fedora/fedora:40
- centos/centos:stream10
- centos/centos:stream9
- rockylinux/rockylinux:9
- rockylinux/rockylinux:8
- alpine:edge
- alpine:3.21
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v4
- name: Work around Docker BuildKit regression
# https://github.com/moby/buildkit/issues/2119: `DOCKER_BUILDKIT=1 docker build` fails if Dockerfile is a symlink
run: [ -L .github/images/${{matrix.dockerenv}}.Dockerfile ] && cp --remove-destination $(readlink -f .github/images/${{matrix.dockerenv}}.Dockerfile) .github/images/${{matrix.dockerenv}}.Dockerfile
- name: Run build on ${{matrix.dockerenv}}
run: docker build . --file .github/images/${{matrix.dockerenv}}.Dockerfile --build-arg image=${{matrix.dockerenv}}

40
.github/workflows/unit-tests.yml vendored Normal file
View File

@@ -0,0 +1,40 @@
name: basic unit tests
on:
pull_request:
types:
- opened
- edited
- reopened
- ready_for_review
- synchronize
push:
branches:
- main
workflow_call:
jobs:
output-unit-tests:
name: output unit tests
runs-on: ubuntu-24.04
steps:
- name: clone repo
uses: actions/checkout@v4
- name: install pre-reqs
run: |
sudo apt-get update
DEBIAN_FRONTEND=noninteractive sudo apt-get -y --no-install-recommends install autoconf automake libtool make
- name: build bgpq4
run: |
./bootstrap
./configure
make
./bgpq4 -v
- name: generate output
run: ./tests/generate_outputs.sh ./bgpq4 /tmp
- name: check output
run: >
for file in tests/reference/*.txt;
do
echo "$(sha256sum "${file}" | awk '{print $1}') /tmp/$(basename "${file}")" | sha256sum --check;
done

51
CHANGES
View File

@@ -1,3 +1,54 @@
1.15 (2024-05-15)
- Apologies, debug code slipped into the last release
1.14 (2024-05-14)
- Small performance gain: set TCP_NODELAY on the socket
1.13 (2024-05-01)
- Fixed a bug for Mac users by removing sx_maxsockbuf()
- Fixed a comma printing bug in IOS XR as-path-set output
1.12 (2024-02-12)
- Fix a bug in the mikrotik printer
1.11 (2023-06-20)
- disallow AS 23456 as origin (can be bypassed via -p)
1.10 (2023-06-03)
- Add support for Nokia SR Linux IP prefix lists / ACL filters
- Accept -3 as a no-op for bgpq3 compatibility
1.9 (2023-03-05)
- Bugfix for -S problem (bgpq4#83) by James Bensley
1.8 (2023-01-20)
- Downgrade 'key not found' to DEBUG level to reduce noise
- Re-introduce -p for private ASN support option
1.7 (2022-11-03)
- Support SOURCE:: syntax (contributed by James Bensley)
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
1.3 (2021-08-20)
- Change versioning from X.Y.Z to Y.Z
- The repository file hierachy has been reorganized (compat/ include/)
- Man page has been extended
- Large portions of code have been reformatted to adhere to OpenBSD's source
file style guide to improve readability.
- Refactor: replace two-dimensional array for ASN storage with Red-Black tree
- Reduced memory usage
0.0.9 (2021-08-18)
- Fix various memory errors
0.0.8 (2021-08-17)
- Reorganize automake files and includes
- Normalize code to adhere to KNF

View File

@@ -1,4 +1,4 @@
/*
/*-
* Copyright (c) 2007-2019 Alexandre Snarskii <snar@snar.spb.ru>
* All rights reserved.
*
@@ -22,26 +22,5 @@
* 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.
*
*/
#ifndef SX_SLENTRY_H_
#define SX_SLENTRY_H_
#include <sys/queue.h>
#include <sys/tree.h>
struct sx_slentry {
STAILQ_ENTRY(sx_slentry) next;
char* text;
};
struct sx_slentry* sx_slentry_new(char* text);
struct sx_tentry {
RB_ENTRY(sx_tentry) entry;
char* text;
};
struct sx_tentry* sx_tentry_new(char* text);
#endif

29
IDEAS Normal file
View File

@@ -0,0 +1,29 @@
Ben Maddison taught me another aggregation trick:
route-set: AS37271:RS-EXAMPLE
mp-members: 192.0.2.0/27
mp-members: 192.0.2.32/27
mp-members: 192.0.2.64/27
mp-members: 192.0.2.96/27
mp-members: 192.0.2.128/26
mp-members: 192.0.2.128/27
mp-members: 192.0.2.160/27
mp-members: 192.0.2.192/27
mp-members: 192.0.2.224/27
descr: Example route-set
mnt-by: MAINT-AS37271
changed: benm@workonline.africa 20210819
source: RADB
BGPQ4 produces the following:
$ bgpq4 -A AS37271:RS-EXAMPLE
no ip prefix-list NN
ip prefix-list NN permit 192.0.2.0/25 ge 27 le 27
ip prefix-list NN permit 192.0.2.128/26 le 27
ip prefix-list NN permit 192.0.2.192/26 ge 27 le 27
But the following aggregation also is valid, and shorter:
ip prefix-list NN permit 192.0.2.0/24 ge 27 le 27
ip prefix-list NN permit 192.0.2.128/26

View File

@@ -1,4 +1,4 @@
SUBDIRS = include compat
SUBDIRS = include
ACLOCAL_AMFLAGS = -I m4
AM_CPPFLAGS = -I$(top_srcdir)/include
@@ -10,15 +10,19 @@ bin_PROGRAMS=bgpq4
dist_man8_MANS=bgpq4.8
bgpq4_LDADD = $(PLATFORM_LDADD) $(PROG_LDADD)
if !HAVE_STRLCPY
SUBDIRS += compat
bgpq4_LDADD += $(top_builddir)/compat/libcompat.la
endif
bgpq4_SOURCES=bgpq4.c extern.h bgpq4_printer.c bgpq_expander.c \
expander_freeall.c sx_maxsockbuf.c \
sx_prefix.c sx_prefix.h sx_report.c sx_report.h \
sx_slentry.c sx_slentry.h
bgpq4_SOURCES=main.c extern.h printer.c expander.c \
sx_prefix.c sx_prefix.h \
sx_report.c sx_report.h \
sx_slentry.c
EXTRA_DIST=bootstrap README.md CHANGES bgpq4.spec
EXTRA_DIST=bootstrap README.md CHANGES
MAINTAINERCLEANFILES=configure aclocal.m4 compile \
install-sh missing Makefile.in depcomp \
@@ -28,3 +32,12 @@ MAINTAINERCLEANFILES=configure aclocal.m4 compile \
maintainer-clean-local:
-rm -rf m4 autom4te.cache
check:
./bgpq4 -v
@echo
-if [ -s /etc/resolv.conf ]; then \
./bgpq4 -ddd -6 AS15562:AS-SNIJDERS ; \
else \
echo "No or empty /etc/resolv.conf, skipping online test"; \
fi

604
README.md
View File

@@ -1,237 +1,252 @@
NAME
----
[![CI](https://github.com/bgp/bgpq4/actions/workflows/unit-tests.yml/badge.svg)](https://github.com/bgp/bgpq4/actions/workflows/unit-tests.yml)
`bgpq4` - bgp filtering automation tool
<a href="https://repology.org/project/bgpq4/versions">
<img src="https://repology.org/badge/vertical-allrepos/bgpq4.svg" alt="Packaging status" align="right">
</a>
SYNOPSIS
--------
# NAME
```
bgpq4 [-h host[:port]] [-S sources] [-Ez] [-f asn | -F fmt | -G asn | -t] [-46ABbDdeJjNnpsUX] [-a asn] [-r len] [-R len] [-m max] [-W len] OBJECTS [...] EXCEPT OBJECTS
```
**bgpq4** - bgp filtering automation tool
DESCRIPTION
-----------
# SYNOPSIS
The bgpq4 utility used to generate configuration (prefix-lists,
extended access-lists, policy-statement terms and as-path lists)
based on IRR routing data.
**bgpq4**
\[**-h**&nbsp;*host\[:port]*]
\[**-S**&nbsp;*sources*]
\[**-EPz**]
\[**-f**&nbsp;*asn*&nbsp;|
**-F**&nbsp;*fmt*&nbsp;|
**-G**&nbsp;*asn*
**-H**&nbsp;*asn*
**-t**]
\[**-46ABbDdJjNnpsXU**]
\[**-a**&nbsp;*asn*]
\[**-r**&nbsp;*len*]
\[**-R**&nbsp;*len*]
\[**-m**&nbsp;*max*]
\[**-W**&nbsp;*len*]
*OBJECTS*
\[...]
\[EXCEPT&nbsp;OBJECTS]
The options are as follows:
# DESCRIPTION
#### -4
The
**bgpq4**
utility is used to generate configurations (prefix-lists, extended
access-lists, policy-statement terms and as-path lists) based on IRR data.
Generate IPv4 prefix/access-lists (default).
It's options are as follows:
#### -6
**-4**
Generate IPv6 prefix/access-lists (IPv4 by default).
> generate IPv4 prefix/access-lists (default).
#### -A
**-6**
Try to aggregate generated filters as much as possible (not all output formats
supported).
> generate IPv6 prefix/access-lists (IPv4 by default).
#### -a asn
**-A**
Specify ASN that shall be denied in case of empty prefix-list (OpenBGPD).
> try to aggregate prefix-lists as much as possible (not all output
> formats supported).
#### -B
**-a** *asn*
Generate output in OpenBGPD format.
> specify what asn shall be denied in case of empty prefix-list (OpenBGPD)
#### -b
**-B**
Generate output in BIRD format.
> generate output in OpenBGPD format (default: Cisco)
#### -d
**-b**
Enable some debugging output.
> generate output in BIRD format (default: Cisco).
#### -E
**-d**
Generate extended access-list (Cisco) or policy-statement term using
route-filters (Juniper), [ip|ipv6]-prefix-list (Nokia) or prefix-filter
(OpenBGPD)
> enable some debugging output.
#### -e
**-e**
Generate output in Arista EOS format.
> generate output in Arista EOS format (default: Cisco).
#### -f `AS number`
**-E**
Generate input as-path access-list for adjacent as `AS number`.
> generate extended access-list (Cisco), policy-statement term using
> route-filters (Juniper), \[ip|ipv6]-prefix-list (Nokia) or prefix-sets
> (OpenBGPd).
#### -F `fmt`
**-f** *number*
Generate output in user-defined format.
> generate input as-path access-list.
#### -G `number`
**-F** *fmt*
Generate output as-path access-list.
> generate output in user-defined format.
#### -h `host[:port]`
**-G** *number*
Host running IRRD database (default: `rr.ntt.net`).
> generate output as-path access-list.
#### -J
**-H** *number*
Generate config for Juniper.
> generate output as-list for JunOS 21.3R1+ `as-path-origin` filter (JunOS only)
#### -j
**-h** *host\[:port]*
Generate output in JSON format.
> host running IRRD database (default: rr.ntt.net).
#### -K
**-J**
Generate config for MikroTik.
> generate config for Juniper (default: Cisco).
#### -m `length`
**-j**
Maximum length of accepted prefixes (default: `32` for IPv4, `128` for IPv6).
> generate output in JSON format (default: Cisco).
#### -M `match`
**-K**
Extra match conditions for Juniper route-filters. See the examples section.
> generate config for Mikrotik ROSv6 (default: Cisco).
#### -n
**-K7**
Generate config for Nokia SR OS (former Alcatel-Lucent) MD-CLI.
> generate config for Mikrotik ROSv7 (default: Cisco).
#### -N
**-l** *name*
Generate config for Nokia SR OS (former Alcatel-Lucent) classic CLI.
> name of generated entry.
#### -l `name`
**-L** *limit*
`Name` of generated configuration stanza.
> limit recursion depth when expanding as-sets.
#### -L `limit`
**-m** *len*
Limit recursion depth when expanding. This slows `bgpq4` a bit, but sometimes
is a useful feature to prevent generated filters from growing too big.
> maximum prefix-length of accepted prefixes (default: 32 for IPv4 and
> 128 for IPv6).
#### -p
**-M** *match*
Enable use of private ASNs and ASNs used for documentation purpose only
(default: disabled).
> extra match conditions for Juniper route-filters.
#### -r `length`
**-n**
Allow more-specific routes with masklen starting with specified length.
> generate config for Nokia SR OS MD-CLI (Cisco IOS by default)
#### -R `length`
**-n2**
Allow more-specific routes up to specified masklen too. (Please, note: objects
with prefix-length greater than specified length will be always allowed.)
> generate config for Nokia SR Linux (Cisco IOS by default)
#### -s
**-N**
Generate sequence numbers in IOS-style prefix-lists.
> generate config for Nokia SR OS classic CLI (Cisco IOS by default).
#### -S `sources`
**-p**
Use specified sources only (recommended: RADB,RIPE,APNIC).
> emit prefixes where the origin ASN is in the private ASN range
> (disabled by default).
#### -t
**-r** *len*
Generate as-sets for OpenBGPD (OpenBSD 6.4+), BIRD and JSON formats.
> allow more specific routes starting with specified masklen too.
#### -T
**-R** *len*
Disable pipelining (not recommended).
> allow more specific routes up to specified masklen too.
#### -U
**-s**
Generate output in Huawei format.
> generate sequence numbers in IOS-style prefix-lists.
#### -W `length`
**-S** *sources*
Generate as-path strings of a given length maximum (0 for infinity).
> use specified sources only (recommended: RPKI,AFRINIC,ARIN,APNIC,LACNIC,RIPE).
#### -X
**-t**
Generate output in Cisco IOS XR format.
> generate as-sets for OpenBGPd, BIRD and JSON formats.
#### -z
**-T**
Generate Juniper route-filter-list (JunOS 16.2+).
> disable pipelining (not recommended).
#### `OBJECTS`
**-W** *len*
`OBJECTS` means networks (in prefix format), autonomous systems, as-sets and
route-sets. If multiple objects are specified they will be merged.
> generate as-path strings of no more than len items (use 0 for infinity).
#### `EXCEPT OBJECTS`
**-U**
You can exclude autonomous sets, as-sets and route-sets found during
expansion from future expansion.
> generate config for Huawei devices (Cisco IOS by default)
EXAMPLES
--------
Generating prefix filter for MikroTik for `AS20597`:
**-u**
$ ./bgpq4 -Kl eltel-v4 AS20597
/routing filter add action=accept chain="eltel-v4" prefix=81.9.0.0/20
/routing filter add action=accept chain="eltel-v4" prefix=81.9.32.0/20
/routing filter add action=accept chain="eltel-v4" prefix=81.9.96.0/20
/routing filter add action=accept chain="eltel-v4" prefix=81.222.128.0/20
/routing filter add action=accept chain="eltel-v4" prefix=81.222.160.0/20
/routing filter add action=accept chain="eltel-v4" prefix=81.222.192.0/18
/routing filter add action=accept chain="eltel-v4" prefix=85.249.8.0/21
/routing filter add action=accept chain="eltel-v4" prefix=85.249.224.0/19
/routing filter add action=accept chain="eltel-v4" prefix=89.112.0.0/17
/routing filter add action=accept chain="eltel-v4" prefix=217.170.64.0/19
> generate output in Huawei XPL format.
Generating named Juniper prefix-filter for `AS20597`:
**-X**
$ bgpq4 -Jl eltel-v4 AS20597
policy-options {
replace:
prefix-list eltel-v4 {
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;
}
}
> generate config for Cisco IOS XR devices (plain IOS by default).
**-z**
> generate route-filter-lists (JunOS 16.2+).
*OBJECTS*
> means networks (in prefix format), autonomous systems, as-sets and route-sets.
*EXCEPT OBJECTS*
> those objects will be excluded from expansion.
# EXAMPLES
Generating named juniper prefix-filter for AS20597:
$ bgpq4 -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:
$ bgpq4 -Al eltel-v4 AS20597
no ip prefix-list eltel-v4
ip prefix-list eltel-v4 permit 81.9.0.0/20
ip prefix-list eltel-v4 permit 81.9.32.0/20
ip prefix-list eltel-v4 permit 81.9.96.0/20
ip prefix-list eltel-v4 permit 81.222.128.0/20
ip prefix-list eltel-v4 permit 81.222.192.0/18
ip prefix-list eltel-v4 permit 85.249.8.0/21
ip prefix-list eltel-v4 permit 85.249.224.0/19
ip prefix-list eltel-v4 permit 89.112.0.0/18 ge 19 le 19
ip prefix-list eltel-v4 permit 89.112.4.0/22
ip prefix-list eltel-v4 permit 89.112.64.0/19
ip prefix-list eltel-v4 permit 217.170.64.0/19 ge 20 le 20
$ bgpq4 -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.0.0/19` and `89.112.32.0/19` now aggregated
into single entry
Prefixes 89.112.0.0/19 and 89.112.32.0/19 now aggregated
into single entry 89.112.0.0/18 ge 19 le 19.
ip prefix-list eltel permit 89.112.0.0/18 ge 19 le 19.
Well, for Juniper we can generate even more interesting policy-options,
using -M &lt;extra match conditions&gt;, -R &lt;len&gt; and hierarchical names:
Well, for Juniper we can generate even more interesting policy-statement,
using `-M <extra match conditions>`, `-r <len>`, `-R <len>` and hierarchical
names:
$ bgpq4 -AJEl eltel/specifics -r 29 -R 32 -M "community blackhole" AS20597
$ bgpq4 -AJEl eltel/specifics -r 29 -R 32 -M "community blackhole" AS20597
policy-options {
policy-statement eltel {
term specifics {
@@ -252,51 +267,83 @@ names:
}
}
generated policy-option term now allows all specifics with prefix-length
between /29 and /32 for eltel networks if they match with special community
blackhole (defined elsewhere in configuration).
generated policy-option term now allows more-specific routes in range
/29 - /32 for eltel networks if they marked with community 'blackhole'
(defined elsewhere in configuration).
Of course, this version supports IPv6 (-6):
Of course, `bgpq4` supports IPv6 (-6):
$ bgpq4 -6l as-retn-v6 AS-RETN6
no ipv6 prefix-list as-retn-v6
ipv6 prefix-list as-retn-v6 permit 2001:7fb:fe00::/48
ipv6 prefix-list as-retn-v6 permit 2001:7fb:fe01::/48
[....]
$ bgpq4 -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 assumes your device supports 32-bit ASNs
$ bgpq4 -Jf 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|23600|24151|25152|31529|34127|34906)$";
as-path a3 "^112(.)*(35052|41720|43628|44450|196611)$";
}
}
$ bgpq4 -Jf 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 a 32-bit ASN.
see \`AS196611\` in the end of the list ? That's a 32-bit ASN.
USER-DEFINED FORMAT
-------------------
# USER-DEFINED FORMAT
If you want to generate configuration not for routers, but for some
other programs/systems, you may use user-defined formatting, like in
example below:
$ bgpq4 -F "ipfw add pass all from %n/%l to any\\n" as3254
$ bgpq4 -F "ipfw add pass all from %n/%l to any\n" as3254
ipfw add pass all from 62.244.0.0/18 to any
ipfw add pass all from 91.219.29.0/24 to any
ipfw add pass all from 91.219.30.0/24 to any
ipfw add pass all from 193.193.192.0/19 to any
Recognized format characters: '%n' - network, '%l' - mask length,
'%a' - aggregate low mask length, '%A' - aggregate high mask length,
'%N' - object name, '%m' - object mask and '%i' - inversed mask.
Recognized escape characters: '\n' - new line, '\t' - tabulation.
Recognized format sequences are:
**%n**
> network
**%l**
> mask length
**%a**
> aggregate low mask length
**%A**
> aggregate high mask length
**%N**
> object name
**%m**
> object mask
**%i**
> inversed mask
**&#92;n**
> new line
**&#92;t**
> tabulation
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):
@@ -304,101 +351,192 @@ be in one line (sometimes it makes sense):
$ bgpq4 -6F "%n/%l; " as-eltel
2001:1b00::/32; 2620:4f:8000::/48; 2a04:bac0::/29; 2a05:3a80::/48;
DIAGNOSTICS
-----------
# NOTES ON SOURCES
When everything is OK, `bgpq4` 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.
By default *bgpq4* trusts data from all databases mirrored into NTT's IRR service.
Unfortunately, not all these databases are equal in how much can we trust their
data.
RIR maintained databases (AFRINIC, ARIN, APNIC, LACNIC and RIPE)
shall be trusted more than the others because they have the knowledge about
which address space is allocated to each ASN, other databases lack this
knowledge and can (and actually do) contain some stale data: nobody but RIRs
care to remove outdated route-objects when address space is revoked from one
ASN and allocated to another. In order to keep their filters both compact and
current, *bgpq4 users* are encouraged to use one of two method to limit
database sources to only ones they trust.
NOTES ON ULTRA-LARGE PREFIX-LISTS
---------------------------------
One option is to use the '-S' flag. This limits all queries to a specific data
source. For example, the following command tells IIRd to only use data from
the RIPE RIR DB to build the prefix list for the AS-SET:
To improve `bgpq4` performance when expanding extra-large AS-SETs you
$./bgpq4 -S RIPE AS-VOSTRON
no ip prefix-list NN
ip prefix-list NN permit 89.21.224.0/19
ip prefix-list NN permit 134.0.64.0/21
Be aware though, than an AS-SET may contain members from other data sources.
In this case IRRd won't respond to the bgpq4 query will all the prefixes in the
AS-SET tree. Make sure to use the '-S' flag with all the data sources required
for the AS-SET being expanded:
$./bgpq4 -S RIPE,ARIN AS-VOSTRON
no ip prefix-list NN
ip prefix-list NN permit 89.21.224.0/19
ip prefix-list NN permit 134.0.64.0/21
ip prefix-list NN permit 208.86.232.0/24
ip prefix-list NN permit 208.86.233.0/24
ip prefix-list NN permit 208.86.234.0/24
ip prefix-list NN permit 208.86.235.0/24
The other option is to specify a source for an AS-SET or Route Set using the
"::" notation. When bgpq4 detects this, it will look for "::" in the specified
AS-SET or RS on the CLI, and in all members of the AS-SET/RS, and for each
member with a data source specified in "::" format, it will set the IRRd data
source to the given value, query the AS-SET/RS, then reset the data sources back
to the default list for the next object in the tree.
$./bgpq4 RIPE::AS-VOSTRON
no ip prefix-list NN
ip prefix-list NN permit 89.21.224.0/19
ip prefix-list NN permit 134.0.64.0/21
ip prefix-list NN permit 208.86.232.0/22
ip prefix-list NN permit 208.86.232.0/24
ip prefix-list NN permit 208.86.233.0/24
ip prefix-list NN permit 208.86.234.0/24
ip prefix-list NN permit 208.86.235.0/24
In comparison to the '-S' flag, this method return all the prefixes under the
AS-SET, but the root of the tree "AS-VOSTRON" was queries from RIPE only. None
of the member objects used the "::" notation so they were queries from the
default source list (which is all sources).
General recommendations:
Use minimal set of RIR databases (only those in which you and your
customers have registered route-objects).
Avoid using ARIN-NONAUTH and RIPE-NONAUTH as trusted sources: 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.
$ bgpq4 -S RIPE,RADB as-space
no ip prefix-list NN
ip prefix-list NN permit 195.190.32.0/19
$ bgpq4 -S RADB,RIPE as-space
no ip prefix-list NN
ip prefix-list NN permit 45.4.4.0/22
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
[...]
When known, use the "::" notation to speicy the authortative data source for
an AS-SET or RS instead of the -S flag.
# PERFORMANCE
To improve \`bgpq4\` performance when expanding extra-large AS-SETs you
shall tune OS settings to enlarge TCP send buffer.
FreeBSD can be tuned in the following way:
sysctl -w net.inet.tcp.sendbuf_max=2097152
sysctl -w net.inet.tcp.sendbuf_max=2097152
Linux can be tuned in the following way:
sysctl -w net.ipv4.tcp_window_scaling=1
sysctl -w net.core.rmem_max=2097152
sysctl -w net.core.wmem_max=2097152
sysctl -w net.ipv4.tcp_rmem="4096 87380 2097152"
sysctl -w net.ipv4.tcp_wmem="4096 65536 2097152"
sysctl -w net.ipv4.tcp_window_scaling=1
Please note that generated prefix-lists may not fit your router's
limitations. For example, JunOS supports only 85,325 prefixes in
each prefix-list [4](http://www.juniper.net/techpubs/en_US/junos11.4/topics/reference/configuration-statement/prefix-list-edit-policy-options.html).
sysctl -w net.core.rmem_max=2097152
sysctl -w net.core.wmem_max=2097152
BUILDING
--------
sysctl -w net.ipv4.tcp_rmem="4096 87380 2097152"
sysctl -w net.ipv4.tcp_wmem="4096 65536 2097152"
# CONTAINER IMAGE
A multi-arch (linux/amd64 and linux/arm64) container image is built automatically for all tagged releases and `main` branch. The image is based on Alpine Linux and is available on [GitHub Container Registry](https://github.com/bgp/bgpq4/pkgs/container/bgpq4).
Using the image is as simple as:
```
docker run --rm ghcr.io/bgp/bgpq4:latest -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.160.0/20;
81.222.192.0/18;
85.249.8.0/21;
85.249.224.0/19;
89.112.0.0/17;
217.170.64.0/19;
}
}
```
# BUILDING
This project uses autotools. If you are building from the repository,
run the following command to prepare the build system:
./bootstrap
./bootstrap
In order to compile the software, run:
./configure
make
make install
./configure
make
make install
If you wish to remove the generated build system files from your
working tree, run:
make maintainer-clean
make maintainer-clean
In order to create a distribution archive, run:
make dist
make dist
PACKAGE INSTALLATION
--------------------
# DIAGNOSTICS
In FreeBSD binary package can be installed using
When everything is OK,
**bgpq4**
generates access-list to standard output and exits with status == 0.
In case of errors they are printed to stderr and the program exits with
non-zero status.
```shell
pkg install bgpq4
```
# TESTS
Or from ports with `portmaster`
The [tests/](tests/) folder contains reference output data in [text files](tests/reference/). The [generate_outputs.sh](tests/generate_outputs.sh) script is used in the [Github workflow](.github/workflows/unit-tests.yml) to generate the same output data, using the latest commit, and compare the output data to the stored "known-good" reference data, and check there are no changes.
```shell
portmaster net-mgmt/bgpq4
```
To update the reference data (i.e. if the bgpq4 output is modified), simply run the script again (`./tests/generate_outputs.sh ./bgpq4 tests/reference`) and commit the changes.
On Arch Linux, BGPQ4 is [available in AUR](https://aur.archlinux.org/packages/bgpq4/):
```shell
yay -S bgpq4
```
MAILING LIST
------------
Users and interested parties can subscribe to the BGPQ4 mailing list [bgpq4@tcp0.com](https://tcp0.com/cgi-bin/mailman/listinfo/bgpq4).
SEE ALSO
--------
NLNOG's [BGP Filter Guide](http://bgpfilterguide.nlnog.net/)
AUTHORS
-------
# AUTHORS
Alexandre Snarskii, Christian David, Claudio Jeker, Job Snijders,
Massimiliano Stucchi, Michail Litvak, Peter Schoenmaker, Roelf Wichertjes,
and contributions from many others.
Project
-------
# SEE ALSO
BGPQ4 is maintained by Job Snijders `<job@sobornost.net>`.
**https://github.com/bgp/bgpq4**
BGPQ4 on Github.
[https://github.com/bgp/bgpq4](https://github.com/bgp/bgpq4)
**http://bgpfilterguide.nlnog.net/**
NLNOG's BGP Filter Guide.
**https://tcp0.com/cgi-bin/mailman/listinfo/bgpq4**
Users and interested parties can subscribe to the BGPQ4 mailing list bgpq4@tcp0.com
# PROJECT MAINTAINER
Job Snijders &lt;job@sobornost.net&gt;

View File

@@ -1 +1 @@
0.0.8
1.15

148
bgpq4.8
View File

@@ -37,9 +37,10 @@
.Fl f Ar asn |
.Fl F Ar fmt |
.Fl G Ar asn
.Fl H Ar asn
.Fl t
.Oc
.Op Fl 46ABbDdJjNnsXU
.Op Fl 46ABbDdJjNnpsXU
.Op Fl a Ar asn
.Op Fl r Ar len
.Op Fl R Ar len
@@ -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
@@ -90,7 +95,9 @@ generate config for Juniper (default: Cisco).
.It Fl j
generate output in JSON format (default: Cisco).
.It Fl K
generate config for Mikrotik (default: Cisco).
generate config for Mikrotik ROSv6 (default: Cisco).
.It Fl K7
generate config for Mikrotik ROSv7 (default: Cisco).
.It Fl l Ar name
name of generated entry.
.It Fl L Ar limit
@@ -102,12 +109,13 @@ maximum prefix-length of accepted prefixes (default: 32 for IPv4 and
extra match conditions for Juniper route-filters.
.It Fl n
generate config for Nokia SR OS MD-CLI (Cisco IOS by default)
.It Fl n2
generate config for Nokia SR Linux (Cisco IOS by default)
.It Fl N
generate config for Nokia SR OS classic CLI (Cisco IOS by default).
.It Fl p
accept routes registered for private ASNs (default: disabled)
.It Fl P
generate prefix-list (default, backward compatibility).
emit prefixes where the origin ASN is 23456 or in the private ASN range
(disabled by default).
.It Fl r Ar len
allow more specific routes starting with specified masklen too.
.It Fl R Ar len
@@ -115,15 +123,17 @@ 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
disable pipelining (not recommended).
.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 u
generate config for Huawei devices in XPL format (Cisco IOS by default)
.It Fl W Ar len
generate as-path strings of no more than len items (use 0 for infinity).
.It Fl X
generate config for Cisco IOS XR devices (plain IOS by default).
.It Fl z
@@ -178,7 +188,8 @@ ip prefix-list eltel permit 89.112.64.0/19
ip prefix-list eltel permit 217.170.64.0/19 ge 20 le 20
.Ed
.fi
- you see, prefixes 89.112.0.0/19 and 89.112.32.0/19 now aggregated
.Pp
Prefixes 89.112.0.0/19 and 89.112.32.0/19 now aggregated
into single entry 89.112.0.0/18 ge 19 le 19.
.Pp
Well, for Juniper we can generate even more interesting policy-options,
@@ -251,27 +262,130 @@ ipfw add pass all from 193.193.192.0/19 to any
.Ed
.fi
.Pp
Recognized format characters: %n - network, %l - mask length,
%a - aggregate low mask length, %A - aggregate high mask length,
%N - object name, %m - object mask and %i - inversed mask.
Recognized escape characters: \\n - new line, \\t - tabulation.
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):
Recognized format sequences are:
.Pp
.Bl -tag -width Ds -offset indent -compact
.It Cm %n
network
.It Cm %l
mask length
.It Cm %a
aggregate low mask length
.It Cm \&%A
aggregate high mask length
.It Cm \&%N
object name
.It Cm %m
object mask
.It Cm %i
inversed mask
.It Cm \en
new line
.It Cm \et
tabulation
.El
.Pp
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
2001:1b00::/32; 2620:4f:8000::/48; 2a04:bac0::/29; 2a05:3a80::/48;
.Ed
.fi
.Sh NOTES ON SOURCES
By default
.Em bgpq4
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 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
the ones they trust.
.Pp
General recommendations:
.Pp
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 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
ip prefix-list NN permit 195.190.32.0/19
$ bgpq4 -S RADB,RIPE as-space
no ip prefix-list NN
ip prefix-list NN permit 45.4.4.0/22
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.
.Pp
FreeBSD can be tuned in the following way:
.Pp
.Dl sysctl -w net.inet.tcp.sendbuf_max=2097152
.Pp
Linux can be tuned in the following way:
.Pp
.Dl sysctl -w net.ipv4.tcp_window_scaling=1
.Dl sysctl -w net.core.rmem_max=2097152
.Dl sysctl -w net.core.wmem_max=2097152
.Dl sysctl -w net.ipv4.tcp_rmem="4096 87380 2097152"
.Dl sysctl -w net.ipv4.tcp_wmem="4096 65536 2097152"
.Sh BUILDING
This project uses autotools. If you are building from the repository,
run the following command to prepare the build system:
.Pp
.Dl ./bootstrap
.Pp
In order to compile the software, run:
.Pp
.Dl ./configure
.Dl make
.Dl make install
.Pp
If you wish to remove the generated build system files from your
working tree, run:
.Pp
.Dl make maintainer-clean
.Pp
In order to create a distribution archive, run:
.Pp
.Dl make dist
.Sh DIAGNOSTICS
When everything is OK,
.Nm
generates access-list to standard output and exits with status == 0.
In case of errors they are printed to stderr and program exits with
non-zero status.
.Sh AUTHORS
Alexandre Snarskii, Christian David, Claudio Jeker, Job Snijders,
Massimiliano Stucchi, Michail Litvak, Peter Schoenmaker, Roelf Wichertjes,
and contributions from many others.
.Sh SEE ALSO
.Sy https://github.com/bgp/bgpq4
BGPQ4 on Github.
.Pp
.Sy http://bgpfilterguide.nlnog.net/
NLNOG's BGP Filter Guide.
.Pp
.Sy https://tcp0.com/cgi-bin/mailman/listinfo/bgpq4
Users and interested parties can subscribe to the BGPQ4 mailing list bgpq4@tcp0.com
.Sh PROJECT MAINTAINER
.An Job Snijders Aq job@sobornost.net

View File

@@ -1,88 +0,0 @@
Name: bgpq4
Version: 0.0.6
Release: 0%{?dist}
Group: System/Utilities
Summary: Generate BGP filters based on routing database information
URL: https://github.com/bgp/bgpq4
License: BSD
Source0: https://github.com/bgp/bgpq4
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
%description
You are running BGP in your network and want to automate filter generation for your routers? Well, with BGPQ4 it's easy.
%prep
%setup -q
%global debug_package %{nil}
%build
./configure --prefix=$RPM_BUILD_ROOT%{_prefix} --mandir=%{_mandir}
make
%install
rm -rf $RPM_BUILD_ROOT
mkdir -p $RPM_BUILD_ROOT/usr/bin
make install
%files
%defattr(-,root,root,-)
/usr/bin/bgpq4
/usr/man/man8/bgpq4.8.gz
%doc COPYRIGHT CHANGES
%clean
rm -rf $RPM_BUILD_ROOT
%changelog
* Thu Mar 12 2020 Job Snijders <job@ntt.net> 0.0.6:
- bugfixes (Thanks Chris Caputo!)
* Wed Jan 01 2020 Job Snijders <job@ntt.net> 0.0.5:
- bugfixes
* Tue Dec 31 2019 Job Snijders <job@ntt.net> 0.0.4
- Remove '-3' command line option, assume all devices are 32-bit ASN safe
* Mon Dec 30 2019 Job Snijders <job@ntt.net> 0.0.3
- Remove the '-2' command line option
- Significant code reformating
- Improve performance by using IRRd 4's A query when available
* Sat Dec 14 2019 Job Snijders <job@ntt.net> 0.0.2
- Add Mikrotik support
- Remove ASDDOT support
* Sat Dec 14 2019 Job Snijders <job@ntt.net> 0.0.1
- Fork from bgpq3
* Tue Nov 30 2018 Alexandre Snarskii <snar@snar.spb.ru> 0.1.35
- Version updated
* Fri Oct 14 2016 Alexandre Snarskii <snar@snar.spb.ru> 0.1.33
- Version updated
* Tue Jun 23 Alexandre Snarskii <snar@snar.spb.ru> 0.1.31
- Version updated
* Tue Mar 10 Alexandre Snarskii <snar@snar.spb.ru> 0.1.28
- Version updated
* Wed Oct 29 Alexandre Snarskii <snar@snar.spb.ru> 0.1.25
- Version updated
* Thu Jun 5 2014 Alexandre Snarskii <snar@snar.spb.ru> 0.1.21-0.snar
- Version updated
* Thu May 9 2013 Alexandre Snarskii <snar@snar.spb.ru> 0.1.19-0.snar
- Version updated
* Sun Feb 24 2013 Alexandre Snarskii <snar@snar.spb.ru> 0.1.18-3.snar
- License corrected
* Wed Feb 20 2013 Arnoud Vermeer <arnoud@tumblr.com> 0.1.18-2.tumblr
- Adding missing group info (arnoud@tumblr.com)
* Wed Feb 20 2013 Arnoud Vermeer <arnoud@tumblr.com> 0.1.18-1.tumblr
- new package built with tito

View File

@@ -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

View File

@@ -2,9 +2,6 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
noinst_LTLIBRARIES = libcompat.la
libcompat_la_SOURCES =
libcompat_la_LIBADD = $(PLATFORM_LDADD)
if !HAVE_STRLCPY
libcompat_la_SOURCES += strlcpy.c
endif
libcompat_la_SOURCES = strlcpy.c

View File

@@ -13,7 +13,7 @@
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
AC_INIT([bgpq4], m4_esyscmd([tr -d '\n' < VERSION]), job@sobornost.net)
AC_INIT([bgpq4], m4_esyscmd([tr -d '\n' < VERSION]), [job@sobornost.net])
AC_CANONICAL_HOST
AM_INIT_AUTOMAKE([subdir-objects foreign])
@@ -56,9 +56,8 @@ AM_CONDITIONAL([HOST_NETBSD], [test x$HOST_OS = xnetbsd])
AM_CONDITIONAL([HOST_SOLARIS], [test x$HOST_OS = xsolaris])
AC_PROG_CC
AC_PROG_CC_STDC
AM_PROG_CC_C_O
AC_PROG_LIBTOOL
LT_INIT
AC_PROG_INSTALL
AC_ARG_ENABLE(warnings,
@@ -107,6 +106,7 @@ AC_CHECK_LIB(nsl,getaddrinfo)
AC_CHECK_HEADERS([sys/cdefs.h sys/queue.h sys/tree.h sys/select.h])
AM_CONDITIONAL([HAVE_PLEDGE], [test "x$ac_cv_func_pledge" = xyes])
AM_CONDITIONAL([HAVE_STRLCPY], [test "x$ac_cv_func_strlcpy" = xyes])
AC_CONFIG_FILES([

File diff suppressed because it is too large Load Diff

View File

@@ -1,109 +0,0 @@
/*
* Copyright (c) 2019-2020 Job Snijders <job@sobornost.net>
* Copyright (c) 2018 Peter Schoenmaker <pds@ntt.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include "extern.h"
void
sx_radix_node_freeall(struct sx_radix_node *n) {
if (n->l != NULL)
sx_radix_node_freeall(n->l);
if (n->r != NULL)
sx_radix_node_freeall(n->r);
if (n->son != NULL)
sx_radix_node_freeall(n->son);
if (n->payload)
free(n->payload);
sx_prefix_destroy(n->prefix);
free(n);
}
void
sx_radix_tree_freeall(struct sx_radix_tree *t) {
if (t->head != NULL)
sx_radix_node_freeall(t->head);
free(t);
}
void
bgpq_prequest_freeall(struct bgpq_prequest *bpr) {
}
void
expander_freeall(struct bgpq_expander *expander) {
// printf("starting to free all\n");
// seg fault here
// if (expander->sources != NULL) {
// printf("freeing soruces\n");
// free(expander->sources);
//}
// if (expander->name != NULL) {
// printf("freeing name\n");
// free(expander->name);
//}
// printf("freeing asn32s\n");
for (int i = 0; i < 65536; i++) {
if (expander->asn32s[i] != NULL) {
free(expander->asn32s[i]);
}
}
// if (expander->match != NULL) {
// printf("freeing match\n");
// free(expander->match);
//}
//if (expander->server != NULL) {
// printf("freeing server\n");
// free(expander->server);
//}
//if (expander->port != NULL) {
// printf("freeing port\n");
// free(expander->port);
//}
//if (expander->format != NULL) {
// printf("freeing format\n");
// free(expander->format);
//}
sx_radix_tree_freeall(expander->tree);
bgpq_prequest_freeall(expander->firstpipe);
bgpq_prequest_freeall(expander->lastpipe);
// printf("finished freeing all\n");
}

137
extern.h
View File

@@ -25,9 +25,28 @@
*/
#include <sys/queue.h>
#include <sys/tree.h>
#include "sx_prefix.h"
#include "sx_slentry.h"
struct slentry {
STAILQ_ENTRY(slentry) entry;
char *text;
};
struct slentry *sx_slentry_new(char *text);
struct sx_tentry {
RB_ENTRY(sx_tentry) entry;
char *text;
};
struct sx_tentry *sx_tentry_new(char *text);
struct asn_entry {
RB_ENTRY(asn_entry) entry;
uint32_t asn;
};
typedef enum {
V_CISCO = 0,
@@ -39,15 +58,19 @@ typedef enum {
V_FORMAT,
V_NOKIA,
V_HUAWEI,
V_MIKROTIK,
V_HUAWEI_XPL,
V_MIKROTIK6,
V_MIKROTIK7,
V_NOKIA_MD,
V_ARISTA
V_ARISTA,
V_NOKIA_SRL,
} bgpq_vendor_t;
typedef enum {
T_NONE = 0,
T_ASPATH,
T_OASPATH,
T_ASLIST,
T_ASSET,
T_PREFIXLIST,
T_EACL,
@@ -56,68 +79,76 @@ typedef enum {
struct bgpq_expander;
struct bgpq_request {
STAILQ_ENTRY(bgpq_request) next;
char *request;
int size, offset;
int (*callback)(char*, struct bgpq_expander*, struct bgpq_request*);
void *udata;
unsigned int depth;
struct request {
STAILQ_ENTRY(request) next;
char *request;
int size, offset;
void *udata;
unsigned int depth;
int (*callback)(char *, struct bgpq_expander *,
struct request *);
};
struct bgpq_expander {
struct sx_radix_tree *tree;
STAILQ_HEAD(sx_slentries, sx_slentry) macroses, rsets;
RB_HEAD(tentree, sx_tentry) already, stoplist;
int family;
char *sources;
uint32_t asnumber;
int aswidth;
char *name;
bgpq_vendor_t vendor;
bgpq_gen_t generation;
int identify;
int sequence;
unsigned int maxdepth;
unsigned int cdepth;
int validate_asns;
unsigned char *asn32s[65536];
struct bgpq_prequest *firstpipe, *lastpipe;
int piped;
char *match;
char *server;
char *port;
char *format;
unsigned int maxlen;
STAILQ_HEAD(bgpq_requests, bgpq_request) wq, rq;
int fd;
struct sx_radix_tree *tree;
int family;
char *sources;
char *defaultsources;
unsigned int usesource;
uint32_t asnumber;
int aswidth;
char *name;
bgpq_vendor_t vendor;
bgpq_gen_t generation;
int identify;
int sequence;
unsigned int maxdepth;
unsigned int cdepth;
int validate_asns;
struct bgpq_prequest *firstpipe, *lastpipe;
int piped;
char *match;
char *server;
char *port;
char *format;
unsigned int maxlen;
int fd;
RB_HEAD(asn_tree, asn_entry) asnlist;
STAILQ_HEAD(requests, request) wq, rq;
STAILQ_HEAD(slentries, slentry) macroses, rsets;
RB_HEAD(tentree, sx_tentry) already, stoplist;
};
int bgpq_expander_init(struct bgpq_expander* b, int af);
int bgpq_expander_add_asset(struct bgpq_expander* b, char* set);
int bgpq_expander_add_rset(struct bgpq_expander* b, char* set);
int bgpq_expander_add_as(struct bgpq_expander* b, char* as);
int bgpq_expander_add_prefix(struct bgpq_expander* b, char* prefix);
int bgpq_expander_add_prefix_range(struct bgpq_expander* b, char* prefix);
int bgpq_expander_add_stop(struct bgpq_expander* b, char* object);
int asn_cmp(struct asn_entry *, struct asn_entry *);
RB_PROTOTYPE(asn_tree, asn_entry, entry, asn_cmp);
int bgpq_expand(struct bgpq_expander* b);
int bgpq_expander_init(struct bgpq_expander *b, int af);
int bgpq_expander_add_asset(struct bgpq_expander *b, char *set);
int bgpq_expander_add_rset(struct bgpq_expander *b, char *set);
int bgpq_expander_add_as(struct bgpq_expander *b, char *as);
int bgpq_expander_add_prefix(struct bgpq_expander *b, char *prefix);
int bgpq_expander_add_prefix_range(struct bgpq_expander *b, char *prefix);
int bgpq_expander_add_stop(struct bgpq_expander *b, char *object);
int bgpq4_print_prefixlist(FILE* f, struct bgpq_expander* b);
int bgpq4_print_eacl(FILE* f, struct bgpq_expander* b);
int bgpq4_print_aspath(FILE* f, struct bgpq_expander* b);
int bgpq4_print_asset(FILE* f, struct bgpq_expander* b);
int bgpq4_print_oaspath(FILE* f, struct bgpq_expander* b);
int bgpq4_print_route_filter_list(FILE* f, struct bgpq_expander* b);
char* bgpq_get_asset(char *object);
char* bgpq_get_rset(char *object);
char* bgpq_get_source(char *object);
int bgpq_expand(struct bgpq_expander *b);
void bgpq4_print_prefixlist(FILE *f, struct bgpq_expander *b);
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);
void sx_radix_tree_freeall(struct sx_radix_tree *t);
void bgpq_prequest_freeall(struct bgpq_prequest *bpr);
void expander_freeall(struct bgpq_expander *expander);
/* s - number of opened socket, dir is either SO_SNDBUF or SO_RCVBUF */
int sx_maxsockbuf(int s, int dir);
#ifndef HAVE_STRLCPY
size_t strlcpy(char* dst, const char* src, size_t size);
size_t strlcpy(char *dst, const char *src, size_t size);
#endif

View File

@@ -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,19 +50,22 @@ extern int expand_special_asn;
static int
usage(int ecode)
{
printf("\nUsage: bgpq4 [-h host[:port]] [-S sources] [-E|G <num>"
"|f <num>|t] [-46ABbdJjKNnwXz] [-R len] <OBJECTS> ... "
printf("\nUsage: bgpq4 [-h host[:port]] [-S sources] [-E|G|H <num>"
"|f <num>|t] [-46ABbdJjKNnpwXz] [-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");
printf(" -K : MikroTik RouterOSv6\n");
printf(" -K7 : MikroTik RouterOSv7\n");
printf(" -b : NIC.CZ BIRD\n");
printf(" -N : Nokia SR OS (Classic CLI)\n");
printf(" -n : Nokia SR OS (MD-CLI)\n");
printf(" -n2 : Nokia SR Linux\n");
printf(" -B : OpenBSD OpenBGPD\n");
printf(" -e : Arista EOS\n");
printf(" -F fmt : User defined format (example: '-F %%n/%%l')\n");
@@ -81,6 +82,7 @@ usage(int ecode)
"registered routes\n");
printf("\nOutput modifiers:\n");
printf(" -3 : assume that your device is asn32-safe (default)\n");
printf(" -A : try to aggregate prefix-lists/route-filters\n");
printf(" -E : generate extended access-list (Cisco), "
"route-filter (Juniper)\n"
@@ -88,16 +90,18 @@ 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");
printf(" -p : allow special ASNs like 23456 or in the private range\n");
printf(" -R len : allow more specific routes up to specified masklen\n");
printf(" -r len : allow more specific routes from masklen specified\n");
printf(" -s : generate sequence numbers in prefix-lists (IOS only)\n");
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");
@@ -124,8 +128,8 @@ version(void)
static void
exclusive(void)
{
fprintf(stderr,"-E, -f <asnum>, -G <asnum>, and -t are mutually "
"exclusive\n");
fprintf(stderr,"-E, -F, -K , -f <asnum>, -G <asnum>, and -t are mutually"
" exclusive\n");
exit(1);
}
@@ -133,9 +137,9 @@ static void
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");
" -j (JSON), -K[7] (Microtik ROS), -N (Nokia SR OS Classic),"
" -n (Nokia SR OS MD-CLI), -U (Huawei), -u (Huawei XPL),"
"-e (Arista) and -X (IOS XR) options are mutually exclusive\n");
exit(1);
}
@@ -190,161 +194,175 @@ main(int argc, char* argv[])
exit(1);
}
#endif
bgpq_expander_init(&expander, af);
if (getenv("IRRD_SOURCES"))
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) {
"23467a:AbBdDEeF:S:jJKf:l:L:m:M:NnpW:r: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 '2':
if (expander.vendor != V_NOKIA_MD) {
sx_report(SX_FATAL, "'2' can only be used after -n\n");
exit(1);
}
expander.vendor = V_NOKIA_SRL;
break;
case '3':
/* do nothing, 32-bit ASN support is assumed */
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);
}
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 '7':
if (expander.vendor != V_MIKROTIK6) {
sx_report(SX_FATAL, "'7' can only be used after -K\n");
exit(1);
}
expander.vendor = V_MIKROTIK7;
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_MIKROTIK6;
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) {
if (*mc == '\\') {
if (*(mc+1) == '\n') {
if (*(mc + 1) == '\n') {
*md = '\n';
md++;
mc += 2;
@@ -377,64 +395,71 @@ 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 'p':
expand_special_asn = 1;
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);
}
}
@@ -447,16 +472,22 @@ main(int argc, char* argv[])
switch (vendor) {
case V_ARISTA:
case V_CISCO:
case V_MIKROTIK:
case V_MIKROTIK6:
case V_MIKROTIK7:
expander.aswidth = 4;
break;
case V_CISCO_XR:
expander.aswidth = 6;
break;
case V_JUNIPER:
case V_NOKIA:
case V_NOKIA_MD:
case V_NOKIA_SRL:
expander.aswidth = 8;
break;
case V_BIRD:
expander.aswidth = 10;
break;
}
} else if (expander.generation == T_OASPATH) {
int vendor = expander.vendor;
@@ -464,12 +495,23 @@ main(int argc, char* argv[])
case V_ARISTA:
case V_CISCO:
expander.aswidth = 5;
break;
case V_CISCO_XR:
expander.aswidth = 7;
break;
case V_JUNIPER:
case V_NOKIA:
case V_NOKIA_MD:
case V_NOKIA_SRL:
expander.aswidth = 8;
break;
}
} else if (expander.generation == T_ASLIST) {
int vendor = expander.vendor;
switch (vendor) {
case V_JUNIPER:
expander.aswidth = 8;
break;
}
}
}
@@ -533,7 +575,7 @@ main(int argc, char* argv[])
}
if (aggregate
&& (expander.vendor == V_NOKIA_MD || expander.vendor == V_NOKIA)
&& (expander.vendor == V_NOKIA_MD || expander.vendor == V_NOKIA || expander.vendor == V_NOKIA_SRL)
&& expander.generation != T_PREFIXLIST) {
sx_report(SX_FATAL, "Sorry, aggregation (-A) is not supported with "
"ip-prefix-lists (-E) on Nokia.\n");
@@ -541,7 +583,7 @@ main(int argc, char* argv[])
}
if (refine
&& (expander.vendor == V_NOKIA_MD || expander.vendor == V_NOKIA)
&& (expander.vendor == V_NOKIA_MD || expander.vendor == V_NOKIA || expander.vendor == V_NOKIA_SRL)
&& expander.generation != T_PREFIXLIST) {
sx_report(SX_FATAL, "Sorry, more-specifics (-R) is not supported with "
"ip-prefix-lists (-E) on Nokia.\n");
@@ -549,7 +591,7 @@ main(int argc, char* argv[])
}
if (refineLow
&& (expander.vendor == V_NOKIA_MD || expander.vendor == V_NOKIA)
&& (expander.vendor == V_NOKIA_MD || expander.vendor == V_NOKIA || expander.vendor == V_NOKIA_SRL)
&& expander.generation != T_PREFIXLIST) {
sx_report(SX_FATAL, "Sorry, more-specifics (-r) is not supported with "
"ip-prefix-lists (-E) on Nokia.\n");
@@ -562,6 +604,14 @@ main(int argc, char* argv[])
exit(1);
}
if (expander.vendor == V_ARISTA
&& expander.generation == T_EACL
&& expander.family == AF_INET6) {
sx_report(SX_FATAL, "Sorry, extended access-lists is not compatible "
"with Arista EOS and IPv6\n");
exit(1);
}
if (expander.sequence
&& (expander.vendor != V_CISCO && expander.vendor != V_ARISTA)) {
sx_report(SX_FATAL, "Sorry, prefix-lists sequencing (-s) supported"
@@ -656,14 +706,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");
}
@@ -672,17 +726,23 @@ main(int argc, char* argv[])
usage(1);
while (argv[0]) {
char *obj = argv[0];
char *delim = strstr(argv[0], "::");
if (delim) {
expander.usesource = 1;
obj = delim + 2;
}
if (!strcmp(argv[0], "EXCEPT")) {
exceptmode = 1;
} else if (exceptmode) {
bgpq_expander_add_stop(&expander, argv[0]);
} else if (!strncasecmp(argv[0], "AS-", 3)) {
} else if (!strncasecmp(obj, "AS-", 3)) {
bgpq_expander_add_asset(&expander, argv[0]);
} else if (!strncasecmp(argv[0], "RS-", 3)) {
} else if (!strncasecmp(obj, "RS-", 3)) {
bgpq_expander_add_rset(&expander, argv[0]);
} else if (!strncasecmp(argv[0], "AS", 2)) {
} else if (!strncasecmp(obj, "AS", 2)) {
char *ec;
if ((ec = strchr(argv[0], ':'))) {
if ((ec = strchr(obj, ':'))) {
if (!strncasecmp(ec + 1, "AS-", 3)) {
bgpq_expander_add_asset(&expander, argv[0]);
} else if (!strncasecmp(ec + 1, "RS-", 3)) {
@@ -700,7 +760,8 @@ main(int argc, char* argv[])
sx_report(SX_ERROR, "Unable to add prefix %s "
"(bad prefix or address-family)\n", argv[0]);
exit(1);
} else if (ec && !bgpq_expander_add_prefix_range(&expander, argv[0])) {
} else if (ec && !bgpq_expander_add_prefix_range(&expander,
argv[0])) {
sx_report(SX_ERROR, "Unable to add prefix-range "
"%s (bad range or address-family)\n",
argv[0]);
@@ -725,22 +786,25 @@ 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);
bgpq4_print_aspath(stdout, &expander);
break;
case T_OASPATH:
bgpq4_print_oaspath(stdout,&expander);
bgpq4_print_oaspath(stdout, &expander);
break;
case T_ASLIST:
bgpq4_print_aslist(stdout, &expander);
break;
case T_ASSET:
bgpq4_print_asset(stdout,&expander);
bgpq4_print_asset(stdout, &expander);
break;
case T_PREFIXLIST:
bgpq4_print_prefixlist(stdout,&expander);
bgpq4_print_prefixlist(stdout, &expander);
break;
case T_EACL:
bgpq4_print_eacl(stdout,&expander);
bgpq4_print_eacl(stdout, &expander);
break;
case T_ROUTE_FILTER_LIST:
bgpq4_print_route_filter_list(stdout, &expander);

File diff suppressed because it is too large Load Diff

View File

@@ -1,137 +0,0 @@
/*
* Copyright (c) 2019-2020 Job Snijders <job@sobornost.net>
* Copyright (c) 2007-2019 Alexandre Snarskii <snar@snar.spb.ru>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* 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.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "extern.h"
#include "sx_report.h"
#ifndef SX_MAXSOCKBUF_MAX
#define SX_MAXSOCKBUF_MAX (2*1024*1024)
#endif
int
sx_maxsockbuf(int s, int dir)
{
int optval = 0, voptval;
int hiconf = -1, loconf = -1;
unsigned int voptlen;
int phase = 0, iterations = 0;
if (s<0) {
sx_report(SX_FATAL,"Unable to maximize sockbuf on invalid "
"socket %i\n", s);
exit(1);
}
voptlen = sizeof(optval);
if (getsockopt(s, SOL_SOCKET, dir, (void*)&optval, &voptlen) == -1) {
sx_report(SX_ERROR,"initial getsockopt failed: %s\n",
strerror(errno));
return -1;
}
for (;;) {
iterations++;
if (phase == 0)
optval<<=1;
else {
if (optval == (hiconf + loconf) / 2)
break;
optval = (hiconf + loconf) / 2;
}
if (optval > SX_MAXSOCKBUF_MAX && phase == 0)
break;
if (setsockopt(s, SOL_SOCKET, dir, (void*)&optval,
sizeof(optval)) == -1) {
if (phase == 0)
phase = 1;
hiconf = optval;
continue;
} else {
loconf = optval;
}
voptlen = sizeof(voptval);
if (getsockopt(s, SOL_SOCKET, dir, (void*)&voptval,
&voptlen) == -1) {
sx_report(SX_ERROR,"getsockopt failed: %s\n",
strerror(errno));
return -1;
} else if (voptval < optval) {
if (phase == 0) {
phase = 1;
optval >>= 1;
continue;
} else if (phase == 1) {
phase = 2;
optval -= 2048;
continue;
} else
break;
} else if (voptval >= SX_MAXSOCKBUF_MAX) {
/*
* ... and getsockopt not failed and voptval>=optval.
* Do not allow to increase sockbuf too much even in
* case OS permits it
*/
break;
}
}
voptlen = sizeof(voptval);
if (getsockopt(s, SOL_SOCKET, dir, (void*)&voptval,
&voptlen) == -1) {
sx_report(SX_ERROR,"getsockopt(final stage) failed: %s\n",
strerror(errno));
return -1;
} else {
/*
printf("Finally got %i bytes of recvspace in %i interations\n",
voptval, iterations);
*/
}
return voptval;
}

View File

@@ -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
@@ -133,16 +135,16 @@ sx_prefix_parse(struct sx_prefix *p, int af, char *text)
{
char *c = NULL;
int masklen, ret;
char mtext[INET6_ADDRSTRLEN+5];
char mtext[INET6_ADDRSTRLEN + 5];
strlcpy(mtext, text, sizeof(mtext));
c = strchr(mtext,'/');
if (c) {
char* eod;
char *eod;
*c = 0;
masklen = strtol(c+1, &eod, 10);
masklen = strtol(c + 1, &eod, 10);
if (eod && eod[0] && !isspace(eod[0])) {
*c = '/';
sx_report(SX_ERROR, "Invalid masklen in prefix %s\n",
@@ -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,46 +280,44 @@ 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);
d + 1);
return 0;
}
*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;
min = strtoul(d+1, &dm, 10);
min = strtoul(d + 1, &dm, 10);
if (dm && *dm == '-' && isdigit(dm[1])) {
max = strtoul(dm + 1, NULL, 10);
} else if (dm && *dm) {
@@ -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;
}
@@ -483,7 +477,7 @@ sx_prefix_snprintf_fmt(struct sx_prefix *p, FILE *f,
}
c += 2;
} else if (*c == '\\') {
switch(*(c+1)) {
switch(*(c + 1)) {
case 'n':
fprintf(f, "\n");
break;
@@ -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);
@@ -925,7 +918,7 @@ sx_radix_node_aggregate(struct sx_radix_node *node)
if (!node->r->isAggregate && !node->l->isAggregate
&& !node->r->isGlue && !node->l->isGlue
&& node->r->prefix->masklen == node->l->prefix->masklen) {
if (node->r->prefix->masklen == node->prefix->masklen+1) {
if (node->r->prefix->masklen == node->prefix->masklen + 1) {
node->isAggregate = 1;
node->r->isGlue = 1;
node->l->isGlue = 1;
@@ -1019,7 +1012,7 @@ sx_radix_node_aggregate(struct sx_radix_node *node)
&& node->l->aggregateHi == node->r->son->aggregateHi
&& node->l->aggregateLow == node->r->son->aggregateLow) {
if (node->l->prefix->masklen == node->prefix->masklen + 1
&& node->r->prefix->masklen == node->prefix->masklen+1) {
&& node->r->prefix->masklen == node->prefix->masklen + 1) {
if (node->isGlue) {
node->l->isGlue = 1;
node->r->son->isGlue = 1;
@@ -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;

View File

@@ -59,43 +59,43 @@ typedef struct sx_radix_tree {
} sx_radix_tree_t;
/* most common operations with the tree is to: lookup/insert/unlink */
struct sx_radix_node* sx_radix_tree_lookup(struct sx_radix_tree* tree,
struct sx_prefix* prefix);
struct sx_radix_node* sx_radix_tree_insert(struct sx_radix_tree* tree,
struct sx_prefix* prefix);
void sx_radix_tree_unlink(struct sx_radix_tree* t, struct sx_radix_node* n);
struct sx_radix_node* sx_radix_tree_lookup_exact(struct sx_radix_tree* tree,
struct sx_prefix* prefix);
struct sx_radix_node *sx_radix_tree_lookup(struct sx_radix_tree *tree,
struct sx_prefix *prefix);
struct sx_radix_node *sx_radix_tree_insert(struct sx_radix_tree *tree,
struct sx_prefix *prefix);
void sx_radix_tree_unlink(struct sx_radix_tree *t, struct sx_radix_node *n);
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_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);
int sx_prefix_parse(struct sx_prefix* p, int af, char* text);
int sx_prefix_range_parse(struct sx_radix_tree* t, int af, unsigned 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*);
void sx_prefix_snprintf_fmt(struct sx_prefix* p, FILE* f,
const char* name, const char* fmt,
unsigned int aggregateLow, unsigned int aggregateHi);
int sx_prefix_jsnprintf(struct sx_prefix* p, char* rbuffer, int srb);
struct sx_radix_tree* sx_radix_tree_new(int af);
struct sx_radix_node* sx_radix_node_new(struct sx_prefix* prefix);
struct sx_prefix* sx_prefix_overlay(struct sx_prefix* p, int n);
int sx_radix_tree_empty(struct sx_radix_tree* t);
void 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);
int sx_radix_tree_foreach(struct sx_radix_tree* tree,
void (*func)(struct sx_radix_node*, void*), void* udata);
int sx_radix_tree_aggregate(struct sx_radix_tree* tree);
int sx_radix_tree_refine(struct sx_radix_tree* tree, unsigned refine);
int sx_radix_tree_refineLow(struct sx_radix_tree* tree, unsigned refineLow);
struct sx_prefix *sx_prefix_alloc(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);
int sx_prefix_parse(struct sx_prefix *p, int af, char *text);
int sx_prefix_range_parse(struct sx_radix_tree *t, int af, unsigned 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 *);
void sx_prefix_snprintf_fmt(struct sx_prefix *p, FILE *f,
const char *name, const char *fmt, unsigned int aggregateLow,
unsigned int aggregateHi);
int sx_prefix_jsnprintf(struct sx_prefix *p, char *rbuffer, int srb);
struct sx_radix_tree *sx_radix_tree_new(int af);
struct sx_radix_node *sx_radix_node_new(struct sx_prefix *prefix);
struct sx_prefix *sx_prefix_overlay(struct sx_prefix *p, int n);
int sx_radix_tree_empty(struct sx_radix_tree *t);
void 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);
int sx_radix_tree_foreach(struct sx_radix_tree *tree,
void (*func)(struct sx_radix_node *, void *), void *udata);
int sx_radix_tree_aggregate(struct sx_radix_tree *tree);
int sx_radix_tree_refine(struct sx_radix_tree *tree, unsigned refine);
int sx_radix_tree_refineLow(struct sx_radix_tree *tree, unsigned refineLow);
#ifndef HAVE_STRLCPY
size_t strlcpy(char* dst, const char* src, size_t size);
size_t strlcpy(char *dst, const char *src, size_t size);
#endif
#endif

View File

@@ -24,24 +24,24 @@
* SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "sx_slentry.h"
#include "extern.h"
struct sx_slentry *
struct slentry *
sx_slentry_new(char *t)
{
struct sx_slentry *e = malloc(sizeof(struct sx_slentry));
struct slentry *e = malloc(sizeof(struct slentry));
if (!e)
return NULL;
memset(e, 0, sizeof(struct sx_slentry));
memset(e, 0, sizeof(struct slentry));
if (t)
e->text = strdup(t);
e->text = strdup(t);
return e;
}
@@ -55,6 +55,7 @@ sx_tentry_new(char *t)
return NULL;
memset(te, 0, sizeof(struct sx_tentry));
te->text = strdup(t);
return te;

90
tests/generate_outputs.sh Executable file
View File

@@ -0,0 +1,90 @@
#!/bin/bash
set -e
if [ $# -ne 2 ]
then
echo "Usage: pass the following arguments in order:"
echo ""
echo "path to bgpq4 binary"
echo "output directory path"
echo ""
echo "${0} ./bgpq4 /tmp"
exit 1
fi
BGPQ4_PATH="${1}"
TEST_ASN="112"
TEST_AS_SET="AS-AS112"
OUT_DIR="${2}"
if [ ! -f "${BGPQ4_PATH}" ]
then
echo "File ${BGPQ4_PATH} does't exist"
exit 1
fi
if [ ! -e "${OUT_DIR}" ]
then
echo "Output directory ${OUT_DIR} does't exist"
exit 1
fi
# Test the IPv4 output formatting for each supported NOS:
"${BGPQ4_PATH}" -4 -b "AS${TEST_ASN}" > "${OUT_DIR}/bird--4.txt"
"${BGPQ4_PATH}" -4 -e "AS${TEST_ASN}" > "${OUT_DIR}/eos--4.txt"
"${BGPQ4_PATH}" -4 -F '%n/%l ' "AS${TEST_ASN}" > "${OUT_DIR}/formated--4.txt"
"${BGPQ4_PATH}" -4 -U "AS${TEST_ASN}" > "${OUT_DIR}/huawei--4.txt"
"${BGPQ4_PATH}" -4 -u "AS${TEST_ASN}" > "${OUT_DIR}/huawei-xpl--4.txt"
"${BGPQ4_PATH}" -4 "AS${TEST_ASN}" > "${OUT_DIR}/ios--4.txt"
"${BGPQ4_PATH}" -4 -X "AS${TEST_ASN}" > "${OUT_DIR}/ios-xr--4.txt"
"${BGPQ4_PATH}" -4 -j "AS${TEST_ASN}" > "${OUT_DIR}/json--4.txt"
"${BGPQ4_PATH}" -4 -J "AS${TEST_ASN}" > "${OUT_DIR}/junos--4.txt"
"${BGPQ4_PATH}" -4 -B "AS${TEST_ASN}" > "${OUT_DIR}/openbgpd--4.txt"
"${BGPQ4_PATH}" -4 -K "AS${TEST_ASN}" > "${OUT_DIR}/routeros6--4.txt"
"${BGPQ4_PATH}" -4 -K7 "AS${TEST_ASN}" > "${OUT_DIR}/routeros7--4.txt"
"${BGPQ4_PATH}" -4 -N "AS${TEST_ASN}" > "${OUT_DIR}/sros--4.txt"
"${BGPQ4_PATH}" -4 -n "AS${TEST_ASN}" > "${OUT_DIR}/sros-mdcli--4.txt"
"${BGPQ4_PATH}" -4 -n2 "AS${TEST_ASN}" > "${OUT_DIR}/srlinux--4.txt"
# Test the IPv6 prefix-list output formatting for each supported NOS:
"${BGPQ4_PATH}" -6 -b "AS${TEST_ASN}" > "${OUT_DIR}/bird--6.txt"
"${BGPQ4_PATH}" -6 -e "AS${TEST_ASN}" > "${OUT_DIR}/eos--6.txt"
"${BGPQ4_PATH}" -6 -F '%n/%l ' "AS${TEST_ASN}" > "${OUT_DIR}/formated--6.txt"
"${BGPQ4_PATH}" -6 -U "AS${TEST_ASN}" > "${OUT_DIR}/huawei--6.txt"
"${BGPQ4_PATH}" -6 -u "AS${TEST_ASN}" > "${OUT_DIR}/huawei-xpl--6.txt"
"${BGPQ4_PATH}" -6 "AS${TEST_ASN}" > "${OUT_DIR}/ios--6.txt"
"${BGPQ4_PATH}" -6 -X "AS${TEST_ASN}" > "${OUT_DIR}/ios-xr--6.txt"
"${BGPQ4_PATH}" -6 -j "AS${TEST_ASN}" > "${OUT_DIR}/json--6.txt"
"${BGPQ4_PATH}" -6 -J "AS${TEST_ASN}" > "${OUT_DIR}/junos--6.txt"
"${BGPQ4_PATH}" -6 -B "AS${TEST_ASN}" > "${OUT_DIR}/openbgpd--6.txt"
"${BGPQ4_PATH}" -6 -K "AS${TEST_ASN}" > "${OUT_DIR}/routeros6--6.txt"
"${BGPQ4_PATH}" -6 -K7 "AS${TEST_ASN}" > "${OUT_DIR}/routeros7--6.txt"
"${BGPQ4_PATH}" -6 -N "AS${TEST_ASN}" > "${OUT_DIR}/sros--6.txt"
"${BGPQ4_PATH}" -6 -n "AS${TEST_ASN}" > "${OUT_DIR}/sros-mdcli--6.txt"
"${BGPQ4_PATH}" -6 -n2 "AS${TEST_ASN}" > "${OUT_DIR}/srlinux--6.txt"
# Test the AS path list output formatting for each supported NOS:
"${BGPQ4_PATH}" "${TEST_AS_SET}" -f "${TEST_ASN}" -b > "${OUT_DIR}/bird--asp.txt"
# "${BGPQ4_PATH}" "${TEST_AS_SET}" -f "${TEST_ASN}" -e > "${OUT_DIR}/eos--asp.txt" # Not supported
"${BGPQ4_PATH}" "${TEST_AS_SET}" -f "${TEST_ASN}" -U > "${OUT_DIR}/huawei--asp.txt"
"${BGPQ4_PATH}" "${TEST_AS_SET}" -f "${TEST_ASN}" -u > "${OUT_DIR}/huawei-xpl--asp.txt"
"${BGPQ4_PATH}" "${TEST_AS_SET}" -f "${TEST_ASN}" > "${OUT_DIR}/ios--asp.txt"
"${BGPQ4_PATH}" "${TEST_AS_SET}" -f "${TEST_ASN}" -X > "${OUT_DIR}/ios-xr--asp.txt"
"${BGPQ4_PATH}" "${TEST_AS_SET}" -f "${TEST_ASN}" -j > "${OUT_DIR}/json--asp.txt"
"${BGPQ4_PATH}" "${TEST_AS_SET}" -f "${TEST_ASN}" -J > "${OUT_DIR}/junos--asp.txt"
"${BGPQ4_PATH}" "${TEST_AS_SET}" -f "${TEST_ASN}" -B > "${OUT_DIR}/openbgpd--asp.txt"
# "${BGPQ4_PATH}" "${TEST_AS_SET}" -f "${TEST_ASN}" -K > "${OUT_DIR}/routeros6--asp.txt" # Not supported
# "${BGPQ4_PATH}" "${TEST_AS_SET}" -f "${TEST_ASN}" -K7 > "${OUT_DIR}/routeros7--asp.txt" # Not supported
"${BGPQ4_PATH}" "${TEST_AS_SET}" -f "${TEST_ASN}" -N > "${OUT_DIR}/sros--asp.txt"
"${BGPQ4_PATH}" "${TEST_AS_SET}" -f "${TEST_ASN}" -n > "${OUT_DIR}/sros-mdcli--asp.txt"
# Test IRR source scopes
# Limit ASN to valid source:
"${BGPQ4_PATH}" "AS${TEST_ASN}" -S RIPE-NONAUTH > "${OUT_DIR}/as112-ripe-nonauth.txt"
# Limit ASN to invalid sources:
"${BGPQ4_PATH}" "AS${TEST_ASN}" -S APNIC,AFRINIC > "${OUT_DIR}/as112-apnic.txt"
# Limit AS-SET using IRR prefix notation to valid source:
"${BGPQ4_PATH}" "RIPE::${TEST_AS_SET}" > "${OUT_DIR}/as-as112-ripe-notation.txt"
# Limit AS-SET using IRR prefix notation to invalid source:
"${BGPQ4_PATH}" "APNIC::${TEST_AS_SET}" > "${OUT_DIR}/as-as112-apnic-notation.txt"

View File

@@ -0,0 +1,3 @@
no ip prefix-list NN
! generated prefix-list NN is empty
ip prefix-list NN deny 0.0.0.0/0

View File

@@ -0,0 +1,3 @@
no ip prefix-list NN
ip prefix-list NN permit 192.31.196.0/24
ip prefix-list NN permit 192.175.48.0/24

View File

@@ -0,0 +1,3 @@
no ip prefix-list NN
! generated prefix-list NN is empty
ip prefix-list NN deny 0.0.0.0/0

View File

@@ -0,0 +1,3 @@
no ip prefix-list NN
ip prefix-list NN permit 192.31.196.0/24
ip prefix-list NN permit 192.175.48.0/24

View File

@@ -0,0 +1,4 @@
NN = [
192.31.196.0/24,
192.175.48.0/24
];

View File

@@ -0,0 +1,4 @@
NN = [
2001:4:112::/48,
2620:4f:8000::/48
];

View File

@@ -0,0 +1,3 @@
NN = [
112
];

View File

@@ -0,0 +1,4 @@
no ip prefix-list NN
ip prefix-list NN
seq 1 permit 192.31.196.0/24
seq 2 permit 192.175.48.0/24

View File

@@ -0,0 +1,4 @@
no ipv6 prefix-list NN
ipv6 prefix-list NN
seq 1 permit 2001:4:112::/48
seq 2 permit 2620:4f:8000::/48

View File

@@ -0,0 +1 @@
192.31.196.0/24 192.175.48.0/24

View File

@@ -0,0 +1 @@
2001:4:112::/48 2620:4f:8000::/48

View File

@@ -0,0 +1,3 @@
undo ip ip-prefix NN
ip ip-prefix NN permit 192.31.196.0 24
ip ip-prefix NN permit 192.175.48.0 24

View File

@@ -0,0 +1,3 @@
undo ip ipv6-prefix NN
ip ipv6-prefix NN permit 2001:4:112:: 48
ip ipv6-prefix NN permit 2620:4f:8000:: 48

View File

@@ -0,0 +1,2 @@
undo ip as-path-filter NN
ip as-path-filter NN permit ^112(_112)*$

View File

@@ -0,0 +1,5 @@
no xpl ip-prefix-list NN
xpl ip-prefix-list NN
192.31.196.0 24,
192.175.48.0 24
end-list

View File

@@ -0,0 +1,5 @@
no xpl ipv6-prefix-list NN
xpl ipv6-prefix-list NN
2001:4:112:: 48,
2620:4f:8000:: 48
end-list

View File

@@ -0,0 +1,3 @@
xpl as-path-list NN
regular ^112(_112)*$
end-list

View File

@@ -0,0 +1,3 @@
no ip prefix-list NN
ip prefix-list NN permit 192.31.196.0/24
ip prefix-list NN permit 192.175.48.0/24

View File

@@ -0,0 +1,3 @@
no ipv6 prefix-list NN
ipv6 prefix-list NN permit 2001:4:112::/48
ipv6 prefix-list NN permit 2620:4f:8000::/48

View File

@@ -0,0 +1,2 @@
no ip as-path access-list NN
ip as-path access-list NN permit ^112(_112)*$

View File

@@ -0,0 +1,5 @@
no prefix-set NN
prefix-set NN
192.31.196.0/24,
192.175.48.0/24
end-set

View File

@@ -0,0 +1,5 @@
no prefix-set NN
prefix-set NN
2001:4:112::/48,
2620:4f:8000::/48
end-set

View File

@@ -0,0 +1,3 @@
as-path-set NN
ios-regex '^112(_112)*$'
end-set

View File

@@ -0,0 +1,4 @@
{ "NN": [
{ "prefix": "192.31.196.0\/24", "exact": true },
{ "prefix": "192.175.48.0\/24", "exact": true }
] }

View File

@@ -0,0 +1,4 @@
{ "NN": [
{ "prefix": "2001:4:112::\/48", "exact": true },
{ "prefix": "2620:4f:8000::\/48", "exact": true }
] }

View File

@@ -0,0 +1,3 @@
{"NN": [
112
]}

View File

@@ -0,0 +1,7 @@
policy-options {
replace:
prefix-list NN {
192.31.196.0/24;
192.175.48.0/24;
}
}

View File

@@ -0,0 +1,7 @@
policy-options {
replace:
prefix-list NN {
2001:4:112::/48;
2620:4f:8000::/48;
}
}

View File

@@ -0,0 +1,6 @@
policy-options {
replace:
as-path-group NN {
as-path a0 "^112(112)*$";
}
}

View File

@@ -0,0 +1,4 @@
prefix {
192.31.196.0/24
192.175.48.0/24
}

View File

@@ -0,0 +1,4 @@
prefix {
2001:4:112::/48
2620:4f:8000::/48
}

View File

@@ -0,0 +1 @@
allow from AS 112 AS 112

View File

@@ -0,0 +1,2 @@
/routing filter add action=accept chain="NN-V4" prefix=192.31.196.0/24
/routing filter add action=accept chain="NN-V4" prefix=192.175.48.0/24

View File

@@ -0,0 +1,2 @@
/routing filter add action=accept chain="NN-V6" prefix=2001:4:112::/48
/routing filter add action=accept chain="NN-V6" prefix=2620:4f:8000::/48

View File

@@ -0,0 +1,2 @@
/routing filter rule add chain="NN-V4" rule="if (dst==192.31.196.0/24) {accept}"
/routing filter rule add chain="NN-V4" rule="if (dst==192.175.48.0/24) {accept}"

View File

@@ -0,0 +1,2 @@
/routing filter rule add chain="NN-V6" rule="if (dst==2001:4:112::/48) {accept}"
/routing filter rule add chain="NN-V6" rule="if (dst==2620:4f:8000::/48) {accept}"

View File

@@ -0,0 +1,6 @@
/routing-policy
delete prefix-set "NN"
prefix-set "NN" {
prefix 192.31.196.0/24 mask-length-range exact { }
prefix 192.175.48.0/24 mask-length-range exact { }
}

View File

@@ -0,0 +1,6 @@
/routing-policy
delete prefix-set "NN"
prefix-set "NN" {
prefix 2001:4:112::/48 mask-length-range exact { }
prefix 2620:4f:8000::/48 mask-length-range exact { }
}

View File

@@ -0,0 +1,8 @@
configure router policy-options
begin
no prefix-list "NN"
prefix-list "NN"
prefix 192.31.196.0/24 exact
prefix 192.175.48.0/24 exact
exit
commit

View File

@@ -0,0 +1,8 @@
configure router policy-options
begin
no prefix-list "NN"
prefix-list "NN"
prefix 2001:4:112::/48 exact
prefix 2620:4f:8000::/48 exact
exit
commit

View File

@@ -0,0 +1,7 @@
configure router policy-options
begin
no as-path-group "NN"
as-path-group "NN"
entry 1 expression "112+"
exit
commit

View File

@@ -0,0 +1,8 @@
/configure policy-options
delete prefix-list "NN"
prefix-list "NN" {
prefix 192.31.196.0/24 type exact {
}
prefix 192.175.48.0/24 type exact {
}
}

View File

@@ -0,0 +1,8 @@
/configure policy-options
delete prefix-list "NN"
prefix-list "NN" {
prefix 2001:4:112::/48 type exact {
}
prefix 2620:4f:8000::/48 type exact {
}
}

View File

@@ -0,0 +1,7 @@
/configure policy-options
delete as-path-group "NN"
as-path-group "NN" {
entry 1 {
expression "112+"
}
}