212 Commits
0.0.4 ... 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
Job Snijders
cb15aea505 Release 0.0.8 2021-08-17 22:54:15 +00:00
Job Snijders
f1a339985a Fix SX_TEST_EBITS 2021-08-17 22:51:22 +00:00
Job Snijders
24daa48a67 Style fixes 2021-08-17 22:33:04 +00:00
Job Snijders
b21c8b30ca remove unused includes 2021-08-17 22:23:33 +00:00
Job Snijders
270e04dd23 The string returned by inet_ntoa() resides in a static memory area 2021-08-17 22:20:16 +00:00
Job Snijders
32a3520e62 Fix -Wstrict-aliasing messages
Moving from uint32 -> struct in_addr
2021-08-17 22:16:56 +00:00
Job Snijders
b816c1023b Fix more warnings 2021-08-17 20:19:17 +00:00
Job Snijders
85d833ca48 Fix style and compiler warnings 2021-08-17 19:34:30 +00:00
Job Snijders
791f3d7790 Fixing style and compiler warnings 2021-08-17 18:03:03 +00:00
Job Snijders
6a4207f940 rename headerfile 2021-08-17 17:26:10 +00:00
Job Snijders
af10798afd Move to Brent Cooks portable 2021-08-17 17:18:59 +00:00
Job Snijders
81112ec2de install libtool 2021-08-17 14:36:30 +00:00
Job Snijders
08801e2068 Change macro for manpage 2021-08-17 14:30:18 +00:00
Job Snijders
b1a9f4f089 Add 0.0.7 changelog 2021-08-17 14:27:06 +00:00
Job Snijders
408b7d8852 add _null.h to include Makefile 2021-08-17 14:25:47 +00:00
Job Snijders
3754a01a2b No need for -O0 libcompat 2021-08-17 14:22:33 +00:00
Job Snijders
8bc07f3cb0 use portability shim for string.h 2021-08-17 14:19:10 +00:00
Job Snijders
bbcd4ae18f set libcompat_la 2021-08-17 12:52:14 +00:00
Job Snijders
f1e9242814 define bgpq4_LDADD 2021-08-17 12:50:08 +00:00
Job Snijders
222b89e631 add types.h 2021-08-17 12:36:33 +00:00
Job Snijders
ea95e6d27a add types.h 2021-08-17 12:34:21 +00:00
Job Snijders
dc0e8c32f7 Use OpenBSD string.h 2021-08-17 12:33:00 +00:00
Job Snijders
21b574fc91 Current OpenBSD queue.h has STAILQ_ 2021-08-17 12:23:50 +00:00
Job Snijders
757dc33bb0 Add compat dir to AM flags 2021-08-17 12:19:29 +00:00
Job Snijders
82146e291b Add _null.h from OpenBSD 2021-08-17 12:14:07 +00:00
Job Snijders
ac93dcfeef include local headers too 2021-08-17 12:11:05 +00:00
Job Snijders
e6d488ca5b Sync with latest OpenBSD tree.h/queue.h 2021-08-17 12:11:05 +00:00
Job Snijders
dee79b0408 Sync to latest strlcpy() from OpenBSD 2021-08-17 12:11:05 +00:00
Job Snijders
6f7a8db6aa Add m4/ dir to cleanup list 2021-08-17 12:11:05 +00:00
Job Snijders
276b2cfc52 clean up maintainer files 2021-08-17 12:11:05 +00:00
Job Snijders
82b44b1304 Add license to each individual file 2021-08-17 12:11:05 +00:00
Job Snijders
4eb9566de8 Reorganize automake 2021-08-17 12:11:05 +00:00
Job Snijders
f473454ff7 Reorganize compat dir 2021-08-17 12:11:05 +00:00
Job Snijders
16fd7f7668 move .h into include dir 2021-08-17 12:11:05 +00:00
Job Snijders
a0b9343551 Move strlcpy into compat dir 2021-08-17 12:11:05 +00:00
Job Snijders
d998a73652 KNF 2021-08-17 12:11:05 +00:00
Job Snijders
0b554d4aa1 KNF 2021-08-17 10:12:40 +00:00
Job Snijders
406b984aa4 KNF 2021-08-12 08:25:36 +00:00
Stefan Marti
c2223849fc Huawei aspath bugfix (#44)
* bugfix huawei input as-path

* bgpq4_print_huawei_oaspath bug fix
2021-07-13 11:10:22 +00:00
Tony Lee
56432d3c74 Update bgpq4_printer.c (#43)
Correction Juniper route filter list ouput.
2021-07-03 18:41:45 +02:00
Robert Scheck
65f157581b Remove unused markdown check (no more bgpq4.html) (#41) 2021-04-26 23:33:25 +00:00
Robert Scheck
d103cc6e3b Bump version to 0.0.7 to match GitHub tags (#42) 2021-04-26 23:33:02 +00:00
Melchior Aelmans
d4b53ba67e Update README.md (#40)
"data data" is one time "data" too much.
2021-03-30 14:42:51 +00:00
Job Snijders
9498d7f368 Revert conditional clauses around XR prefix list generation
This fixes #39

Thank you Octavio & Lukas
2021-03-16 09:57:43 +00:00
Job Snijders
5f5ce4cff3 Remove select, use system default
Remove not-needed shutdown()

Thanks Theo
2020-12-29 20:03:12 +00:00
Job Snijders
f29576d973 remove readme.header 2020-12-23 15:18:46 +00:00
Brooks Swinnerton
d000627465 Arista EOS Support (#35)
Add Arista EOS support

Thanks Brooks!

This adds support for Arista EOS using a new flag: -e. EOS shares a lot of similarities with IOS,
but there is a difference in the syntax of prefix-lists that I wanted to fix.

The difference can be seen with bgpq4 -S ARIN -4 -s AS36459, which returns:

no ip prefix-list NN
ip prefix-list NN seq 1 permit 192.30.252.0/22
ip prefix-list NN seq 2 permit 192.30.252.0/23
ip prefix-list NN seq 3 permit 192.30.252.0/24
ip prefix-list NN seq 4 permit 192.30.253.0/24
ip prefix-list NN seq 5 permit 192.30.254.0/24
ip prefix-list NN seq 6 permit 192.30.255.0/24

Interestingly, this syntax works fine in EOS, but EOS isn't able to handle the same syntax for ipv6
prefix-lists. Instead, the seq and permit/deny that compose the rule needs to be inside the prefix-list
block.

Now bgpq4 -S ARIN -4 -e AS36459 generates:

no ip prefix-list NN
ip prefix-list NN
    seq 1 permit 192.30.252.0/22
    seq 2 permit 192.30.252.0/23
    seq 3 permit 192.30.252.0/24
    seq 4 permit 192.30.253.0/24
    seq 5 permit 192.30.254.0/24
    seq 6 permit 192.30.255.0/24
2020-12-23 15:07:23 +00:00
Job Snijders
884a982718 Update contact 2020-12-23 15:01:51 +00:00
Job Snijders
71cbcf7019 more cleanup 2020-12-23 15:01:32 +00:00
Job Snijders
03bc8d47dc Remove bgpq4.html 2020-12-23 14:59:34 +00:00
Job Snijders
b361671c45 Improve manpage 2020-12-23 13:49:50 +00:00
Job Snijders
a624dc9649 Merge pull request #26 from robert-scheck/man
Avoid man page macro warnings
2020-12-23 14:41:40 +01:00
Job Snijders
fd6150a2dd update contact info 2020-12-23 13:40:37 +00:00
Job Snijders
c05dea14a7 Merge pull request #34 from bswinnerton/respect-sequence-when-no-results
Respect -s when there are no prefix lists
2020-12-23 13:55:07 +01:00
Brooks Swinnerton
12da3fc231 Respect -s when there are no prefix lists
This commit fixes a bug with when there are no prefix list results but
the `-s` argument is passed.
2020-12-20 17:47:40 -05:00
Job Snijders
e21b687467 Merge pull request #29 from mxsasha/patch-1
Add Arch Linux package to readme
2020-09-22 09:06:08 +02:00
Sasha Romijn
7c483de7d3 Add Arch Linux package to readme 2020-09-22 08:52:56 +02:00
Job Snijders
78825a18cf Merge pull request #27 from DamianZaremba/feature/dzaremba/increase-select-timeout
bgpq_expander - Increase the read select timeout to 30 seconds
2020-06-29 15:25:45 +00:00
Damian Zaremba
95edf74de7 bgpq_expander - Increase the read select timeout to 30 seconds
With the current 10 second timeout I have observed intermittent failures reporting `FATAL ERROR:select timeout` when querying large objects.

This has only been observed when using IRRD instances supporting `A` queries which led me down a path of investigating the server side timeout, the default of which in irrd4 is 30 seconds, thus 30 seconds was chosen as the read timeout (bgpq4 currently has no option to pass `!T`).

The increased timeout has been running as a local patch in my environment for more than two months with no observed failures, testing the upstream version locally still results in intermittent failures.

Commentary on the Github issue indicated ~9 second response times from Europe, which could be related to the higher latency (150ms+) cross region.
2020-06-29 16:12:56 +02:00
Robert Scheck
a3f0cd39e2 Avoid man page macro warnings
$ LC_ALL=en_US.UTF-8 MANROFFSEQ='' MANWIDTH=80 man --warnings -E UTF-8 -l -Tutf8 -Z bgpq4.8 > /dev/null
<standard input>:137: warning: macro `RS' not defined
<standard input>:157: warning: macro `RE' not defined
$
2020-06-29 00:34:34 +02:00
Job Snijders
a3053a34b7 Merge pull request #25 from robert-scheck/autotools
AM_CONFIG_HEADER is superseded by AC_CONFIG_HEADERS since July 2002
2020-06-28 22:05:27 +00:00
Robert Scheck
2d96ae5ff8 AM_CONFIG_HEADER is superseded by AC_CONFIG_HEADERS since July 2002
See: https://lists.gnu.org/archive/html/automake/2012-12/msg00038.html
2020-06-29 00:00:03 +02:00
Job Snijders
a3ca5cbcc9 Update README.md 2020-04-26 16:01:31 +02:00
Job Snijders
bb775897d8 Merge pull request #22 from 5u623l20/5u623l20-patch-FreeBSD
Add information about FreeBSD installation
2020-03-29 12:08:07 +02:00
Moin
521aa51262 Add information about FreeBSD installation
bgpq4 has been ported into FreeBSD.
https://svnweb.freebsd.org/ports?view=revision&revision=529782
2020-03-29 15:38:46 +06:00
Job Snijders
d9a2ee92a6 Release 0.0.6 2020-03-12 13:24:44 +01:00
Job Snijders
62b2a56af7 Merge pull request #21 from ccaputo/master
Various for consideration...
2020-03-11 18:09:09 +01:00
Chris Caputo
92d52b9133 Fix totally broken final newline code with '-F'. 2020-03-11 16:22:46 +00:00
Chris Caputo
1d5b375cc3 Enable aggregate support with '-F' (user-defined). 2020-03-11 16:22:46 +00:00
Chris Caputo
e4d72f0505 Fix user-defined format stack-smash ability.
'-F' option: Avoids risk of stack-smashing which was ever so present,
by just fprintf'ing directly to output stream.
2020-03-11 16:22:46 +00:00
Chris Caputo
b71aa3f21d Compiler warning fixes and improved error handling.
Fixes multiple:
  warning: ignoring return value of 'read', declared with attribute warn_unused_result [-Wunused-result]
  warning: ignoring return value of 'write', declared with attribute warn_unused_result [-Wunused-result]

Improves some error messages.
2020-03-08 22:57:45 +00:00
Chris Caputo
d8fbae0643 Make A query test only be performed when needed.
Saves an RTT.
2020-03-08 22:51:37 +00:00
Job Snijders
b8e92b5456 update readme 2020-01-03 15:43:29 +01:00
Job Snijders
20d04b5d54 Release 0.0.5 2020-01-01 19:19:35 +01:00
Job Snijders
de3c94ac9d Unbreak -G
(And some formatting changes)

Thanks for reporting sthen@openbsd.org!
2020-01-01 17:49:28 +01:00
Job Snijders
0a49b8a6ea Move -S to Input filter 2019-12-31 14:47:41 +01:00
Job Snijders
cfa1a00433 Add -v version command line option 2019-12-31 14:36:44 +01:00
Job Snijders
ef9889dda3 Move -L to input filters 2019-12-31 14:24:01 +01:00
Job Snijders
fb6fde65c8 Rework usage() 2019-12-31 14:19:12 +01:00
Job Snijders
e9f4eeaa57 Update usage() 2019-12-31 14:04:26 +01:00
Job Snijders
f5ba86dfa5 Change prompt in docs 2019-12-31 13:29:05 +01:00
Job Snijders
425e8dbdb4 Make the -3 command line option a no-op 2019-12-31 13:24:12 +01:00
Job Snijders
d3eb845c9b Remove -3 option from docs 2019-12-31 13:11:18 +01:00
Job Snijders
8b5459cf05 Add additional debug lines 2019-12-31 11:32:25 +01:00
113 changed files with 7188 additions and 5547 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
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

@@ -7,7 +7,10 @@ RUN apt-get update && apt-get install -y locales && rm -rf /var/lib/apt/lists/*
ENV LANG en_US.utf8
# Install dependencies
RUN apt-get update && apt-get dist-upgrade -y && apt-get install -y build-essential autoconf automake markdown && rm -rf /var/lib/apt/lists/*
RUN apt-get update \
&& apt-get dist-upgrade -y \
&& apt-get install -y build-essential autoconf libtool automake markdown \
&& rm -rf /var/lib/apt/lists/*
# Add source code
ADD . /src

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

37
.gitignore vendored
View File

@@ -1,37 +0,0 @@
CVS/
Makefile
config.h
*.o
bgpq4
bgpq4.html
Makefile.in
.deps
/bgpq4-*.tar.gz
/ar-lib
/mdate-sh
/py-compile
/test-driver
/ylwrap
autom4te.cache
/autoscan.log
/autoscan-*.log
/aclocal.m4
/compile
/config.guess
/config.h.in
/config.log
/config.status
/config.sub
/configure
/configure.scan
/depcomp
/install-sh
/missing
/stamp-h1
/ltmain.sh
/texinfo.tex
m4/libtool.m4
m4/ltoptions.m4
m4/ltsugar.m4
m4/ltversion.m4
m4/lt~obsolete.m4

62
CHANGES
View File

@@ -1,3 +1,65 @@
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
- Fix all compiler warnings
0.0.6 (2020-03-12):
- Bugfixes - Thanks Chris Caputo!
0.0.5 (2020-01-01):
- Bugfixes
0.0.4 (2019-12-31):
- Remove the '-3' command line option, assume all devices are
32-bit ASN safe

View File

@@ -1,5 +1,4 @@
/*-
* Copyright (c) 2019 Job Snijders <job@ntt.net>
* Copyright (c) 2007-2019 Alexandre Snarskii <snar@snar.spb.ru>
* All rights reserved.
*

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,19 +1,43 @@
SUBDIRS = include
ACLOCAL_AMFLAGS = -I m4
AM_CPPFLAGS = -I$(top_srcdir)/include
AM_CPPFLAGS += -I$(top_srcdir)/compat
AUTOMAKE_OPTIONS=foreign subdir-objects
bin_PROGRAMS=bgpq4
bgpq4_SOURCES=bgpq4.c bgpq4.h config.h bgpq4_printer.c bgpq_expander.c \
expander_freeall.c expander_freeall.h strlcpy.c sx_maxsockbuf.c \
sx_maxsockbuf.h sx_prefix.c sx_prefix.h sx_report.c sx_report.h \
sx_slentry.c sx_slentry.h sys_queue.h sys_tree.h
dist_doc_DATA=bgpq4.html
dist_man8_MANS=bgpq4.8
EXTRA_DIST=bootstrap readme.header README.md CHANGES COPYRIGHT bgpq4.spec
CLEANFILES=bgpq4.html
bgpq4_LDADD = $(PLATFORM_LDADD) $(PROG_LDADD)
if !HAVE_STRLCPY
SUBDIRS += compat
bgpq4_LDADD += $(top_builddir)/compat/libcompat.la
endif
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
MAINTAINERCLEANFILES=configure aclocal.m4 compile \
install-sh missing Makefile.in depcomp \
stamp-h1 config.h.in
bgpq4.html: readme.header README.md
cat readme.header README.md | @MARKDOWN@ > bgpq4.html
stamp-h1 compat/Makefile.in \
config.guess config.sub include/Makefile.in \
ltmain.sh
maintainer-clean-local:
-rm -rf autom4te.cache config.h.in~
-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

605
README.md
View File

@@ -1,233 +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] [-46ABbDdJjNnpsUX] [-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 RADB 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.
#### -f `AS number`
**-e**
Generate input as-path access-list for adjacent as `AS number`.
> generate output in Arista EOS format (default: Cisco).
#### -F `fmt`
**-E**
Generate output in user-defined format.
> generate extended access-list (Cisco), policy-statement term using
> route-filters (Juniper), \[ip|ipv6]-prefix-list (Nokia) or prefix-sets
> (OpenBGPd).
#### -G `number`
**-f** *number*
Generate output as-path access-list.
> generate input as-path access-list.
#### -h `host[:port]`
**-F** *fmt*
Host running IRRD database (default: `rr.ntt.net`).
> generate output in user-defined format.
#### -J
**-G** *number*
Generate config for Juniper.
> generate output as-path access-list.
#### -j
**-H** *number*
Generate output in JSON format.
> generate output as-list for JunOS 21.3R1+ `as-path-origin` filter (JunOS only)
#### -K
**-h** *host\[:port]*
Generate config for MikroTik.
> host running IRRD database (default: rr.ntt.net).
#### -m `length`
**-J**
Maximum length of accepted prefixes (default: `32` for IPv4, `128` for IPv6).
> generate config for Juniper (default: Cisco).
#### -M `match`
**-j**
Extra match conditions for Juniper route-filters. See the examples section.
> generate output in JSON format (default: Cisco).
#### -n
**-K**
Generate config for Nokia SR OS (former Alcatel-Lucent) MD-CLI.
> generate config for Mikrotik ROSv6 (default: Cisco).
#### -N
**-K7**
Generate config for Nokia SR OS (former Alcatel-Lucent) classic CLI.
> generate config for Mikrotik ROSv7 (default: Cisco).
#### -l `name`
**-l** *name*
`Name` of generated configuration stanza.
> name of generated entry.
#### -L `limit`
**-L** *limit*
Limit recursion depth when expanding. This slows `bgpq4` a bit, but sometimes
is a useful feature to prevent generated filters from growing too big.
> limit recursion depth when expanding as-sets.
#### -p
**-m** *len*
Enable use of private ASNs and ASNs used for documentation purpose only
(default: disabled).
> maximum prefix-length of accepted prefixes (default: 32 for IPv4 and
> 128 for IPv6).
#### -r `length`
**-M** *match*
Allow more-specific routes with masklen starting with specified length.
> extra match conditions for Juniper route-filters.
#### -R `length`
**-n**
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 OS MD-CLI (Cisco IOS by default)
#### -s
**-n2**
Generate sequence numbers in IOS-style prefix-lists.
> generate config for Nokia SR Linux (Cisco IOS by default)
#### -S `sources`
**-N**
Use specified sources only (recommended: RADB,RIPE,APNIC).
> generate config for Nokia SR OS classic CLI (Cisco IOS by default).
#### -t
**-p**
Generate as-sets for OpenBGPD (OpenBSD 6.4+), BIRD and JSON formats.
> emit prefixes where the origin ASN is in the private ASN range
> (disabled by default).
#### -T
**-r** *len*
Disable pipelining. (not recommended)
> allow more specific routes starting with specified masklen too.
#### -U
**-R** *len*
Generate output in Huawei format.
> allow more specific routes up to specified masklen too.
#### -W `length`
**-s**
Generate as-path strings of a given length maximum (0 for infinity).
> generate sequence numbers in IOS-style prefix-lists.
#### -X
**-S** *sources*
Generate output in Cisco IOS XR format.
> use specified sources only (recommended: RPKI,AFRINIC,ARIN,APNIC,LACNIC,RIPE).
#### -z
**-t**
Generate Juniper route-filter-list (JunOS 16.2+).
> generate as-sets for OpenBGPd, BIRD and JSON formats.
#### `OBJECTS`
**-T**
`OBJECTS` means networks (in prefix format), autonomous systems, as-sets and
route-sets. If multiple objects are specified they will be merged.
> disable pipelining (not recommended).
#### `EXCEPT OBJECTS`
**-W** *len*
You can exclude autonomous sets, as-sets and route-sets found during
expansion from future expansion.
> generate as-path strings of no more than len items (use 0 for infinity).
EXAMPLES
--------
Generating prefix filter for MikroTik for `AS20597`:
**-U**
user@host:~>./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 config for Huawei devices (Cisco IOS by default)
Generating named Juniper prefix-filter for `AS20597`:
**-u**
user@host:~>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 output in Huawei XPL format.
**-X**
> 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:
user@host:~>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:
user@host:~>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 {
@@ -248,144 +267,276 @@ 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-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
[....]
user@host:~>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
[....]
and assumes your device supports 32-bit ASNs
and ASN32
$ 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)$";
}
}
user@host:~>bgpq4 -J3f 112 AS-SPACENET
policy-options {
replace:
as-path-group NN {
as-path a0 "^112(112)*$";
as-path a1 "^112(.)*(1898|5539|8495|8763|8878|12136|12931|15909)$";
as-path a2 "^112(.)*(21358|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 `AS3.3` in 'asplain' notation.
If your router does not support ASN32 (yet) you should not use switch -3,
and the result will be next:
user@host:~>bgpq4 -f 112 AS-SPACENET
no ip as-path access-list NN
ip as-path access-list NN permit ^112( 112)*$
ip as-path access-list NN permit ^112( [0-9]+)* (1898|5539|8495|8763)$
ip as-path access-list NN permit ^112( [0-9]+)* (8878|12136|12931|15909)$
ip as-path access-list NN permit ^112( [0-9]+)* (21358|23456|23600|24151)$
ip as-path access-list NN permit ^112( [0-9]+)* (25152|31529|34127|34906)$
ip as-path access-list NN permit ^112( [0-9]+)* (35052|41720|43628|44450)$
`AS196611` is no more in the list, however, `AS23456` (transition AS) would
have been added to list if it were not present.
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:
user@host:~>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,
'%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):
user@host:~>bgpq4 -6F "%n/%l; " as-eltel
$ 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
SEE ALSO
--------
# DIAGNOSTICS
1. [Routing Arbiter](http://www.radb.net/)
2. [Cisco documentation](http://www.cisco.com/en/US/prod/collateral/iosswrel/ps6537/ps6554/ps6599/data_sheet_C78-521821.html)
for information on Cisco implementation of ASN32.
3. [JunOS prefix-lists limitation](http://www.juniper.net/techpubs/en_US/junos11.4/topics/reference/configuration-statement/prefix-list-edit-policy-options.html)
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.
AUTHORS
-------
# TESTS
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.
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.
# 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@ntt.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;

1
VERSION Normal file
View File

@@ -0,0 +1 @@
1.15

263
bgpq4.8
View File

@@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd Dec 1, 2019
.Dd December 23, 2020
.Dt BGPQ4 8
.Os
.Sh NAME
@@ -36,10 +36,11 @@
.Oo
.Fl f Ar asn |
.Fl F Ar fmt |
.Fl G Ar asn
.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
@@ -50,15 +51,15 @@
.Op EXCEPT OBJECTS
.Sh DESCRIPTION
The
.Nm
.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:
The options are as follows:
.Bl -tag -width Ds
.It Fl 4
.It Fl 4
generate IPv4 prefix/access-lists (default).
.It Fl 6
.It Fl 6
generate IPv6 prefix/access-lists (IPv4 by default).
.It Fl A
try to aggregate prefix-lists as much as possible (not all output
@@ -71,6 +72,8 @@ generate output in OpenBGPD format (default: Cisco)
generate output in BIRD format (default: Cisco).
.It Fl d
enable some debugging output.
.It Fl e
generate output in Arista EOS format (default: Cisco).
.It Fl E
generate extended access-list (Cisco), policy-statement term using
route-filters (Juniper), [ip|ipv6]-prefix-list (Nokia) or prefix-sets
@@ -81,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
@@ -88,54 +95,59 @@ 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).
.It Fl l Ar name
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
limit recursion depth when expanding as-sets.
.It Fl m Ar len
maximum prefix-length of accepted prefixes (default: 32 for IPv4 and
maximum prefix-length of accepted prefixes (default: 32 for IPv4 and
128 for IPv6).
.It Fl M Ar match
.It Fl M Ar match
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.
allow more specific routes starting with specified masklen too.
.It Fl R Ar len
allow more specific routes up to specified masklen too.
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 (OpenBSD 6.4+), BIRD and JSON formats.
generate as-sets for OpenBGPd, BIRD and JSON formats.
.It Fl T
disable pipelining.
.It Fl W Ar len
generate as-path strings of no more than len items (use 0 for inifinity).
disable pipelining (not recommended).
.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
generate route-filter-lists (JunOS 16.2+).
.It Ar OBJECTS
.It Ar OBJECTS
means networks (in prefix format), autonomous systems, as-sets and route-sets.
.It Ar EXCEPT OBJECTS
those objects will be excluded from expansion.
.El
.Sh EXAMPLES
Generating named juniper prefix-filter for AS20597:
Generating named juniper prefix-filter for AS20597:
.nf
.RS
~>bgpq4 -Jl eltel AS20597
.Bd -literal
$ bgpq4 -Jl eltel AS20597
policy-options {
replace:
prefix-list eltel {
@@ -154,14 +166,14 @@ replace:
217.170.80.0/20;
}
}
.RE
.Ed
.fi
.Pp
For Cisco we can use aggregation (-A) flag to make this prefix-filter
more compact:
more compact:
.nf
.RS
~>bgpq4 -Al eltel AS20597
.Bd -literal
$ 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
@@ -174,16 +186,17 @@ 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
.RE
.Ed
.fi
- you see, 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
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,
using -M <extra match conditions>, -R <len> and hierarchical names:
using -M <extra match conditions>, -R <len> and hierarchical names:
.nf
.RS
~>bgpq4 -AJEl eltel/specifics -r 29 -R 32 -M "community blackhole" AS20597
.Bd -literal
$ bgpq4 -AJEl eltel/specifics -r 29 -R 32 -M "community blackhole" AS20597
policy-options {
policy-statement eltel {
term specifics {
@@ -203,26 +216,26 @@ replace:
}
}
}
.RE
.Ed
.fi
generated policy-option term now allows all specifics with prefix-length
between /29 and /32 for eltel networks if they match with special community
between /29 and /32 for eltel networks if they match with special community
blackhole (defined elsewhere in configuration).
.Pp
Of course, this version supports IPv6 (-6):
Of course, this version supports IPv6 (-6):
.nf
.RS
~>bgpq4 -6l as-retn-6 AS-RETN6
.Bd -literal
$ 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
[....]
.RE
.Ed
.fi
and support for ASN 32 is also here
and assumes your device supports 32-bit ASNs
.nf
.RS
~>bgpq4 -J3f 112 AS-SPACENET
.Bd -literal
$ bgpq4 -Jf 112 AS-SPACENET
policy-options {
replace:
as-path-group NN {
@@ -232,61 +245,147 @@ replace:
as-path a3 "^112(.)*(35052|41720|43628|44450|196611)$";
}
}
.RE
.Ed
.fi
see AS196611 in the end of the list ? That's AS3.3 in 'asplain' notation.
.Pp
For non-ASN32 capable routers you should not use switch -3,
and the result will be next:
.nf
.RS
~>bgpq4 -f 112 AS-SPACENET
no ip as-path access-list NN
ip as-path access-list NN permit ^112(_112)*$
ip as-path access-list NN permit ^112(_[0-9]+)*_(1898|5539|8495|8763)$
ip as-path access-list NN permit ^112(_[0-9]+)*_(8878|12136|12931|15909)$
ip as-path access-list NN permit ^112(_[0-9]+)*_(21358|23456|23600|24151)$
ip as-path access-list NN permit ^112(_[0-9]+)*_(25152|31529|34127|34906)$
ip as-path access-list NN permit ^112(_[0-9]+)*_(35052|41720|43628|44450)$
.RE
.fi
.Pp
AS196611 is no more in the list, however, AS23456 (transition AS)
would be added to list if it were not present.
see `AS196611` in the end of the list ? That's a 32-bit ASN.
.Sh 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:
.nf
.RS
user@host:~>bgpq4 -F "ipfw add pass all from %n/%l to any\\n" as3254
.Bd -literal
$ 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
.RE
.Ed
.fi
.Pp
Recognized format characters: %n - network, %l - 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
.RS
user@host:~>bgpq4 -6F "%n/%l; " as-eltel
.Bd -literal
$ bgpq4 -6F "%n/%l; " as-eltel
2001:1b00::/32; 2620:4f:8000::/48; 2a04:bac0::/29; 2a05:3a80::/48;
.RE
.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,
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.
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@ntt.net
.An Job Snijders Aq job@sobornost.net

683
bgpq4.c
View File

@@ -1,683 +0,0 @@
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include "bgpq4.h"
#include "sx_report.h"
#include "expander_freeall.h"
extern int debug_expander;
extern int debug_aggregation;
extern int pipelining;
extern int expand_special_asn;
int
usage(int ecode)
{
printf("\nUsage: bgpq4 [-h host[:port]] [-S sources] [-E|G <num>"
"|f <num>|t] [-46ABbdJjKNnwXz] [-R len] <OBJECTS>...\n");
printf(" -4 : generate IPv4 prefix-lists (default)\n");
printf(" -6 : generate IPv6 prefix-lists\n");
printf(" -A : try to aggregate prefix-lists/route-filters\n");
printf(" -B : generate OpenBGPD output\n");
printf(" -b : generate BIRD output\n");
printf(" -d : generate some debugging output\n");
printf(" -E : generate extended access-list(Cisco), "
"route-filter (Juniper)\n"
" [ip|ipv6]-prefix-list (Nokia) or prefix-set "
"(OpenBGPD)\n");
printf(" -F fmt : generate output in user-defined format\n");
printf(" -f number : generate input as-path access-list\n");
printf(" -G number : generate output as-path access-list\n");
printf(" -h host : host running IRRD software (rr.ntt.net by "
"default)\n"
" (use host:port to specify alternate port)\n");
printf(" -J : generate config for JunOS\n");
printf(" -j : generate JSON output\n");
printf(" -K : generate config for MikroTik RouterOS\n");
printf(" -M match : extra match conditions for JunOS route-filters\n");
printf(" -m len : maximum prefix length (default: 32 for IPv4, "
"128 for IPv6)\n");
printf(" -L depth : limit recursion depth (default: unlimited)\n"),
printf(" -l name : use specified name for generated access/prefix/.."
" list\n");
printf(" -N : generate config for Nokia SR OS classic CLI\n");
printf(" -n : generate config for Nokia SR OS MD-CLI\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 sources: use only specified sources (recommended:"
" RADB,RIPE,APNIC)\n");
printf(" -s : generate sequence numbers in prefix-lists (IOS only)\n");
printf(" -T : disable pipelining (experimental, faster mode)\n");
printf(" -t : generate as-sets for OpenBGPD (OpenBSD 6.4+), BIRD "
"and JSON formats\n");
printf(" -U : generate config for Huawei\n");
printf(" -W len : specify max-entries on as-path line (use 0 for "
"infinity)\n");
printf(" -w : 'validate' AS numbers: accept only ones with "
"registered routes\n");
printf(" -X : generate Cisco IOS XR output\n");
printf("\n" PACKAGE_NAME " version: " PACKAGE_VERSION "\n");
exit(ecode);
}
void
exclusive()
{
fprintf(stderr,"-E, -f <asnum>, -G <asnum>, and -t are mutually "
"exclusive\n");
exit(1);
}
void
vendor_exclusive()
{
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) and -X (IOS XR) options are mutually exclusive\n");
exit(1);
}
int
parseasnumber(struct bgpq_expander* expander, char* optarg)
{
char* eon=NULL;
expander->asnumber=strtoul(optarg,&eon, 10);
if (expander->asnumber < 1 || expander->asnumber > (65535ul * 65535)) {
sx_report(SX_FATAL,"Invalid AS number: %s\n", optarg);
exit(1);
}
if(eon && *eon == '.') {
/* -f 3.3, for example */
uint32_t loas = strtoul(eon+1, &eon, 10);
if(expander->asnumber > 65535) {
/* should prevent incorrect numbers like 65537.1 */
sx_report(SX_FATAL,"Invalid AS number: %s\n", optarg);
exit(1);
}
if(loas < 1 || loas > 65535) {
sx_report(SX_FATAL,"Invalid AS number: %s\n", optarg);
exit(1);
}
if (eon && *eon) {
sx_report(SX_FATAL,"Invalid symbol in AS number: "
"%c (%s)\n", *eon, optarg);
exit(1);
}
expander->asnumber=(expander->asnumber << 16) + loas;
} else if (eon && *eon) {
sx_report(SX_FATAL,"Invalid symbol in AS number: %c (%s)\n",
*eon, optarg);
exit(1);
}
return 0;
}
int
main(int argc, char* argv[])
{
int c;
struct bgpq_expander expander;
int af = AF_INET, selectedipv4 = 0, exceptmode = 0;
int widthSet = 0, aggregate = 0, refine = 0, refineLow = 0;
unsigned long maxlen = 0;
#ifdef HAVE_PLEDGE
if (pledge("stdio inet dns", NULL) == -1) {
sx_report(SX_ERROR, "pledge() failed");
exit(1);
}
#endif
bgpq_expander_init(&expander, af);
if (getenv("IRRD_SOURCES"))
expander.sources=getenv("IRRD_SOURCES");
while ((c = getopt(argc,argv,"46a:AbBdDEF:S:jJKf:l:L:m:M:NnW:pr:R:G:tTh:UwXsz"))
!=EOF) {
switch (c) {
case '4':
/* do nothing, expander already configured for IPv4 */
if (expander.family == AF_INET6) {
sx_report(SX_FATAL, "-4 and -6 are mutually "
"exclusive\n");
exit(1);
}
selectedipv4=1;
break;
case '6':
if (selectedipv4) {
sx_report(SX_FATAL, "-4 and -6 are mutually "
"exclusive\n");
exit(1);
}
af = AF_INET6;
expander.family = AF_INET6;
expander.tree->family = AF_INET6;
break;
case 'a':
parseasnumber(&expander, optarg);
break;
case 'A':
if (aggregate)
debug_aggregation++;
aggregate = 1;
break;
case 'b':
if (expander.vendor)
vendor_exclusive();
expander.vendor = V_BIRD;
break;
case 'B':
if (expander.vendor)
vendor_exclusive();
expander.vendor = V_OPENBGPD;
break;
case 'd':
debug_expander++;
break;
case 'E':
if (expander.generation)
exclusive();
expander.generation = T_EACL;
break;
case '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* c, *d;
expander.match = strdup(optarg);
c = d = expander.match;
while (*c) {
if (*c == '\\') {
if (*(c+1) == '\n') {
*d = '\n';
d++;
c += 2;
} else if (*(c + 1) == 'r') {
*d = '\r';
d++;
c += 2;
} else if (*(c + 1) == 't') {
*d = '\t';
d++;
c += 2;
} else if (*(c + 1) == '\\') {
*d = '\\';
d++;
c += 2;
} else {
sx_report(SX_FATAL, "Unsupported"
" escape \%c (0x%2.2x) in "
"'%s'\n",
isprint(*c) ? *c : 20,
*c, optarg);
exit(1);
}
} else {
if (c != d) {
*d = *c;
}
d++;
c++;
}
}
*d = 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 'z':
if (expander.generation)
exclusive();
expander.generation = T_ROUTE_FILTER_LIST;
break;
default:
usage(1);
}
}
argc -= optind;
argv += optind;
if (!widthSet) {
if (expander.generation==T_ASPATH) {
if (expander.vendor == V_CISCO) {
expander.aswidth = 4;
} else if (expander.vendor == V_CISCO_XR) {
expander.aswidth = 6;
} else if (expander.vendor == V_JUNIPER) {
expander.aswidth = 8;
} else if (expander.vendor == V_MIKROTIK) {
expander.aswidth = 4;
} else if (expander.vendor == V_BIRD) {
expander.aswidth = 10;
} else if (expander.vendor == V_NOKIA ||
expander.vendor == V_NOKIA_MD) {
expander.aswidth = 8;
}
} else if (expander.generation == T_OASPATH) {
if (expander.vendor == V_CISCO) {
expander.aswidth = 5;
} else if (expander.vendor == V_CISCO_XR) {
expander.aswidth = 7;
} else if (expander.vendor==V_JUNIPER) {
expander.aswidth = 8;
} else if (expander.vendor == V_NOKIA ||
expander.vendor == V_NOKIA_MD) {
expander.aswidth = 8;
}
}
}
if (!expander.generation) {
expander.generation = T_PREFIXLIST;
}
if (expander.generation != (T_PREFIXLIST & T_ASPATH & T_OASPATH) &&
expander.vendor == V_CISCO_XR) {
sx_report(SX_FATAL, "Sorry, only prefix-sets and as-paths "
"supported for IOS XR\n");
}
if (expander.vendor == V_BIRD && expander.generation != T_PREFIXLIST &&
expander.generation != T_ASPATH && expander.generation != T_ASSET) {
sx_report(SX_FATAL, "Sorry, only prefix-lists and as-paths/as-sets "
"supported for BIRD output\n");
}
if (expander.vendor == V_JSON && expander.generation != T_PREFIXLIST &&
expander.generation != T_ASPATH && expander.generation != T_ASSET) {
sx_report(SX_FATAL, "Sorry, only prefix-lists and as-paths/as-sets "
"supported for JSON output\n");
}
if (expander.vendor == V_FORMAT && expander.generation != T_PREFIXLIST)
sx_report(SX_FATAL, "Sorry, only prefix-lists supported in formatted "
"output\n");
if (expander.vendor == V_FORMAT && (refine || refineLow)) {
sx_report(SX_FATAL, "Sorry, formatted output (-F <fmt>) in not "
"compatible with -R/-r options\n");
exit(1);
}
if (expander.vendor == V_HUAWEI && expander.generation != T_ASPATH &&
expander.generation != T_OASPATH && expander.generation != T_PREFIXLIST)
sx_report(SX_FATAL, "Sorry, only as-paths and prefix-lists supported "
"for Huawei output\n");
if (expander.generation == T_ROUTE_FILTER_LIST && expander.vendor != V_JUNIPER)
sx_report(SX_FATAL, "Route-filter-lists (-z) supported for Juniper (-J)"
" output only\n");
if (expander.generation == T_ASSET && expander.vendor != V_JSON &&
expander.vendor != V_OPENBGPD && expander.vendor != V_BIRD)
sx_report(SX_FATAL, "As-Sets (-t) supported for JSON (-j), OpenBGPD "
"(-B) and BIRD (-b) output only\n");
if (aggregate && expander.vendor == V_JUNIPER && expander.generation == T_PREFIXLIST) {
sx_report(SX_FATAL, "Sorry, aggregation (-A) does not work in"
" Juniper prefix-lists\nYou can try route-filters (-E) "
"or route-filter-lists (-z) instead of prefix-lists\n.");
exit(1);
}
if(aggregate && expander.vendor == V_FORMAT) {
sx_report(SX_FATAL, "Sorry, aggregation (-A) is not compatible with "
"formatted output (-F <fmt>)\n");
exit(1);
}
if (aggregate && (expander.vendor == V_NOKIA_MD || expander.vendor == V_NOKIA)
&& expander.generation != T_PREFIXLIST) {
sx_report(SX_FATAL, "Sorry, aggregation (-A) is not supported with "
"ip-prefix-lists (-E) on Nokia.\n");
exit(1);
}
if (refine && (expander.vendor == V_NOKIA_MD || expander.vendor == V_NOKIA)
&& expander.generation != T_PREFIXLIST) {
sx_report(SX_FATAL, "Sorry, more-specifics (-R) is not supported with "
"ip-prefix-lists (-E) on Nokia.\n");
exit(1);
}
if (refineLow && (expander.vendor == V_NOKIA_MD || expander.vendor == V_NOKIA)
&& expander.generation != T_PREFIXLIST) {
sx_report(SX_FATAL, "Sorry, more-specifics (-r) is not supported with "
"ip-prefix-lists (-E) on Nokia.\n");
exit(1);
}
if (aggregate && expander.generation < T_PREFIXLIST) {
sx_report(SX_FATAL, "Sorry, aggregation (-A) used only for prefix-"
"lists, extended access-lists and route-filters\n");
exit(1);
}
if (expander.sequence && expander.vendor != V_CISCO) {
sx_report(SX_FATAL, "Sorry, prefix-lists sequencing (-s) supported"
" only for IOS\n");
exit(1);
}
if (expander.sequence && expander.generation < T_PREFIXLIST) {
sx_report(SX_FATAL, "Sorry, prefix-lists sequencing (-s) can't be "
" used for non prefix-list\n");
exit(1);
}
if (refineLow && !refine) {
if (expander.family == AF_INET)
refine = 32;
else
refine = 128;
}
if (refineLow && refineLow > refine) {
sx_report(SX_FATAL, "Incompatible values for -r %u and -R %u\n",
refineLow, refine);
}
if (refine || refineLow) {
if (expander.family == AF_INET6 && refine > 128) {
sx_report(SX_FATAL, "Invalid value for refine(-R): %u (1-128 for"
" IPv6)\n", refine);
} else if (expander.family == AF_INET6 && refineLow > 128) {
sx_report(SX_FATAL, "Invalid value for refineLow(-r): %u (1-128 for"
" IPv6)\n", refineLow);
} else if (expander.family == AF_INET && refine > 32) {
sx_report(SX_FATAL, "Invalid value for refine(-R): %u (1-32 for"
" IPv4)\n", refine);
} else if (expander.family == AF_INET && refineLow > 32) {
sx_report(SX_FATAL, "Invalid value for refineLow(-r): %u (1-32 for"
" IPv4)\n", refineLow);
}
if (expander.vendor == V_JUNIPER && expander.generation == T_PREFIXLIST) {
if (refine) {
sx_report(SX_FATAL, "Sorry, more-specific filters (-R %u) "
"is not supported for Juniper prefix-lists.\n"
"Use router-filters (-E) or route-filter-lists (-z) "
"instead\n", refine);
} else {
sx_report(SX_FATAL, "Sorry, more-specific filters (-r %u) "
"is not supported for Juniper prefix-lists.\n"
"Use route-filters (-E) or route-filter-lists (-z) "
"instead\n", refineLow);
}
}
if (expander.generation < T_PREFIXLIST) {
if (refine) {
sx_report(SX_FATAL, "Sorry, more-specific filter (-R %u) "
"supported only with prefix-list generation\n", refine);
} else {
sx_report(SX_FATAL, "Sorry, more-specific filter (-r %u) "
"supported only with prefix-list generation\n", refineLow);
}
}
}
if (maxlen) {
if ((expander.family == AF_INET6 && maxlen > 128)
|| (expander.family == AF_INET && maxlen > 32)) {
sx_report(SX_FATAL, "Invalid value for max-prefixlen: %lu (1-128 "
"for IPv6, 1-32 for IPv4)\n", maxlen);
exit(1);
} else if ((expander.family == AF_INET6 && maxlen < 128)
|| (expander.family == AF_INET && maxlen < 32)) {
/*
* inet6/128 and inet4/32 does not make sense - all
* routes will be accepted, so save some CPU cycles :)
*/
expander.maxlen = maxlen;
}
} else if (expander.family == AF_INET) {
expander.maxlen = 32;
} else if (expander.family == AF_INET6) {
expander.maxlen = 128;
}
if (expander.generation == T_EACL && expander.vendor == V_CISCO
&& expander.family == AF_INET6) {
sx_report(SX_FATAL,"Sorry, ipv6 access-lists not supported "
"for Cisco yet.\n");
}
if (expander.match != NULL
&& (expander.vendor != V_JUNIPER || expander.generation != T_EACL)) {
sx_report(SX_FATAL, "Sorry, extra match conditions (-M) can be used "
"only with Juniper route-filters\n");
}
if ((expander.generation == T_ASPATH || expander.generation == T_OASPATH)
&& af != AF_INET && !expander.validate_asns) {
sx_report(SX_FATAL, "Sorry, -6 makes no sense with as-path (-f/-G) "
"generation\n");
}
if (expander.validate_asns && expander.generation != T_ASPATH
&& expander.generation != T_OASPATH) {
sx_report(SX_FATAL, "Sorry, -w makes sense only for as-path "
"(-f/-G) generation\n");
}
if (!argv[0])
usage(1);
while (argv[0]) {
if (!strcmp(argv[0], "EXCEPT")) {
exceptmode = 1;
} else if (exceptmode) {
bgpq_expander_add_stop(&expander,argv[0]);
} else if (!strncasecmp(argv[0], "AS-", 3)) {
bgpq_expander_add_asset(&expander,argv[0]);
} else if (!strncasecmp(argv[0], "RS-", 3)) {
bgpq_expander_add_rset(&expander,argv[0]);
} else if (!strncasecmp(argv[0], "AS", 2)) {
char* c;
if ((c = strchr(argv[0], ':'))) {
if (!strncasecmp(c + 1, "AS-", 3)) {
bgpq_expander_add_asset(&expander, argv[0]);
} else if (!strncasecmp(c + 1, "RS-", 3)) {
bgpq_expander_add_rset(&expander, argv[0]);
} else {
SX_DEBUG(debug_expander,"Unknown sub-as"
" object %s\n", argv[0]);
}
} else {
bgpq_expander_add_as(&expander,argv[0]);
}
} else {
char* c = strchr(argv[0], '^');
if (!c && !bgpq_expander_add_prefix(&expander, argv[0])) {
sx_report(SX_ERROR, "Unable to add prefix %s "
"(bad prefix or address-family)\n", argv[0]);
exit(1);
} else if (c && !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]);
exit(1);
}
}
argv++;
argc--;
}
if (!bgpq_expand(&expander))
exit(1);
if (refine)
sx_radix_tree_refine(expander.tree, refine);
if (refineLow)
sx_radix_tree_refineLow(expander.tree, refineLow);
if (aggregate)
sx_radix_tree_aggregate(expander.tree);
switch (expander.generation) {
case T_NONE:
sx_report(SX_FATAL,"Unreachable point... call snar\n");
exit(1);
case T_ASPATH:
bgpq4_print_aspath(stdout,&expander);
break;
case T_OASPATH:
bgpq4_print_oaspath(stdout,&expander);
break;
case T_ASSET:
bgpq4_print_asset(stdout,&expander);
break;
case T_PREFIXLIST:
bgpq4_print_prefixlist(stdout,&expander);
break;
case T_EACL:
bgpq4_print_eacl(stdout,&expander);
break;
case T_ROUTE_FILTER_LIST:
bgpq4_print_route_filter_list(stdout, &expander);
break;
}
expander_freeall(&expander);
return 0;
}

97
bgpq4.h
View File

@@ -1,97 +0,0 @@
#ifndef BGPQ4_H_
#define BGPQ4_H_
#if HAVE_SYS_QUEUE_H && HAVE_STAILQ_IN_SYS_QUEUE
#include <sys/queue.h>
#else
#include "sys_queue.h"
#endif
#include "sx_prefix.h"
#include "sx_slentry.h"
typedef enum {
V_CISCO = 0,
V_JUNIPER,
V_CISCO_XR,
V_JSON,
V_BIRD,
V_OPENBGPD,
V_FORMAT,
V_NOKIA,
V_HUAWEI,
V_MIKROTIK,
V_NOKIA_MD
} bgpq_vendor_t;
typedef enum {
T_NONE = 0,
T_ASPATH,
T_OASPATH,
T_ASSET,
T_PREFIXLIST,
T_EACL,
T_ROUTE_FILTER_LIST
} bgpq_gen_t;
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 depth;
};
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;
int maxdepth;
int validate_asns;
unsigned char* asn32s[65536];
struct bgpq_prequest* firstpipe, *lastpipe;
int piped;
char* match;
char* server;
char* port;
char* format;
unsigned maxlen;
STAILQ_HEAD(bgpq_requests, bgpq_request) wq, rq;
int fd, cdepth;
};
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 bgpq_expand(struct bgpq_expander* b);
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);
#ifndef HAVE_STRLCPY
size_t strlcpy(char* dst, const char* src, size_t size);
#endif
#endif

View File

@@ -1,82 +0,0 @@
Name: bgpq4
Version: 0.0.4
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
* 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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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

7
compat/Makefile.am Normal file
View File

@@ -0,0 +1,7 @@
AM_CPPFLAGS = -I$(top_srcdir)/include
noinst_LTLIBRARIES = libcompat.la
libcompat_la_LIBADD = $(PLATFORM_LDADD)
libcompat_la_SOURCES = strlcpy.c

50
compat/strlcpy.c Normal file
View File

@@ -0,0 +1,50 @@
/* $OpenBSD: strlcpy.c,v 1.16 2019/01/25 00:19:25 millert Exp $ */
/*
* Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <string.h>
/*
* Copy string src to buffer dst of size dsize. At most dsize-1
* chars will be copied. Always NUL terminates (unless dsize == 0).
* Returns strlen(src); if retval >= dsize, truncation occurred.
*/
size_t
strlcpy(char *dst, const char *src, size_t dsize)
{
const char *osrc = src;
size_t nleft = dsize;
/* Copy as many bytes as will fit. */
if (nleft != 0) {
while (--nleft != 0) {
if ((*dst++ = *src++) == '\0')
break;
}
}
/* Not enough room in dst, add NUL and traverse rest of src. */
if (nleft == 0) {
if (dsize != 0)
*dst = '\0'; /* NUL-terminate dst */
while (*src++)
;
}
return(src - osrc - 1); /* count does not include NUL */
}

View File

@@ -1,34 +1,102 @@
AC_INIT(bgpq4,0.0.4,job@ntt.net)
AM_INIT_AUTOMAKE
AC_PACKAGE_URL(https://github.com/bgp/bgpq4)
AM_CONFIG_HEADER(config.h)
AM_SILENT_RULES([yes])
#
# Copyright (c) 2019 Brent Cook
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# 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_CANONICAL_HOST
AM_INIT_AUTOMAKE([subdir-objects foreign])
AC_CONFIG_MACRO_DIR([m4])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
AC_PROG_CC([cc gcc])
case $host_os in
*darwin*)
HOST_OS=darwin
AC_DEFINE([SPT_TYPE], [SPT_REUSEARGV])
;;
*freebsd*)
HOST_OS=freebsd
;;
*linux*)
HOST_OS=linux
CFLAGS="$CFLAGS -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_GNU_SOURCE"
AC_DEFINE([SPT_TYPE], [SPT_REUSEARGV])
;;
*netbsd*)
HOST_OS=netbsd
;;
*openbsd*)
HOST_OS=openbsd
AC_DEFINE([HAVE_ATTRIBUTE__BOUNDED__], [1], [OpenBSD has __bounded__])
AC_DEFINE([HAVE_ATTRIBUTE__DEAD], [1], [OpenBSD has __dead])
;;
*solaris*)
HOST_OS=solaris
CFLAGS="$CFLAGS -D__EXTENSIONS__ -D_XOPEN_SOURCE=600 -DBSD_COMP"
;;
*) ;;
esac
AM_CONDITIONAL([HOST_DARWIN], [test x$HOST_OS = xdarwin])
AM_CONDITIONAL([HOST_FREEBSD], [test x$HOST_OS = xfreebsd])
AM_CONDITIONAL([HOST_LINUX], [test x$HOST_OS = xlinux])
AM_CONDITIONAL([HOST_NETBSD], [test x$HOST_OS = xnetbsd])
AM_CONDITIONAL([HOST_SOLARIS], [test x$HOST_OS = xsolaris])
AC_PROG_CC
CC=cc
CFLAGS="${CFLAGS} -std=gnu11"
AM_PROG_CC_C_O
LT_INIT
AC_PROG_INSTALL
AC_CHECK_HEADERS([sys/cdefs.h sys/queue.h sys/tree.h sys/select.h])
AC_ARG_ENABLE(warnings,
AS_HELP_STRING([--disable-warnings],
[ enable compiler warnings [default=enabled]]),
[case $enableval in
yes) enable_warnings=yes;;
no) enable_warnings=no;;
*) enable_warnings=yes;; esac],
enable_warnings=yes)
AC_MSG_CHECKING([for STAILQ_ interface in queue.h])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
#if HAVE_SYS_QUEUE_H
#include <sys/queue.h>
#else
#include "sys_queue.h"
if test "$enable_warnings" = yes; then
AM_CFLAGS="$AM_CFLAGS -Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wshadow -Wpointer-arith -Wsign-compare -Werror-implicit-function-declaration"
save_cflags="$CFLAGS"
CFLAGS=-Wno-pointer-sign
AC_MSG_CHECKING([whether CC supports -Wno-pointer-sign])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_RESULT([yes])]
[WARN_CFLAGS=-Wno-pointer-sign],
[AC_MSG_RESULT([no])]
)
AM_CFLAGS="$AM_CFLAGS $WARN_CFLAGS"
CFLAGS="$save_cflags"
fi
AC_MSG_CHECKING([if compiling with clang])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [[
#ifndef __clang__
not clang
#endif
struct blah {
STAILQ_ENTRY(blah) next;
};
])],
[AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_STAILQ_IN_SYS_QUEUE], [1], [sys/queue.h have STAILQ_])],
[AC_MSG_RESULT(no)])
AC_CHECK_PROGS([MARKDOWN], [markdown_py markdown2 markdown], [echo])
]])],
[AC_MSG_RESULT([yes])]
[CLANG_FLAGS=-Qunused-arguments],
[AC_MSG_RESULT([no])]
)
AM_CFLAGS="$AM_CFLAGS $CLANG_FLAGS"
AM_LDFLAGS="$LDFLAGS $CLANG_FLAGS"
AC_SUBST(AM_CFLAGS)
AC_SUBST(AM_LDFLAGS)
AC_CHECK_FUNCS(strlcpy)
AC_CHECK_FUNCS(pledge)
@@ -36,5 +104,15 @@ AC_CHECK_FUNCS(pledge)
AC_CHECK_LIB(socket,socket)
AC_CHECK_LIB(nsl,getaddrinfo)
AC_OUTPUT(Makefile)
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([
Makefile
include/Makefile
compat/Makefile
])
AC_OUTPUT

1464
expander.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,83 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <bgpq4.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");
}

View File

@@ -1,5 +0,0 @@
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);

154
extern.h Normal file
View File

@@ -0,0 +1,154 @@
/*
* 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/queue.h>
#include <sys/tree.h>
#include "sx_prefix.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,
V_JUNIPER,
V_CISCO_XR,
V_JSON,
V_BIRD,
V_OPENBGPD,
V_FORMAT,
V_NOKIA,
V_HUAWEI,
V_HUAWEI_XPL,
V_MIKROTIK6,
V_MIKROTIK7,
V_NOKIA_MD,
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,
T_ROUTE_FILTER_LIST
} bgpq_gen_t;
struct bgpq_expander;
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;
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 asn_cmp(struct asn_entry *, struct asn_entry *);
RB_PROTOTYPE(asn_tree, asn_entry, entry, asn_cmp);
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);
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);
#ifndef HAVE_STRLCPY
size_t strlcpy(char *dst, const char *src, size_t size);
#endif

6
include/Makefile.am Normal file
View File

@@ -0,0 +1,6 @@
noinst_HEADERS =
noinst_HEADERS += sys/_null.h
noinst_HEADERS += sys/queue.h
noinst_HEADERS += sys/tree.h
noinst_HEADERS += sys/types.h
noinst_HEADERS += string.h

24
include/string.h Normal file
View File

@@ -0,0 +1,24 @@
/*
* Public domain
* string.h compatibility shim
*/
#include_next <string.h>
#ifndef LIBCOMPAT_STRING_H
#define LIBCOMPAT_STRING_H
#include <sys/types.h>
#if defined(__sun) || defined(__hpux)
/* Some functions historically defined in string.h were placed in strings.h by
* SUS. Use the same hack as OS X and FreeBSD use to work around on Solaris and HPUX.
*/
#include <strings.h>
#endif
#ifndef HAVE_STRLCPY
size_t strlcpy(char *dst, const char *src, size_t siz);
#endif
#endif

18
include/sys/_null.h Normal file
View File

@@ -0,0 +1,18 @@
/* $OpenBSD: _null.h,v 1.2 2016/09/09 22:07:58 millert Exp $ */
/*
* Written by Todd C. Miller, September 9, 2016
* Public domain.
*/
#ifndef NULL
#if !defined(__cplusplus)
#define NULL ((void *)0)
#elif __cplusplus >= 201103L
#define NULL nullptr
#elif defined(__GNUG__)
#define NULL __null
#else
#define NULL 0L
#endif
#endif

633
include/sys/queue.h Normal file
View File

@@ -0,0 +1,633 @@
/* $OpenBSD: queue.h,v 1.46 2020/12/30 13:33:12 millert Exp $ */
/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
/*
* Copyright (c) 1991, 1993
* The Regents of the University of California. 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)queue.h 8.5 (Berkeley) 8/20/94
*/
#ifndef _SYS_QUEUE_H_
#define _SYS_QUEUE_H_
#include <sys/_null.h>
/*
* This file defines five types of data structures: singly-linked lists,
* lists, simple queues, tail queues and XOR simple queues.
*
*
* A singly-linked list is headed by a single forward pointer. The elements
* are singly linked for minimum space and pointer manipulation overhead at
* the expense of O(n) removal for arbitrary elements. New elements can be
* added to the list after an existing element or at the head of the list.
* Elements being removed from the head of the list should use the explicit
* macro for this purpose for optimum efficiency. A singly-linked list may
* only be traversed in the forward direction. Singly-linked lists are ideal
* for applications with large datasets and few or no removals or for
* implementing a LIFO queue.
*
* A list is headed by a single forward pointer (or an array of forward
* pointers for a hash table header). The elements are doubly linked
* so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before
* or after an existing element or at the head of the list. A list
* may only be traversed in the forward direction.
*
* A simple queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are singly
* linked to save space, so elements can only be removed from the
* head of the list. New elements can be added to the list before or after
* an existing element, at the head of the list, or at the end of the
* list. A simple queue may only be traversed in the forward direction.
*
* A tail queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or
* after an existing element, at the head of the list, or at the end of
* the list. A tail queue may be traversed in either direction.
*
* An XOR simple queue is used in the same way as a regular simple queue.
* The difference is that the head structure also includes a "cookie" that
* is XOR'd with the queue pointer (first, last or next) to generate the
* real pointer value.
*
* For details on the use of these macros, see the queue(3) manual page.
*/
#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC))
#define _Q_INVALID ((void *)-1)
#define _Q_INVALIDATE(a) (a) = _Q_INVALID
#else
#define _Q_INVALIDATE(a)
#endif
/*
* Singly-linked List definitions.
*/
#define SLIST_HEAD(name, type) \
struct name { \
struct type *slh_first; /* first element */ \
}
#define SLIST_HEAD_INITIALIZER(head) \
{ NULL }
#define SLIST_ENTRY(type) \
struct { \
struct type *sle_next; /* next element */ \
}
/*
* Singly-linked List access methods.
*/
#define SLIST_FIRST(head) ((head)->slh_first)
#define SLIST_END(head) NULL
#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
#define SLIST_FOREACH(var, head, field) \
for((var) = SLIST_FIRST(head); \
(var) != SLIST_END(head); \
(var) = SLIST_NEXT(var, field))
#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = SLIST_FIRST(head); \
(var) && ((tvar) = SLIST_NEXT(var, field), 1); \
(var) = (tvar))
/*
* Singly-linked List functions.
*/
#define SLIST_INIT(head) { \
SLIST_FIRST(head) = SLIST_END(head); \
}
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
(elm)->field.sle_next = (slistelm)->field.sle_next; \
(slistelm)->field.sle_next = (elm); \
} while (0)
#define SLIST_INSERT_HEAD(head, elm, field) do { \
(elm)->field.sle_next = (head)->slh_first; \
(head)->slh_first = (elm); \
} while (0)
#define SLIST_REMOVE_AFTER(elm, field) do { \
(elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \
} while (0)
#define SLIST_REMOVE_HEAD(head, field) do { \
(head)->slh_first = (head)->slh_first->field.sle_next; \
} while (0)
#define SLIST_REMOVE(head, elm, type, field) do { \
if ((head)->slh_first == (elm)) { \
SLIST_REMOVE_HEAD((head), field); \
} else { \
struct type *curelm = (head)->slh_first; \
\
while (curelm->field.sle_next != (elm)) \
curelm = curelm->field.sle_next; \
curelm->field.sle_next = \
curelm->field.sle_next->field.sle_next; \
} \
_Q_INVALIDATE((elm)->field.sle_next); \
} while (0)
/*
* List definitions.
*/
#define LIST_HEAD(name, type) \
struct name { \
struct type *lh_first; /* first element */ \
}
#define LIST_HEAD_INITIALIZER(head) \
{ NULL }
#define LIST_ENTRY(type) \
struct { \
struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \
}
/*
* List access methods.
*/
#define LIST_FIRST(head) ((head)->lh_first)
#define LIST_END(head) NULL
#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head))
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
#define LIST_FOREACH(var, head, field) \
for((var) = LIST_FIRST(head); \
(var)!= LIST_END(head); \
(var) = LIST_NEXT(var, field))
#define LIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = LIST_FIRST(head); \
(var) && ((tvar) = LIST_NEXT(var, field), 1); \
(var) = (tvar))
/*
* List functions.
*/
#define LIST_INIT(head) do { \
LIST_FIRST(head) = LIST_END(head); \
} while (0)
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
(listelm)->field.le_next->field.le_prev = \
&(elm)->field.le_next; \
(listelm)->field.le_next = (elm); \
(elm)->field.le_prev = &(listelm)->field.le_next; \
} while (0)
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.le_prev = (listelm)->field.le_prev; \
(elm)->field.le_next = (listelm); \
*(listelm)->field.le_prev = (elm); \
(listelm)->field.le_prev = &(elm)->field.le_next; \
} while (0)
#define LIST_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.le_next = (head)->lh_first) != NULL) \
(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
(head)->lh_first = (elm); \
(elm)->field.le_prev = &(head)->lh_first; \
} while (0)
#define LIST_REMOVE(elm, field) do { \
if ((elm)->field.le_next != NULL) \
(elm)->field.le_next->field.le_prev = \
(elm)->field.le_prev; \
*(elm)->field.le_prev = (elm)->field.le_next; \
_Q_INVALIDATE((elm)->field.le_prev); \
_Q_INVALIDATE((elm)->field.le_next); \
} while (0)
#define LIST_REPLACE(elm, elm2, field) do { \
if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
(elm2)->field.le_next->field.le_prev = \
&(elm2)->field.le_next; \
(elm2)->field.le_prev = (elm)->field.le_prev; \
*(elm2)->field.le_prev = (elm2); \
_Q_INVALIDATE((elm)->field.le_prev); \
_Q_INVALIDATE((elm)->field.le_next); \
} while (0)
/*
* Simple queue definitions.
*/
#define SIMPLEQ_HEAD(name, type) \
struct name { \
struct type *sqh_first; /* first element */ \
struct type **sqh_last; /* addr of last next element */ \
}
#define SIMPLEQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).sqh_first }
#define SIMPLEQ_ENTRY(type) \
struct { \
struct type *sqe_next; /* next element */ \
}
/*
* Simple queue access methods.
*/
#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
#define SIMPLEQ_END(head) NULL
#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
#define SIMPLEQ_FOREACH(var, head, field) \
for((var) = SIMPLEQ_FIRST(head); \
(var) != SIMPLEQ_END(head); \
(var) = SIMPLEQ_NEXT(var, field))
#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = SIMPLEQ_FIRST(head); \
(var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); \
(var) = (tvar))
/*
* Simple queue functions.
*/
#define SIMPLEQ_INIT(head) do { \
(head)->sqh_first = NULL; \
(head)->sqh_last = &(head)->sqh_first; \
} while (0)
#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
(head)->sqh_last = &(elm)->field.sqe_next; \
(head)->sqh_first = (elm); \
} while (0)
#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.sqe_next = NULL; \
*(head)->sqh_last = (elm); \
(head)->sqh_last = &(elm)->field.sqe_next; \
} while (0)
#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
(head)->sqh_last = &(elm)->field.sqe_next; \
(listelm)->field.sqe_next = (elm); \
} while (0)
#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
(head)->sqh_last = &(head)->sqh_first; \
} while (0)
#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \
if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \
== NULL) \
(head)->sqh_last = &(elm)->field.sqe_next; \
} while (0)
#define SIMPLEQ_CONCAT(head1, head2) do { \
if (!SIMPLEQ_EMPTY((head2))) { \
*(head1)->sqh_last = (head2)->sqh_first; \
(head1)->sqh_last = (head2)->sqh_last; \
SIMPLEQ_INIT((head2)); \
} \
} while (0)
/*
* XOR Simple queue definitions.
*/
#define XSIMPLEQ_HEAD(name, type) \
struct name { \
struct type *sqx_first; /* first element */ \
struct type **sqx_last; /* addr of last next element */ \
unsigned long sqx_cookie; \
}
#define XSIMPLEQ_ENTRY(type) \
struct { \
struct type *sqx_next; /* next element */ \
}
/*
* XOR Simple queue access methods.
*/
#define XSIMPLEQ_XOR(head, ptr) ((__typeof(ptr))((head)->sqx_cookie ^ \
(unsigned long)(ptr)))
#define XSIMPLEQ_FIRST(head) XSIMPLEQ_XOR(head, ((head)->sqx_first))
#define XSIMPLEQ_END(head) NULL
#define XSIMPLEQ_EMPTY(head) (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head))
#define XSIMPLEQ_NEXT(head, elm, field) XSIMPLEQ_XOR(head, ((elm)->field.sqx_next))
#define XSIMPLEQ_FOREACH(var, head, field) \
for ((var) = XSIMPLEQ_FIRST(head); \
(var) != XSIMPLEQ_END(head); \
(var) = XSIMPLEQ_NEXT(head, var, field))
#define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = XSIMPLEQ_FIRST(head); \
(var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \
(var) = (tvar))
/*
* XOR Simple queue functions.
*/
#define XSIMPLEQ_INIT(head) do { \
arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \
(head)->sqx_first = XSIMPLEQ_XOR(head, NULL); \
(head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \
} while (0)
#define XSIMPLEQ_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.sqx_next = (head)->sqx_first) == \
XSIMPLEQ_XOR(head, NULL)) \
(head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
(head)->sqx_first = XSIMPLEQ_XOR(head, (elm)); \
} while (0)
#define XSIMPLEQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL); \
*(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \
(head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
} while (0)
#define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
if (((elm)->field.sqx_next = (listelm)->field.sqx_next) == \
XSIMPLEQ_XOR(head, NULL)) \
(head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
(listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm)); \
} while (0)
#define XSIMPLEQ_REMOVE_HEAD(head, field) do { \
if (((head)->sqx_first = XSIMPLEQ_XOR(head, \
(head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \
(head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \
} while (0)
#define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do { \
if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head, \
(elm)->field.sqx_next)->field.sqx_next) \
== XSIMPLEQ_XOR(head, NULL)) \
(head)->sqx_last = \
XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
} while (0)
/*
* Tail queue definitions.
*/
#define TAILQ_HEAD(name, type) \
struct name { \
struct type *tqh_first; /* first element */ \
struct type **tqh_last; /* addr of last next element */ \
}
#define TAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).tqh_first }
#define TAILQ_ENTRY(type) \
struct { \
struct type *tqe_next; /* next element */ \
struct type **tqe_prev; /* address of previous next element */ \
}
/*
* Tail queue access methods.
*/
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_END(head) NULL
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
/* XXX */
#define TAILQ_PREV(elm, headname, field) \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
#define TAILQ_EMPTY(head) \
(TAILQ_FIRST(head) == TAILQ_END(head))
#define TAILQ_FOREACH(var, head, field) \
for((var) = TAILQ_FIRST(head); \
(var) != TAILQ_END(head); \
(var) = TAILQ_NEXT(var, field))
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = TAILQ_FIRST(head); \
(var) != TAILQ_END(head) && \
((tvar) = TAILQ_NEXT(var, field), 1); \
(var) = (tvar))
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
for((var) = TAILQ_LAST(head, headname); \
(var) != TAILQ_END(head); \
(var) = TAILQ_PREV(var, headname, field))
#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
for ((var) = TAILQ_LAST(head, headname); \
(var) != TAILQ_END(head) && \
((tvar) = TAILQ_PREV(var, headname, field), 1); \
(var) = (tvar))
/*
* Tail queue functions.
*/
#define TAILQ_INIT(head) do { \
(head)->tqh_first = NULL; \
(head)->tqh_last = &(head)->tqh_first; \
} while (0)
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
(head)->tqh_first->field.tqe_prev = \
&(elm)->field.tqe_next; \
else \
(head)->tqh_last = &(elm)->field.tqe_next; \
(head)->tqh_first = (elm); \
(elm)->field.tqe_prev = &(head)->tqh_first; \
} while (0)
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.tqe_next = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &(elm)->field.tqe_next; \
} while (0)
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
(elm)->field.tqe_next->field.tqe_prev = \
&(elm)->field.tqe_next; \
else \
(head)->tqh_last = &(elm)->field.tqe_next; \
(listelm)->field.tqe_next = (elm); \
(elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
} while (0)
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
(elm)->field.tqe_next = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
} while (0)
#define TAILQ_REMOVE(head, elm, field) do { \
if (((elm)->field.tqe_next) != NULL) \
(elm)->field.tqe_next->field.tqe_prev = \
(elm)->field.tqe_prev; \
else \
(head)->tqh_last = (elm)->field.tqe_prev; \
*(elm)->field.tqe_prev = (elm)->field.tqe_next; \
_Q_INVALIDATE((elm)->field.tqe_prev); \
_Q_INVALIDATE((elm)->field.tqe_next); \
} while (0)
#define TAILQ_REPLACE(head, elm, elm2, field) do { \
if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
(elm2)->field.tqe_next->field.tqe_prev = \
&(elm2)->field.tqe_next; \
else \
(head)->tqh_last = &(elm2)->field.tqe_next; \
(elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
*(elm2)->field.tqe_prev = (elm2); \
_Q_INVALIDATE((elm)->field.tqe_prev); \
_Q_INVALIDATE((elm)->field.tqe_next); \
} while (0)
#define TAILQ_CONCAT(head1, head2, field) do { \
if (!TAILQ_EMPTY(head2)) { \
*(head1)->tqh_last = (head2)->tqh_first; \
(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
(head1)->tqh_last = (head2)->tqh_last; \
TAILQ_INIT((head2)); \
} \
} while (0)
/*
* Singly-linked Tail queue declarations.
*/
#define STAILQ_HEAD(name, type) \
struct name { \
struct type *stqh_first; /* first element */ \
struct type **stqh_last; /* addr of last next element */ \
}
#define STAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).stqh_first }
#define STAILQ_ENTRY(type) \
struct { \
struct type *stqe_next; /* next element */ \
}
/*
* Singly-linked Tail queue access methods.
*/
#define STAILQ_FIRST(head) ((head)->stqh_first)
#define STAILQ_END(head) NULL
#define STAILQ_EMPTY(head) (STAILQ_FIRST(head) == STAILQ_END(head))
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
#define STAILQ_FOREACH(var, head, field) \
for ((var) = STAILQ_FIRST(head); \
(var) != STAILQ_END(head); \
(var) = STAILQ_NEXT(var, field))
#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = STAILQ_FIRST(head); \
(var) && ((tvar) = STAILQ_NEXT(var, field), 1); \
(var) = (tvar))
/*
* Singly-linked Tail queue functions.
*/
#define STAILQ_INIT(head) do { \
STAILQ_FIRST((head)) = NULL; \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_INSERT_HEAD(head, elm, field) do { \
if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
STAILQ_FIRST((head)) = (elm); \
} while (0)
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
STAILQ_NEXT((elm), field) = NULL; \
*(head)->stqh_last = (elm); \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0)
#define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((elm), field)) == NULL)\
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
STAILQ_NEXT((elm), field) = (elm); \
} while (0)
#define STAILQ_REMOVE_HEAD(head, field) do { \
if ((STAILQ_FIRST((head)) = \
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
if ((STAILQ_NEXT(elm, field) = \
STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0)
#define STAILQ_REMOVE(head, elm, type, field) do { \
if (STAILQ_FIRST((head)) == (elm)) { \
STAILQ_REMOVE_HEAD((head), field); \
} else { \
struct type *curelm = (head)->stqh_first; \
while (STAILQ_NEXT(curelm, field) != (elm)) \
curelm = STAILQ_NEXT(curelm, field); \
STAILQ_REMOVE_AFTER(head, curelm, field); \
} \
} while (0)
#define STAILQ_CONCAT(head1, head2) do { \
if (!STAILQ_EMPTY((head2))) { \
*(head1)->stqh_last = (head2)->stqh_first; \
(head1)->stqh_last = (head2)->stqh_last; \
STAILQ_INIT((head2)); \
} \
} while (0)
#define STAILQ_LAST(head, type, field) \
(STAILQ_EMPTY((head)) ? NULL : \
((struct type *)(void *) \
((char *)((head)->stqh_last) - offsetof(struct type, field))))
#endif /* !_SYS_QUEUE_H_ */

View File

@@ -1,8 +1,5 @@
/* $NetBSD: tree.h,v 1.8 2004/03/28 19:38:30 provos Exp $ */
/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */
/* $FreeBSD: stable/10/sys/sys/tree.h 189204 2009-03-01 04:57:23Z bms $ */
/*-
/* $OpenBSD: tree.h,v 1.30 2020/10/10 18:03:41 otto Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
@@ -30,9 +27,7 @@
#ifndef _SYS_TREE_H_
#define _SYS_TREE_H_
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
#include <sys/_null.h>
/*
* This file defines data structures for different types of trees:
@@ -71,7 +66,7 @@ struct name { \
#define SPLAY_INIT(root) do { \
(root)->sph_root = NULL; \
} while (/*CONSTCOND*/ 0)
} while (0)
#define SPLAY_ENTRY(type) \
struct { \
@@ -89,32 +84,32 @@ struct { \
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
(head)->sph_root = tmp; \
} while (/*CONSTCOND*/ 0)
} while (0)
#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
(head)->sph_root = tmp; \
} while (/*CONSTCOND*/ 0)
} while (0)
#define SPLAY_LINKLEFT(head, tmp, field) do { \
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
tmp = (head)->sph_root; \
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
} while (/*CONSTCOND*/ 0)
} while (0)
#define SPLAY_LINKRIGHT(head, tmp, field) do { \
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
tmp = (head)->sph_root; \
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
} while (/*CONSTCOND*/ 0)
} while (0)
#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
} while (/*CONSTCOND*/ 0)
} while (0)
/* Generates prototypes and inline functions */
@@ -125,7 +120,7 @@ struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
\
/* Finds the node with the same key as elm */ \
static __inline struct type * \
static __unused __inline struct type * \
name##_SPLAY_FIND(struct name *head, struct type *elm) \
{ \
if (SPLAY_EMPTY(head)) \
@@ -136,7 +131,7 @@ name##_SPLAY_FIND(struct name *head, struct type *elm) \
return (NULL); \
} \
\
static __inline struct type * \
static __unused __inline struct type * \
name##_SPLAY_NEXT(struct name *head, struct type *elm) \
{ \
name##_SPLAY(head, elm); \
@@ -150,7 +145,7 @@ name##_SPLAY_NEXT(struct name *head, struct type *elm) \
return (elm); \
} \
\
static __inline struct type * \
static __unused __inline struct type * \
name##_SPLAY_MIN_MAX(struct name *head, int val) \
{ \
name##_SPLAY_MINMAX(head, val); \
@@ -215,7 +210,7 @@ name##_SPLAY(struct name *head, struct type *elm) \
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
__left = __right = &__node; \
\
while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \
while ((__comp = (cmp)(elm, (head)->sph_root))) { \
if (__comp < 0) { \
__tmp = SPLAY_LEFT((head)->sph_root, field); \
if (__tmp == NULL) \
@@ -305,7 +300,7 @@ struct name { \
#define RB_INIT(root) do { \
(root)->rbh_root = NULL; \
} while (/*CONSTCOND*/ 0)
} while (0)
#define RB_BLACK 0
#define RB_RED 1
@@ -328,12 +323,12 @@ struct { \
RB_PARENT(elm, field) = parent; \
RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
RB_COLOR(elm, field) = RB_RED; \
} while (/*CONSTCOND*/ 0)
} while (0)
#define RB_SET_BLACKRED(black, red, field) do { \
RB_COLOR(black, field) = RB_BLACK; \
RB_COLOR(red, field) = RB_RED; \
} while (/*CONSTCOND*/ 0)
} while (0)
#ifndef RB_AUGMENT
#define RB_AUGMENT(x) do {} while (0)
@@ -341,11 +336,11 @@ struct { \
#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
(tmp) = RB_RIGHT(elm, field); \
if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \
if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \
RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
} \
RB_AUGMENT(elm); \
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
else \
@@ -357,15 +352,15 @@ struct { \
RB_AUGMENT(tmp); \
if ((RB_PARENT(tmp, field))) \
RB_AUGMENT(RB_PARENT(tmp, field)); \
} while (/*CONSTCOND*/ 0)
} while (0)
#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
(tmp) = RB_LEFT(elm, field); \
if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \
if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \
RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
} \
RB_AUGMENT(elm); \
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
else \
@@ -377,13 +372,13 @@ struct { \
RB_AUGMENT(tmp); \
if ((RB_PARENT(tmp, field))) \
RB_AUGMENT(RB_PARENT(tmp, field)); \
} while (/*CONSTCOND*/ 0)
} while (0)
/* Generates prototypes and inline functions */
#define RB_PROTOTYPE(name, type, field, cmp) \
RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static)
RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static)
#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \
attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
@@ -402,13 +397,13 @@ attr struct type *name##_RB_MINMAX(struct name *, int); \
#define RB_GENERATE(name, type, field, cmp) \
RB_GENERATE_INTERNAL(name, type, field, cmp,)
#define RB_GENERATE_STATIC(name, type, field, cmp) \
RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static)
RB_GENERATE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static)
#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \
attr void \
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
{ \
struct type *parent, *gparent, *tmp; \
while ((parent = RB_PARENT(elm, field)) != NULL && \
while ((parent = RB_PARENT(elm, field)) && \
RB_COLOR(parent, field) == RB_RED) { \
gparent = RB_PARENT(parent, field); \
if (parent == RB_LEFT(gparent, field)) { \
@@ -472,8 +467,7 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm)
if (RB_RIGHT(tmp, field) == NULL || \
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
struct type *oleft; \
if ((oleft = RB_LEFT(tmp, field)) \
!= NULL) \
if ((oleft = RB_LEFT(tmp, field)))\
RB_COLOR(oleft, field) = RB_BLACK;\
RB_COLOR(tmp, field) = RB_RED; \
RB_ROTATE_RIGHT(head, tmp, oleft, field);\
@@ -505,8 +499,7 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm)
if (RB_LEFT(tmp, field) == NULL || \
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
struct type *oright; \
if ((oright = RB_RIGHT(tmp, field)) \
!= NULL) \
if ((oright = RB_RIGHT(tmp, field)))\
RB_COLOR(oright, field) = RB_BLACK;\
RB_COLOR(tmp, field) = RB_RED; \
RB_ROTATE_LEFT(head, tmp, oright, field);\
@@ -538,7 +531,7 @@ name##_RB_REMOVE(struct name *head, struct type *elm) \
else { \
struct type *left; \
elm = RB_RIGHT(elm, field); \
while ((left = RB_LEFT(elm, field)) != NULL) \
while ((left = RB_LEFT(elm, field))) \
elm = left; \
child = RB_RIGHT(elm, field); \
parent = RB_PARENT(elm, field); \
@@ -571,7 +564,7 @@ name##_RB_REMOVE(struct name *head, struct type *elm) \
left = parent; \
do { \
RB_AUGMENT(left); \
} while ((left = RB_PARENT(left, field)) != NULL); \
} while ((left = RB_PARENT(left, field))); \
} \
goto color; \
} \
@@ -739,14 +732,9 @@ name##_RB_MINMAX(struct name *head, int val) \
(x) != NULL; \
(x) = name##_RB_NEXT(x))
#define RB_FOREACH_FROM(x, name, y) \
for ((x) = (y); \
((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
(x) = (y))
#define RB_FOREACH_SAFE(x, name, head, y) \
for ((x) = RB_MIN(name, head); \
((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
((x) != NULL) && ((y) = name##_RB_NEXT(x), 1); \
(x) = (y))
#define RB_FOREACH_REVERSE(x, name, head) \
@@ -754,14 +742,265 @@ name##_RB_MINMAX(struct name *head, int val) \
(x) != NULL; \
(x) = name##_RB_PREV(x))
#define RB_FOREACH_REVERSE_FROM(x, name, y) \
for ((x) = (y); \
((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
(x) = (y))
#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \
for ((x) = RB_MAX(name, head); \
((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
((x) != NULL) && ((y) = name##_RB_PREV(x), 1); \
(x) = (y))
/*
* Copyright (c) 2016 David Gwynne <dlg@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
struct rb_type {
int (*t_compare)(const void *, const void *);
void (*t_augment)(void *);
unsigned int t_offset; /* offset of rb_entry in type */
};
struct rb_tree {
struct rb_entry *rbt_root;
};
struct rb_entry {
struct rb_entry *rbt_parent;
struct rb_entry *rbt_left;
struct rb_entry *rbt_right;
unsigned int rbt_color;
};
#define RBT_HEAD(_name, _type) \
struct _name { \
struct rb_tree rbh_root; \
}
#define RBT_ENTRY(_type) struct rb_entry
static inline void
_rb_init(struct rb_tree *rbt)
{
rbt->rbt_root = NULL;
}
static inline int
_rb_empty(struct rb_tree *rbt)
{
return (rbt->rbt_root == NULL);
}
void *_rb_insert(const struct rb_type *, struct rb_tree *, void *);
void *_rb_remove(const struct rb_type *, struct rb_tree *, void *);
void *_rb_find(const struct rb_type *, struct rb_tree *, const void *);
void *_rb_nfind(const struct rb_type *, struct rb_tree *, const void *);
void *_rb_root(const struct rb_type *, struct rb_tree *);
void *_rb_min(const struct rb_type *, struct rb_tree *);
void *_rb_max(const struct rb_type *, struct rb_tree *);
void *_rb_next(const struct rb_type *, void *);
void *_rb_prev(const struct rb_type *, void *);
void *_rb_left(const struct rb_type *, void *);
void *_rb_right(const struct rb_type *, void *);
void *_rb_parent(const struct rb_type *, void *);
void _rb_set_left(const struct rb_type *, void *, void *);
void _rb_set_right(const struct rb_type *, void *, void *);
void _rb_set_parent(const struct rb_type *, void *, void *);
void _rb_poison(const struct rb_type *, void *, unsigned long);
int _rb_check(const struct rb_type *, void *, unsigned long);
#define RBT_INITIALIZER(_head) { { NULL } }
#define RBT_PROTOTYPE(_name, _type, _field, _cmp) \
extern const struct rb_type *const _name##_RBT_TYPE; \
\
__unused static inline void \
_name##_RBT_INIT(struct _name *head) \
{ \
_rb_init(&head->rbh_root); \
} \
\
__unused static inline struct _type * \
_name##_RBT_INSERT(struct _name *head, struct _type *elm) \
{ \
return _rb_insert(_name##_RBT_TYPE, &head->rbh_root, elm); \
} \
\
__unused static inline struct _type * \
_name##_RBT_REMOVE(struct _name *head, struct _type *elm) \
{ \
return _rb_remove(_name##_RBT_TYPE, &head->rbh_root, elm); \
} \
\
__unused static inline struct _type * \
_name##_RBT_FIND(struct _name *head, const struct _type *key) \
{ \
return _rb_find(_name##_RBT_TYPE, &head->rbh_root, key); \
} \
\
__unused static inline struct _type * \
_name##_RBT_NFIND(struct _name *head, const struct _type *key) \
{ \
return _rb_nfind(_name##_RBT_TYPE, &head->rbh_root, key); \
} \
\
__unused static inline struct _type * \
_name##_RBT_ROOT(struct _name *head) \
{ \
return _rb_root(_name##_RBT_TYPE, &head->rbh_root); \
} \
\
__unused static inline int \
_name##_RBT_EMPTY(struct _name *head) \
{ \
return _rb_empty(&head->rbh_root); \
} \
\
__unused static inline struct _type * \
_name##_RBT_MIN(struct _name *head) \
{ \
return _rb_min(_name##_RBT_TYPE, &head->rbh_root); \
} \
\
__unused static inline struct _type * \
_name##_RBT_MAX(struct _name *head) \
{ \
return _rb_max(_name##_RBT_TYPE, &head->rbh_root); \
} \
\
__unused static inline struct _type * \
_name##_RBT_NEXT(struct _type *elm) \
{ \
return _rb_next(_name##_RBT_TYPE, elm); \
} \
\
__unused static inline struct _type * \
_name##_RBT_PREV(struct _type *elm) \
{ \
return _rb_prev(_name##_RBT_TYPE, elm); \
} \
\
__unused static inline struct _type * \
_name##_RBT_LEFT(struct _type *elm) \
{ \
return _rb_left(_name##_RBT_TYPE, elm); \
} \
\
__unused static inline struct _type * \
_name##_RBT_RIGHT(struct _type *elm) \
{ \
return _rb_right(_name##_RBT_TYPE, elm); \
} \
\
__unused static inline struct _type * \
_name##_RBT_PARENT(struct _type *elm) \
{ \
return _rb_parent(_name##_RBT_TYPE, elm); \
} \
\
__unused static inline void \
_name##_RBT_SET_LEFT(struct _type *elm, struct _type *left) \
{ \
_rb_set_left(_name##_RBT_TYPE, elm, left); \
} \
\
__unused static inline void \
_name##_RBT_SET_RIGHT(struct _type *elm, struct _type *right) \
{ \
_rb_set_right(_name##_RBT_TYPE, elm, right); \
} \
\
__unused static inline void \
_name##_RBT_SET_PARENT(struct _type *elm, struct _type *parent) \
{ \
_rb_set_parent(_name##_RBT_TYPE, elm, parent); \
} \
\
__unused static inline void \
_name##_RBT_POISON(struct _type *elm, unsigned long poison) \
{ \
_rb_poison(_name##_RBT_TYPE, elm, poison); \
} \
\
__unused static inline int \
_name##_RBT_CHECK(struct _type *elm, unsigned long poison) \
{ \
return _rb_check(_name##_RBT_TYPE, elm, poison); \
}
#define RBT_GENERATE_INTERNAL(_name, _type, _field, _cmp, _aug) \
static int \
_name##_RBT_COMPARE(const void *lptr, const void *rptr) \
{ \
const struct _type *l = lptr, *r = rptr; \
return _cmp(l, r); \
} \
static const struct rb_type _name##_RBT_INFO = { \
_name##_RBT_COMPARE, \
_aug, \
offsetof(struct _type, _field), \
}; \
const struct rb_type *const _name##_RBT_TYPE = &_name##_RBT_INFO
#define RBT_GENERATE_AUGMENT(_name, _type, _field, _cmp, _aug) \
static void \
_name##_RBT_AUGMENT(void *ptr) \
{ \
struct _type *p = ptr; \
return _aug(p); \
} \
RBT_GENERATE_INTERNAL(_name, _type, _field, _cmp, _name##_RBT_AUGMENT)
#define RBT_GENERATE(_name, _type, _field, _cmp) \
RBT_GENERATE_INTERNAL(_name, _type, _field, _cmp, NULL)
#define RBT_INIT(_name, _head) _name##_RBT_INIT(_head)
#define RBT_INSERT(_name, _head, _elm) _name##_RBT_INSERT(_head, _elm)
#define RBT_REMOVE(_name, _head, _elm) _name##_RBT_REMOVE(_head, _elm)
#define RBT_FIND(_name, _head, _key) _name##_RBT_FIND(_head, _key)
#define RBT_NFIND(_name, _head, _key) _name##_RBT_NFIND(_head, _key)
#define RBT_ROOT(_name, _head) _name##_RBT_ROOT(_head)
#define RBT_EMPTY(_name, _head) _name##_RBT_EMPTY(_head)
#define RBT_MIN(_name, _head) _name##_RBT_MIN(_head)
#define RBT_MAX(_name, _head) _name##_RBT_MAX(_head)
#define RBT_NEXT(_name, _elm) _name##_RBT_NEXT(_elm)
#define RBT_PREV(_name, _elm) _name##_RBT_PREV(_elm)
#define RBT_LEFT(_name, _elm) _name##_RBT_LEFT(_elm)
#define RBT_RIGHT(_name, _elm) _name##_RBT_RIGHT(_elm)
#define RBT_PARENT(_name, _elm) _name##_RBT_PARENT(_elm)
#define RBT_SET_LEFT(_name, _elm, _l) _name##_RBT_SET_LEFT(_elm, _l)
#define RBT_SET_RIGHT(_name, _elm, _r) _name##_RBT_SET_RIGHT(_elm, _r)
#define RBT_SET_PARENT(_name, _elm, _p) _name##_RBT_SET_PARENT(_elm, _p)
#define RBT_POISON(_name, _elm, _p) _name##_RBT_POISON(_elm, _p)
#define RBT_CHECK(_name, _elm, _p) _name##_RBT_CHECK(_elm, _p)
#define RBT_FOREACH(_e, _name, _head) \
for ((_e) = RBT_MIN(_name, (_head)); \
(_e) != NULL; \
(_e) = RBT_NEXT(_name, (_e)))
#define RBT_FOREACH_SAFE(_e, _name, _head, _n) \
for ((_e) = RBT_MIN(_name, (_head)); \
(_e) != NULL && ((_n) = RBT_NEXT(_name, (_e)), 1); \
(_e) = (_n))
#define RBT_FOREACH_REVERSE(_e, _name, _head) \
for ((_e) = RBT_MAX(_name, (_head)); \
(_e) != NULL; \
(_e) = RBT_PREV(_name, (_e)))
#define RBT_FOREACH_REVERSE_SAFE(_e, _name, _head, _n) \
for ((_e) = RBT_MAX(_name, (_head)); \
(_e) != NULL && ((_n) = RBT_PREV(_name, (_e)), 1); \
(_e) = (_n))
#endif /* _SYS_TREE_H_ */

25
include/sys/types.h Normal file
View File

@@ -0,0 +1,25 @@
/*
* Public domain
* sys/types.h compatibility shim
*/
#include_next <sys/types.h>
#ifndef LIBCOMPAT_SYS_TYPES_H
#define LIBCOMPAT_SYS_TYPES_H
#include <stdint.h>
#ifdef __MINGW32__
#include <_bsd_types.h>
#endif
#if !defined(HAVE_ATTRIBUTE__DEAD) && !defined(__dead)
#define __dead __attribute__((__noreturn__))
#endif
#if !defined(HAVE_ATTRIBUTE__BOUNDED__) && !defined(__bounded__)
# define __bounded__(x, y, z)
#endif
#endif

817
main.c Normal file
View File

@@ -0,0 +1,817 @@
/*
* Copyright (c) 2019-2021 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.
*/
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <sys/types.h>
#include <sys/socket.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include "extern.h"
#include "sx_report.h"
extern int debug_expander;
extern int debug_aggregation;
extern int pipelining;
extern int expand_special_asn;
static int
usage(int ecode)
{
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 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");
printf("\nInput filters:\n");
printf(" -4 : generate IPv4 prefix-lists (default)\n");
printf(" -6 : generate IPv6 prefix-lists\n");
printf(" -m len : maximum prefix length (default: 32 for IPv4, "
"128 for IPv6)\n");
printf(" -L depth : limit recursion depth (default: unlimited)\n"),
printf(" -S sources: only use specified IRR sources, in the specified "
"order (comma separated)\n");
printf(" -w : 'validate' AS numbers: accept only ones with "
"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"
" [ip|ipv6]-prefix-list (Nokia) or prefix-set "
"(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/as-list line (use 0 for "
"infinity)\n");
printf("\nUtility operations:\n");
printf(" -d : generate some debugging output\n");
printf(" -h host : host running IRRD software (default: rr.ntt.net)\n"
" use 'host:port' to specify alternate port\n");
printf(" -T : disable pipelining (not recommended)\n");
printf(" -v : print version and exit\n");
printf("\n" PACKAGE_NAME " version: " PACKAGE_VERSION " "
"(https://github.com/bgp/bgpq4)\n");
exit(ecode);
}
static void
version(void)
{
printf(PACKAGE_NAME " - a versatile utility to generate BGP filters\n"
"version: " PACKAGE_VERSION "\n"
"website: https://github.com/bgp/bgpq4\n"
"maintainer: Job Snijders <job@sobornost.net>\n");
exit(0);
}
static void
exclusive(void)
{
fprintf(stderr,"-E, -F, -K , -f <asnum>, -G <asnum>, and -t are mutually"
" exclusive\n");
exit(1);
}
static void
vendor_exclusive(void)
{
fprintf(stderr, "-b (BIRD), -B (OpenBGPD), -F (formatted), -J (Junos),"
" -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);
}
static int
parseasnumber(struct bgpq_expander *expander, char *asnstr)
{
char *eon = NULL;
expander->asnumber = strtoul(asnstr, &eon, 10);
if (expander->asnumber < 1 || expander->asnumber > (65535ul * 65535)) {
sx_report(SX_FATAL, "Invalid AS number: %s\n", asnstr);
exit(1);
}
if (eon && *eon == '.') {
/* -f 3.3, for example */
uint32_t loas = strtoul(eon + 1, &eon, 10);
if (expander->asnumber > 65535) {
/* should prevent incorrect numbers like 65537.1 */
sx_report(SX_FATAL,"Invalid AS number: %s\n", asnstr);
exit(1);
}
if (loas < 1 || loas > 65535) {
sx_report(SX_FATAL,"Invalid AS number: %s\n", asnstr);
exit(1);
}
if (eon && *eon) {
sx_report(SX_FATAL,"Invalid symbol in AS number: "
"%c (%s)\n", *eon, asnstr);
exit(1);
}
expander->asnumber=(expander->asnumber << 16) + loas;
} else if (eon && *eon) {
sx_report(SX_FATAL,"Invalid symbol in AS number: %c (%s)\n",
*eon, asnstr);
exit(1);
}
return 0;
}
int
main(int argc, char* argv[])
{
int c;
struct bgpq_expander expander;
int af = AF_INET, selectedipv4 = 0, exceptmode = 0;
int widthSet = 0, aggregate = 0, refine = 0, refineLow = 0;
unsigned long maxlen = 0;
#ifdef HAVE_PLEDGE
if (pledge("stdio inet dns", NULL) == -1) {
sx_report(SX_ERROR, "pledge() failed");
exit(1);
}
#endif
bgpq_expander_init(&expander, af);
if (getenv("IRRD_SOURCES"))
expander.sources=getenv("IRRD_SOURCES");
while ((c = getopt(argc, argv,
"23467a:AbBdDEeF:S:jJKf:l:L:m:M:NnpW:r:R:G:H:tTh:UuwXsvz")) != EOF) {
switch (c) {
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;
}
}
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') {
*md = '\n';
md++;
mc += 2;
} else if (*(mc + 1) == 'r') {
*md = '\r';
md++;
mc += 2;
} else if (*(mc + 1) == 't') {
*md = '\t';
md++;
mc += 2;
} else if (*(mc + 1) == '\\') {
*md = '\\';
md++;
mc += 2;
} else {
sx_report(SX_FATAL, "Unsupported"
" escape \%c (0x%2.2x) in "
"'%s'\n",
isprint(*mc) ? *mc : 20,
*mc, optarg);
exit(1);
}
} else {
if (mc != md) {
*md = *mc;
}
md++;
mc++;
}
}
*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 '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);
}
}
argc -= optind;
argv += optind;
if (!widthSet) {
if (expander.generation == T_ASPATH) {
int vendor = expander.vendor;
switch (vendor) {
case V_ARISTA:
case V_CISCO:
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;
switch (vendor) {
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;
}
}
}
if (!expander.generation)
expander.generation = T_PREFIXLIST;
if (expander.vendor == V_CISCO_XR
&& expander.generation != T_PREFIXLIST
&& expander.generation != T_ASPATH
&& expander.generation != T_OASPATH) {
sx_report(SX_FATAL, "Sorry, only prefix-sets and as-paths "
"supported for IOS XR\n");
}
if (expander.vendor == V_BIRD
&& expander.generation != T_PREFIXLIST
&& expander.generation != T_ASPATH
&& expander.generation != T_ASSET) {
sx_report(SX_FATAL, "Sorry, only prefix-lists and as-paths/as-sets "
"supported for BIRD output\n");
}
if (expander.vendor == V_JSON
&& expander.generation != T_PREFIXLIST
&& expander.generation != T_ASPATH
&& expander.generation != T_ASSET) {
sx_report(SX_FATAL, "Sorry, only prefix-lists and as-paths/as-sets "
"supported for JSON output\n");
}
if (expander.vendor == V_FORMAT
&& expander.generation != T_PREFIXLIST)
sx_report(SX_FATAL, "Sorry, only prefix-lists supported in formatted "
"output\n");
if (expander.vendor == V_HUAWEI
&& expander.generation != T_ASPATH
&& expander.generation != T_OASPATH
&& expander.generation != T_PREFIXLIST)
sx_report(SX_FATAL, "Sorry, only as-paths and prefix-lists supported "
"for Huawei output\n");
if (expander.generation == T_ROUTE_FILTER_LIST
&& expander.vendor != V_JUNIPER)
sx_report(SX_FATAL, "Route-filter-lists (-z) supported for Juniper (-J)"
" output only\n");
if (expander.generation == T_ASSET
&& expander.vendor != V_JSON
&& expander.vendor != V_OPENBGPD
&& expander.vendor != V_BIRD)
sx_report(SX_FATAL, "As-Sets (-t) supported for JSON (-j), OpenBGPD "
"(-B) and BIRD (-b) output only\n");
if (aggregate
&& expander.vendor == V_JUNIPER
&& expander.generation == T_PREFIXLIST) {
sx_report(SX_FATAL, "Sorry, aggregation (-A) does not work in"
" Juniper prefix-lists\nYou can try route-filters (-E) "
"or route-filter-lists (-z) instead of prefix-lists\n.");
exit(1);
}
if (aggregate
&& (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");
exit(1);
}
if (refine
&& (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");
exit(1);
}
if (refineLow
&& (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");
exit(1);
}
if (aggregate && expander.generation < T_PREFIXLIST) {
sx_report(SX_FATAL, "Sorry, aggregation (-A) used only for prefix-"
"lists, extended access-lists and route-filters\n");
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"
" only for IOS and EOS\n");
exit(1);
}
if (expander.sequence && expander.generation < T_PREFIXLIST) {
sx_report(SX_FATAL, "Sorry, prefix-lists sequencing (-s) can't be "
" used for non prefix-list\n");
exit(1);
}
if (refineLow && !refine) {
if (expander.family == AF_INET)
refine = 32;
else
refine = 128;
}
if (refineLow && refineLow > refine)
sx_report(SX_FATAL, "Incompatible values for -r %u and -R %u\n",
refineLow, refine);
if (refine || refineLow) {
if (expander.family == AF_INET6 && refine > 128) {
sx_report(SX_FATAL, "Invalid value for refine(-R): %u (1-128 for"
" IPv6)\n", refine);
} else if (expander.family == AF_INET6 && refineLow > 128) {
sx_report(SX_FATAL, "Invalid value for refineLow(-r): %u (1-128 for"
" IPv6)\n", refineLow);
} else if (expander.family == AF_INET && refine > 32) {
sx_report(SX_FATAL, "Invalid value for refine(-R): %u (1-32 for"
" IPv4)\n", refine);
} else if (expander.family == AF_INET && refineLow > 32) {
sx_report(SX_FATAL, "Invalid value for refineLow(-r): %u (1-32 for"
" IPv4)\n", refineLow);
}
if (expander.vendor == V_JUNIPER && expander.generation == T_PREFIXLIST) {
if (refine) {
sx_report(SX_FATAL, "Sorry, more-specific filters (-R %u) "
"is not supported for Juniper prefix-lists.\n"
"Use router-filters (-E) or route-filter-lists (-z) "
"instead\n", refine);
} else {
sx_report(SX_FATAL, "Sorry, more-specific filters (-r %u) "
"is not supported for Juniper prefix-lists.\n"
"Use route-filters (-E) or route-filter-lists (-z) "
"instead\n", refineLow);
}
}
if (expander.generation < T_PREFIXLIST) {
if (refine)
sx_report(SX_FATAL, "Sorry, more-specific filter (-R %u) "
"supported only with prefix-list generation\n", refine);
else
sx_report(SX_FATAL, "Sorry, more-specific filter (-r %u) "
"supported only with prefix-list generation\n", refineLow);
}
}
if (maxlen) {
if ((expander.family == AF_INET6 && maxlen > 128)
|| (expander.family == AF_INET && maxlen > 32)) {
sx_report(SX_FATAL, "Invalid value for max-prefixlen: %lu (1-128 "
"for IPv6, 1-32 for IPv4)\n", maxlen);
exit(1);
} else if ((expander.family == AF_INET6 && maxlen < 128)
|| (expander.family == AF_INET && maxlen < 32)) {
/*
* inet6/128 and inet4/32 does not make sense - all
* routes will be accepted, so save some CPU cycles :)
*/
expander.maxlen = maxlen;
}
} else if (expander.family == AF_INET)
expander.maxlen = 32;
else if (expander.family == AF_INET6)
expander.maxlen = 128;
if (expander.generation == T_EACL && expander.vendor == V_CISCO
&& expander.family == AF_INET6) {
sx_report(SX_FATAL,"Sorry, ipv6 access-lists not supported "
"for Cisco yet.\n");
}
if (expander.match != NULL
&& (expander.vendor != V_JUNIPER || expander.generation != T_EACL)) {
sx_report(SX_FATAL, "Sorry, extra match conditions (-M) can be used "
"only with Juniper route-filters\n");
}
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) or as-list (-H) "
"generation\n");
}
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");
}
if (!argv[0])
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(obj, "AS-", 3)) {
bgpq_expander_add_asset(&expander, argv[0]);
} else if (!strncasecmp(obj, "RS-", 3)) {
bgpq_expander_add_rset(&expander, argv[0]);
} else if (!strncasecmp(obj, "AS", 2)) {
char *ec;
if ((ec = strchr(obj, ':'))) {
if (!strncasecmp(ec + 1, "AS-", 3)) {
bgpq_expander_add_asset(&expander, argv[0]);
} else if (!strncasecmp(ec + 1, "RS-", 3)) {
bgpq_expander_add_rset(&expander, argv[0]);
} else {
SX_DEBUG(debug_expander,"Unknown sub-as"
" object %s\n", argv[0]);
}
} else {
bgpq_expander_add_as(&expander, argv[0]);
}
} else {
char *ec = strchr(argv[0], '^');
if (!ec && !bgpq_expander_add_prefix(&expander, argv[0])) {
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])) {
sx_report(SX_ERROR, "Unable to add prefix-range "
"%s (bad range or address-family)\n",
argv[0]);
exit(1);
}
}
argv++;
argc--;
}
if (!bgpq_expand(&expander))
exit(1);
if (refine)
sx_radix_tree_refine(expander.tree, refine);
if (refineLow)
sx_radix_tree_refineLow(expander.tree, refineLow);
if (aggregate)
sx_radix_tree_aggregate(expander.tree);
switch (expander.generation) {
case T_NONE:
sx_report(SX_FATAL,"Unreachable point");
exit(1);
case T_ASPATH:
bgpq4_print_aspath(stdout, &expander);
break;
case T_OASPATH:
bgpq4_print_oaspath(stdout, &expander);
break;
case T_ASLIST:
bgpq4_print_aslist(stdout, &expander);
break;
case T_ASSET:
bgpq4_print_asset(stdout, &expander);
break;
case T_PREFIXLIST:
bgpq4_print_prefixlist(stdout, &expander);
break;
case T_EACL:
bgpq4_print_eacl(stdout, &expander);
break;
case T_ROUTE_FILTER_LIST:
bgpq4_print_route_filter_list(stdout, &expander);
break;
}
expander_freeall(&expander);
return 0;
}

2008
printer.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.or
g/TR/html4/loose.dtd">
<html><head><style type='text/css'>
h1 { color: #3c78b5; border-bottom: 3px solid #3c78b5; font-size: 180%; }
h2 { color: #3c78b5; border-bottom: 2px solid #3c78b5; font-size: 140%; }
h3 { color: #3c78b5; border-bottom: 1px dotted #3c78b5; font-size: 129%; }
em { color: #0000FF; }
code { font-size:12px; background-color:#f8f8ff; border:1px; }
pre { border: 1px dotted #3c78b5; background-color: #f8f8ff; margin: 1em 1em;}
body { width: 80%; margin: 0 3em; }
ul { list-style: none; }
</style></head><body>

View File

@@ -1,72 +0,0 @@
/* $OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $ */
/*
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
* 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``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 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.
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#ifndef HAVE_STRLCPY
#include <sys/types.h>
#include <string.h>
/*
* Copy src to string dst of size siz. At most siz-1 characters
* will be copied. Always NUL terminates (unless siz == 0).
* Returns strlen(src); if retval >= siz, truncation occurred.
*/
size_t
strlcpy(dst, src, siz)
char *dst;
const char *src;
size_t siz;
{
char *d = dst;
const char *s = src;
size_t n = siz;
/* Copy as many bytes as will fit */
if (n != 0 && --n != 0) {
do {
if ((*d++ = *s++) == 0)
break;
} while (--n != 0);
}
/* Not enough room in dst, add NUL and traverse rest of src */
if (n == 0) {
if (siz != 0)
*d = '\0'; /* NUL-terminate dst */
while (*s++)
;
}
return(s - src - 1); /* count does not include NUL */
}
#endif

View File

@@ -1,109 +0,0 @@
#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 "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

@@ -1,8 +0,0 @@
#ifndef SX_MAXSOCKBUF_H_
#define SX_MAXSOCKBUF_H_
/* s - number of opened socket, dir is either SO_SNDBUF or SO_RCVBUF */
int sx_maxsockbuf(int s, int dir);
#endif

View File

@@ -1,8 +1,32 @@
#if HAVE_CONFIG_H
#include "config.h"
#endif
/*
* 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 <ctype.h>
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -12,16 +36,16 @@
#include "sx_prefix.h"
#include "sx_report.h"
int debug_aggregation=0;
int debug_aggregation = 0;
extern int debug_expander;
struct sx_prefix*
sx_prefix_alloc(struct sx_prefix* p)
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));
@@ -32,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);
@@ -41,28 +65,29 @@ 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
sx_prefix_adjust_masklen(struct sx_prefix* p)
sx_prefix_adjust_masklen(struct sx_prefix *p)
{
int nbytes = (p->family == AF_INET ? 4 : 16);
int i;
unsigned int nbytes = (p->family == AF_INET ? 4 : 16);
unsigned int i;
if (p->masklen == nbytes * 8)
return; /* mask is all ones */
for (i = nbytes -1; i > p->masklen / 8; i--) {
p->addr.addrs[i]=0;
p->addr.addrs[i] = 0;
}
for (i = 1; i <= 8 - p->masklen % 8; i++) {
@@ -70,10 +95,10 @@ sx_prefix_adjust_masklen(struct sx_prefix* p)
}
}
void
sx_prefix_mask(struct sx_prefix* p, struct sx_prefix* q)
static void
sx_prefix_mask(struct sx_prefix *p, struct sx_prefix *q)
{
int i;
unsigned int i;
memset(q->addr.addrs, 0, sizeof(q->addr.addrs));
@@ -87,10 +112,10 @@ sx_prefix_mask(struct sx_prefix* p, struct sx_prefix* q)
q->addr.addrs[p->masklen / 8] |= (1 << (8 - i));
}
void
sx_prefix_imask(struct sx_prefix* p, struct sx_prefix* q)
static void
sx_prefix_imask(struct sx_prefix *p, struct sx_prefix *q)
{
int i;
unsigned int i;
memset(q->addr.addrs, 0xff, sizeof(q->addr.addrs));
@@ -106,20 +131,20 @@ sx_prefix_imask(struct sx_prefix* p, struct sx_prefix* q)
int
sx_prefix_parse(struct sx_prefix* p, int af, char* text)
sx_prefix_parse(struct sx_prefix *p, int af, char *text)
{
char* c = NULL;
int masklen, ret;
char mtext[INET6_ADDRSTRLEN+5];
char *c = NULL;
int masklen, ret;
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",
@@ -169,7 +194,7 @@ sx_prefix_parse(struct sx_prefix* p, int af, char* text)
if (masklen == -1)
p->masklen = 32;
else {
if(masklen < 0 || masklen > 32) {
if (masklen < 0 || masklen > 32) {
p->masklen = 32;
} else {
p->masklen = masklen;
@@ -202,10 +227,10 @@ fixups:
return 0;
}
int
sx_prefix_isbitset(struct sx_prefix* p, int n)
static int
sx_prefix_isbitset(struct sx_prefix *p, int n)
{
unsigned char s;
unsigned char s;
/* bits outside the prefix considered unset */
if (p->family == AF_INET && (n < 0 || n > 32))
@@ -217,10 +242,10 @@ sx_prefix_isbitset(struct sx_prefix* p, int n)
return (s & (0x80 >> ((n - 1) % 8))) ? 1 : 0;
}
void
sx_prefix_setbit(struct sx_prefix* p, int n)
static void
sx_prefix_setbit(struct sx_prefix *p, int n)
{
unsigned char* s;
unsigned char *s;
if (p->family == AF_INET && (n < 0 || n > 32))
return;
@@ -233,74 +258,66 @@ sx_prefix_setbit(struct sx_prefix* p, int n)
}
int
sx_radix_tree_insert_specifics(struct sx_radix_tree* t, struct sx_prefix *p,
static int
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;
}
int
sx_prefix_range_parse(struct sx_radix_tree* tree, int af, int maxlen,
char* text)
sx_prefix_range_parse(struct sx_radix_tree *tree, int af, unsigned int maxlen,
char *text)
{
char* d = strchr(text, '^');
struct sx_prefix *p;
unsigned long min, max;
p = sx_prefix_alloc(NULL);
struct sx_prefix p;
unsigned long min, max = 0;
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);
char *dm = NULL;
min = strtoul(d + 1, &dm, 10);
if (dm && *dm == '-' && isdigit(dm[1])) {
max = strtoul(dm + 1, NULL, 10);
} else if (dm && *dm) {
@@ -313,9 +330,9 @@ sx_prefix_range_parse(struct sx_radix_tree* tree, int af, 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;
}
@@ -340,10 +357,10 @@ sx_prefix_range_parse(struct sx_radix_tree* tree, int af, int maxlen,
return 1;
}
struct sx_prefix*
sx_prefix_new(int af, char* text)
struct sx_prefix *
sx_prefix_new(int af, char *text)
{
struct sx_prefix* p = NULL;
struct sx_prefix *p = NULL;
if (!text)
return NULL;
@@ -354,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;
}
@@ -362,7 +379,7 @@ sx_prefix_new(int af, char* text)
}
int
sx_prefix_fprint(FILE* f, struct sx_prefix* p)
sx_prefix_fprint(FILE *f, struct sx_prefix *p)
{
char buffer[128];
@@ -376,7 +393,7 @@ sx_prefix_fprint(FILE* f, struct sx_prefix* p)
}
int
sx_prefix_snprintf_sep(struct sx_prefix* p, char* rbuffer, int srb, char* sep)
sx_prefix_snprintf_sep(struct sx_prefix *p, char *rbuffer, int srb, char *sep)
{
char buffer[128];
@@ -394,83 +411,96 @@ sx_prefix_snprintf_sep(struct sx_prefix* p, char* rbuffer, int srb, char* sep)
}
int
sx_prefix_snprintf(struct sx_prefix* p, char* rbuffer, int srb)
sx_prefix_snprintf(struct sx_prefix *p, char *rbuffer, int srb)
{
return sx_prefix_snprintf_sep(p, rbuffer, srb, "/");
}
int
sx_prefix_snprintf_fmt(struct sx_prefix* p, char* buffer, int size,
const char* name, const char* format)
void
sx_prefix_snprintf_fmt(struct sx_prefix *p, FILE *f,
const char *name, const char *format,
unsigned int aggregateLow, unsigned int aggregateHi)
{
unsigned off = 0;
const char* c = format;
struct sx_prefix *q = sx_prefix_alloc(NULL);
const char *c = format;
struct sx_prefix *q = sx_prefix_alloc(NULL);
char prefix[128];
while (*c) {
if(*c == '%') {
if (*c == '%') {
switch (*(c + 1)) {
case 'r':
case 'n':
inet_ntop(p->family, &p->addr, buffer+off, size-off);
off = strlen(buffer);
if (NULL != inet_ntop(p->family, &p->addr, prefix, sizeof(prefix))) {
fprintf(f, "%s", prefix);
} else {
sx_report(SX_ERROR, "inet_ntop failed\n");
return;
}
break;
case 'l':
off += snprintf(buffer + off, size - off,
"%i", p->masklen);
fprintf(f, "%i", p->masklen);
break;
case 'a':
fprintf(f, "%u", aggregateLow);
break;
case 'A':
fprintf(f, "%u", aggregateHi);
break;
case '%':
buffer[off++] = '%';
fprintf(f, "%%");
break;
case 'N':
off += snprintf(buffer + off, size - off,
"%s", name);
fprintf(f, "%s", name);
break;
case 'm':
sx_prefix_mask(p, q);
inet_ntop(p->family, &q->addr, buffer + off,
size - off);
off = strlen(buffer);
if (NULL != inet_ntop(p->family, &q->addr, prefix, sizeof(prefix))) {
fprintf(f, "%s", prefix);
} else {
sx_report(SX_ERROR, "inet_ntop failed\n");
return;
}
break;
case 'i':
sx_prefix_imask(p, q);
inet_ntop(p->family, &q->addr, buffer + off,
size - off);
off = strlen(buffer);
if (NULL != inet_ntop(p->family, &q->addr, prefix, sizeof(prefix))) {
fprintf(f, "%s", prefix);
} else {
sx_report(SX_ERROR, "inet_ntop failed\n");
return;
}
break;
default :
sx_report(SX_ERROR, "Unknown format char "
"'%c'\n", *(c + 1));
return 0;
return;
}
c += 2;
} else if (*c == '\\') {
switch(*(c+1)) {
switch(*(c + 1)) {
case 'n':
buffer[off++] = '\n';
fprintf(f, "\n");
break;
case 't':
buffer[off++] = '\t';
fprintf(f, "\t");
break;
case '\\':
buffer[off++] = '\\';
fprintf(f, "\\");
break;
default:
buffer[off++] = *(c + 1);
fprintf(f, "%c", *(c + 1));
break;
}
c += 2;
} else {
buffer[off++] = *c;
fprintf(f, "%c", *c);
c++;
}
}
return strlen(buffer);
}
int
sx_prefix_jsnprintf(struct sx_prefix* p, char* rbuffer, int srb)
sx_prefix_jsnprintf(struct sx_prefix *p, char *rbuffer, int srb)
{
char buffer[128];
@@ -483,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;
@@ -498,18 +528,18 @@ sx_radix_tree_new(int af)
}
int
sx_radix_tree_empty(struct sx_radix_tree* t)
sx_radix_tree_empty(struct sx_radix_tree *t)
{
return t->head == NULL;
}
struct sx_radix_node*
sx_radix_node_new(struct sx_prefix* prefix)
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));
@@ -519,20 +549,20 @@ sx_radix_node_new(struct sx_prefix* prefix)
return rn;
}
int
sx_prefix_eqbits(struct sx_prefix* a, struct sx_prefix* b)
static int
sx_prefix_eqbits(struct sx_prefix *a, struct sx_prefix *b)
{
int i;
int nbytes = (a->family == AF_INET ? 4 : 16);
unsigned int i;
unsigned int nbytes = (a->family == AF_INET ? 4 : 16);
for (i = 0; i < nbytes; i++) {
if (a->addr.addrs[i] == b->addr.addrs[i])
continue;
else {
int j;
unsigned int j;
for (j = 0; j < 8 && i * 8 + j <= a->masklen
&& i * 8 + j<= b->masklen; j++) {
&& i * 8 + j <= b->masklen; j++) {
if ((a->addr.addrs[i] & (0x80 >> j))
!= (b->addr.addrs[i] & (0x80 >> j)))
return i * 8 + j;
@@ -546,10 +576,10 @@ sx_prefix_eqbits(struct sx_prefix* a, struct sx_prefix* b)
return b->masklen;
}
struct sx_prefix*
sx_prefix_overlay(struct sx_prefix* p, int n)
struct sx_prefix *
sx_prefix_overlay(struct sx_prefix *p, int n)
{
struct sx_prefix* sp = sx_prefix_alloc(p);
struct sx_prefix *sp = sx_prefix_alloc(p);
sp->masklen = n;
sx_prefix_adjust_masklen(sp);
@@ -557,7 +587,7 @@ sx_prefix_overlay(struct sx_prefix* p, int n)
}
void
sx_radix_tree_unlink(struct sx_radix_tree* tree, struct sx_radix_node* node)
sx_radix_tree_unlink(struct sx_radix_tree *tree, struct sx_radix_node *node)
{
next:
if (node->r && node->l)
@@ -589,14 +619,14 @@ next:
if (node->parent->r == node) {
node->parent->r = node->l;
node->l->parent = node->parent;
} else if(node->parent->l==node) {
} else if (node->parent->l==node) {
node->parent->l=node->l;
node->l->parent=node->parent;
} else {
sx_report(SX_ERROR,"Unlinking node which is not descendant "
"of its parent\n");
}
} else if(tree->head==node) {
} else if (tree->head==node) {
tree->head=node->l;
node->l->parent=NULL;
} else {
@@ -607,7 +637,7 @@ next:
} else {
/* the only case - node does not have descendants */
if (node->parent) {
if(node->parent->l == node)
if (node->parent->l == node)
node->parent->l = NULL;
else if (node->parent->r == node)
node->parent->r=NULL;
@@ -632,11 +662,11 @@ next:
}
struct sx_radix_node*
sx_radix_tree_lookup(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)
{
int eb;
struct sx_radix_node* candidate = NULL, *chead;
unsigned int eb;
struct sx_radix_node *candidate = NULL, *chead;
if (!tree || !prefix)
return NULL;
@@ -689,43 +719,43 @@ 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*
sx_radix_tree_insert(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)
{
int eb;
struct sx_radix_node** candidate=NULL, *chead;
unsigned int eb;
struct sx_radix_node *chead, **candidate = NULL;
if (!tree || !prefix)
return NULL;
if (tree->family!=prefix->family)
if (tree->family != prefix->family)
return NULL;
if (!tree->head) {
tree->head=sx_radix_node_new(prefix);
tree->head = sx_radix_node_new(prefix);
return tree->head;
}
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);
struct sx_radix_node* rn, *ret=sx_radix_node_new(prefix);
struct sx_radix_node *rn, *ret=sx_radix_node_new(prefix);
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",
@@ -748,12 +778,11 @@ next:
*candidate = rn;
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)) {
struct sx_radix_node *ret = sx_radix_node_new(prefix);
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;
@@ -790,17 +819,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", eb,
printf("Unreachable point... eb=%i, prefix=%s, chead=%s\n", eb,
pbuffer, cbuffer);
abort();
}
}
void
sx_radix_node_fprintf(struct sx_radix_node* node, void* udata)
sx_radix_node_fprintf(struct sx_radix_node *node, void *udata)
{
FILE* out = (udata?udata:stdout);
char buffer[128];
FILE *out = (udata?udata:stdout);
char buffer[128];
if (!node) {
fprintf(out, "(null)\n");
} else {
@@ -810,10 +840,10 @@ 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)
sx_radix_node_foreach(struct sx_radix_node *node,
void (*func)(struct sx_radix_node *, void *), void *udata)
{
func(node,udata);
func(node, udata);
if (node->l)
sx_radix_node_foreach(node->l, func, udata);
@@ -825,25 +855,27 @@ sx_radix_node_foreach(struct sx_radix_node* node,
}
int
sx_radix_tree_foreach(struct sx_radix_tree* tree,
void (*func)(struct sx_radix_node*, void*), void* udata)
sx_radix_tree_foreach(struct sx_radix_tree *tree,
void (*func)(struct sx_radix_node *, void *), void *udata)
{
if(!func || !tree || !tree->head) return 0;
sx_radix_node_foreach(tree->head,func,udata);
if (!func || !tree || !tree->head)
return 0;
sx_radix_node_foreach(tree->head, func, udata);
return 0;
}
int
sx_radix_node_aggregate(struct sx_radix_node* node)
static int
sx_radix_node_aggregate(struct sx_radix_node *node)
{
if(node->l)
if (node->l)
sx_radix_node_aggregate(node->l);
if(node->r)
if (node->r)
sx_radix_node_aggregate(node->r);
if(debug_aggregation) {
if (debug_aggregation) {
printf("Aggregating on node: ");
sx_prefix_fprint(stdout,node->prefix);
sx_prefix_fprint(stdout, node->prefix);
printf(" %s%s%u,%u\n", node->isGlue?"Glue ":"",
node->isAggregate?"Aggregate ":"",node->aggregateLow,
node->aggregateHi);
@@ -886,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;
@@ -980,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;
@@ -1005,7 +1037,7 @@ sx_radix_node_aggregate(struct sx_radix_node* node)
}
int
sx_radix_tree_aggregate(struct sx_radix_tree* tree)
sx_radix_tree_aggregate(struct sx_radix_tree *tree)
{
if (tree && tree->head)
return sx_radix_node_aggregate(tree->head);
@@ -1014,16 +1046,16 @@ sx_radix_tree_aggregate(struct sx_radix_tree* tree)
}
static void
setGlueUpTo(struct sx_radix_node* node, void* udata)
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;
}
int
sx_radix_node_refine(struct sx_radix_node* node, unsigned refine)
static int
sx_radix_node_refine(struct sx_radix_node *node, unsigned refine)
{
if (!node->isGlue && node->prefix->masklen<refine) {
node->isAggregate = 1;
@@ -1065,7 +1097,7 @@ sx_radix_node_refine(struct sx_radix_node* node, unsigned refine)
}
int
sx_radix_tree_refine(struct sx_radix_tree* tree, unsigned refine)
sx_radix_tree_refine(struct sx_radix_tree *tree, unsigned refine)
{
if (tree && tree->head)
return sx_radix_node_refine(tree->head, refine);
@@ -1074,16 +1106,16 @@ sx_radix_tree_refine(struct sx_radix_tree* tree, unsigned refine)
}
static void
setGlueFrom(struct sx_radix_node* node, void* udata)
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;
node->isGlue = 1;
}
static int
sx_radix_node_refineLow(struct sx_radix_node* node, unsigned refineLow)
sx_radix_node_refineLow(struct sx_radix_node *node, unsigned refineLow)
{
if (!node->isGlue && node->prefix->masklen<=refineLow) {
@@ -1134,7 +1166,7 @@ sx_radix_node_refineLow(struct sx_radix_node* node, unsigned refineLow)
}
int
sx_radix_tree_refineLow(struct sx_radix_tree* tree, unsigned refineLow)
sx_radix_tree_refineLow(struct sx_radix_tree *tree, unsigned refineLow)
{
if (tree && tree->head)
return sx_radix_node_refineLow(tree->head, refineLow);
@@ -1145,10 +1177,10 @@ sx_radix_tree_refineLow(struct sx_radix_tree* tree, unsigned refineLow)
#if SX_PTREE_TEST
int
main() {
struct sx_prefix* p;
int n;
struct sx_radix_tree* tree;
struct sx_radix_node* node;
struct sx_prefix *p;
struct sx_radix_tree *tree;
struct sx_radix_node *node;
int n;
p = sx_prefix_new(0, "10.11.12.13/24");
sx_prefix_fprint(stdout, p);
@@ -1200,14 +1232,12 @@ main() {
sx_prefix_fprint(stdout, p);
printf("\n");
#define SX_TEST_EBITS(a,b,susp) n = sx_prefix_eqbits(sx_prefix_new(0,a)),\
sx_prefix_new(0,b))); \
if (n != susp) \
printf("FAILED: %s eqbits %s=%i, not %i\n", a, b, n,
susp);\
else
printf("OK, %s eqbits %s = %i, as suspected\n", a, b,
n);
#define SX_TEST_EBITS(a, b, susp) \
n = sx_prefix_eqbits(sx_prefix_new(0, a), sx_prefix_new(0, b)); \
if (n != susp) \
printf("FAILED: %s eqbits %s=%i, not %i\n", a, b, n, susp); \
else \
printf("OK, %s eqbits %s = %i, as suspected\n", a, b, n);
SX_TEST_EBITS("192.168.0.0/24", "192.168.1.0/24", 23);
SX_TEST_EBITS("192.168.0.0/32", "192.168.0.1/32", 31);
#if SX_LIBPTREE_IPV6

View File

@@ -1,3 +1,29 @@
/*
* 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.
*/
#ifndef _SX_PREFIX_H_
#define _SX_PREFIX_H_
@@ -8,7 +34,7 @@
typedef struct sx_prefix {
int family;
int masklen;
unsigned int masklen;
union {
struct in_addr addr;
struct in6_addr addr6;
@@ -17,58 +43,59 @@ typedef struct sx_prefix {
} sx_prefix_t;
typedef struct sx_radix_node {
struct sx_radix_node* parent, *l, *r, *son;
void* payload;
unsigned int isGlue:1;
unsigned int isAggregated:1;
unsigned int isAggregate:1;
unsigned int aggregateLow;
unsigned int aggregateHi;
struct sx_prefix *prefix;
struct sx_radix_node *parent, *l, *r, *son;
void *payload;
unsigned int isGlue:1;
unsigned int isAggregated:1;
unsigned int isAggregate:1;
unsigned int aggregateLow;
unsigned int aggregateHi;
struct sx_prefix *prefix;
} sx_radix_node_t;
typedef struct sx_radix_tree {
int family;
struct sx_radix_node* head;
int family;
struct sx_radix_node *head;
} 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, int ml, char* text);
int sx_prefix_fprint(FILE* f, struct sx_prefix* p);
int sx_prefix_snprintf(struct sx_prefix* p, char* rbuffer, int srb);
int sx_prefix_snprintf_sep(struct sx_prefix* p, char* rbuffer, int srb, char*);
int sx_prefix_snprintf_fmt(struct sx_prefix* p, char* rbuffer, int srb,
const char* name, const char* fmt);
int sx_prefix_jsnprintf(struct sx_prefix* p, char* rbuffer, int srb);
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

@@ -1,6 +1,28 @@
#if HAVE_CONFIG_H
#include <config.h>
#endif
/*
* 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 <errno.h>
#include <inttypes.h>

View File

@@ -1,3 +1,29 @@
/*
* 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.
*/
#ifndef SX_REPORT_H_
#define SX_REPORT_H_

View File

@@ -1,35 +1,61 @@
/*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "sx_slentry.h"
#include "extern.h"
struct sx_slentry*
sx_slentry_new(char* t)
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;
}
struct sx_tentry*
sx_tentry_new(char* t)
struct sx_tentry *
sx_tentry_new(char *t)
{
struct sx_tentry* te = malloc(sizeof(struct sx_tentry));
struct sx_tentry *te = malloc(sizeof(struct sx_tentry));
if (!te)
return NULL;
memset(te, 0, sizeof(struct sx_tentry));
te->text = strdup(t);
return te;

View File

@@ -1,30 +0,0 @@
#ifndef SX_SLENTRY_H_
#define SX_SLENTRY_H_
#if HAVE_SYS_QUEUE_H && HAVE_STAILQ_IN_SYS_QUEUE
#include <sys/queue.h>
#else
#include "sys_queue.h"
#endif
#if HAVE_SYS_TREE_H
#include <sys/tree.h>
#else
#include "sys_tree.h"
#endif
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

View File

@@ -1,696 +0,0 @@
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. 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.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)queue.h 8.5 (Berkeley) 8/20/94
* $FreeBSD: stable/10/sys/sys/queue.h 251887 2013-06-18 02:57:56Z lstewart $
*/
#ifndef _SYS_QUEUE_H_
#define _SYS_QUEUE_H_
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
/*
* This file defines four types of data structures: singly-linked lists,
* singly-linked tail queues, lists and tail queues.
*
* A singly-linked list is headed by a single forward pointer. The elements
* are singly linked for minimum space and pointer manipulation overhead at
* the expense of O(n) removal for arbitrary elements. New elements can be
* added to the list after an existing element or at the head of the list.
* Elements being removed from the head of the list should use the explicit
* macro for this purpose for optimum efficiency. A singly-linked list may
* only be traversed in the forward direction. Singly-linked lists are ideal
* for applications with large datasets and few or no removals or for
* implementing a LIFO queue.
*
* A singly-linked tail queue is headed by a pair of pointers, one to the
* head of the list and the other to the tail of the list. The elements are
* singly linked for minimum space and pointer manipulation overhead at the
* expense of O(n) removal for arbitrary elements. New elements can be added
* to the list after an existing element, at the head of the list, or at the
* end of the list. Elements being removed from the head of the tail queue
* should use the explicit macro for this purpose for optimum efficiency.
* A singly-linked tail queue may only be traversed in the forward direction.
* Singly-linked tail queues are ideal for applications with large datasets
* and few or no removals or for implementing a FIFO queue.
*
* A list is headed by a single forward pointer (or an array of forward
* pointers for a hash table header). The elements are doubly linked
* so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before
* or after an existing element or at the head of the list. A list
* may be traversed in either direction.
*
* A tail queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or
* after an existing element, at the head of the list, or at the end of
* the list. A tail queue may be traversed in either direction.
*
* For details on the use of these macros, see the queue(3) manual page.
*
*
* SLIST LIST STAILQ TAILQ
* _HEAD + + + +
* _HEAD_INITIALIZER + + + +
* _ENTRY + + + +
* _INIT + + + +
* _EMPTY + + + +
* _FIRST + + + +
* _NEXT + + + +
* _PREV - + - +
* _LAST - - + +
* _FOREACH + + + +
* _FOREACH_FROM + + + +
* _FOREACH_SAFE + + + +
* _FOREACH_FROM_SAFE + + + +
* _FOREACH_REVERSE - - - +
* _FOREACH_REVERSE_FROM - - - +
* _FOREACH_REVERSE_SAFE - - - +
* _FOREACH_REVERSE_FROM_SAFE - - - +
* _INSERT_HEAD + + + +
* _INSERT_BEFORE - + - +
* _INSERT_AFTER + + + +
* _INSERT_TAIL - - + +
* _CONCAT - - + +
* _REMOVE_AFTER + - + -
* _REMOVE_HEAD + - + -
* _REMOVE + + + +
* _SWAP + + + +
*
*/
#ifdef QUEUE_MACRO_DEBUG
/* Store the last 2 places the queue element or head was altered */
struct qm_trace {
unsigned long lastline;
unsigned long prevline;
const char *lastfile;
const char *prevfile;
};
#define TRACEBUF struct qm_trace trace;
#define TRACEBUF_INITIALIZER { __FILE__, __LINE__, NULL, 0 } ,
#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
#define QMD_SAVELINK(name, link) void **name = (void *)&(link)
#define QMD_TRACE_HEAD(head) do { \
(head)->trace.prevline = (head)->trace.lastline; \
(head)->trace.prevfile = (head)->trace.lastfile; \
(head)->trace.lastline = __LINE__; \
(head)->trace.lastfile = __FILE__; \
} while (0)
#define QMD_TRACE_ELEM(elem) do { \
(elem)->trace.prevline = (elem)->trace.lastline; \
(elem)->trace.prevfile = (elem)->trace.lastfile; \
(elem)->trace.lastline = __LINE__; \
(elem)->trace.lastfile = __FILE__; \
} while (0)
#else
#define QMD_TRACE_ELEM(elem)
#define QMD_TRACE_HEAD(head)
#define QMD_SAVELINK(name, link)
#define TRACEBUF
#define TRACEBUF_INITIALIZER
#define TRASHIT(x)
#endif /* QUEUE_MACRO_DEBUG */
/*
* Singly-linked List declarations.
*/
#define SLIST_HEAD(name, type) \
struct name { \
struct type *slh_first; /* first element */ \
}
#define SLIST_HEAD_INITIALIZER(head) \
{ NULL }
#define SLIST_ENTRY(type) \
struct { \
struct type *sle_next; /* next element */ \
}
/*
* Singly-linked List functions.
*/
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
#define SLIST_FIRST(head) ((head)->slh_first)
#define SLIST_FOREACH(var, head, field) \
for ((var) = SLIST_FIRST((head)); \
(var); \
(var) = SLIST_NEXT((var), field))
#define SLIST_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
(var); \
(var) = SLIST_NEXT((var), field))
#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = SLIST_FIRST((head)); \
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
(var) = (tvar))
#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
(var) = (tvar))
#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
for ((varp) = &SLIST_FIRST((head)); \
((var) = *(varp)) != NULL; \
(varp) = &SLIST_NEXT((var), field))
#define SLIST_INIT(head) do { \
SLIST_FIRST((head)) = NULL; \
} while (0)
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
SLIST_NEXT((slistelm), field) = (elm); \
} while (0)
#define SLIST_INSERT_HEAD(head, elm, field) do { \
SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
SLIST_FIRST((head)) = (elm); \
} while (0)
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
#define SLIST_REMOVE(head, elm, type, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.sle_next); \
if (SLIST_FIRST((head)) == (elm)) { \
SLIST_REMOVE_HEAD((head), field); \
} \
else { \
struct type *curelm = SLIST_FIRST((head)); \
while (SLIST_NEXT(curelm, field) != (elm)) \
curelm = SLIST_NEXT(curelm, field); \
SLIST_REMOVE_AFTER(curelm, field); \
} \
TRASHIT(*oldnext); \
} while (0)
#define SLIST_REMOVE_AFTER(elm, field) do { \
SLIST_NEXT(elm, field) = \
SLIST_NEXT(SLIST_NEXT(elm, field), field); \
} while (0)
#define SLIST_REMOVE_HEAD(head, field) do { \
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
} while (0)
#define SLIST_SWAP(head1, head2, type) do { \
struct type *swap_first = SLIST_FIRST(head1); \
SLIST_FIRST(head1) = SLIST_FIRST(head2); \
SLIST_FIRST(head2) = swap_first; \
} while (0)
/*
* Singly-linked Tail queue declarations.
*/
#define STAILQ_HEAD(name, type) \
struct name { \
struct type *stqh_first;/* first element */ \
struct type **stqh_last;/* addr of last next element */ \
}
#define STAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).stqh_first }
#define STAILQ_ENTRY(type) \
struct { \
struct type *stqe_next; /* next element */ \
}
/*
* Singly-linked Tail queue functions.
*/
#define STAILQ_CONCAT(head1, head2) do { \
if (!STAILQ_EMPTY((head2))) { \
*(head1)->stqh_last = (head2)->stqh_first; \
(head1)->stqh_last = (head2)->stqh_last; \
STAILQ_INIT((head2)); \
} \
} while (0)
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
#define STAILQ_FIRST(head) ((head)->stqh_first)
#define STAILQ_FOREACH(var, head, field) \
for((var) = STAILQ_FIRST((head)); \
(var); \
(var) = STAILQ_NEXT((var), field))
#define STAILQ_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
(var); \
(var) = STAILQ_NEXT((var), field))
#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = STAILQ_FIRST((head)); \
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define STAILQ_INIT(head) do { \
STAILQ_FIRST((head)) = NULL; \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
STAILQ_NEXT((tqelm), field) = (elm); \
} while (0)
#define STAILQ_INSERT_HEAD(head, elm, field) do { \
if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
STAILQ_FIRST((head)) = (elm); \
} while (0)
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
STAILQ_NEXT((elm), field) = NULL; \
*(head)->stqh_last = (elm); \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0)
#define STAILQ_LAST(head, type, field) \
(STAILQ_EMPTY((head)) ? NULL : \
__containerof((head)->stqh_last, struct type, field.stqe_next))
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
#define STAILQ_REMOVE(head, elm, type, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \
if (STAILQ_FIRST((head)) == (elm)) { \
STAILQ_REMOVE_HEAD((head), field); \
} \
else { \
struct type *curelm = STAILQ_FIRST((head)); \
while (STAILQ_NEXT(curelm, field) != (elm)) \
curelm = STAILQ_NEXT(curelm, field); \
STAILQ_REMOVE_AFTER(head, curelm, field); \
} \
TRASHIT(*oldnext); \
} while (0)
#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
if ((STAILQ_NEXT(elm, field) = \
STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0)
#define STAILQ_REMOVE_HEAD(head, field) do { \
if ((STAILQ_FIRST((head)) = \
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_SWAP(head1, head2, type) do { \
struct type *swap_first = STAILQ_FIRST(head1); \
struct type **swap_last = (head1)->stqh_last; \
STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \
(head1)->stqh_last = (head2)->stqh_last; \
STAILQ_FIRST(head2) = swap_first; \
(head2)->stqh_last = swap_last; \
if (STAILQ_EMPTY(head1)) \
(head1)->stqh_last = &STAILQ_FIRST(head1); \
if (STAILQ_EMPTY(head2)) \
(head2)->stqh_last = &STAILQ_FIRST(head2); \
} while (0)
/*
* List declarations.
*/
#define LIST_HEAD(name, type) \
struct name { \
struct type *lh_first; /* first element */ \
}
#define LIST_HEAD_INITIALIZER(head) \
{ NULL }
#define LIST_ENTRY(type) \
struct { \
struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \
}
/*
* List functions.
*/
#if (defined(_KERNEL) && defined(INVARIANTS))
#define QMD_LIST_CHECK_HEAD(head, field) do { \
if (LIST_FIRST((head)) != NULL && \
LIST_FIRST((head))->field.le_prev != \
&LIST_FIRST((head))) \
panic("Bad list head %p first->prev != head", (head)); \
} while (0)
#define QMD_LIST_CHECK_NEXT(elm, field) do { \
if (LIST_NEXT((elm), field) != NULL && \
LIST_NEXT((elm), field)->field.le_prev != \
&((elm)->field.le_next)) \
panic("Bad link elm %p next->prev != elm", (elm)); \
} while (0)
#define QMD_LIST_CHECK_PREV(elm, field) do { \
if (*(elm)->field.le_prev != (elm)) \
panic("Bad link elm %p prev->next != elm", (elm)); \
} while (0)
#else
#define QMD_LIST_CHECK_HEAD(head, field)
#define QMD_LIST_CHECK_NEXT(elm, field)
#define QMD_LIST_CHECK_PREV(elm, field)
#endif /* (_KERNEL && INVARIANTS) */
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
#define LIST_FIRST(head) ((head)->lh_first)
#define LIST_FOREACH(var, head, field) \
for ((var) = LIST_FIRST((head)); \
(var); \
(var) = LIST_NEXT((var), field))
#define LIST_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
(var); \
(var) = LIST_NEXT((var), field))
#define LIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = LIST_FIRST((head)); \
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
(var) = (tvar))
#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
(var) = (tvar))
#define LIST_INIT(head) do { \
LIST_FIRST((head)) = NULL; \
} while (0)
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
QMD_LIST_CHECK_NEXT(listelm, field); \
if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
LIST_NEXT((listelm), field)->field.le_prev = \
&LIST_NEXT((elm), field); \
LIST_NEXT((listelm), field) = (elm); \
(elm)->field.le_prev = &LIST_NEXT((listelm), field); \
} while (0)
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
QMD_LIST_CHECK_PREV(listelm, field); \
(elm)->field.le_prev = (listelm)->field.le_prev; \
LIST_NEXT((elm), field) = (listelm); \
*(listelm)->field.le_prev = (elm); \
(listelm)->field.le_prev = &LIST_NEXT((elm), field); \
} while (0)
#define LIST_INSERT_HEAD(head, elm, field) do { \
QMD_LIST_CHECK_HEAD((head), field); \
if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
LIST_FIRST((head)) = (elm); \
(elm)->field.le_prev = &LIST_FIRST((head)); \
} while (0)
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
#define LIST_PREV(elm, head, type, field) \
((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \
__containerof((elm)->field.le_prev, struct type, field.le_next))
#define LIST_REMOVE(elm, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.le_next); \
QMD_SAVELINK(oldprev, (elm)->field.le_prev); \
QMD_LIST_CHECK_NEXT(elm, field); \
QMD_LIST_CHECK_PREV(elm, field); \
if (LIST_NEXT((elm), field) != NULL) \
LIST_NEXT((elm), field)->field.le_prev = \
(elm)->field.le_prev; \
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
TRASHIT(*oldnext); \
TRASHIT(*oldprev); \
} while (0)
#define LIST_SWAP(head1, head2, type, field) do { \
struct type *swap_tmp = LIST_FIRST((head1)); \
LIST_FIRST((head1)) = LIST_FIRST((head2)); \
LIST_FIRST((head2)) = swap_tmp; \
if ((swap_tmp = LIST_FIRST((head1))) != NULL) \
swap_tmp->field.le_prev = &LIST_FIRST((head1)); \
if ((swap_tmp = LIST_FIRST((head2))) != NULL) \
swap_tmp->field.le_prev = &LIST_FIRST((head2)); \
} while (0)
/*
* Tail queue declarations.
*/
#define TAILQ_HEAD(name, type) \
struct name { \
struct type *tqh_first; /* first element */ \
struct type **tqh_last; /* addr of last next element */ \
TRACEBUF \
}
#define TAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).tqh_first, TRACEBUF_INITIALIZER }
#define TAILQ_ENTRY(type) \
struct { \
struct type *tqe_next; /* next element */ \
struct type **tqe_prev; /* address of previous next element */ \
TRACEBUF \
}
/*
* Tail queue functions.
*/
#if (defined(_KERNEL) && defined(INVARIANTS))
#define QMD_TAILQ_CHECK_HEAD(head, field) do { \
if (!TAILQ_EMPTY(head) && \
TAILQ_FIRST((head))->field.tqe_prev != \
&TAILQ_FIRST((head))) \
panic("Bad tailq head %p first->prev != head", (head)); \
} while (0)
#define QMD_TAILQ_CHECK_TAIL(head, field) do { \
if (*(head)->tqh_last != NULL) \
panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \
} while (0)
#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \
if (TAILQ_NEXT((elm), field) != NULL && \
TAILQ_NEXT((elm), field)->field.tqe_prev != \
&((elm)->field.tqe_next)) \
panic("Bad link elm %p next->prev != elm", (elm)); \
} while (0)
#define QMD_TAILQ_CHECK_PREV(elm, field) do { \
if (*(elm)->field.tqe_prev != (elm)) \
panic("Bad link elm %p prev->next != elm", (elm)); \
} while (0)
#else
#define QMD_TAILQ_CHECK_HEAD(head, field)
#define QMD_TAILQ_CHECK_TAIL(head, headname)
#define QMD_TAILQ_CHECK_NEXT(elm, field)
#define QMD_TAILQ_CHECK_PREV(elm, field)
#endif /* (_KERNEL && INVARIANTS) */
#define TAILQ_CONCAT(head1, head2, field) do { \
if (!TAILQ_EMPTY(head2)) { \
*(head1)->tqh_last = (head2)->tqh_first; \
(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
(head1)->tqh_last = (head2)->tqh_last; \
TAILQ_INIT((head2)); \
QMD_TRACE_HEAD(head1); \
QMD_TRACE_HEAD(head2); \
} \
} while (0)
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_FOREACH(var, head, field) \
for ((var) = TAILQ_FIRST((head)); \
(var); \
(var) = TAILQ_NEXT((var), field))
#define TAILQ_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
(var); \
(var) = TAILQ_NEXT((var), field))
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = TAILQ_FIRST((head)); \
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
for ((var) = TAILQ_LAST((head), headname); \
(var); \
(var) = TAILQ_PREV((var), headname, field))
#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \
for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
(var); \
(var) = TAILQ_PREV((var), headname, field))
#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
for ((var) = TAILQ_LAST((head), headname); \
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
(var) = (tvar))
#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \
for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
(var) = (tvar))
#define TAILQ_INIT(head) do { \
TAILQ_FIRST((head)) = NULL; \
(head)->tqh_last = &TAILQ_FIRST((head)); \
QMD_TRACE_HEAD(head); \
} while (0)
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
QMD_TAILQ_CHECK_NEXT(listelm, field); \
if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
TAILQ_NEXT((elm), field)->field.tqe_prev = \
&TAILQ_NEXT((elm), field); \
else { \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
QMD_TRACE_HEAD(head); \
} \
TAILQ_NEXT((listelm), field) = (elm); \
(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
QMD_TRACE_ELEM(&(elm)->field); \
QMD_TRACE_ELEM(&listelm->field); \
} while (0)
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
QMD_TAILQ_CHECK_PREV(listelm, field); \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
TAILQ_NEXT((elm), field) = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
QMD_TRACE_ELEM(&(elm)->field); \
QMD_TRACE_ELEM(&listelm->field); \
} while (0)
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
QMD_TAILQ_CHECK_HEAD(head, field); \
if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
TAILQ_FIRST((head))->field.tqe_prev = \
&TAILQ_NEXT((elm), field); \
else \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
TAILQ_FIRST((head)) = (elm); \
(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
QMD_TRACE_HEAD(head); \
QMD_TRACE_ELEM(&(elm)->field); \
} while (0)
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
QMD_TAILQ_CHECK_TAIL(head, field); \
TAILQ_NEXT((elm), field) = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
QMD_TRACE_HEAD(head); \
QMD_TRACE_ELEM(&(elm)->field); \
} while (0)
#define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define TAILQ_PREV(elm, headname, field) \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
#define TAILQ_REMOVE(head, elm, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \
QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \
QMD_TAILQ_CHECK_NEXT(elm, field); \
QMD_TAILQ_CHECK_PREV(elm, field); \
if ((TAILQ_NEXT((elm), field)) != NULL) \
TAILQ_NEXT((elm), field)->field.tqe_prev = \
(elm)->field.tqe_prev; \
else { \
(head)->tqh_last = (elm)->field.tqe_prev; \
QMD_TRACE_HEAD(head); \
} \
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
TRASHIT(*oldnext); \
TRASHIT(*oldprev); \
QMD_TRACE_ELEM(&(elm)->field); \
} while (0)
#define TAILQ_SWAP(head1, head2, type, field) do { \
struct type *swap_first = (head1)->tqh_first; \
struct type **swap_last = (head1)->tqh_last; \
(head1)->tqh_first = (head2)->tqh_first; \
(head1)->tqh_last = (head2)->tqh_last; \
(head2)->tqh_first = swap_first; \
(head2)->tqh_last = swap_last; \
if ((swap_first = (head1)->tqh_first) != NULL) \
swap_first->field.tqe_prev = &(head1)->tqh_first; \
else \
(head1)->tqh_last = &(head1)->tqh_first; \
if ((swap_first = (head2)->tqh_first) != NULL) \
swap_first->field.tqe_prev = &(head2)->tqh_first; \
else \
(head2)->tqh_last = &(head2)->tqh_first; \
} while (0)
#endif /* !_SYS_QUEUE_H_ */

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
}

Some files were not shown because too many files have changed in this diff Show More