mirror of
https://github.com/bgp/bgpq4
synced 2025-02-28 08:53:11 +00:00
Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1074667e8 | ||
|
|
bdc455d72e | ||
|
|
8cc7ba2751 | ||
|
|
06b430b420 | ||
|
|
8c51669da9 | ||
|
|
dc1270f10f | ||
|
|
362f747f0f | ||
|
|
6c8c6cfec1 | ||
|
|
fb29cd54e1 | ||
|
|
903704ef3b | ||
|
|
b481111cf6 | ||
|
|
80b7dcf4de | ||
|
|
5ce7d7bfea | ||
|
|
8ec260f03f | ||
|
|
675155356d | ||
|
|
da750ed48f | ||
|
|
7fdb481130 | ||
|
|
fa84d146b3 | ||
|
|
c90c59dba8 | ||
|
|
5730525f11 | ||
|
|
78f57867cc | ||
|
|
2391fdb317 | ||
|
|
9f8d82db21 | ||
|
|
a6792d2495 | ||
|
|
af202a821b | ||
|
|
ed8ee8368d | ||
|
|
bf5f10def9 | ||
|
|
1f7572c2f1 | ||
|
|
34cc813446 | ||
|
|
5c57bb2bb6 | ||
|
|
e6bf77058a | ||
|
|
139e0d972b | ||
|
|
99f036b186 | ||
|
|
cb98214f0c | ||
|
|
ed28cf6734 | ||
|
|
9ac2087d24 | ||
|
|
58adb550bd |
12
CHANGES
12
CHANGES
@@ -1,3 +1,15 @@
|
||||
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
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*-
|
||||
* Copyright (c) 2007-2019 Alexandre Snarskii <snar@snar.spb.ru>
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -22,26 +22,5 @@
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SX_SLENTRY_H_
|
||||
#define SX_SLENTRY_H_
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <sys/tree.h>
|
||||
|
||||
struct sx_slentry {
|
||||
STAILQ_ENTRY(sx_slentry) entries;
|
||||
char* text;
|
||||
};
|
||||
|
||||
struct sx_slentry* sx_slentry_new(char* text);
|
||||
|
||||
struct sx_tentry {
|
||||
RB_ENTRY(sx_tentry) entries;
|
||||
char* text;
|
||||
};
|
||||
|
||||
struct sx_tentry* sx_tentry_new(char* text);
|
||||
|
||||
#endif
|
||||
29
IDEAS
Normal file
29
IDEAS
Normal 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
|
||||
10
Makefile.am
10
Makefile.am
@@ -1,4 +1,4 @@
|
||||
SUBDIRS = include compat
|
||||
SUBDIRS = include
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||
@@ -10,16 +10,20 @@ bin_PROGRAMS=bgpq4
|
||||
dist_man8_MANS=bgpq4.8
|
||||
|
||||
bgpq4_LDADD = $(PLATFORM_LDADD) $(PROG_LDADD)
|
||||
|
||||
if !HAVE_STRLCPY
|
||||
SUBDIRS += compat
|
||||
bgpq4_LDADD += $(top_builddir)/compat/libcompat.la
|
||||
endif
|
||||
|
||||
bgpq4_SOURCES=main.c extern.h printer.c expander.c \
|
||||
sx_maxsockbuf.c \
|
||||
sx_prefix.c sx_prefix.h \
|
||||
sx_report.c sx_report.h \
|
||||
sx_slentry.c sx_slentry.h
|
||||
sx_slentry.c
|
||||
|
||||
|
||||
EXTRA_DIST=bootstrap README.md CHANGES bgpq4.spec
|
||||
EXTRA_DIST=bootstrap README.md CHANGES
|
||||
|
||||
MAINTAINERCLEANFILES=configure aclocal.m4 compile \
|
||||
install-sh missing Makefile.in depcomp \
|
||||
|
||||
512
README.md
512
README.md
@@ -1,237 +1,232 @@
|
||||
NAME
|
||||
----
|
||||
# NAME
|
||||
|
||||
`bgpq4` - bgp filtering automation tool
|
||||
**bgpq4** - bgp filtering automation tool
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
# SYNOPSIS
|
||||
|
||||
```
|
||||
bgpq4 [-h host[:port]] [-S sources] [-Ez] [-f asn | -F fmt | -G asn | -t] [-46ABbDdeJjNnpsUX] [-a asn] [-r len] [-R len] [-m max] [-W len] OBJECTS [...] EXCEPT OBJECTS
|
||||
```
|
||||
**bgpq4**
|
||||
\[**-h** *host\[:port]*]
|
||||
\[**-S** *sources*]
|
||||
\[**-EPz**]
|
||||
\[**-f** *asn* |
|
||||
**-F** *fmt* |
|
||||
**-G** *asn*
|
||||
**-t**]
|
||||
\[**-46ABbDdJjNnsXU**]
|
||||
\[**-a** *asn*]
|
||||
\[**-r** *len*]
|
||||
\[**-R** *len*]
|
||||
\[**-m** *max*]
|
||||
\[**-W** *len*]
|
||||
*OBJECTS*
|
||||
\[...]
|
||||
\[EXCEPT OBJECTS]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
# DESCRIPTION
|
||||
|
||||
The bgpq4 utility used to generate configuration (prefix-lists,
|
||||
extended access-lists, policy-statement terms and as-path lists)
|
||||
based on IRR routing data.
|
||||
The
|
||||
**bgpq4**
|
||||
utility used to generate configurations (prefix-lists, extended
|
||||
access-lists, policy-statement terms and as-path lists) based on RADB data.
|
||||
|
||||
The options are as follows:
|
||||
|
||||
#### -4
|
||||
**-4**
|
||||
|
||||
Generate IPv4 prefix/access-lists (default).
|
||||
> generate IPv4 prefix/access-lists (default).
|
||||
|
||||
#### -6
|
||||
**-6**
|
||||
|
||||
Generate IPv6 prefix/access-lists (IPv4 by default).
|
||||
> generate IPv6 prefix/access-lists (IPv4 by default).
|
||||
|
||||
#### -A
|
||||
**-A**
|
||||
|
||||
Try to aggregate generated filters as much as possible (not all output formats
|
||||
supported).
|
||||
> try to aggregate prefix-lists as much as possible (not all output
|
||||
> formats supported).
|
||||
|
||||
#### -a asn
|
||||
**-a** *asn*
|
||||
|
||||
Specify ASN that shall be denied in case of empty prefix-list (OpenBGPD).
|
||||
> specify what asn shall be denied in case of empty prefix-list (OpenBGPD)
|
||||
|
||||
#### -B
|
||||
**-B**
|
||||
|
||||
Generate output in OpenBGPD format.
|
||||
> generate output in OpenBGPD format (default: Cisco)
|
||||
|
||||
#### -b
|
||||
**-b**
|
||||
|
||||
Generate output in BIRD format.
|
||||
> generate output in BIRD format (default: Cisco).
|
||||
|
||||
#### -d
|
||||
**-d**
|
||||
|
||||
Enable some debugging output.
|
||||
> enable some debugging output.
|
||||
|
||||
#### -E
|
||||
**-e**
|
||||
|
||||
Generate extended access-list (Cisco) or policy-statement term using
|
||||
route-filters (Juniper), [ip|ipv6]-prefix-list (Nokia) or prefix-filter
|
||||
(OpenBGPD)
|
||||
> generate output in Arista EOS format (default: Cisco).
|
||||
|
||||
#### -e
|
||||
**-E**
|
||||
|
||||
Generate output in Arista EOS format.
|
||||
> generate extended access-list (Cisco), policy-statement term using
|
||||
> route-filters (Juniper), \[ip|ipv6]-prefix-list (Nokia) or prefix-sets
|
||||
> (OpenBGPd).
|
||||
|
||||
#### -f `AS number`
|
||||
**-f** *number*
|
||||
|
||||
Generate input as-path access-list for adjacent as `AS number`.
|
||||
> generate input as-path access-list.
|
||||
|
||||
#### -F `fmt`
|
||||
**-F** *fmt*
|
||||
|
||||
Generate output in user-defined format.
|
||||
> generate output in user-defined format.
|
||||
|
||||
#### -G `number`
|
||||
**-G** *number*
|
||||
|
||||
Generate output as-path access-list.
|
||||
> generate output as-path access-list.
|
||||
|
||||
#### -h `host[:port]`
|
||||
**-h** *host\[:port]*
|
||||
|
||||
Host running IRRD database (default: `rr.ntt.net`).
|
||||
> host running IRRD database (default: rr.ntt.net).
|
||||
|
||||
#### -J
|
||||
**-J**
|
||||
|
||||
Generate config for Juniper.
|
||||
> generate config for Juniper (default: Cisco).
|
||||
|
||||
#### -j
|
||||
**-j**
|
||||
|
||||
Generate output in JSON format.
|
||||
> generate output in JSON format (default: Cisco).
|
||||
|
||||
#### -K
|
||||
**-K**
|
||||
|
||||
Generate config for MikroTik.
|
||||
> generate config for Mikrotik (default: Cisco).
|
||||
|
||||
#### -m `length`
|
||||
**-l** *name*
|
||||
|
||||
Maximum length of accepted prefixes (default: `32` for IPv4, `128` for IPv6).
|
||||
> name of generated entry.
|
||||
|
||||
#### -M `match`
|
||||
**-L** *limit*
|
||||
|
||||
Extra match conditions for Juniper route-filters. See the examples section.
|
||||
> limit recursion depth when expanding as-sets.
|
||||
|
||||
#### -n
|
||||
**-m** *len*
|
||||
|
||||
Generate config for Nokia SR OS (former Alcatel-Lucent) MD-CLI.
|
||||
> maximum prefix-length of accepted prefixes (default: 32 for IPv4 and
|
||||
> 128 for IPv6).
|
||||
|
||||
#### -N
|
||||
**-M** *match*
|
||||
|
||||
Generate config for Nokia SR OS (former Alcatel-Lucent) classic CLI.
|
||||
> extra match conditions for Juniper route-filters.
|
||||
|
||||
#### -l `name`
|
||||
**-n**
|
||||
|
||||
`Name` of generated configuration stanza.
|
||||
> generate config for Nokia SR OS MD-CLI (Cisco IOS by default)
|
||||
|
||||
#### -L `limit`
|
||||
**-N**
|
||||
|
||||
Limit recursion depth when expanding. This slows `bgpq4` a bit, but sometimes
|
||||
is a useful feature to prevent generated filters from growing too big.
|
||||
> generate config for Nokia SR OS classic CLI (Cisco IOS by default).
|
||||
|
||||
#### -p
|
||||
**-p**
|
||||
|
||||
Enable use of private ASNs and ASNs used for documentation purpose only
|
||||
(default: disabled).
|
||||
> accept routes registered for private ASNs (default: disabled)
|
||||
|
||||
#### -r `length`
|
||||
**-P**
|
||||
|
||||
Allow more-specific routes with masklen starting with specified length.
|
||||
> generate prefix-list (default, backward compatibility).
|
||||
|
||||
#### -R `length`
|
||||
**-r** *len*
|
||||
|
||||
Allow more-specific routes up to specified masklen too. (Please, note: objects
|
||||
with prefix-length greater than specified length will be always allowed.)
|
||||
> allow more specific routes starting with specified masklen too.
|
||||
|
||||
#### -s
|
||||
**-R** *len*
|
||||
|
||||
Generate sequence numbers in IOS-style prefix-lists.
|
||||
> allow more specific routes up to specified masklen too.
|
||||
|
||||
#### -S `sources`
|
||||
**-s**
|
||||
|
||||
Use specified sources only (recommended: RADB,RIPE,APNIC).
|
||||
> generate sequence numbers in IOS-style prefix-lists.
|
||||
|
||||
#### -t
|
||||
**-S** *sources*
|
||||
|
||||
Generate as-sets for OpenBGPD (OpenBSD 6.4+), BIRD and JSON formats.
|
||||
> use specified sources only (recommended: RADB,RIPE,APNIC).
|
||||
|
||||
#### -T
|
||||
**-t**
|
||||
|
||||
Disable pipelining (not recommended).
|
||||
> generate as-sets for OpenBGPd, BIRD and JSON formats.
|
||||
|
||||
#### -U
|
||||
**-T**
|
||||
|
||||
Generate output in Huawei format.
|
||||
> disable pipelining (not recommended).
|
||||
|
||||
#### -W `length`
|
||||
**-W** *len*
|
||||
|
||||
Generate as-path strings of a given length maximum (0 for infinity).
|
||||
> generate as-path strings of no more than len items (use 0 for inifinity).
|
||||
|
||||
#### -X
|
||||
**-U**
|
||||
|
||||
Generate output in Cisco IOS XR format.
|
||||
> generate config for Huawei devices (Cisco IOS by default)
|
||||
|
||||
#### -z
|
||||
**-X**
|
||||
|
||||
Generate Juniper route-filter-list (JunOS 16.2+).
|
||||
> generate config for Cisco IOS XR devices (plain IOS by default).
|
||||
|
||||
#### `OBJECTS`
|
||||
**-z**
|
||||
|
||||
`OBJECTS` means networks (in prefix format), autonomous systems, as-sets and
|
||||
route-sets. If multiple objects are specified they will be merged.
|
||||
> generate route-filter-lists (JunOS 16.2+).
|
||||
|
||||
#### `EXCEPT OBJECTS`
|
||||
*OBJECTS*
|
||||
|
||||
You can exclude autonomous sets, as-sets and route-sets found during
|
||||
expansion from future expansion.
|
||||
> means networks (in prefix format), autonomous systems, as-sets and route-sets.
|
||||
|
||||
EXAMPLES
|
||||
--------
|
||||
Generating prefix filter for MikroTik for `AS20597`:
|
||||
*EXCEPT OBJECTS*
|
||||
|
||||
$ ./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
|
||||
> those objects will be excluded from expansion.
|
||||
|
||||
Generating named Juniper prefix-filter for `AS20597`:
|
||||
# EXAMPLES
|
||||
|
||||
$ 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;
|
||||
}
|
||||
}
|
||||
Generating named juniper prefix-filter for AS20597:
|
||||
|
||||
$ bgpq4 -Jl eltel AS20597
|
||||
policy-options {
|
||||
replace:
|
||||
prefix-list eltel {
|
||||
81.9.0.0/20;
|
||||
81.9.32.0/20;
|
||||
81.9.96.0/20;
|
||||
81.222.128.0/20;
|
||||
81.222.192.0/18;
|
||||
85.249.8.0/21;
|
||||
85.249.224.0/19;
|
||||
89.112.0.0/19;
|
||||
89.112.4.0/22;
|
||||
89.112.32.0/19;
|
||||
89.112.64.0/19;
|
||||
217.170.64.0/20;
|
||||
217.170.80.0/20;
|
||||
}
|
||||
}
|
||||
|
||||
For Cisco we can use aggregation (-A) flag to make this prefix-filter
|
||||
more compact:
|
||||
|
||||
$ bgpq4 -Al eltel-v4 AS20597
|
||||
no ip prefix-list eltel-v4
|
||||
ip prefix-list eltel-v4 permit 81.9.0.0/20
|
||||
ip prefix-list eltel-v4 permit 81.9.32.0/20
|
||||
ip prefix-list eltel-v4 permit 81.9.96.0/20
|
||||
ip prefix-list eltel-v4 permit 81.222.128.0/20
|
||||
ip prefix-list eltel-v4 permit 81.222.192.0/18
|
||||
ip prefix-list eltel-v4 permit 85.249.8.0/21
|
||||
ip prefix-list eltel-v4 permit 85.249.224.0/19
|
||||
ip prefix-list eltel-v4 permit 89.112.0.0/18 ge 19 le 19
|
||||
ip prefix-list eltel-v4 permit 89.112.4.0/22
|
||||
ip prefix-list eltel-v4 permit 89.112.64.0/19
|
||||
ip prefix-list eltel-v4 permit 217.170.64.0/19 ge 20 le 20
|
||||
$ bgpq4 -Al eltel AS20597
|
||||
no ip prefix-list eltel
|
||||
ip prefix-list eltel permit 81.9.0.0/20
|
||||
ip prefix-list eltel permit 81.9.32.0/20
|
||||
ip prefix-list eltel permit 81.9.96.0/20
|
||||
ip prefix-list eltel permit 81.222.128.0/20
|
||||
ip prefix-list eltel permit 81.222.192.0/18
|
||||
ip prefix-list eltel permit 85.249.8.0/21
|
||||
ip prefix-list eltel permit 85.249.224.0/19
|
||||
ip prefix-list eltel permit 89.112.0.0/18 ge 19 le 19
|
||||
ip prefix-list eltel permit 89.112.4.0/22
|
||||
ip prefix-list eltel permit 89.112.64.0/19
|
||||
ip prefix-list eltel permit 217.170.64.0/19 ge 20 le 20
|
||||
|
||||
and, as you see, prefixes `89.112.0.0/19` and `89.112.32.0/19` now aggregated
|
||||
into single entry
|
||||
Prefixes 89.112.0.0/19 and 89.112.32.0/19 now aggregated
|
||||
into single entry 89.112.0.0/18 ge 19 le 19.
|
||||
|
||||
ip prefix-list eltel permit 89.112.0.0/18 ge 19 le 19.
|
||||
Well, for Juniper we can generate even more interesting policy-options,
|
||||
using -M <extra match conditions>, -R <len> and hierarchical names:
|
||||
|
||||
Well, for Juniper we can generate even more interesting policy-statement,
|
||||
using `-M <extra match conditions>`, `-r <len>`, `-R <len>` and hierarchical
|
||||
names:
|
||||
|
||||
$ bgpq4 -AJEl eltel/specifics -r 29 -R 32 -M "community blackhole" AS20597
|
||||
$ bgpq4 -AJEl eltel/specifics -r 29 -R 32 -M "community blackhole" AS20597
|
||||
policy-options {
|
||||
policy-statement eltel {
|
||||
term specifics {
|
||||
@@ -252,51 +247,83 @@ names:
|
||||
}
|
||||
}
|
||||
|
||||
generated policy-option term now allows all specifics with prefix-length
|
||||
between /29 and /32 for eltel networks if they match with special community
|
||||
blackhole (defined elsewhere in configuration).
|
||||
|
||||
generated policy-option term now allows more-specific routes in range
|
||||
/29 - /32 for eltel networks if they marked with community 'blackhole'
|
||||
(defined elsewhere in configuration).
|
||||
Of course, this version supports IPv6 (-6):
|
||||
|
||||
Of course, `bgpq4` supports IPv6 (-6):
|
||||
|
||||
$ bgpq4 -6l as-retn-v6 AS-RETN6
|
||||
no ipv6 prefix-list as-retn-v6
|
||||
ipv6 prefix-list as-retn-v6 permit 2001:7fb:fe00::/48
|
||||
ipv6 prefix-list as-retn-v6 permit 2001:7fb:fe01::/48
|
||||
[....]
|
||||
$ bgpq4 -6l as-retn-6 AS-RETN6
|
||||
no ipv6 prefix-list as-retn-6
|
||||
ipv6 prefix-list as-retn-6 permit 2001:7fb:fe00::/48
|
||||
ipv6 prefix-list as-retn-6 permit 2001:7fb:fe01::/48
|
||||
[....]
|
||||
|
||||
and assumes your device supports 32-bit ASNs
|
||||
|
||||
$ bgpq4 -Jf 112 AS-SPACENET
|
||||
policy-options {
|
||||
replace:
|
||||
as-path-group NN {
|
||||
as-path a0 "^112(112)*$";
|
||||
as-path a1 "^112(.)*(1898|5539|8495|8763|8878|12136|12931|15909)$";
|
||||
as-path a2 "^112(.)*(21358|23600|24151|25152|31529|34127|34906)$";
|
||||
as-path a3 "^112(.)*(35052|41720|43628|44450|196611)$";
|
||||
}
|
||||
}
|
||||
$ bgpq4 -Jf 112 AS-SPACENET
|
||||
policy-options {
|
||||
replace:
|
||||
as-path-group NN {
|
||||
as-path a0 "^112(112)*$";
|
||||
as-path a1 "^112(.)*(1898|5539|8495|8763|8878|12136|12931|15909)$";
|
||||
as-path a2 "^112(.)*(21358|23456|23600|24151|25152|31529|34127|34906)$";
|
||||
as-path a3 "^112(.)*(35052|41720|43628|44450|196611)$";
|
||||
}
|
||||
}
|
||||
|
||||
see `AS196611` in the end of the list ? That's a 32-bit ASN.
|
||||
see \`AS196611\` in the end of the list ? That's a 32-bit ASN.
|
||||
|
||||
USER-DEFINED FORMAT
|
||||
-------------------
|
||||
# USER-DEFINED FORMAT
|
||||
|
||||
If you want to generate configuration not for routers, but for some
|
||||
other programs/systems, you may use user-defined formatting, like in
|
||||
example below:
|
||||
|
||||
$ bgpq4 -F "ipfw add pass all from %n/%l to any\\n" as3254
|
||||
$ bgpq4 -F "ipfw add pass all from %n/%l to any\n" as3254
|
||||
ipfw add pass all from 62.244.0.0/18 to any
|
||||
ipfw add pass all from 91.219.29.0/24 to any
|
||||
ipfw add pass all from 91.219.30.0/24 to any
|
||||
ipfw add pass all from 193.193.192.0/19 to any
|
||||
|
||||
Recognized format characters: '%n' - network, '%l' - mask length,
|
||||
'%a' - aggregate low mask length, '%A' - aggregate high mask length,
|
||||
'%N' - object name, '%m' - object mask and '%i' - inversed mask.
|
||||
Recognized escape characters: '\n' - new line, '\t' - tabulation.
|
||||
Recognized format sequences are:
|
||||
|
||||
**%n**
|
||||
|
||||
> network
|
||||
|
||||
**%l**
|
||||
|
||||
> mask length
|
||||
|
||||
**%a**
|
||||
|
||||
> aggregate low mask length
|
||||
|
||||
**%A**
|
||||
|
||||
> aggregate high mask length
|
||||
|
||||
**%N**
|
||||
|
||||
> object name
|
||||
|
||||
**%m**
|
||||
|
||||
> object mask
|
||||
|
||||
**%i**
|
||||
|
||||
> inversed mask
|
||||
|
||||
**\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):
|
||||
@@ -304,101 +331,116 @@ be in one line (sometimes it makes sense):
|
||||
$ bgpq4 -6F "%n/%l; " as-eltel
|
||||
2001:1b00::/32; 2620:4f:8000::/48; 2a04:bac0::/29; 2a05:3a80::/48;
|
||||
|
||||
DIAGNOSTICS
|
||||
-----------
|
||||
# NOTES ON SOURCES
|
||||
|
||||
When everything is OK, `bgpq4` generates result to standard output and
|
||||
exits with status == 0. In case of errors they are printed to stderr and
|
||||
program exits with non-zero status.
|
||||
By default
|
||||
*bgpq4*
|
||||
trusts to 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 are indeed have the
|
||||
knowledge about which address space allocated to this or that ASn,
|
||||
other databases lack this knowledge and can (and, actually, do) contain
|
||||
some stale data: noone but RIRs care to remove outdated route-objects
|
||||
when address space revoked from one ASn and allocated to another.
|
||||
In order to keep their filters both compact and actual,
|
||||
*bgpq4 users*
|
||||
are encouraged to use '-S' flag to limit database sources to only
|
||||
ones they trust.
|
||||
|
||||
NOTES ON ULTRA-LARGE PREFIX-LISTS
|
||||
---------------------------------
|
||||
General recommendations:
|
||||
|
||||
To improve `bgpq4` performance when expanding extra-large AS-SETs you
|
||||
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 source: these records
|
||||
were created in database but for address space allocated to different RIR,
|
||||
so the NONAUTH databases have no chance to confirm validity of this route
|
||||
object.
|
||||
|
||||
$ 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
|
||||
[...]
|
||||
|
||||
# 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"
|
||||
|
||||
# BUILDING
|
||||
|
||||
This project uses autotools. If you are building from the repository,
|
||||
run the following command to prepare the build system:
|
||||
|
||||
./bootstrap
|
||||
./bootstrap
|
||||
|
||||
In order to compile the software, run:
|
||||
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
./configure
|
||||
|
||||
make
|
||||
|
||||
make install
|
||||
|
||||
If you wish to remove the generated build system files from your
|
||||
working tree, run:
|
||||
|
||||
make maintainer-clean
|
||||
make maintainer-clean
|
||||
|
||||
In order to create a distribution archive, run:
|
||||
|
||||
make dist
|
||||
make dist
|
||||
|
||||
PACKAGE INSTALLATION
|
||||
--------------------
|
||||
# DIAGNOSTICS
|
||||
|
||||
In FreeBSD binary package can be installed using
|
||||
When everything is OK,
|
||||
**bgpq4**
|
||||
generates access-list to standard output and exits with status == 0.
|
||||
In case of errors they are printed to stderr and program exits with
|
||||
non-zero status.
|
||||
|
||||
```shell
|
||||
pkg install bgpq4
|
||||
```
|
||||
|
||||
Or from ports with `portmaster`
|
||||
|
||||
```shell
|
||||
portmaster net-mgmt/bgpq4
|
||||
```
|
||||
|
||||
On Arch Linux, BGPQ4 is [available in AUR](https://aur.archlinux.org/packages/bgpq4/):
|
||||
|
||||
```shell
|
||||
yay -S bgpq4
|
||||
```
|
||||
|
||||
MAILING LIST
|
||||
------------
|
||||
|
||||
Users and interested parties can subscribe to the BGPQ4 mailing list [bgpq4@tcp0.com](https://tcp0.com/cgi-bin/mailman/listinfo/bgpq4).
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
|
||||
NLNOG's [BGP Filter Guide](http://bgpfilterguide.nlnog.net/)
|
||||
|
||||
AUTHORS
|
||||
-------
|
||||
# AUTHORS
|
||||
|
||||
Alexandre Snarskii, Christian David, Claudio Jeker, Job Snijders,
|
||||
Massimiliano Stucchi, Michail Litvak, Peter Schoenmaker, Roelf Wichertjes,
|
||||
and contributions from many others.
|
||||
|
||||
Project
|
||||
-------
|
||||
# SEE ALSO
|
||||
|
||||
BGPQ4 is maintained by Job Snijders `<job@sobornost.net>`.
|
||||
**https://github.com/bgp/bgpq4**
|
||||
BGPQ4 on Github.
|
||||
|
||||
[https://github.com/bgp/bgpq4](https://github.com/bgp/bgpq4)
|
||||
**http://bgpfilterguide.nlnog.net/**
|
||||
NLNOG's BGP Filter Guide.
|
||||
|
||||
**https://tcp0.com/cgi-bin/mailman/listinfo/bgpq4**
|
||||
Users and interested parties can subscribe to the BGPQ4 mailing list bgpq4@tcp0.com
|
||||
|
||||
# PROJECT MAINTAINER
|
||||
|
||||
Job Snijders <job@sobornost.net>
|
||||
|
||||
113
bgpq4.8
113
bgpq4.8
@@ -178,7 +178,8 @@ ip prefix-list eltel permit 89.112.64.0/19
|
||||
ip prefix-list eltel permit 217.170.64.0/19 ge 20 le 20
|
||||
.Ed
|
||||
.fi
|
||||
- you see, prefixes 89.112.0.0/19 and 89.112.32.0/19 now aggregated
|
||||
.Pp
|
||||
Prefixes 89.112.0.0/19 and 89.112.32.0/19 now aggregated
|
||||
into single entry 89.112.0.0/18 ge 19 le 19.
|
||||
.Pp
|
||||
Well, for Juniper we can generate even more interesting policy-options,
|
||||
@@ -251,10 +252,29 @@ ipfw add pass all from 193.193.192.0/19 to any
|
||||
.Ed
|
||||
.fi
|
||||
.Pp
|
||||
Recognized format characters: %n - network, %l - mask length,
|
||||
%a - aggregate low mask length, %A - aggregate high mask length,
|
||||
%N - object name, %m - object mask and %i - inversed mask.
|
||||
Recognized escape characters: \\n - new line, \\t - tabulation.
|
||||
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 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):
|
||||
@@ -264,14 +284,97 @@ $ bgpq4 -6F "%n/%l; " as-eltel
|
||||
2001:1b00::/32; 2620:4f:8000::/48; 2a04:bac0::/29; 2a05:3a80::/48;
|
||||
.Ed
|
||||
.fi
|
||||
.Sh NOTES ON SOURCES
|
||||
By default
|
||||
.Em bgpq4
|
||||
trusts to 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 are indeed have the
|
||||
knowledge about which address space allocated to this or that ASn,
|
||||
other databases lack this knowledge and can (and, actually, do) contain
|
||||
some stale data: noone but RIRs care to remove outdated route-objects
|
||||
when address space revoked from one ASn and allocated to another.
|
||||
In order to keep their filters both compact and actual,
|
||||
.Em bgpq4 users
|
||||
are encouraged to use '-S' flag to limit database sources to only
|
||||
ones they trust.
|
||||
.Pp
|
||||
General recommendations:
|
||||
.Pp
|
||||
Use minimal set of RIR databases (only those in which you and your
|
||||
customers have registered route-objects).
|
||||
.Pp
|
||||
Avoid using ARIN-NONAUTH and RIPE-NONAUTH as trusted source: these records
|
||||
were created in database but for address space allocated to different RIR,
|
||||
so the NONAUTH databases have no chance to confirm validity of this route
|
||||
object.
|
||||
.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
|
||||
[...]
|
||||
.Sh PERFORMANCE
|
||||
To improve `bgpq4` performance when expanding extra-large AS-SETs you
|
||||
shall tune OS settings to enlarge TCP send buffer.
|
||||
.Pp
|
||||
FreeBSD can be tuned in the following way:
|
||||
.Pp
|
||||
.Dl sysctl -w net.inet.tcp.sendbuf_max=2097152
|
||||
.Pp
|
||||
Linux can be tuned in the following way:
|
||||
.Pp
|
||||
.Dl sysctl -w net.ipv4.tcp_window_scaling=1
|
||||
.Dl sysctl -w net.core.rmem_max=2097152
|
||||
.Dl sysctl -w net.core.wmem_max=2097152
|
||||
.Dl sysctl -w net.ipv4.tcp_rmem="4096 87380 2097152"
|
||||
.Dl sysctl -w net.ipv4.tcp_wmem="4096 65536 2097152"
|
||||
.Sh BUILDING
|
||||
This project uses autotools. If you are building from the repository,
|
||||
run the following command to prepare the build system:
|
||||
.Pp
|
||||
.Dl ./bootstrap
|
||||
.Pp
|
||||
In order to compile the software, run:
|
||||
.Pp
|
||||
.Dl ./configure
|
||||
.Dl make
|
||||
.Dl make install
|
||||
.Pp
|
||||
If you wish to remove the generated build system files from your
|
||||
working tree, run:
|
||||
.Pp
|
||||
.Dl make maintainer-clean
|
||||
.Pp
|
||||
In order to create a distribution archive, run:
|
||||
.Pp
|
||||
.Dl make dist
|
||||
.Sh DIAGNOSTICS
|
||||
When everything is OK,
|
||||
.Nm
|
||||
generates access-list to standard output and exits with status == 0.
|
||||
In case of errors they are printed to stderr and program exits with
|
||||
non-zero status.
|
||||
.Sh AUTHORS
|
||||
Alexandre Snarskii, Christian David, Claudio Jeker, Job Snijders,
|
||||
Massimiliano Stucchi, Michail Litvak, Peter Schoenmaker, Roelf Wichertjes,
|
||||
and contributions from many others.
|
||||
.Sh SEE ALSO
|
||||
.Sy https://github.com/bgp/bgpq4
|
||||
BGPQ4 on Github.
|
||||
.Pp
|
||||
.Sy http://bgpfilterguide.nlnog.net/
|
||||
NLNOG's BGP Filter Guide.
|
||||
.Pp
|
||||
.Sy https://tcp0.com/cgi-bin/mailman/listinfo/bgpq4
|
||||
Users and interested parties can subscribe to the BGPQ4 mailing list bgpq4@tcp0.com
|
||||
.Sh PROJECT MAINTAINER
|
||||
.An Job Snijders Aq job@sobornost.net
|
||||
|
||||
88
bgpq4.spec
88
bgpq4.spec
@@ -1,88 +0,0 @@
|
||||
Name: bgpq4
|
||||
Version: 0.0.6
|
||||
Release: 0%{?dist}
|
||||
|
||||
Group: System/Utilities
|
||||
Summary: Generate BGP filters based on routing database information
|
||||
URL: https://github.com/bgp/bgpq4
|
||||
License: BSD
|
||||
Source0: https://github.com/bgp/bgpq4
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
|
||||
%description
|
||||
You are running BGP in your network and want to automate filter generation for your routers? Well, with BGPQ4 it's easy.
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
%global debug_package %{nil}
|
||||
|
||||
%build
|
||||
./configure --prefix=$RPM_BUILD_ROOT%{_prefix} --mandir=%{_mandir}
|
||||
make
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/bin
|
||||
make install
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
/usr/bin/bgpq4
|
||||
/usr/man/man8/bgpq4.8.gz
|
||||
%doc COPYRIGHT CHANGES
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%changelog
|
||||
* Thu Mar 12 2020 Job Snijders <job@ntt.net> 0.0.6:
|
||||
- bugfixes (Thanks Chris Caputo!)
|
||||
|
||||
* Wed Jan 01 2020 Job Snijders <job@ntt.net> 0.0.5:
|
||||
- bugfixes
|
||||
|
||||
* Tue Dec 31 2019 Job Snijders <job@ntt.net> 0.0.4
|
||||
- Remove '-3' command line option, assume all devices are 32-bit ASN safe
|
||||
|
||||
* Mon Dec 30 2019 Job Snijders <job@ntt.net> 0.0.3
|
||||
- Remove the '-2' command line option
|
||||
- Significant code reformating
|
||||
- Improve performance by using IRRd 4's A query when available
|
||||
|
||||
* Sat Dec 14 2019 Job Snijders <job@ntt.net> 0.0.2
|
||||
- Add Mikrotik support
|
||||
- Remove ASDDOT support
|
||||
|
||||
* Sat Dec 14 2019 Job Snijders <job@ntt.net> 0.0.1
|
||||
- Fork from bgpq3
|
||||
|
||||
* Tue Nov 30 2018 Alexandre Snarskii <snar@snar.spb.ru> 0.1.35
|
||||
- Version updated
|
||||
|
||||
* Fri Oct 14 2016 Alexandre Snarskii <snar@snar.spb.ru> 0.1.33
|
||||
- Version updated
|
||||
|
||||
* Tue Jun 23 Alexandre Snarskii <snar@snar.spb.ru> 0.1.31
|
||||
- Version updated
|
||||
|
||||
* Tue Mar 10 Alexandre Snarskii <snar@snar.spb.ru> 0.1.28
|
||||
- Version updated
|
||||
|
||||
* Wed Oct 29 Alexandre Snarskii <snar@snar.spb.ru> 0.1.25
|
||||
- Version updated
|
||||
|
||||
* Thu Jun 5 2014 Alexandre Snarskii <snar@snar.spb.ru> 0.1.21-0.snar
|
||||
- Version updated
|
||||
|
||||
* Thu May 9 2013 Alexandre Snarskii <snar@snar.spb.ru> 0.1.19-0.snar
|
||||
- Version updated
|
||||
|
||||
* Sun Feb 24 2013 Alexandre Snarskii <snar@snar.spb.ru> 0.1.18-3.snar
|
||||
- License corrected
|
||||
|
||||
* Wed Feb 20 2013 Arnoud Vermeer <arnoud@tumblr.com> 0.1.18-2.tumblr
|
||||
- Adding missing group info (arnoud@tumblr.com)
|
||||
|
||||
* Wed Feb 20 2013 Arnoud Vermeer <arnoud@tumblr.com> 0.1.18-1.tumblr
|
||||
- new package built with tito
|
||||
@@ -2,9 +2,6 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||
|
||||
noinst_LTLIBRARIES = libcompat.la
|
||||
|
||||
libcompat_la_SOURCES =
|
||||
libcompat_la_LIBADD = $(PLATFORM_LDADD)
|
||||
|
||||
if !HAVE_STRLCPY
|
||||
libcompat_la_SOURCES += strlcpy.c
|
||||
endif
|
||||
libcompat_la_SOURCES = strlcpy.c
|
||||
|
||||
305
expander.c
305
expander.c
@@ -31,17 +31,18 @@
|
||||
#include <sys/select.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <netdb.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "extern.h"
|
||||
@@ -57,7 +58,15 @@ tentry_cmp(struct sx_tentry *a, struct sx_tentry *b)
|
||||
return strcasecmp(a->text, b->text);
|
||||
}
|
||||
|
||||
RB_GENERATE_STATIC(tentree, sx_tentry, entries, tentry_cmp);
|
||||
RB_GENERATE_STATIC(tentree, sx_tentry, entry, tentry_cmp);
|
||||
|
||||
int
|
||||
asn_cmp(struct asn_entry *a, struct asn_entry *b)
|
||||
{
|
||||
return (a->asn < b->asn ? -1 : a->asn > b->asn);
|
||||
}
|
||||
|
||||
RB_GENERATE(asn_tree, asn_entry, entry, asn_cmp);
|
||||
|
||||
int
|
||||
bgpq_expander_init(struct bgpq_expander *b, int af)
|
||||
@@ -79,22 +88,12 @@ bgpq_expander_init(struct bgpq_expander *b, int af)
|
||||
b->sources = "";
|
||||
b->name = "NN";
|
||||
b->aswidth = 8;
|
||||
b->asn32s[0] = malloc(8192);
|
||||
if (!b->asn32s[0]) {
|
||||
sx_report(SX_FATAL,"Unable to allocate 8192 bytes: %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
memset(b->asn32s[0], 0, 8192);
|
||||
b->identify = 1;
|
||||
b->server = "rr.ntt.net";
|
||||
b->port = "43";
|
||||
|
||||
// b->wq = STAILQ_HEAD_INITIALZIER(b->wq);
|
||||
// b->rq = STAILQ_HEAD_INITIALZIER(b->rq);
|
||||
// b->rsets = STAILQ_HEAD_INITIALZIER(b->rsets);
|
||||
// b->macroses = STAILQ_HEAD_INITIALZIER(b->macroses);
|
||||
|
||||
RB_INIT(&b->asnlist);
|
||||
|
||||
STAILQ_INIT(&b->wq);
|
||||
STAILQ_INIT(&b->rq);
|
||||
STAILQ_INIT(&b->rsets);
|
||||
@@ -115,14 +114,14 @@ fixups:
|
||||
int
|
||||
bgpq_expander_add_asset(struct bgpq_expander *b, char *as)
|
||||
{
|
||||
struct sx_slentry *le;
|
||||
struct slentry *le;
|
||||
|
||||
if (!b || !as)
|
||||
return 0;
|
||||
|
||||
le = sx_slentry_new(as);
|
||||
|
||||
STAILQ_INSERT_TAIL(&b->macroses, le, entries);
|
||||
STAILQ_INSERT_TAIL(&b->macroses, le, entry);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -130,7 +129,7 @@ bgpq_expander_add_asset(struct bgpq_expander *b, char *as)
|
||||
int
|
||||
bgpq_expander_add_rset(struct bgpq_expander *b, char *rs)
|
||||
{
|
||||
struct sx_slentry *le;
|
||||
struct slentry *le;
|
||||
|
||||
if (!b || !rs)
|
||||
return 0;
|
||||
@@ -140,7 +139,7 @@ bgpq_expander_add_rset(struct bgpq_expander *b, char *rs)
|
||||
if (!le)
|
||||
return 0;
|
||||
|
||||
STAILQ_INSERT_TAIL(&b->rsets, le, entries);
|
||||
STAILQ_INSERT_TAIL(&b->rsets, le, entry);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -182,46 +181,29 @@ bgpq_expander_add_stop(struct bgpq_expander *b, char *rs)
|
||||
int
|
||||
bgpq_expander_add_as(struct bgpq_expander *b, char *as)
|
||||
{
|
||||
char *eoa;
|
||||
uint32_t asn1 = 0, asn2 = 0;
|
||||
uint32_t asno = 0;
|
||||
char *eoa;
|
||||
uint32_t asno = 0;
|
||||
struct asn_entry *asne;
|
||||
|
||||
if (!b || !as)
|
||||
return 0;
|
||||
|
||||
asno = strtoul(as + 2, &eoa, 10);
|
||||
|
||||
if (eoa && *eoa != 0) {
|
||||
sx_report(SX_ERROR,"Invalid symbol in AS number: '%c' in %s\n",
|
||||
*eoa, as);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (asno > 65535) {
|
||||
asn1 = asno / 65536;
|
||||
asn2 = asno % 65536;
|
||||
} else
|
||||
asn1 = asno;
|
||||
|
||||
if (!expand_special_asn &&
|
||||
((asno >= 4200000000ul) || (asno >= 64496 && asno <= 65551)))
|
||||
return 0;
|
||||
|
||||
if (!b->asn32s[asn1]) {
|
||||
b->asn32s[asn1] = malloc(8192);
|
||||
if (!b->asn32s[asn1]) {
|
||||
sx_report(SX_FATAL, "Unable to allocate 8192 "
|
||||
"bytes: %s. Unable to add asn32 %s to "
|
||||
" future expansion\n", strerror(errno), as);
|
||||
return 0;
|
||||
}
|
||||
memset(b->asn32s[asn1], 0, 8192);
|
||||
}
|
||||
if ((asne = malloc(sizeof(struct asn_entry))) == NULL)
|
||||
err(1, NULL);
|
||||
|
||||
if (asno > 65535)
|
||||
b->asn32s[asn1][asn2 / 8] |= (0x80 >> (asn2 % 8));
|
||||
else
|
||||
b->asn32s[0][asn1 / 8] |= (0x80 >> (asn1 % 8));
|
||||
asne->asn = asno;
|
||||
RB_INSERT(asn_tree, &b->asnlist, asne);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -260,35 +242,36 @@ bgpq_expander_add_prefix_range(struct bgpq_expander *b, char *prefix)
|
||||
|
||||
static int
|
||||
bgpq_expanded_macro(char *as, struct bgpq_expander *ex,
|
||||
struct bgpq_request *req)
|
||||
struct request *req)
|
||||
{
|
||||
bgpq_expander_add_as(ex, as);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct bgpq_request *bgpq_pipeline(struct bgpq_expander *b,
|
||||
int (*callback)(char*, struct bgpq_expander *b, struct bgpq_request *req),
|
||||
void *udata, char *fmt, ...);
|
||||
struct request *bgpq_pipeline(struct bgpq_expander *b,
|
||||
int (*callback)(char *, struct bgpq_expander *b, struct request *req),
|
||||
void *udata, char *fmt, ...);
|
||||
|
||||
int bgpq_expand_irrd(struct bgpq_expander *b,
|
||||
int (*callback)(char*, struct bgpq_expander *b, struct bgpq_request *req),
|
||||
void *udata, char *fmt, ...);
|
||||
int (*callback)(char*, struct bgpq_expander *b, struct request *req),
|
||||
void *udata, char *fmt, ...);
|
||||
|
||||
static int
|
||||
bgpq_expanded_macro_limit(char *as, struct bgpq_expander *b,
|
||||
struct bgpq_request *req)
|
||||
struct request *req)
|
||||
{
|
||||
if (!strncasecmp(as, "AS-", 3) || strchr(as, '-') || strchr(as, ':')) {
|
||||
struct sx_tentry tkey = { .text = as };
|
||||
|
||||
if (RB_FIND(tentree, &b->already, &tkey)) {
|
||||
SX_DEBUG(debug_expander>2, "%s is already expanding, "
|
||||
SX_DEBUG(debug_expander > 2, "%s is already expanding, "
|
||||
"ignore\n", as);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (RB_FIND(tentree, &b->stoplist, &tkey)) {
|
||||
SX_DEBUG(debug_expander>2, "%s is in the stoplist, "
|
||||
SX_DEBUG(debug_expander > 2, "%s is in the stoplist, "
|
||||
"ignore\n", as);
|
||||
return 0;
|
||||
}
|
||||
@@ -298,10 +281,10 @@ bgpq_expanded_macro_limit(char *as, struct bgpq_expander *b,
|
||||
req->depth + 1 < b->maxdepth)) {
|
||||
bgpq_expander_add_already(b, as);
|
||||
if (pipelining) {
|
||||
struct bgpq_request *req1 = bgpq_pipeline(b,
|
||||
struct request *req1 = bgpq_pipeline(b,
|
||||
bgpq_expanded_macro_limit, NULL, "!i%s\n",
|
||||
as);
|
||||
req1->depth = req->depth+1;
|
||||
as);
|
||||
req1->depth = req->depth + 1;
|
||||
} else {
|
||||
b->cdepth++;
|
||||
bgpq_expand_irrd(b, bgpq_expanded_macro_limit,
|
||||
@@ -309,7 +292,7 @@ bgpq_expanded_macro_limit(char *as, struct bgpq_expander *b,
|
||||
b->cdepth--;
|
||||
}
|
||||
} else {
|
||||
SX_DEBUG(debug_expander>2, "ignoring %s at depth %i\n",
|
||||
SX_DEBUG(debug_expander > 2, "ignoring %s at depth %i\n",
|
||||
as,
|
||||
b->cdepth ? (b->cdepth + 1) : (req->depth + 1));
|
||||
}
|
||||
@@ -341,7 +324,7 @@ bgpq_expanded_macro_limit(char *as, struct bgpq_expander *b,
|
||||
|
||||
static int
|
||||
bgpq_expanded_prefix(char *as, struct bgpq_expander *ex,
|
||||
struct bgpq_request *req __attribute__((unused)))
|
||||
struct request *req __attribute__((unused)))
|
||||
{
|
||||
char *d = strchr(as, '^');
|
||||
|
||||
@@ -354,8 +337,8 @@ bgpq_expanded_prefix(char *as, struct bgpq_expander *ex,
|
||||
}
|
||||
|
||||
static int
|
||||
bgpq_expanded_v6prefix(char *prefix, struct bgpq_expander * ex,
|
||||
struct bgpq_request* req)
|
||||
bgpq_expanded_v6prefix(char *prefix, struct bgpq_expander *ex,
|
||||
struct request *req)
|
||||
{
|
||||
char *d = strchr(prefix, '^');
|
||||
|
||||
@@ -369,16 +352,16 @@ bgpq_expanded_v6prefix(char *prefix, struct bgpq_expander * ex,
|
||||
|
||||
int bgpq_pipeline_dequeue(int fd, struct bgpq_expander *b);
|
||||
|
||||
static struct bgpq_request*
|
||||
bgpq_request_alloc(char *request, int (*callback)(char*, struct bgpq_expander*,
|
||||
struct bgpq_request*), void* udata)
|
||||
static struct request *
|
||||
request_alloc(char *request, int (*callback)(char *, struct bgpq_expander *,
|
||||
struct request *), void *udata)
|
||||
{
|
||||
struct bgpq_request* bp = malloc(sizeof(struct bgpq_request));
|
||||
struct request *bp = malloc(sizeof(struct request));
|
||||
|
||||
if (!bp)
|
||||
return NULL;
|
||||
|
||||
memset(bp, 0, sizeof(struct bgpq_request));
|
||||
memset(bp, 0, sizeof(struct request));
|
||||
bp->request = strdup(request);
|
||||
bp->offset = 0;
|
||||
bp->size = strlen(bp->request);
|
||||
@@ -389,7 +372,7 @@ bgpq_request_alloc(char *request, int (*callback)(char*, struct bgpq_expander*,
|
||||
}
|
||||
|
||||
static void
|
||||
bgpq_request_free(struct bgpq_request* req)
|
||||
request_free(struct request *req)
|
||||
{
|
||||
if (req->request)
|
||||
free(req->request);
|
||||
@@ -397,15 +380,15 @@ bgpq_request_free(struct bgpq_request* req)
|
||||
free(req);
|
||||
}
|
||||
|
||||
struct bgpq_request*
|
||||
struct request *
|
||||
bgpq_pipeline(struct bgpq_expander *b,
|
||||
int (*callback)(char*, struct bgpq_expander*, struct bgpq_request*),
|
||||
void* udata, char *fmt, ...)
|
||||
int (*callback)(char *, struct bgpq_expander *, struct request *),
|
||||
void *udata, char *fmt, ...)
|
||||
{
|
||||
char request[128];
|
||||
int ret;
|
||||
struct bgpq_request* bp = NULL;
|
||||
va_list ap;
|
||||
char request[128];
|
||||
int ret;
|
||||
struct request *bp = NULL;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(request, sizeof(request), fmt, ap);
|
||||
@@ -413,11 +396,11 @@ bgpq_pipeline(struct bgpq_expander *b,
|
||||
|
||||
SX_DEBUG(debug_expander,"expander: sending %s", request);
|
||||
|
||||
bp = bgpq_request_alloc(request, callback, udata);
|
||||
bp = request_alloc(request, callback, udata);
|
||||
|
||||
if (!bp) {
|
||||
sx_report(SX_FATAL,"Unable to allocate %lu bytes: %s\n",
|
||||
(unsigned long)sizeof(struct bgpq_request),
|
||||
(unsigned long)sizeof(struct request),
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
@@ -447,23 +430,35 @@ bgpq_pipeline(struct bgpq_expander *b,
|
||||
static void
|
||||
bgpq_expander_invalidate_asn(struct bgpq_expander *b, const char *q)
|
||||
{
|
||||
char *eptr;
|
||||
unsigned long asn = 0;
|
||||
struct asn_entry find, *res;
|
||||
|
||||
if (!strncmp(q, "!gas", 4) || !strncmp(q, "!6as", 4)) {
|
||||
char *eptr;
|
||||
unsigned long asn = strtoul(q+4, &eptr, 10), asn0, asn1 = 0;
|
||||
if (!asn || asn == ULONG_MAX || asn >= 4294967295
|
||||
|| (eptr && *eptr != '\n')) {
|
||||
sx_report(SX_ERROR, "some problem invalidating asn"
|
||||
" %s\n", q);
|
||||
|
||||
errno = 0;
|
||||
asn = strtoul(q + 4, &eptr, 10);
|
||||
if (*eptr != '\n') {
|
||||
sx_report(SX_ERROR, "not a number: %s\n", q);
|
||||
return;
|
||||
}
|
||||
asn1 = asn % 65536;
|
||||
asn0 = asn / 65536;
|
||||
if (!b->asn32s[asn0] ||
|
||||
!(b->asn32s[asn0][asn1/8] & (0x80 >> (asn1 % 8)))) {
|
||||
sx_report(SX_NOTICE, "strange, invalidating inactive "
|
||||
"asn %lu(%s)\n", asn, q);
|
||||
} else {
|
||||
b->asn32s[asn0][asn1 / 8] &= ~(0x80 >> (asn1 % 8));
|
||||
if (errno == ERANGE && asn == ULONG_MAX) {
|
||||
sx_report(SX_ERROR, "overflow: %s\n", q);
|
||||
return;
|
||||
}
|
||||
if (asn == 0 || asn >= 4294967295) {
|
||||
sx_report(SX_ERROR, "out of range: %s\n", q);
|
||||
return;
|
||||
}
|
||||
if (eptr && *eptr != '\n') {
|
||||
sx_report(SX_ERROR, "no number? %s\n", q);
|
||||
return;
|
||||
}
|
||||
|
||||
find.asn = asn;
|
||||
if ((res = RB_FIND(asn_tree, &b->asnlist, &find)) == NULL) {
|
||||
RB_REMOVE(asn_tree, &b->asnlist, res);
|
||||
free(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -472,7 +467,7 @@ static void
|
||||
bgpq_write(struct bgpq_expander *b)
|
||||
{
|
||||
while(!STAILQ_EMPTY(&b->wq)) {
|
||||
struct bgpq_request *req = STAILQ_FIRST(&b->wq);
|
||||
struct request *req = STAILQ_FIRST(&b->wq);
|
||||
|
||||
int ret = write(b->fd, req->request + req->offset,
|
||||
req->size-req->offset);
|
||||
@@ -498,8 +493,8 @@ bgpq_write(struct bgpq_expander *b)
|
||||
static int
|
||||
bgpq_selread(struct bgpq_expander *b, char *buffer, int size)
|
||||
{
|
||||
fd_set rfd, wfd;
|
||||
int ret;
|
||||
fd_set rfd, wfd;
|
||||
int ret;
|
||||
|
||||
repeat:
|
||||
FD_ZERO(&rfd);
|
||||
@@ -538,11 +533,12 @@ bgpq_read(struct bgpq_expander *b)
|
||||
bgpq_write(b);
|
||||
|
||||
while(!STAILQ_EMPTY(&b->rq)) {
|
||||
struct bgpq_request* req = STAILQ_FIRST(&b->rq);
|
||||
int ret = 0;
|
||||
char *cres;
|
||||
struct request *req = STAILQ_FIRST(&b->rq);
|
||||
|
||||
SX_DEBUG(debug_expander > 2, "waiting for answer to %s,"
|
||||
"init %i '%.*s'\n", req->request, off, off, response);
|
||||
int ret = 0;
|
||||
char *cres;
|
||||
|
||||
if ((cres=strchr(response, '\n')) != NULL)
|
||||
goto have;
|
||||
@@ -577,7 +573,7 @@ have:
|
||||
"bytes: %s\n", togot + 2, strerror(errno));
|
||||
}
|
||||
|
||||
memset(recvbuffer,0,togot+2);
|
||||
memset(recvbuffer, 0, togot + 2);
|
||||
|
||||
if (!eon || *eon != '\n') {
|
||||
sx_report(SX_ERROR,"A-code finished with wrong"
|
||||
@@ -599,7 +595,7 @@ have:
|
||||
/* response is not yet fully buffered */
|
||||
memcpy(recvbuffer, eon + 1,
|
||||
off - ((eon + 1) - response));
|
||||
offset = off - ((eon+1) - response);
|
||||
offset = off - ((eon + 1) - response);
|
||||
memset(response, 0, sizeof(response));
|
||||
off = 0;
|
||||
}
|
||||
@@ -630,7 +626,7 @@ reread:
|
||||
recvbuffer + offset);
|
||||
offset += ret;
|
||||
if (offset < togot) {
|
||||
SX_DEBUG(debug_expander>5, "expected %lu, got "
|
||||
SX_DEBUG(debug_expander > 5, "expected %lu, got "
|
||||
"%lu expanding %s", togot,
|
||||
strlen(recvbuffer), req->request);
|
||||
goto reread;
|
||||
@@ -671,7 +667,7 @@ have3:
|
||||
if (c[0] == 0)
|
||||
break;
|
||||
req->callback(c, b, req);
|
||||
c += spn+1;
|
||||
c += spn + 1;
|
||||
}
|
||||
assert(c == recvbuffer + togot);
|
||||
memset(recvbuffer, 0, togot + 2);
|
||||
@@ -701,7 +697,7 @@ have3:
|
||||
}
|
||||
|
||||
memmove(response, cres + 1, off - ((cres + 1) - response));
|
||||
off -= (cres+1) - response;
|
||||
off -= (cres + 1) - response;
|
||||
memset(response + off, 0, sizeof(response) - off);
|
||||
SX_DEBUG(debug_expander > 5,
|
||||
"fixed response of %i, %.*s\n", off, off, response);
|
||||
@@ -709,7 +705,7 @@ have3:
|
||||
STAILQ_REMOVE_HEAD(&b->rq, next);
|
||||
b->piped--;
|
||||
|
||||
bgpq_request_free(req);
|
||||
request_free(req);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -717,29 +713,26 @@ have3:
|
||||
|
||||
int
|
||||
bgpq_expand_irrd(struct bgpq_expander *b,
|
||||
int (*callback)(char*, struct bgpq_expander*, struct bgpq_request* ),
|
||||
void* udata, char *fmt, ...)
|
||||
int (*callback)(char *, struct bgpq_expander *, struct request *),
|
||||
void *udata, char *fmt, ...)
|
||||
{
|
||||
char request[128], response[128];
|
||||
va_list ap;
|
||||
size_t ret;
|
||||
ssize_t ret;
|
||||
int off = 0;
|
||||
struct bgpq_request *req;
|
||||
struct request *req;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(request, sizeof(request), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
req = bgpq_request_alloc(request, callback, udata);
|
||||
req = request_alloc(request, callback, udata);
|
||||
|
||||
SX_DEBUG(debug_expander, "expander: sending '%s'\n", request);
|
||||
SX_DEBUG(debug_expander, "expander sending: %s", request);
|
||||
|
||||
if ((ret = write(b->fd, request, strlen(request)) == 0) || ret == -1)
|
||||
err(1, "write");
|
||||
|
||||
ret=write(b->fd, request, strlen(request));
|
||||
if (ret != strlen(request)) {
|
||||
sx_report(SX_FATAL,"Partial write to IRRd, only %lu bytes "
|
||||
"written: %s\n", ret, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
memset(response, 0, sizeof(response));
|
||||
|
||||
repeat:
|
||||
@@ -763,7 +756,7 @@ repeat:
|
||||
|
||||
if (response[0] == 'A') {
|
||||
char *eon, *c;
|
||||
long togot = strtoul(response+1, &eon, 10);
|
||||
long togot = strtoul(response + 1, &eon, 10);
|
||||
char *recvbuffer = malloc(togot + 2);
|
||||
int offset = 0;
|
||||
|
||||
@@ -773,13 +766,13 @@ repeat:
|
||||
}
|
||||
|
||||
if (eon && *eon != '\n') {
|
||||
sx_report(SX_ERROR,"A-code finised with wrong char "
|
||||
sx_report(SX_ERROR,"A-code finished with wrong char "
|
||||
"'%c' (%s)\n", *eon, response);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (off - ((eon + 1)-response) > togot) {
|
||||
memcpy(recvbuffer, eon+1, togot);
|
||||
if (off - ((eon + 1) - response) > togot) {
|
||||
memcpy(recvbuffer, eon + 1, togot);
|
||||
offset = togot;
|
||||
memmove(response, eon + 1 + togot,
|
||||
off - ((eon + 1) - response) - togot);
|
||||
@@ -826,7 +819,7 @@ have3:
|
||||
if (!strchr(response, '\n'))
|
||||
goto reread2;
|
||||
|
||||
SX_DEBUG(debug_expander>2,"expander: final reply of %lu bytes,"
|
||||
SX_DEBUG(debug_expander > 2,"expander: final reply of %lu bytes,"
|
||||
" %.*sreturn code %.*s",
|
||||
(unsigned long)strlen(recvbuffer), offset, recvbuffer, off,
|
||||
response);
|
||||
@@ -859,7 +852,7 @@ have3:
|
||||
sx_report(SX_ERROR,"Wrong reply: %s\n", response);
|
||||
exit(0);
|
||||
}
|
||||
bgpq_request_free(req);
|
||||
request_free(req);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -868,9 +861,10 @@ int
|
||||
bgpq_expand(struct bgpq_expander *b)
|
||||
{
|
||||
int fd = -1, err, ret, aquery = 0;
|
||||
struct sx_slentry *mc;
|
||||
struct slentry *mc;
|
||||
struct addrinfo hints, *res = NULL, *rp;
|
||||
struct linger sl;
|
||||
struct asn_entry *asne;
|
||||
|
||||
sl.l_onoff = 1;
|
||||
sl.l_linger = 5;
|
||||
@@ -933,7 +927,7 @@ bgpq_expand(struct bgpq_expander *b)
|
||||
b->fd = fd;
|
||||
|
||||
SX_DEBUG(debug_expander, "Sending '!!' to server to request for the"
|
||||
"connection to remain open\n");
|
||||
" connection to remain open\n");
|
||||
if ((ret = write(fd, "!!\n", 3)) != 3) {
|
||||
sx_report(SX_ERROR, "Partial write of multiple command mode "
|
||||
"to IRRd: %i bytes, %s\n", ret, strerror(errno));
|
||||
@@ -1023,7 +1017,7 @@ bgpq_expand(struct bgpq_expander *b)
|
||||
if (pipelining)
|
||||
fcntl(fd, F_SETFL, O_NONBLOCK|(fcntl(fd, F_GETFL)));
|
||||
|
||||
STAILQ_FOREACH(mc, &b->macroses, entries) {
|
||||
STAILQ_FOREACH(mc, &b->macroses, entry) {
|
||||
if (!b->maxdepth && RB_EMPTY(&b->stoplist)) {
|
||||
if (aquery)
|
||||
bgpq_expand_irrd(b, bgpq_expanded_prefix, b,
|
||||
@@ -1052,8 +1046,7 @@ bgpq_expand(struct bgpq_expander *b)
|
||||
}
|
||||
|
||||
if (b->generation >= T_PREFIXLIST || b->validate_asns) {
|
||||
uint32_t i, j, k;
|
||||
STAILQ_FOREACH(mc, &b->rsets, entries) {
|
||||
STAILQ_FOREACH(mc, &b->rsets, entry) {
|
||||
if (b->family == AF_INET)
|
||||
bgpq_expand_irrd(b, bgpq_expanded_prefix,
|
||||
NULL, "!i%s,1\n", mc->text);
|
||||
@@ -1061,33 +1054,27 @@ bgpq_expand(struct bgpq_expander *b)
|
||||
bgpq_expand_irrd(b, bgpq_expanded_v6prefix,
|
||||
NULL, "!i%s,1\n", mc->text);
|
||||
}
|
||||
for (k=0; k < sizeof(b->asn32s) / sizeof(unsigned char*); k++) {
|
||||
if (!b->asn32s[k])
|
||||
continue;
|
||||
for (i=0; i<8192; i++) {
|
||||
for (j=0; j<8; j++) {
|
||||
if (b->asn32s[k][i] & (0x80 >> j)) {
|
||||
if (b->family == AF_INET6) {
|
||||
if (!pipelining) {
|
||||
bgpq_expand_irrd(b, bgpq_expanded_v6prefix,
|
||||
NULL, "!6as%" PRIu32 "\n", ( k << 16) + i * 8 + j);
|
||||
} else {
|
||||
bgpq_pipeline(b, bgpq_expanded_v6prefix,
|
||||
NULL, "!6as%" PRIu32 "\n", (k << 16) + i * 8 + j);
|
||||
}
|
||||
} else {
|
||||
if (!pipelining) {
|
||||
bgpq_expand_irrd(b, bgpq_expanded_prefix,
|
||||
NULL, "!gas%" PRIu32 "\n", (k << 16) + i * 8 + j);
|
||||
} else {
|
||||
bgpq_pipeline(b, bgpq_expanded_prefix,
|
||||
NULL, "!gas%" PRIu32 "\n", ( k<< 16) + i* 8 + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RB_FOREACH(asne, asn_tree, &b->asnlist) {
|
||||
if (b->family == AF_INET6) {
|
||||
if (!pipelining) {
|
||||
bgpq_expand_irrd(b, bgpq_expanded_v6prefix,
|
||||
NULL, "!6as%" PRIu32 "\n", asne->asn);
|
||||
} else {
|
||||
bgpq_pipeline(b, bgpq_expanded_v6prefix,
|
||||
NULL, "!6as%" PRIu32 "\n", asne->asn);
|
||||
}
|
||||
} else {
|
||||
if (!pipelining) {
|
||||
bgpq_expand_irrd(b, bgpq_expanded_prefix,
|
||||
NULL, "!gas%" PRIu32 "\n", asne->asn);
|
||||
} else {
|
||||
bgpq_pipeline(b, bgpq_expanded_prefix,
|
||||
NULL, "!gas%" PRIu32 "\n", asne->asn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pipelining) {
|
||||
if (!STAILQ_EMPTY(&b->wq))
|
||||
bgpq_write(b);
|
||||
@@ -1147,17 +1134,18 @@ bgpq_prequest_freeall(struct bgpq_prequest *bpr) {
|
||||
void
|
||||
expander_freeall(struct bgpq_expander *expander) {
|
||||
struct sx_tentry *var, *nxt;
|
||||
struct asn_entry *asne, *asne_next;
|
||||
|
||||
while (!STAILQ_EMPTY(&expander->macroses)) {
|
||||
struct sx_slentry *n1 = STAILQ_FIRST(&expander->macroses);
|
||||
STAILQ_REMOVE_HEAD(&expander->macroses, entries);
|
||||
struct slentry *n1 = STAILQ_FIRST(&expander->macroses);
|
||||
STAILQ_REMOVE_HEAD(&expander->macroses, entry);
|
||||
free(n1->text);
|
||||
free(n1);
|
||||
}
|
||||
|
||||
while (!STAILQ_EMPTY(&expander->rsets)) {
|
||||
struct sx_slentry *n1 = STAILQ_FIRST(&expander->rsets);
|
||||
STAILQ_REMOVE_HEAD(&expander->rsets, entries);
|
||||
struct slentry *n1 = STAILQ_FIRST(&expander->rsets);
|
||||
STAILQ_REMOVE_HEAD(&expander->rsets, entry);
|
||||
free(n1->text);
|
||||
free(n1);
|
||||
}
|
||||
@@ -1176,10 +1164,11 @@ expander_freeall(struct bgpq_expander *expander) {
|
||||
free(var);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 65536; i++) {
|
||||
if (expander->asn32s[i] != NULL) {
|
||||
free(expander->asn32s[i]);
|
||||
}
|
||||
for (asne = RB_MIN(asn_tree, &expander->asnlist);
|
||||
asne != NULL; asne = asne_next) {
|
||||
asne_next = RB_NEXT(asn_tree, &expander->asnlist, asne);
|
||||
RB_REMOVE(asn_tree, &expander->asnlist, asne);
|
||||
free(asne);
|
||||
}
|
||||
|
||||
sx_radix_tree_freeall(expander->tree);
|
||||
|
||||
104
extern.h
104
extern.h
@@ -25,9 +25,28 @@
|
||||
*/
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <sys/tree.h>
|
||||
|
||||
#include "sx_prefix.h"
|
||||
#include "sx_slentry.h"
|
||||
|
||||
struct slentry {
|
||||
STAILQ_ENTRY(slentry) entry;
|
||||
char *text;
|
||||
};
|
||||
|
||||
struct slentry *sx_slentry_new(char *text);
|
||||
|
||||
struct sx_tentry {
|
||||
RB_ENTRY(sx_tentry) entry;
|
||||
char *text;
|
||||
};
|
||||
|
||||
struct sx_tentry *sx_tentry_new(char *text);
|
||||
|
||||
struct asn_entry {
|
||||
RB_ENTRY(asn_entry) entry;
|
||||
uint32_t asn;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
V_CISCO = 0,
|
||||
@@ -56,44 +75,47 @@ typedef enum {
|
||||
|
||||
struct bgpq_expander;
|
||||
|
||||
struct bgpq_request {
|
||||
STAILQ_ENTRY(bgpq_request) next;
|
||||
char *request;
|
||||
int size, offset;
|
||||
void *udata;
|
||||
unsigned int depth;
|
||||
int (*callback)(char *, struct bgpq_expander *,
|
||||
struct bgpq_request *);
|
||||
struct request {
|
||||
STAILQ_ENTRY(request) next;
|
||||
char *request;
|
||||
int size, offset;
|
||||
void *udata;
|
||||
unsigned int depth;
|
||||
int (*callback)(char *, struct bgpq_expander *,
|
||||
struct request *);
|
||||
};
|
||||
|
||||
struct bgpq_expander {
|
||||
struct sx_radix_tree *tree;
|
||||
STAILQ_HEAD(sx_slentries, sx_slentry) macroses, rsets;
|
||||
RB_HEAD(tentree, sx_tentry) already, stoplist;
|
||||
int family;
|
||||
char *sources;
|
||||
uint32_t asnumber;
|
||||
int aswidth;
|
||||
char *name;
|
||||
bgpq_vendor_t vendor;
|
||||
bgpq_gen_t generation;
|
||||
int identify;
|
||||
int sequence;
|
||||
unsigned int maxdepth;
|
||||
unsigned int cdepth;
|
||||
int validate_asns;
|
||||
unsigned char *asn32s[65536];
|
||||
struct bgpq_prequest *firstpipe, *lastpipe;
|
||||
int piped;
|
||||
char *match;
|
||||
char *server;
|
||||
char *port;
|
||||
char *format;
|
||||
unsigned int maxlen;
|
||||
STAILQ_HEAD(bgpq_requests, bgpq_request) wq, rq;
|
||||
int fd;
|
||||
struct sx_radix_tree *tree;
|
||||
int family;
|
||||
char *sources;
|
||||
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);
|
||||
@@ -104,12 +126,12 @@ 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);
|
||||
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_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);
|
||||
@@ -120,5 +142,5 @@ void expander_freeall(struct bgpq_expander *expander);
|
||||
int sx_maxsockbuf(int s, int dir);
|
||||
|
||||
#ifndef HAVE_STRLCPY
|
||||
size_t strlcpy(char* dst, const char* src, size_t size);
|
||||
size_t strlcpy(char *dst, const char *src, size_t size);
|
||||
#endif
|
||||
|
||||
23
main.c
23
main.c
@@ -124,8 +124,8 @@ version(void)
|
||||
static void
|
||||
exclusive(void)
|
||||
{
|
||||
fprintf(stderr,"-E, -f <asnum>, -G <asnum>, and -t are mutually "
|
||||
"exclusive\n");
|
||||
fprintf(stderr,"-E, -F, -K , -f <asnum>, -G <asnum>, and -t are mutually"
|
||||
" exclusive\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -344,7 +344,7 @@ main(int argc, char* argv[])
|
||||
mc = md = expander.match;
|
||||
while (*mc) {
|
||||
if (*mc == '\\') {
|
||||
if (*(mc+1) == '\n') {
|
||||
if (*(mc + 1) == '\n') {
|
||||
*md = '\n';
|
||||
md++;
|
||||
mc += 2;
|
||||
@@ -449,14 +449,18 @@ main(int argc, char* argv[])
|
||||
case V_CISCO:
|
||||
case V_MIKROTIK:
|
||||
expander.aswidth = 4;
|
||||
break;
|
||||
case V_CISCO_XR:
|
||||
expander.aswidth = 6;
|
||||
break;
|
||||
case V_JUNIPER:
|
||||
case V_NOKIA:
|
||||
case V_NOKIA_MD:
|
||||
expander.aswidth = 8;
|
||||
break;
|
||||
case V_BIRD:
|
||||
expander.aswidth = 10;
|
||||
break;
|
||||
}
|
||||
} else if (expander.generation == T_OASPATH) {
|
||||
int vendor = expander.vendor;
|
||||
@@ -464,12 +468,15 @@ main(int argc, char* argv[])
|
||||
case V_ARISTA:
|
||||
case V_CISCO:
|
||||
expander.aswidth = 5;
|
||||
break;
|
||||
case V_CISCO_XR:
|
||||
expander.aswidth = 7;
|
||||
break;
|
||||
case V_JUNIPER:
|
||||
case V_NOKIA:
|
||||
case V_NOKIA_MD:
|
||||
expander.aswidth = 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -729,19 +736,19 @@ main(int argc, char* argv[])
|
||||
sx_report(SX_FATAL,"Unreachable point... call snar\n");
|
||||
exit(1);
|
||||
case T_ASPATH:
|
||||
bgpq4_print_aspath(stdout,&expander);
|
||||
bgpq4_print_aspath(stdout, &expander);
|
||||
break;
|
||||
case T_OASPATH:
|
||||
bgpq4_print_oaspath(stdout,&expander);
|
||||
bgpq4_print_oaspath(stdout, &expander);
|
||||
break;
|
||||
case T_ASSET:
|
||||
bgpq4_print_asset(stdout,&expander);
|
||||
bgpq4_print_asset(stdout, &expander);
|
||||
break;
|
||||
case T_PREFIXLIST:
|
||||
bgpq4_print_prefixlist(stdout,&expander);
|
||||
bgpq4_print_prefixlist(stdout, &expander);
|
||||
break;
|
||||
case T_EACL:
|
||||
bgpq4_print_eacl(stdout,&expander);
|
||||
bgpq4_print_eacl(stdout, &expander);
|
||||
break;
|
||||
case T_ROUTE_FILTER_LIST:
|
||||
bgpq4_print_route_filter_list(stdout, &expander);
|
||||
|
||||
@@ -39,19 +39,15 @@
|
||||
#include "extern.h"
|
||||
#include "sx_report.h"
|
||||
|
||||
#ifndef SX_MAXSOCKBUF_MAX
|
||||
#define SX_MAXSOCKBUF_MAX (2*1024*1024)
|
||||
#endif
|
||||
|
||||
int
|
||||
sx_maxsockbuf(int s, int dir)
|
||||
{
|
||||
int optval = 0, voptval;
|
||||
int hiconf = -1, loconf = -1;
|
||||
unsigned int voptlen;
|
||||
int phase = 0, iterations = 0;
|
||||
{
|
||||
int optval = 0, voptval;
|
||||
int hiconf = -1, loconf = -1;
|
||||
unsigned int voptlen;
|
||||
int phase = 0, iterations = 0;
|
||||
|
||||
if (s<0) {
|
||||
if (s < 0) {
|
||||
sx_report(SX_FATAL,"Unable to maximize sockbuf on invalid "
|
||||
"socket %i\n", s);
|
||||
exit(1);
|
||||
@@ -65,30 +61,27 @@ sx_maxsockbuf(int s, int dir)
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
for (;;) {
|
||||
iterations++;
|
||||
|
||||
if (phase == 0)
|
||||
optval<<=1;
|
||||
else {
|
||||
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;
|
||||
phase = 1;
|
||||
|
||||
hiconf = optval;
|
||||
hiconf = optval;
|
||||
|
||||
continue;
|
||||
} else {
|
||||
} else {
|
||||
loconf = optval;
|
||||
}
|
||||
|
||||
@@ -99,39 +92,26 @@ sx_maxsockbuf(int s, int dir)
|
||||
sx_report(SX_ERROR,"getsockopt failed: %s\n",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
} else if (voptval < optval) {
|
||||
if (phase == 0) {
|
||||
} else if (voptval < optval) {
|
||||
if (phase == 0) {
|
||||
phase = 1;
|
||||
optval >>= 1;
|
||||
continue;
|
||||
} else if (phase == 1) {
|
||||
} 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",
|
||||
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;
|
||||
} else
|
||||
return voptval;
|
||||
}
|
||||
|
||||
14
sx_prefix.c
14
sx_prefix.c
@@ -133,7 +133,7 @@ sx_prefix_parse(struct sx_prefix *p, int af, char *text)
|
||||
{
|
||||
char *c = NULL;
|
||||
int masklen, ret;
|
||||
char mtext[INET6_ADDRSTRLEN+5];
|
||||
char mtext[INET6_ADDRSTRLEN + 5];
|
||||
|
||||
strlcpy(mtext, text, sizeof(mtext));
|
||||
|
||||
@@ -142,7 +142,7 @@ sx_prefix_parse(struct sx_prefix *p, int af, char *text)
|
||||
if (c) {
|
||||
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",
|
||||
@@ -297,7 +297,7 @@ sx_prefix_range_parse(struct sx_radix_tree *tree, int af, unsigned int maxlen,
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -323,7 +323,7 @@ sx_prefix_range_parse(struct sx_radix_tree *tree, int af, unsigned int maxlen,
|
||||
max = maxlen;
|
||||
} else if (isdigit(d[1])) {
|
||||
char *dm = NULL;
|
||||
min = strtoul(d+1, &dm, 10);
|
||||
min = strtoul(d + 1, &dm, 10);
|
||||
if (dm && *dm == '-' && isdigit(dm[1])) {
|
||||
max = strtoul(dm + 1, NULL, 10);
|
||||
} else if (dm && *dm) {
|
||||
@@ -483,7 +483,7 @@ sx_prefix_snprintf_fmt(struct sx_prefix *p, FILE *f,
|
||||
}
|
||||
c += 2;
|
||||
} else if (*c == '\\') {
|
||||
switch(*(c+1)) {
|
||||
switch(*(c + 1)) {
|
||||
case 'n':
|
||||
fprintf(f, "\n");
|
||||
break;
|
||||
@@ -925,7 +925,7 @@ sx_radix_node_aggregate(struct sx_radix_node *node)
|
||||
if (!node->r->isAggregate && !node->l->isAggregate
|
||||
&& !node->r->isGlue && !node->l->isGlue
|
||||
&& node->r->prefix->masklen == node->l->prefix->masklen) {
|
||||
if (node->r->prefix->masklen == node->prefix->masklen+1) {
|
||||
if (node->r->prefix->masklen == node->prefix->masklen + 1) {
|
||||
node->isAggregate = 1;
|
||||
node->r->isGlue = 1;
|
||||
node->l->isGlue = 1;
|
||||
@@ -1019,7 +1019,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;
|
||||
|
||||
68
sx_prefix.h
68
sx_prefix.h
@@ -59,43 +59,43 @@ typedef struct sx_radix_tree {
|
||||
} sx_radix_tree_t;
|
||||
|
||||
/* most common operations with the tree is to: lookup/insert/unlink */
|
||||
struct sx_radix_node* sx_radix_tree_lookup(struct sx_radix_tree* tree,
|
||||
struct sx_prefix* prefix);
|
||||
struct sx_radix_node* sx_radix_tree_insert(struct sx_radix_tree* tree,
|
||||
struct sx_prefix* prefix);
|
||||
void sx_radix_tree_unlink(struct sx_radix_tree* t, struct sx_radix_node* n);
|
||||
struct sx_radix_node* sx_radix_tree_lookup_exact(struct sx_radix_tree* tree,
|
||||
struct sx_prefix* prefix);
|
||||
struct sx_radix_node *sx_radix_tree_lookup(struct sx_radix_tree *tree,
|
||||
struct sx_prefix *prefix);
|
||||
struct sx_radix_node *sx_radix_tree_insert(struct sx_radix_tree *tree,
|
||||
struct sx_prefix *prefix);
|
||||
void sx_radix_tree_unlink(struct sx_radix_tree *t, struct sx_radix_node *n);
|
||||
struct sx_radix_node *sx_radix_tree_lookup_exact(struct sx_radix_tree *tree,
|
||||
struct sx_prefix *prefix);
|
||||
|
||||
struct sx_prefix* sx_prefix_alloc(struct sx_prefix* p);
|
||||
void sx_prefix_destroy(struct sx_prefix* p);
|
||||
void sx_radix_node_destroy(struct sx_radix_node* p);
|
||||
void sx_prefix_adjust_masklen(struct sx_prefix* p);
|
||||
struct sx_prefix* sx_prefix_new(int af, char* text);
|
||||
int sx_prefix_parse(struct sx_prefix* p, int af, char* text);
|
||||
int sx_prefix_range_parse(struct sx_radix_tree* t, int af, unsigned int ml, char* text);
|
||||
int sx_prefix_fprint(FILE* f, struct sx_prefix* p);
|
||||
int sx_prefix_snprintf(struct sx_prefix* p, char* rbuffer, int srb);
|
||||
int sx_prefix_snprintf_sep(struct sx_prefix* p, char* rbuffer, int srb, char*);
|
||||
void sx_prefix_snprintf_fmt(struct sx_prefix* p, FILE* f,
|
||||
const char* name, const char* fmt,
|
||||
unsigned int aggregateLow, unsigned int aggregateHi);
|
||||
int sx_prefix_jsnprintf(struct sx_prefix* p, char* rbuffer, int srb);
|
||||
struct sx_radix_tree* sx_radix_tree_new(int af);
|
||||
struct sx_radix_node* sx_radix_node_new(struct sx_prefix* prefix);
|
||||
struct sx_prefix* sx_prefix_overlay(struct sx_prefix* p, int n);
|
||||
int sx_radix_tree_empty(struct sx_radix_tree* t);
|
||||
void sx_radix_node_fprintf(struct sx_radix_node* node, void* udata);
|
||||
int sx_radix_node_foreach(struct sx_radix_node* node,
|
||||
void (*func)(struct sx_radix_node*, void*), void* udata);
|
||||
int sx_radix_tree_foreach(struct sx_radix_tree* tree,
|
||||
void (*func)(struct sx_radix_node*, void*), void* udata);
|
||||
int sx_radix_tree_aggregate(struct sx_radix_tree* tree);
|
||||
int sx_radix_tree_refine(struct sx_radix_tree* tree, unsigned refine);
|
||||
int sx_radix_tree_refineLow(struct sx_radix_tree* tree, unsigned refineLow);
|
||||
struct sx_prefix *sx_prefix_alloc(struct sx_prefix *p);
|
||||
void sx_prefix_destroy(struct sx_prefix *p);
|
||||
void sx_radix_node_destroy(struct sx_radix_node *p);
|
||||
void sx_prefix_adjust_masklen(struct sx_prefix *p);
|
||||
struct sx_prefix *sx_prefix_new(int af, char *text);
|
||||
int sx_prefix_parse(struct sx_prefix *p, int af, char *text);
|
||||
int sx_prefix_range_parse(struct sx_radix_tree *t, int af, unsigned int ml, char *text);
|
||||
int sx_prefix_fprint(FILE *f, struct sx_prefix *p);
|
||||
int sx_prefix_snprintf(struct sx_prefix *p, char *rbuffer, int srb);
|
||||
int sx_prefix_snprintf_sep(struct sx_prefix *p, char *rbuffer, int srb, char *);
|
||||
void sx_prefix_snprintf_fmt(struct sx_prefix *p, FILE *f,
|
||||
const char *name, const char *fmt, unsigned int aggregateLow,
|
||||
unsigned int aggregateHi);
|
||||
int sx_prefix_jsnprintf(struct sx_prefix *p, char *rbuffer, int srb);
|
||||
struct sx_radix_tree *sx_radix_tree_new(int af);
|
||||
struct sx_radix_node *sx_radix_node_new(struct sx_prefix *prefix);
|
||||
struct sx_prefix *sx_prefix_overlay(struct sx_prefix *p, int n);
|
||||
int sx_radix_tree_empty(struct sx_radix_tree *t);
|
||||
void sx_radix_node_fprintf(struct sx_radix_node *node, void *udata);
|
||||
int sx_radix_node_foreach(struct sx_radix_node *node,
|
||||
void (*func)(struct sx_radix_node *, void *), void *udata);
|
||||
int sx_radix_tree_foreach(struct sx_radix_tree *tree,
|
||||
void (*func)(struct sx_radix_node *, void *), void *udata);
|
||||
int sx_radix_tree_aggregate(struct sx_radix_tree *tree);
|
||||
int sx_radix_tree_refine(struct sx_radix_tree *tree, unsigned refine);
|
||||
int sx_radix_tree_refineLow(struct sx_radix_tree *tree, unsigned refineLow);
|
||||
|
||||
#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
|
||||
|
||||
@@ -24,21 +24,22 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include "sx_slentry.h"
|
||||
#include "extern.h"
|
||||
|
||||
struct sx_slentry *
|
||||
struct slentry *
|
||||
sx_slentry_new(char *t)
|
||||
{
|
||||
struct sx_slentry *e = malloc(sizeof(struct sx_slentry));
|
||||
struct slentry *e = malloc(sizeof(struct slentry));
|
||||
|
||||
if (!e)
|
||||
return NULL;
|
||||
|
||||
memset(e, 0, sizeof(struct sx_slentry));
|
||||
memset(e, 0, sizeof(struct slentry));
|
||||
|
||||
e->text = strdup(t);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user