pax_global_header00006660000000000000000000000064134002042100014474gustar00rootroot0000000000000052 comment=07246c929b939be9ac44c4b8b23ea635114e33ac bgpq3-0.1.35/000077500000000000000000000000001340020421000125765ustar00rootroot00000000000000bgpq3-0.1.35/.gitignore000066400000000000000000000000721340020421000145650ustar00rootroot00000000000000CVS/ Makefile config.h *.o bgpq3 config.log config.status bgpq3-0.1.35/CHANGES000066400000000000000000000275121340020421000136000ustar00rootroot000000000000000.1.35 (2018-11-30): - initial support for Juniper route-filter-lists (JunOS 16.2+). - too large (>124bytes) sources list was not handled correctly. Reported by Pier Carlo Chiodi. - initial support for Huawei format (prefix-lists and as-path filters) New flag -U. Requested by Alexander Wagberg. - fix ipv6 prefix-ranges. Reported by Jay Ford. - OpenBGPd change: -E now generates prefix-set instead of prefix-list. Based on submission by Denis Fondras - new option -w, allowing to 'validate' AS numbers included in as-path access-lists: only those AS having registered route-objects are allowed. By default checks route[4] presence, to check route6 objects shall be used together with -6. - cleanup OpenBGPd prefix-sets. Submitted by Claudio Jeker. - new flag -t: generate as-sets for OpenBGPD (OpenBSD 6.4+), BIRD and JSON formats. Based on submission by Claudio Jeker. - new flag -n: support for Nokia SR OS MD-CLI. Based on examples provided by Greg Hankins. - irrd queries for asn32 changed from asdot to asplain notation. Thanks to Troy2914 for heads up. 0.1.35-rc2 (2017-06-14) - OpenBSD need . Reported by Denis Fondras. - OpenBGPD output shall not emit 'deny any from any' in case of empty prefix-list. New flag -a introduced to allow peer-as indication. When this flag is not specified, empty prefix-list is generated (will not be accepted by OpenBGPD). Reported by Denis Fondras 0.1.35-rc (2017-30-05) - Nokia SR OS (formerly Alcatel-Lucent) support. Based on submission by Michail Litvak. - sync man-page with readme.md - socket() EAFNOSUPPORT error handling 0.1.33 (2016-10-14) - OpenBGPD support (-B). Submitted by Peter Hessler. 0.1.32 (2016-08-28) - rollback 0.1.32-rc2 (2015-07-01) change: by default all IRRD sources are allowed by default. Documentation updated to mark radb,ripe,apnic as 'recommended', not as 'preset default'. untagged yet (2016-05-10) - fix: was not able to build on Solaris. Thanks to Mansoor Ali Khan. - feature: IOS XR mode now supports as-paths (ios-regexs). Thanks to Tassos Chatzithomaoglou for examples and proofreading. (additions from 2015-09-23) - bugfix: stoplist shall be able to catch AS numbers as promised. - bugfix: bgpq3 shall not hang at unknown escapes in -M.. - gotcha: "ANY" object in recursive mode ignored: shut complaints on "ERROR:unexpected object 'ANY' in expanded_macro_limit (in response to !iAS-SET-SCOPESKY)" (object contains mbrs-by-ref: ANY). (additions from 2015-08-30) - bugfix: OpenBSD sys/queue.h does not have STAILQ_ interface. Thanks to Pedro Caetano for reporting and testing. - feature: alternate whois port can be configured with -h host[:port] - feature: new format char %N (object name) in formatted output. Thanks to Denis Fondras. - feature: new format chars %m (prefix mask) and %i (inverse mask) in formatted output. 0.1.32-rc5 (2015-07-12) - feature: -L : limit recursion depth when expanding as-sets (default: not limited). Based on idea by Eugene Demidov. - feature: stoplist. Now you can add EXCEPT Object... at the end of bgpq3 command line and corresponding as-sets and asns will not be expanded (does not works for prefixes and prefix-sets yet). - internals: major pipelining rewrite and some code cleanup. 0.1.32-rc4 (2015-07-06) - change: BIRD can't handle empty lists (NAME = []), so they are not generated at all. 0.1.32-rc3 (2015-07-01) - feature: option -s can be used to generate sequence numbers in IOS prefix-lists - feature: option -F can be used to generate output in user-defined format. Only prefix-lists supported for now. 0.1.32-rc2 (2015-07-01) - bugfix: when no sources provided in command line and via IRRD_SOURCES env, no source limitation were sent to IRRd. Thanks to Mikhail A. Grishin. 0.1.32-rc (2015-06-28) - bugfix: F source(s) unavailable message from IRRD was ignored. Please note: this error is caught only when all the specified sources are invalid. For example, 'bgpq3 -s nonexistant' will fail, however, 'bgpq3 -s nonexistant,ripe' will not fail and will use only ripe source. Thanks to Mikhail A. Grishin for reporting. - RIPE-style queries (-T route6 -i origin asNNN) replaced with IRRd-style !6asNNN queries. 0.1.31 (2015-06-23) - pipelining mode now counts buffered requests and issues dequeue when new request can overflow allocated buffer. So, bgpq3 shall no more require TCP tuning (it is still recomended, though). - tcp tuning parameters decreased in README (sx_maxsockbuf will not allow buffer over 2Mb anyway). 0.1.30 (2015-06-16) - bugfix: private asns with number > 2^31 were printed as negative integers. Thanks to Henrik Thostrup Jensen. - do not use ASNs reserved for documentation purposes and private use: 64496-64511 For documentation and sample code; reserved by [RFC5398] 64512-65534 For private use; reserved by [RFC6996] 65535 Reserved by [RFC7300] 65536-65551 For documentation and sample code; reserved by [RFC5398] 4200000000-4294967294 For private use; reserved by [RFC6996] 4294967295 Reserved by [RFC7300] Please, use new -p flag to include these asn's. Suggested by Henrik Thostrup Jensen and Job Snijders. - allow as-path generation with BIRD output. Suggested by Jiri Mikulas. - merge README.md changes by Job Snijders. - bugfix: incorrect asdot representation (as101. without symbols after dot) is not allowed anymore. 0.1.29 (2015-05-04) - do not include routes registered for AS23456 (transition-as) by default. Use new option -2 to restore old behaviour. 0.1.28 (2015-03-10) - minor changes: .spec update, non-silent failure on wrong af, more room for masklen... 0.1.27 (2015-03-10) - bugfix: some ipv6 prefixes were not parsed correctly since 0.1.26. Thanks to Job Snijders. 0.1.26 (2015-02-19) - RPSL support, can be found in rs-esnetcustomers. Thanks to Kris O'Connell for reporting. 0.1.25 (2014-10-29) - JSON support extended to handle "as-paths" too. Well, actually, as there are no defined format for as-path in json, bgpq3 just creates simple object like following: snar@fri:~/compile/bgpq3>./bgpq3 -j3f 20597 as-eltel {"NN": [ 112,5495,6857,8377,20597,34102,35357,43951, 52007,56764,197759,197888,198610,201499 ]} Based on suggestion by Henrik Thostrup Jensen. - -W len option documented. 0.1.24 (2014-07-31) - empty prefix-lists (Cisco), extended access-lists (Cisco), as-path filters (Cisco and Juniper) and route-filters (Juniper) handling: explicit 'deny any' entry now generated instead of implicit 'permit-any'. Based on suggestion by Tore Anderson. 0.1.23 (2014-07-30) - bugfix: use of -M option caused major slowdown as it turned off request pipelining... Thanks to Tore Anderson. 0.1.22 (2014-07-27) - bugfix: allow network object with stray spaces after prefix length. Found by Tom Eichhorn in 2620:74:14::/48 (VeriSign Route6, RADB). - bugfix: networks with leading zeros (02.51.252.0/22, as4787) are not parsed correctly in inet_ntop.. Found by Tom Eichhorn. 0.1.21 (2014-06-05) - new flag -b: generate prefix-filters for BIRD (http://bird.network.cz), contributed by Job Snijders. 0.1.20-todo2 (2014-05-01) - new flag -r , allowing bgpq to generate limited set of more-specific routes - only routes with prefix-length >= are accepted. Thanks to Pavel Gulchouck for suggesion. 0.1.20-todo (2013-10-07) - socket close code fixed. Thanks to Martin J. Levy. - new flag -4, "force ipv4". Actually does a little more than allowing for pedantic checks. Thanks to Martin J. Levy. 0.1.19 (2013-05-09) - CLANG compilation issues fixed. - bgpq3.spec added. Thanks to Arnoud Vermeer. 0.1.18 (2013-01-08) - JSON output format. Thanks to Job Snijders (Atrato Networks). 0.1.17 (2012-10-25) - route-sets handling in command-line added. Thanks to Alexandr Turovsky for pointing out. - bug in aggregation documentation fixed. Thanks to Nikolay Shopik. 0.1.16 (2012-01-19) - new option -m : maximum length of accepted prefixes. Suggested by Eugene Demidov, used to discard 'too long prefixes' (like /30-/32) even if they are registered in IRR. By default limit is not set and all prefixes accepted. - documentation redesigned into text/markdown and text/html (manpage supported still). 0.1.15 (2011-07-15) - prefix-set's for Cisco IOS XR now supported too. 0.1.14 (2011-06-18) - Fixed bug in sx_maxsockbuf in rare cases of OS maxsockbuf >2M. Thanks to Andreas Lundin. 0.1.13 (2011-06-14) - never publically released. 0.1.12 (2010-10-08) - Fixed bug preventing AS262144 (that's AS4.0 in asdot) to expand. Thanks to Sergey Matveychuk 0.1.11 (2010-04-19) - Fixed another bug in aggregation (-A) mode, thanks to Dmitry Tejblum. 0.1.10 (2009-06-13) - Fixed bug in aggregation (-A) mode, thanks to Sergey Gonchar. 0.1.9 (2009-03-27) - RIPE changed ASN32 notation to asplain. And RADB does not support asplain indexing (yet?).... Fixed. Thanks to Pavel Gluchouk. 0.1.8 (2008-12-25) - new flag -D for Cisco asdot notation. Cisco behaviour is a bit strange for me, but, well, that's their decision: When the asdot format is enabled as the default, any regular expressions to match 4-byte autonomous system numbers must be written using the asdot format, or else the regular expression match will fail. (c) http://www.cisco.com/en/US/docs/ios/12_0s/release/ntes/120SNEWF.html #wp3521658 (note the URL wrap). 0.1.7 (2008-12-19): - man page. Finally :) - option -h now means not help, but now it can be used to point to alternate IRRD host, like in old bgpq. 0.1.6 (2008-08-08): - maxsockbuf call added, that can help with pipelining of really large as-sets. - new key -M for juniper route-filters, f.e.: bgpq3 -JEM "protocol bgp;\n community no-export" -l PolicyName/TermName will generate term with additional match conditions, like: policy-options { policy-statement PolicyName { term TermName { replace: from { protocol bgp; community no-export; route-filter 10.0.0.0/24 exact; } } } } 0.1.5 (2008-06-02): - route-set's expansion added. Fully functional for IPv4 prefixes, but not for IPv6 - only those prefixes explicitely marked as 'member-of: RS..' will be expanded. This is due to limitation in IRRd. - extended access-lists (Cisco) and route-filters (Juniper) generation is supported now with new -E key. For Cisco ipv6 access-lists is not yet supported. 0.1.4 (2008-05-30): - bugfix for juniper as-path group generation. Thanks to Alexander Shikoff. 0.1.3 (2008-05-20): - aggregation (-A) now supported for Cisco prefix-lists. - pipelining now can be enabled for RIPE-style queries too (ipv6). - more-specific routes (-R len) feature ported from bgpq - pipelining now set by default. -T flag now disables pipelining. - strlcpy.c imported into sources. Not found on Linux :) 0.1.2 (2008-05-19): - final support for asn32, now with correct syntax for Juniper. - experimental 'pipelining' mode (flag -T), much faster when working with big as-set's. - RIPE-style query (-i origin) now requests only route6 objects. 0.1.1 (2008-05-16): - initial support for asn32 added (flag -3). By default it's off, and when bgpq sees 32-bit asn in resolver queue, it either replaces it with AS23456 (in as-path generation mode) or queries radb for prefixes with that origin. Note: for now only JunOS 9.1 can handle asn32, not Cisco IOS.. bgpq3-0.1.35/COPYRIGHT000066400000000000000000000025531340020421000140760ustar00rootroot00000000000000/*- * Copyright (c) 2007-2018 Alexandre Snarskii * 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. * */ bgpq3-0.1.35/Makefile.in000066400000000000000000000017451340020421000146520ustar00rootroot00000000000000CC=@CC@ CFLAGS=@CFLAGS@ @DEFS@ -g -Wall -I. -O0 LDADD=@LDFLAGS@ @LIBS@ INSTALL=@INSTALL@ prefix = @prefix@ bindir = @bindir@ exec_prefix = @exec_prefix@ datarootdir = @datarootdir@ datadir = @datadir@ infodir = @infodir@ mandir = @mandir@ OBJECTS=bgpq3.o sx_report.o bgpq_expander.o sx_slentry.o bgpq3_printer.o \ sx_prefix.o strlcpy.o sx_maxsockbuf.o SRCS=bgpq3.c sx_report.c bgpq_expander.c sx_slentry.c bgpq3_printer.c \ sx_prefix.c strlcpy.c sx_maxsockbuf.c all: bgpq3 bgpq3: ${OBJECTS} ${CC} ${CFLAGS} -o bgpq3 ${OBJECTS} ${LDADD} .c.o: ${CC} ${CFLAGS} -c $< clean: rm -rf Makefile autom4te.cache bgpq3 config.h config.log config.status rm -rf *.o *.core core.* core install: bgpq3 ${INSTALL} -c -s -m 755 bgpq3 @bindir@ if test ! -d @prefix@/man/man8 ; then mkdir -p @prefix@/man/man8 ; fi ${INSTALL} -m 644 bgpq3.8 @prefix@/man/man8 depend: makedepend -- $(CFLAGS) -- $(SRCS) bgpq3.html: readme.header README.md cat readme.header README.md | @MARKDOWN@ > bgpq3.html bgpq3-0.1.35/README.md000066400000000000000000000242231340020421000140600ustar00rootroot00000000000000NAME ---- `bgpq3` - bgp filtering automation for Cisco and Juniper routers SYNOPSIS -------- ``` bgpq3 [-h host[:port]] [-S sources] [-EPz] [-f asn | -F fmt | -G asn | -t] [-2346ABbDdJjNnpsUX] [-a asn] [-r len] [-R len] [-m max] [-W len] OBJECTS [...] EXCEPT OBJECTS ``` DESCRIPTION ----------- The bgpq3 utility used to generate Cisco and Juniper prefix-lists, extended access-lists, policy-statement terms and as-path lists based on RADB data. The options are as follows: #### -2 Allow routes registered for as23456 (transition-as) (default: false) #### -3 Assume that your device is asn32-capable. #### -4 Generate IPv4 prefix/access-lists (default). #### -6 Generate IPv6 prefix/access-lists (IPv4 by default). #### -A Try to aggregate generated filters as much as possible (not all output formats supported). #### -a asn Specify ASN that shall be denied in case of empty prefix-list (OpenBGPD). #### -B Generate output in OpenBGPD format (default: Cisco). #### -b Generate output in BIRD format (default: Cisco). #### -d Enable some debugging output. #### -D Use asdot notation for Cisco as-path access-lists. #### -E Generate extended access-list (Cisco) or policy-statement term using route-filters (Juniper), [ip|ipv6]-prefix-list (Nokia) or prefix-filter (OpenBGPD) #### -f `AS number` Generate input as-path access-list for adjacent as `AS number`. #### -F `fmt` Generate output in user-defined format. #### -G `number` Generate output as-path access-list. #### -h `host[:port]` Host running IRRD database (default: `whois.radb.net`). #### -J Generate config for Juniper (default: Cisco). #### -j Generate output in JSON format (default: Cisco). #### -m `length` Maximum length of accepted prefixes (default: `32` for IPv4, `128` for IPv6). #### -M `match` Extra match conditions for Juniper route-filters. See the examples section. #### -n Generate config for Nokia SR OS (former Alcatel-Lucent) MD-CLI (default: Cisco) #### -N Generate config for Nokia SR OS (former Alcatel-Lucent) classic CLI (default: Cisco) #### -l `name` `Name` of generated configuration stanza. #### -L `limit` Limit recursion depth when expanding. This slows `bgpq3` a bit, but sometimes is a useful feature to prevent generated filters from growing too big. #### -p Enable use of private ASNs and ASNs used for documentation purpose only (default: disabled). #### -P Generate prefix-list (default behaviour, flag added for backward compatibility only). #### -r `length` Allow more-specific routes with masklen starting with specified length. #### -R `length` Allow more-specific routes up to specified masklen too. (Please, note: objects with prefix-length greater than specified length will be always allowed.) #### -s Generate sequence numbers in IOS-style prefix-lists. #### -S `sources` Use specified sources only (recommended: RADB,RIPE,APNIC). #### -t Generate as-sets for OpenBGPD (OpenBSD 6.4+), BIRD and JSON formats. #### -T Disable pipelining. (not recommended) #### -U Generate output in Huawei format (default: Cisco). #### -W `length` Generate as-path strings of a given length maximum (0 for infinity). #### -X Generate config for Cisco IOS XR devices (plain IOS by default). #### -z Generate Juniper route-filter-list (JunOS 16.2+). #### `OBJECTS` `OBJECTS` means networks (in prefix format), autonomous systems, as-sets and route-sets. If multiple objects are specified they will be merged. #### `EXCEPT OBJECTS` You can exclude autonomous sets, as-sets and route-sets found during expansion from future expansion. EXAMPLES -------- Generating named Juniper prefix-filter for `AS20597`: user@host:~>bgpq3 -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:~>bgpq3 -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 ip prefix-list eltel permit 89.112.0.0/18 ge 19 le 19. Well, for Juniper we can generate even more interesting policy-statement, using `-M `, `-r `, `-R ` and hierarchical names: user@host:~>bgpq3 -AJEl eltel/specifics -r 29 -R 32 -M "community blackhole" AS20597 policy-options { policy-statement eltel { term specifics { replace: from { community blackhole; route-filter 81.9.0.0/20 prefix-length-range /29-/32; route-filter 81.9.32.0/20 prefix-length-range /29-/32; route-filter 81.9.96.0/20 prefix-length-range /29-/32; route-filter 81.222.128.0/20 prefix-length-range /29-/32; route-filter 81.222.192.0/18 prefix-length-range /29-/32; route-filter 85.249.8.0/21 prefix-length-range /29-/32; route-filter 85.249.224.0/19 prefix-length-range /29-/32; route-filter 89.112.0.0/17 prefix-length-range /29-/32; route-filter 217.170.64.0/19 prefix-length-range /29-/32; } } } } 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, `bgpq3` supports IPv6 (-6): user@host:~>bgpq3 -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 ASN32 user@host:~>bgpq3 -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|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 `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:~>bgpq3 -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 ------------------- 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:~>bgpq3 -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. 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:~>bgpq3 -6F "%n/%l; " as-eltel 2001:1b00::/32; 2620:4f:8000::/48; 2a04:bac0::/29; 2a05:3a80::/48; DIAGNOSTICS ----------- When everything is OK, `bgpq3` 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. NOTES ON ULTRA-LARGE PREFIX-LISTS --------------------------------- To improve `bgpq3` 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 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" 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). SEE ALSO -------- 1. [Routing Arbiter](http://www.radb.net/) 2. [draft-michaelson-4byte-as-representation-05](https://tools.ietf.org/html/draft-michaelson-4byte-as-representation-05) for information on 'asdot' and 'asplain' notations. 3. [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. 4. [JunOS prefix-lists limitation](http://www.juniper.net/techpubs/en_US/junos11.4/topics/reference/configuration-statement/prefix-list-edit-policy-options.html) AUTHOR ------ Alexandre Snarskii [snar@snar.spb.ru](mailto:snar@snar.spb.ru) Program Homepage ---------------- [http://snar.spb.ru/prog/bgpq3/](http://snar.spb.ru/prog/bgpq3/) bgpq3-0.1.35/bgpq3.8000066400000000000000000000230161340020421000137050ustar00rootroot00000000000000.\" Copyright (c) 2007-2018 Alexandre Snarskii .\" 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. .\" .Dd Oct 27, 2008 .Dt BGPQ3 8 .Os .Sh NAME .Nm bgpq3 .Nd "bgp filtering automation for cisco and juniper routers" .Sh SYNOPSIS .Nm .Op Fl h Ar host[:port] .Op Fl S Ar sources .Op Fl EPz .Oo .Fl f Ar asn | .Fl F Ar fmt | .Fl G Ar asn .Fl t .Oc .Op Fl 2346ABbDdJjNnsXU .Op Fl a Ar asn .Op Fl r Ar len .Op Fl R Ar len .Op Fl m Ar max .Op Fl W Ar len .Ar OBJECTS .Op "..." .Op EXCEPT OBJECTS .Sh DESCRIPTION The .Nm utility used to generate Cisco and Juniper prefix-lists, extended access-lists, policy-statement terms and as-path lists based on RADB data. .Pp The options are as follows: .Bl -tag -width Ds .It Fl 2 accept routes registered for as23456 (transition-as) (default: false) .It Fl 3 assume that your device is asn32-safe. .It Fl 4 generate IPv4 prefix/access-lists (default). .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 formats supported). .It Fl a Ar asn specify what asn shall be denied in case of empty prefix-list (OpenBGPD) .It Fl B generate output in OpenBGPD format (default: Cisco) .It Fl b generate output in BIRD format (default: Cisco). .It Fl d enable some debugging output. .It Fl D use asdot notation for Cisco as-path access-lists. .It Fl E generate extended access-list (Cisco), policy-statement term using route-filters (Juniper), [ip|ipv6]-prefix-list (Nokia) or prefix-sets (OpenBGPd). .It Fl f Ar number generate input as-path access-list. .It Fl F Ar fmt generate output in user-defined format. .It Fl G Ar number generate output as-path access-list. .It Fl h Ar host[:port] host running IRRD database (default: whois.radb.net). .It Fl J generate config for Juniper (default: Cisco). .It Fl j generate output in JSON format (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 128 for IPv6). .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 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). .It Fl r Ar len allow more specific routes starting with specified masklen too. .It Fl R Ar len 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). .It Fl t generate as-sets for OpenBGPD (OpenBSD 6.4+), 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). .It Fl U generate config for Huawei devices (Cisco IOS by default) .It Fl X generate config for Cisco IOS XR devices (plain IOS by default). .It Fl z generate route-filter-lists (JunOS 16.2+). .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: .nf .RS ~>bgpq3 -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; } } .RE .fi .Pp For Cisco we can use aggregation (-A) flag to make this prefix-filter more compact: .nf .RS ~>bgpq3 -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 .RE .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 Well, for Juniper we can generate even more interesting policy-options, using -M , -R and hierarchical names: .nf .RS ~>bgpq3 -AJEl eltel/specifics -r 29 -R 32 -M "community blackhole" AS20597 policy-options { policy-statement eltel { term specifics { replace: from { community blackhole; route-filter 81.9.0.0/20 prefix-length-range /29-/32; route-filter 81.9.32.0/20 prefix-length-range /29-/32; route-filter 81.9.96.0/20 prefix-length-range /29-/32; route-filter 81.222.128.0/20 prefix-length-range /29-/32; route-filter 81.222.192.0/18 prefix-length-range /29-/32; route-filter 85.249.8.0/21 prefix-length-range /29-/32; route-filter 85.249.224.0/19 prefix-length-range /29-/32; route-filter 89.112.0.0/17 prefix-length-range /29-/32; route-filter 217.170.64.0/19 prefix-length-range /29-/32; } } } } .RE .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 blackhole (defined elsewhere in configuration). .Pp Of course, this version supports IPv6 (-6): .nf .RS ~>bgpq3 -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 .fi and support for ASN 32 is also here .nf .RS ~>bgpq3 -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|23456|23600|24151|25152|31529|34127|34906)$"; as-path a3 "^112(.)*(35052|41720|43628|44450|196611)$"; } } .RE .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 ~>bgpq3 -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. .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:~>bgpq3 -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 .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): .nf .RS user@host:~>bgpq3 -6F "%n/%l; " as-eltel 2001:1b00::/32; 2620:4f:8000::/48; 2a04:bac0::/29; 2a05:3a80::/48; .RE .fi .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 SEE ALSO .Sy http://www.radb.net/ Routing Arbiter project .Sy http://tools.ietf.org/html/draft-michaelson-4byte-as-representation-05 for information on 'asdot' and 'asplain' notations. .Sy http://www.cisco.com/en/US/docs/ios/12_0s/release/ntes/120SNEWF.html#wp3521658 for information on Cisco implementation of ASN32. .Sh AUTHOR .An Alexandre Snarskii Aq snar@snar.spb.ru bgpq3-0.1.35/bgpq3.c000066400000000000000000000453471340020421000137730ustar00rootroot00000000000000#if HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include #include "bgpq3.h" #include "sx_report.h" extern int debug_expander; extern int debug_aggregation; extern int pipelining; extern int expand_as23456; extern int expand_special_asn; int usage(int ecode) { printf("\nUsage: bgpq3 [-h host[:port]] [-S sources] [-P|E|G |f |t]" " [-2346ABbDdJjNnwXz] [-R len] ...\n"); printf(" -2 : allow routes belonging to as23456 (transition-as) " "(default: false)\n"); printf(" -3 : assume that your device is asn32-safe\n"); printf(" -4 : generate IPv4 prefix-lists (default)\n"); printf(" -6 : generate IPv6 prefix-lists (IPv4 by default)\n"); printf(" -A : try to aggregate prefix-lists/route-filters\n"); printf(" -B : generate OpenBGPD output (Cisco IOS by default)\n"); printf(" -b : generate BIRD output (Cisco IOS by default)\n"); printf(" -D : use asdot notation in as-path (Cisco only)\n"); printf(" -d : generate some debugging output\n"); printf(" -E : generate extended access-list(Cisco), " "route-filter(Juniper)\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 (whois.radb.net by " "default)\n" " (use host:port to specify alternate port)\n"); printf(" -J : generate config for JunOS (Cisco IOS by default)\n"); printf(" -j : generate JSON output (Cisco IOS by default)\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 " "(Cisco IOS by default)\n"); printf(" -n : generate config for Nokia SR OS MD-CLI (Cisco IOS " "by default)\n"); printf(" -P : generate prefix-list (default, just for backward" " compatibility)\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 (Cisco IOS by default)\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 config for IOS XR (Cisco IOS by default)\n"); printf("\n" PACKAGE_NAME " version: " PACKAGE_VERSION "\n"); printf("Copyright(c) Alexandre Snarskii 2007-2018\n\n"); exit(ecode); }; void exclusive() { fprintf(stderr,"-E, -f , -G , -P 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; bgpq_expander_init(&expander,af); if (getenv("IRRD_SOURCES")) expander.sources=getenv("IRRD_SOURCES"); while((c=getopt(argc,argv,"2346a:AbBdDEF:S:jJf:l:L:m:M:NnW:Ppr:R:G:tTh:UwXsz")) !=EOF) { switch(c) { case '2': expand_as23456=1; break; case '3': expander.asn32=1; 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 '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; expander.asn32=1; break; case 'D': expander.asdot=1; 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 'p': expand_special_asn=1; break; case 'P': if(expander.generation) exclusive(); expander.generation=T_PREFIXLIST; 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_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.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_FORMAT && (refine || refineLow)) { sx_report(SX_FATAL, "Sorry, formatted output (-F ) 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(expander.asdot && expander.vendor!=V_CISCO) { sx_report(SX_FATAL,"asdot notation supported only for Cisco, " "other formats use asplain only\n"); }; if(!expander.asn32 && expander.asnumber>65535) { expander.asnumber=23456; }; 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 " "(-P, default)\n"); exit(1); }; if(aggregate && expander.vendor==V_FORMAT) { sx_report(SX_FATAL, "Sorry, aggregation (-A) is not compatible with " "formatted output (-F )\n"); exit(1); }; if(aggregate && expander.vendor==V_NOKIA) { sx_report(SX_FATAL, "Sorry, aggregation (-A) is not supported on " "Nokia classic CLI (-N)\n"); exit(1); }; if(aggregate && expander.vendor==V_NOKIA_MD && expander.generation!=T_PREFIXLIST) { sx_report(SX_FATAL, "Sorry, aggregation (-A) is not supported with " "match-lists (-E) on Nokia MD-CLI. You can try prefix-lists (-P) " "instead\n"); exit(1); }; if(aggregate && expander.generation 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.vendor==V_NOKIA) { if(refine) { sx_report(SX_FATAL, "Sorry, more-specific filters (-R %u) " "not supported on Nokia classic CLI (-N)\n", refine); } else { sx_report(SX_FATAL, "Sorry, more-specific filters (-r %u) " "not supported on Nokia classic CLI (-N)\n", refineLow); }; }; if(expander.generation128) || (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: bgpq3_print_aspath(stdout,&expander); break; case T_OASPATH: bgpq3_print_oaspath(stdout,&expander); break; case T_ASSET: bgpq3_print_asset(stdout,&expander); break; case T_PREFIXLIST: bgpq3_print_prefixlist(stdout,&expander); break; case T_EACL: bgpq3_print_eacl(stdout,&expander); break; case T_ROUTE_FILTER_LIST: bgpq3_print_route_filter_list(stdout, &expander); break; }; return 0; }; bgpq3-0.1.35/bgpq3.h000066400000000000000000000043101340020421000137610ustar00rootroot00000000000000#ifndef BGPQ3_H_ #define BGPQ3_H_ #if HAVE_SYS_QUEUE_H && HAVE_STAILQ_IN_SYS_QUEUE #include #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_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, asdot; char* name; bgpq_vendor_t vendor; bgpq_gen_t generation; int identify; int sequence; int maxdepth; int validate_asns; unsigned char asn32; 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 bgpq3_print_prefixlist(FILE* f, struct bgpq_expander* b); int bgpq3_print_eacl(FILE* f, struct bgpq_expander* b); int bgpq3_print_aspath(FILE* f, struct bgpq_expander* b); int bgpq3_print_asset(FILE* f, struct bgpq_expander* b); int bgpq3_print_oaspath(FILE* f, struct bgpq_expander* b); int bgpq3_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 bgpq3-0.1.35/bgpq3.html000066400000000000000000000227601340020421000145070ustar00rootroot00000000000000


NAME

bgpq3 - bgp filtering automation for Cisco and Juniper routers

SYNOPSIS

bgpq3 [-h host] [-S sources] [-EP] [-f asn | -G asn] [-2346AbDdJjpX] [-r len] [-R len] [-m max] [-W len] OBJECTS [...]

DESCRIPTION

The bgpq3 utility used to generate Cisco and Juniper prefix-lists, extended access-lists, policy-statement terms and as-path lists based on RADB data.

The options are as follows:

-3

Assume that your device is asn32-capable.

-4

Generate IPv4 prefix/access-lists (default).

-6

Generate IPv6 prefix/access-lists (IPv4 by default).

-A

Try to aggregate generated filters as much as possible (not all output formats supported).

-b

Generate output in BIRD format (default: Cisco).

-d

Enable some debugging output.

-D

Use asdot notation for Cisco as-path access-lists.

-E

Generate extended access-list (Cisco) or policy-statement term using route-filters (Juniper).

-f AS number

Generate input as-path access-list for adjacent as AS number.

-G number

Generate output as-path access-list.

-h host

Host running IRRD database (default: whois.radb.net).

-J

Generate config for Juniper (default: Cisco).

-j

Generate output in JSON format (default: Cisco).

-m length

Maximum length of accepted prefixes (default: 32 for IPv4, 128 for IPv6).

-M match

Extra match conditions for Juniper route-filters. See the examples section.

-l name

Name of generated configuration stanza.

-p

Enable use of private ASNs and ASNs used for documentation purpose only (default: disabled).

-P

Generate prefix-list (default behaviour, flag added for backward compatibility only).

-r length

Allow more-specific routes with masklen starting with specified length.

-R length

Allow more-specific routes up to specified masklen too. (Please, note: objects with prefix-length greater than specified length will be always allowed.)

-S sources

Use specified sources only (default: RADB,RIPE,APNIC).

-T

Disable pipelining. (not recommended)

-W length

Generate as-path strings of a given length maximum (0 for infinity).

-X

Generate config for Cisco IOS XR devices (plain IOS by default).

OBJECTS

OBJECTS means networks (in prefix format), autonomous systems, as-sets and route-sets. If multiple objects are specified they will be merged.

EXAMPLES

Generating named Juniper prefix-filter for AS20597:

 user@host:~>bgpq3 -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:~>bgpq3 -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

ip prefix-list eltel permit 89.112.0.0/18 ge 19 le 19.

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:~>bgpq3 -AJEl eltel/specifics -r 29 -R 32 -M "community blackhole" AS20597
policy-options {
 policy-statement eltel {
  term specifics {
replace:
   from {
    community blackhole;
    route-filter 81.9.0.0/20 prefix-length-range /29-/32;
    route-filter 81.9.32.0/20 prefix-length-range /29-/32;
    route-filter 81.9.96.0/20 prefix-length-range /29-/32;
    route-filter 81.222.128.0/20 prefix-length-range /29-/32;
    route-filter 81.222.192.0/18 prefix-length-range /29-/32;
    route-filter 85.249.8.0/21 prefix-length-range /29-/32;
    route-filter 85.249.224.0/19 prefix-length-range /29-/32;
    route-filter 89.112.0.0/17 prefix-length-range /29-/32;
    route-filter 217.170.64.0/19 prefix-length-range /29-/32;
   }
  }
 }
}

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, bgpq3 supports IPv6 (-6):

 user@host:~>bgpq3 -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 ASN32

 user@host:~>bgpq3 -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|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 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:~>bgpq3 -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.

DIAGNOSTICS

When everything is OK, bgpq3 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.

NOTES ON ULTRA-LARGE PREFIX-LISTS

To improve bgpq3 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

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"

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.

SEE ALSO

  1. Routing Arbiter
  2. draft-michaelson-4byte-as-representation-05.txt for information on 'asdot' and 'asplain' notations.
  3. Cisco documentation for information on Cisco implementation of ASN32.
  4. JunOS prefix-lists limitation

AUTHOR

Alexandre Snarskii snar@snar.spb.ru

Program Homepage

http://snar.spb.ru/prog/bgpq3/

bgpq3-0.1.35/bgpq3.spec000066400000000000000000000033431340020421000144710ustar00rootroot00000000000000Name: bgpq3 Version: 0.1.35 Release: 0%{?dist} Group: System/Utilities Summary: Automate BGP filter generation based on routing database information URL: http://snar.spb.ru/prog/bgpq3/ License: BSD Source0: https://github.com/snar/bgpq3/archive/v0.1.35.tar.gz 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 BGPQ3 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/bgpq3 /usr/man/man8/bgpq3.8.gz %doc COPYRIGHT CHANGES %clean rm -rf $RPM_BUILD_ROOT %changelog * Tue Nov 30 2018 Alexandre Snarskii 0.1.35 - Version updated * Fri Oct 14 2016 Alexandre Snarskii 0.1.33 - Version updated * Tue Jun 23 Alexandre Snarskii 0.1.31 - Version updated * Tue Mar 10 Alexandre Snarskii 0.1.28 - Version updated * Wed Oct 29 Alexandre Snarskii 0.1.25 - Version updated * Thu Jun 5 2014 Alexandre Snarskii 0.1.21-0.snar - Version updated * Thu May 9 2013 Alexandre Snarskii 0.1.19-0.snar - Version updated * Sun Feb 24 2013 Alexandre Snarskii 0.1.18-3.snar - License corrected * Wed Feb 20 2013 Arnoud Vermeer 0.1.18-2.tumblr - Adding missing group info (arnoud@tumblr.com) * Wed Feb 20 2013 Arnoud Vermeer 0.1.18-1.tumblr - new package built with tito bgpq3-0.1.35/bgpq3_printer.c000066400000000000000000001063271340020421000155320ustar00rootroot00000000000000#if HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include "bgpq3.h" #include "sx_report.h" extern int debug_expander; int bgpq3_print_json_aspath(FILE* f, struct bgpq_expander* b); int bgpq3_print_bird_aspath(FILE* f, struct bgpq_expander* b); int bgpq3_print_openbgpd_aspath(FILE* f, struct bgpq_expander* b); int bgpq3_print_openbgpd_asset(FILE* f, struct bgpq_expander* b); int bgpq3_print_cisco_aspath(FILE* f, struct bgpq_expander* b) { int nc=0, i, j, k, empty=1; fprintf(f,"no ip as-path access-list %s\n", b->name?b->name:"NN"); if(b->asn32s[b->asnumber/65536] && b->asn32s[b->asnumber/65536][(b->asnumber%65536)/8]& (0x80>>(b->asnumber%8))) { if(b->asdot && b->asnumber>65535) { fprintf(f,"ip as-path access-list %s permit ^%u.%u(_%u.%u)*$\n", b->name?b->name:"NN",b->asnumber/65536,b->asnumber%65536, b->asnumber/65536,b->asnumber%65536); empty=0; } else { fprintf(f,"ip as-path access-list %s permit ^%u(_%u)*$\n", b->name?b->name:"NN",b->asnumber,b->asnumber); empty=0; }; }; for(k=0;k<65536;k++) { if(!b->asn32s[k]) continue; for(i=0;i<8192;i++) { for(j=0;j<8;j++) { if(b->asn32s[k][i]&(0x80>>j)) { if(k*65536+i*8+j==b->asnumber) continue; if(!nc) { if(b->asdot && k>0) { fprintf(f,"ip as-path access-list %s permit" " ^%u(_[0-9]+)*_(%u.%u", b->name?b->name:"NN", b->asnumber,k,i*8+j); empty=0; } else { fprintf(f,"ip as-path access-list %s permit" " ^%u(_[0-9]+)*_(%u", b->name?b->name:"NN", b->asnumber,k*65536+i*8+j); empty=0; }; } else { if(b->asdot && k>0) { fprintf(f,"|%u.%u",k,i*8+j); empty=0; } else { fprintf(f,"|%u",k*65536+i*8+j); empty=0; }; } nc++; if(nc==b->aswidth) { fprintf(f,")$\n"); nc=0; }; }; }; }; }; if(nc) fprintf(f,")$\n"); if(empty) fprintf(f,"ip as-path access-list %s deny .*\n", b->name?b->name:"NN"); return 0; }; int bgpq3_print_cisco_xr_aspath(FILE* f, struct bgpq_expander* b) { int nc=0, i, j, k, comma=0; fprintf(f, "as-path-set %s", b->name?b->name:"NN"); if(b->asn32s[b->asnumber/65536] && b->asn32s[b->asnumber/65536][(b->asnumber%65536)/8]& (0x80>>(b->asnumber%8))) { fprintf(f,"\n ios-regex '^%u(_%u)*$'", b->asnumber,b->asnumber); comma=1; }; for(k=0;k<65536;k++) { if(!b->asn32s[k]) continue; for(i=0;i<8192;i++) { for(j=0;j<8;j++) { if(b->asn32s[k][i]&(0x80>>j)) { if(k*65536+i*8+j==b->asnumber) continue; if(!nc) { fprintf(f,"%s\n ios-regex '^%u(_[0-9]+)*_(%u", comma?",":"", b->asnumber,k*65536+i*8+j); comma=1; } else { fprintf(f,"|%u",k*65536+i*8+j); } nc++; if(nc==b->aswidth) { fprintf(f,")$'"); nc=0; }; }; }; }; }; if(nc) fprintf(f,")$'"); fprintf(f,"\nend-set\n"); return 0; }; int bgpq3_print_cisco_oaspath(FILE* f, struct bgpq_expander* b) { int nc=0, i, j, k, empty=1; fprintf(f,"no ip as-path access-list %s\n", b->name?b->name:"NN"); if(b->asn32s[b->asnumber/65536] && b->asn32s[b->asnumber/65536][(b->asnumber%65536)/8]& (0x80>>(b->asnumber%8))) { if(b->asdot && b->asnumber>65535) { fprintf(f,"ip as-path access-list %s permit ^(_%u.%u)*$\n", b->name?b->name:"NN",b->asnumber/65536,b->asnumber%65536); } else { fprintf(f,"ip as-path access-list %s permit ^(_%u)*$\n", b->name?b->name:"NN",b->asnumber); }; empty=0; }; for(k=0;k<65536;k++) { if(!b->asn32s[k]) continue; for(i=0;i<8192;i++) { for(j=0;j<8;j++) { if(b->asn32s[k][i]&(0x80>>j)) { if(k*65536+i*8+j==b->asnumber) continue; if(!nc) { if(b->asdot && k>0) { fprintf(f,"ip as-path access-list %s permit" " ^(_[0-9]+)*_(%u.%u", b->name?b->name:"NN", k,i*8+j); empty=0; } else { fprintf(f,"ip as-path access-list %s permit" " ^(_[0-9]+)*_(%u", b->name?b->name:"NN", k*65536+i*8+j); empty=0; }; } else { if(b->asdot && k>0) { fprintf(f,"|%u.%u",k,i*8+j); empty=0; } else { fprintf(f,"|%u",k*65536+i*8+j); empty=0; }; } nc++; if(nc==b->aswidth) { fprintf(f,")$\n"); nc=0; }; }; }; }; }; if(nc) fprintf(f,")$\n"); if(empty) fprintf(f,"ip as-path access-list %s deny .*\n", b->name?b->name:"NN"); return 0; }; int bgpq3_print_cisco_xr_oaspath(FILE* f, struct bgpq_expander* b) { int nc=0, i, j, k, comma=0; fprintf(f, "as-path-set %s", b->name?b->name:"NN"); if(b->asn32s[b->asnumber/65536] && b->asn32s[b->asnumber/65536][(b->asnumber%65536)/8]& (0x80>>(b->asnumber%8))) { fprintf(f,"\n ios-regex '^(_%u)*$'",b->asnumber); comma=1; }; for(k=0;k<65536;k++) { if(!b->asn32s[k]) continue; for(i=0;i<8192;i++) { for(j=0;j<8;j++) { if(b->asn32s[k][i]&(0x80>>j)) { if(k*65536+i*8+j==b->asnumber) continue; if(!nc) { fprintf(f,"%s\n ios-regex '^(_[0-9]+)*_(%u", comma?",":"", k*65536+i*8+j); comma=1; } else { fprintf(f,"|%u",k*65536+i*8+j); } nc++; if(nc==b->aswidth) { fprintf(f,")$'"); nc=0; }; }; }; }; }; if(nc) fprintf(f,")$'"); fprintf(f,"\nend-set\n"); return 0; }; int bgpq3_print_juniper_aspath(FILE* f, struct bgpq_expander* b) { int nc=0, lineNo=0, i, j, k; fprintf(f,"policy-options {\nreplace:\n as-path-group %s {\n", b->name?b->name:"NN"); if(b->asn32s[b->asnumber/65536] && b->asn32s[b->asnumber/65535][(b->asnumber%65536)/8]& (0x80>>(b->asnumber%8))) { fprintf(f," as-path a%u \"^%u(%u)*$\";\n", lineNo, b->asnumber, b->asnumber); lineNo++; }; for(k=0;k<65536;k++) { if(!b->asn32s[k]) continue; for(i=0;i<8192;i++) { for(j=0;j<8;j++) { if(b->asn32s[k][i]&(0x80>>j)) { if(k*65536+i*8+j==b->asnumber) continue; if(!nc) { fprintf(f," as-path a%u \"^%u(.)*(%u", lineNo,b->asnumber,k*65536+i*8+j); } else { fprintf(f,"|%u",k*65536+i*8+j); }; nc++; if(nc==b->aswidth) { fprintf(f,")$\";\n"); nc=0; lineNo++; }; }; }; }; }; if(nc) fprintf(f,")$\";\n"); else if(lineNo==0) fprintf(f," as-path aNone \"!.*\";\n"); fprintf(f," }\n}\n"); return 0; }; int bgpq3_print_juniper_oaspath(FILE* f, struct bgpq_expander* b) { int nc=0, lineNo=0, i, j, k; fprintf(f,"policy-options {\nreplace:\n as-path-group %s {\n", b->name?b->name:"NN"); if(b->asn32s[b->asnumber/65536] && b->asn32s[b->asnumber/65536][(b->asnumber%65536)/8]& (0x80>>(b->asnumber%8))) { fprintf(f," as-path a%u \"^%u(%u)*$\";\n", lineNo, b->asnumber, b->asnumber); lineNo++; }; for(k=0;k<65536;k++) { if(!b->asn32s[k]) continue; for(i=0;i<8192;i++) { for(j=0;j<8;j++) { if(b->asn32s[k][i]&(0x80>>j)) { if(k*65536+i*8+j==b->asnumber) continue; if(!nc) { fprintf(f," as-path a%u \"^(.)*(%u", lineNo,k*65536+i*8+j); } else { fprintf(f,"|%u",k*65536+i*8+j); } nc++; if(nc==b->aswidth) { fprintf(f,")$\";\n"); nc=0; lineNo++; }; }; }; }; }; if(nc) fprintf(f,")$\";\n"); else if(lineNo==0) fprintf(f," as-path aNone \"!.*\";\n"); fprintf(f," }\n}\n"); return 0; }; int bgpq3_print_openbgpd_oaspath(FILE* f, struct bgpq_expander* b) { int i, j, k, lineNo=0; for(k=0;k<65536;k++) { if(!b->asn32s[k]) continue; for(i=0;i<8192;i++) { for(j=0;j<8;j++) { if(b->asn32s[k][i]&(0x80>>j)) { fprintf(f, "allow to AS %u AS %u\n", b->asnumber, k*65536+i*8+j); lineNo++; }; }; }; }; if(!lineNo) fprintf(f, "deny to AS %u\n", b->asnumber); return 0; }; int bgpq3_print_nokia_aspath(FILE* f, struct bgpq_expander* b) { int nc=0, lineNo=1, i, j, k; fprintf(f,"configure router policy-options\nbegin\nno as-path-group \"%s\"\n", b->name ? b->name : "NN"); fprintf(f,"as-path-group \"%s\"\n", b->name ? b->name : "NN"); if(b->asn32s[b->asnumber/65536] && b->asn32s[b->asnumber/65535][(b->asnumber%65536)/8]& (0x80>>(b->asnumber%8))) { fprintf(f," entry %u expression \"%u+\"\n", lineNo, b->asnumber); lineNo++; }; for(k=0;k<65536;k++) { if(!b->asn32s[k]) continue; for(i=0;i<8192;i++) { for(j=0;j<8;j++) { if(b->asn32s[k][i]&(0x80>>j)) { if(k*65536+i*8+j==b->asnumber) continue; if(!nc) { fprintf(f," entry %u expression \"%u.*[%u", lineNo,b->asnumber,k*65536+i*8+j); } else { fprintf(f," %u",k*65536+i*8+j); }; nc++; if(nc==b->aswidth) { fprintf(f,"]\"\n"); nc=0; lineNo++; }; }; }; }; }; if(nc) fprintf(f,"]\"\n"); fprintf(f,"exit\ncommit\n"); return 0; }; int bgpq3_print_nokia_md_aspath(FILE* f, struct bgpq_expander* b) { int nc=0, lineNo=1, i, j, k; fprintf(f,"/configure policy-options\ndelete as-path-group \"%s\"\n", b->name ? b->name : "NN"); fprintf(f,"as-path-group \"%s\" {\n", b->name ? b->name : "NN"); if(b->asn32s[b->asnumber/65536] && b->asn32s[b->asnumber/65535][(b->asnumber%65536)/8]& (0x80>>(b->asnumber%8))) { fprintf(f," entry %u {\n expression \"%u+\"\n }\n", lineNo, b->asnumber); lineNo++; }; for(k=0;k<65536;k++) { if(!b->asn32s[k]) continue; for(i=0;i<8192;i++) { for(j=0;j<8;j++) { if(b->asn32s[k][i]&(0x80>>j)) { if(k*65536+i*8+j==b->asnumber) continue; if(!nc) { fprintf(f," entry %u {\n expression \"%u.*[%u", lineNo,b->asnumber,k*65536+i*8+j); } else { fprintf(f," %u",k*65536+i*8+j); }; nc++; if(nc==b->aswidth) { fprintf(f,"]\"\n }\n"); nc=0; lineNo++; }; }; }; }; }; if(nc) fprintf(f,"]\"\n }\n"); fprintf(f, "}\n"); return 0; }; int bgpq3_print_huawei_aspath(FILE* f, struct bgpq_expander* b) { int nc=0, i, j, k, empty=1; fprintf(f,"undo ip as-path-filter %s\n", b->name ? b->name : "NN"); if(b->asn32s[b->asnumber/65536] && b->asn32s[b->asnumber/65535][(b->asnumber%65536)/8]& (0x80>>(b->asnumber%8))) { fprintf(f,"ip as-path-filter %s permit ^%u(%u)*$\n", b->name?b->name:"NN",b->asnumber,b->asnumber); empty=0; }; for(k=0;k<65536;k++) { if(!b->asn32s[k]) continue; for(i=0;i<8192;i++) { for(j=0;j<8;j++) { if(b->asn32s[k][i]&(0x80>>j)) { if(k*65536+i*8+j==b->asnumber) continue; if(!nc) { fprintf(f,"ip as-path-filter %s permit ^%u([0-9]+)*" "_(%u", b->name?b->name:"NN",b->asnumber,k*65536+i*8+j); empty=0; } else { fprintf(f,"|%u",k*65536+i*8+j); }; nc++; if(nc==b->aswidth) { fprintf(f,")$\n"); nc=0; }; }; }; }; }; if(nc) fprintf(f,")$\n"); if(empty) fprintf(f,"ip as-path-filter %s deny .*\n", b->name?b->name:"NN"); return 0; }; int bgpq3_print_huawei_oaspath(FILE* f, struct bgpq_expander* b) { int nc=0, i, j, k, empty=1; fprintf(f,"undo ip as-path-filter %s\n", b->name ? b->name : "NN"); if(b->asn32s[b->asnumber/65536] && b->asn32s[b->asnumber/65536][(b->asnumber%65536)/8]& (0x80>>(b->asnumber%8))) { fprintf(f,"ip as-path-filter %s permit (_%u)*$\n", b->name?b->name:"NN", b->asnumber); empty=0; }; for(k=0;k<65536;k++) { if(!b->asn32s[k]) continue; for(i=0;i<8192;i++) { for(j=0;j<8;j++) { if(b->asn32s[k][i]&(0x80>>j)) { if(k*65536+i*8+j==b->asnumber) continue; if(!nc) { fprintf(f,"ip as-path-filter %s permit ^(_[0-9]+)*_(%u", b->name?b->name:"NN",k*65536+i*8+j); } else { fprintf(f,"|%u",k*65536+i*8+j); } nc++; empty=0; if(nc==b->aswidth) { fprintf(f,")$\n"); nc=0; }; }; }; }; }; if(nc) fprintf(f,")$\n"); if(empty) fprintf(f, "ip as-path-filter %s deny .*\n", b->name?b->name:"NN"); return 0; }; int bgpq3_print_nokia_oaspath(FILE* f, struct bgpq_expander* b) { int nc=0, lineNo=1, i, j, k; fprintf(f,"configure router policy-options\nbegin\nno as-path-group \"%s\"\n", b->name ? b->name : "NN"); fprintf(f,"as-path-group \"%s\"\n", b->name ? b->name : "NN"); if(b->asn32s[b->asnumber/65536] && b->asn32s[b->asnumber/65536][(b->asnumber%65536)/8]& (0x80>>(b->asnumber%8))) { fprintf(f," entry %u expression \"%u+\"\n", lineNo, b->asnumber); lineNo++; }; for(k=0;k<65536;k++) { if(!b->asn32s[k]) continue; for(i=0;i<8192;i++) { for(j=0;j<8;j++) { if(b->asn32s[k][i]&(0x80>>j)) { if(k*65536+i*8+j==b->asnumber) continue; if(!nc) { fprintf(f," entry %u expression \".*[%u", lineNo,k*65536+i*8+j); } else { fprintf(f," %u",k*65536+i*8+j); } nc++; if(nc==b->aswidth) { fprintf(f,"]\"\n"); nc=0; lineNo++; }; }; }; }; }; if(nc) fprintf(f,"]\"\n"); return 0; }; int bgpq3_print_nokia_md_oaspath(FILE* f, struct bgpq_expander* b) { int nc=0, lineNo=1, i, j, k; fprintf(f,"/configure policy-options\ndelete as-path-group \"%s\"\n", b->name ? b->name : "NN"); fprintf(f,"as-path-group \"%s\" {\n", b->name ? b->name : "NN"); if(b->asn32s[b->asnumber/65536] && b->asn32s[b->asnumber/65536][(b->asnumber%65536)/8]& (0x80>>(b->asnumber%8))) { fprintf(f," entry %u {\n expression \"%u+\"\n }\n", lineNo, b->asnumber); lineNo++; }; for(k=0;k<65536;k++) { if(!b->asn32s[k]) continue; for(i=0;i<8192;i++) { for(j=0;j<8;j++) { if(b->asn32s[k][i]&(0x80>>j)) { if(k*65536+i*8+j==b->asnumber) continue; if(!nc) { fprintf(f," entry %u {\n expression \".*[%u", lineNo,k*65536+i*8+j); } else { fprintf(f," %u",k*65536+i*8+j); } nc++; if(nc==b->aswidth) { fprintf(f,"]\"\n }\n"); nc=0; lineNo++; }; }; }; }; }; if(nc) fprintf(f,"]\"\n }\n"); fprintf(f, "}\n"); return 0; }; int bgpq3_print_aspath(FILE* f, struct bgpq_expander* b) { if(b->vendor==V_JUNIPER) { return bgpq3_print_juniper_aspath(f,b); } else if(b->vendor==V_CISCO) { return bgpq3_print_cisco_aspath(f,b); } else if(b->vendor==V_CISCO_XR) { return bgpq3_print_cisco_xr_aspath(f,b); } else if(b->vendor==V_JSON) { return bgpq3_print_json_aspath(f,b); } else if(b->vendor==V_BIRD) { return bgpq3_print_bird_aspath(f,b); } else if(b->vendor==V_OPENBGPD) { return bgpq3_print_openbgpd_aspath(f,b); } else if(b->vendor==V_NOKIA) { return bgpq3_print_nokia_aspath(f,b); } else if(b->vendor==V_NOKIA_MD) { return bgpq3_print_nokia_md_aspath(f,b); } else if(b->vendor==V_HUAWEI) { return bgpq3_print_huawei_aspath(f,b); } else { sx_report(SX_FATAL,"Unknown vendor %i\n", b->vendor); }; return 0; }; int bgpq3_print_oaspath(FILE* f, struct bgpq_expander* b) { if(b->vendor==V_JUNIPER) { return bgpq3_print_juniper_oaspath(f,b); } else if(b->vendor==V_CISCO) { return bgpq3_print_cisco_oaspath(f,b); } else if(b->vendor==V_CISCO_XR) { return bgpq3_print_cisco_xr_oaspath(f,b); } else if(b->vendor==V_OPENBGPD) { return bgpq3_print_openbgpd_oaspath(f,b); } else if(b->vendor==V_NOKIA) { return bgpq3_print_nokia_oaspath(f,b); } else if(b->vendor==V_NOKIA_MD) { return bgpq3_print_nokia_md_oaspath(f,b); } else if(b->vendor==V_HUAWEI) { return bgpq3_print_huawei_oaspath(f,b); } else { sx_report(SX_FATAL,"Unknown vendor %i\n", b->vendor); }; return 0; }; int bgpq3_print_asset(FILE* f, struct bgpq_expander* b) { switch(b->vendor) { case V_JSON: return bgpq3_print_json_aspath(f,b); case V_OPENBGPD: return bgpq3_print_openbgpd_asset(f,b); case V_BIRD: return bgpq3_print_bird_aspath(f,b); default: sx_report(SX_FATAL, "as-sets (-t) supported for JSON, OpenBGPD " "and BIRD only\n"); return -1; }; }; void bgpq3_print_jprefix(struct sx_radix_node* n, void* ff) { char prefix[128]; FILE* f=(FILE*)ff; if(n->isGlue) return; if(!f) f=stdout; sx_prefix_snprintf(&n->prefix,prefix,sizeof(prefix)); fprintf(f," %s;\n",prefix); }; static int needscomma=0; void bgpq3_print_json_prefix(struct sx_radix_node* n, void* ff) { char prefix[128]; FILE* f=(FILE*)ff; if(n->isGlue) goto checkSon; if(!f) f=stdout; sx_prefix_jsnprintf(&n->prefix, prefix, sizeof(prefix)); if (!n->isAggregate) { fprintf(f, "%s\n { \"prefix\": \"%s\", \"exact\": true }", needscomma?",":"", prefix); } else if (n->aggregateLow > n->prefix.masklen) { fprintf(f, "%s\n { \"prefix\": \"%s\", \"exact\": false,\n " "\"greater-equal\": %u, \"less-equal\": %u }", needscomma?",":"", prefix, n->aggregateLow, n->aggregateHi); } else { fprintf(f, "%s\n { \"prefix\": \"%s\", \"exact\": false, " "\"less-equal\": %u }", needscomma?",":"", prefix, n->aggregateHi); }; needscomma=1; checkSon: if(n->son) bgpq3_print_json_prefix(n->son, ff); }; int bgpq3_print_json_aspath(FILE* f, struct bgpq_expander* b) { int nc=0, i, j, k; fprintf(f,"{\"%s\": [", b->name?b->name:"NN"); for(k=0;k<65536;k++) { if(!b->asn32s[k]) continue; for(i=0;i<8192;i++) { for(j=0;j<8;j++) { if(b->asn32s[k][i]&(0x80>>j)) { if(!nc) { fprintf(f,"%s\n %u",needscomma?",":"", k*65536+i*8+j); needscomma=1; } else { fprintf(f,"%s%u",needscomma?",":"", k*65536+i*8+j); needscomma=1; } nc++; if(nc==b->aswidth) { nc=0; }; }; }; }; }; fprintf(f,"\n]}\n"); return 0; }; void bgpq3_print_bird_prefix(struct sx_radix_node* n, void* ff) { char prefix[128]; FILE* f=(FILE*)ff; if(n->isGlue) goto checkSon; if(!f) f=stdout; sx_prefix_snprintf(&n->prefix, prefix, sizeof(prefix)); if (!n->isAggregate) { fprintf(f, "%s\n %s", needscomma?",":"", prefix); } else if (n->aggregateLow > n->prefix.masklen) { fprintf(f, "%s\n %s{%u,%u}", needscomma?",":"", prefix, n->aggregateLow, n->aggregateHi); } else { fprintf(f, "%s\n %s{%u,%u}", needscomma?",":"", prefix, n->prefix.masklen, n->aggregateHi); }; needscomma=1; checkSon: if(n->son) bgpq3_print_bird_prefix(n->son, ff); }; int bgpq3_print_bird_aspath(FILE* f, struct bgpq_expander* b) { int nc=0, i, j, k, empty=1; char buffer[2048]; snprintf(buffer, sizeof(buffer), "%s = [", b->name?b->name:"NN"); for(k=0;k<65536;k++) { if(!b->asn32s[k]) continue; for(i=0;i<8192;i++) { for(j=0;j<8;j++) { if(b->asn32s[k][i]&(0x80>>j)) { if(buffer[0]) fprintf(f, "%s", buffer); buffer[0]=0; if(!nc) { fprintf(f, "%s%u", empty?"":",\n ", k*65536+i*8+j); empty = 0; } else { fprintf(f, ", %u", k*65536+i*8+j); }; nc++; if(nc==b->aswidth) { nc=0; }; }; }; }; }; if(!empty) fprintf(f,"];\n"); return 0; }; void bgpq3_print_openbgpd_prefix(struct sx_radix_node* n, void* ff) { char prefix[128]; FILE* f=(FILE*)ff; if(n->isGlue) goto checkSon; if(!f) f=stdout; sx_prefix_snprintf(&n->prefix, prefix, sizeof(prefix)); if (!n->isAggregate) { fprintf(f, "\n\t%s", prefix); } else if (n->aggregateLow == n->aggregateHi) { fprintf(f, "\n\t%s prefixlen = %u", prefix, n->aggregateHi); } else if (n->aggregateLow > n->prefix.masklen) { fprintf(f, "\n\t%s prefixlen %u - %u", prefix, n->aggregateLow, n->aggregateHi); } else { fprintf(f, "\n\t%s prefixlen %u - %u", prefix, n->prefix.masklen, n->aggregateHi); }; checkSon: if(n->son) bgpq3_print_openbgpd_prefix(n->son, ff); }; int bgpq3_print_openbgpd_asset(FILE* f, struct bgpq_expander* b) { int i, j, k, nc=0; fprintf(f, "as-set %s {", b->name?b->name:"NN"); for(k=0;k<65536;k++) { if(!b->asn32s[k]) continue; for(i=0;i<8192;i++) { for(j=0;j<8;j++) { if(b->asn32s[k][i]&(0x80>>j)) { fprintf(f, "%s%u", nc==0 ? "\n\t" : " ", k*65536+i*8+j); nc++; if(nc==b->aswidth) nc=0; }; }; }; }; fprintf(f, "\n}\n"); return 0; }; int bgpq3_print_openbgpd_aspath(FILE* f, struct bgpq_expander* b) { int i, j, k, lineNo=0; for(k=0;k<65536;k++) { if(!b->asn32s[k]) continue; for(i=0;i<8192;i++) { for(j=0;j<8;j++) { if(b->asn32s[k][i]&(0x80>>j)) { fprintf(f, "allow from AS %u AS %u\n", b->asnumber, k*65536+i*8+j); lineNo++; }; }; }; }; if(!lineNo) fprintf(f, "deny from AS %u\n", b->asnumber); return 0; }; static int jrfilter_prefixed=1; void bgpq3_print_jrfilter(struct sx_radix_node* n, void* ff) { char prefix[128]; FILE* f=(FILE*)ff; if(n->isGlue) goto checkSon; if(!f) f=stdout; sx_prefix_snprintf(&n->prefix,prefix,sizeof(prefix)); if(!n->isAggregate) { fprintf(f," %s%s exact;\n", jrfilter_prefixed ? "route-filter " : "", prefix); } else { if(n->aggregateLow>n->prefix.masklen) { fprintf(f," %s%s prefix-length-range /%u-/%u;\n", jrfilter_prefixed ? "route-filter " : "", prefix,n->aggregateLow,n->aggregateHi); } else { fprintf(f," %s%s upto /%u;\n", jrfilter_prefixed ? "route-filter " : "", prefix,n->aggregateHi); }; }; checkSon: if(n->son) bgpq3_print_jrfilter(n->son, ff); }; static char* bname=NULL; static int seq=0; void bgpq3_print_cprefix(struct sx_radix_node* n, void* ff) { char prefix[128], seqno[16]=""; FILE* f=(FILE*)ff; if(!f) f=stdout; if(n->isGlue) goto checkSon; sx_prefix_snprintf(&n->prefix,prefix,sizeof(prefix)); if(seq) snprintf(seqno, sizeof(seqno), " seq %i", seq++); if(n->isAggregate) { if(n->aggregateLow>n->prefix.masklen) { fprintf(f,"%s prefix-list %s%s permit %s ge %u le %u\n", n->prefix.family==AF_INET?"ip":"ipv6",bname?bname:"NN",seqno, prefix,n->aggregateLow,n->aggregateHi); } else { fprintf(f,"%s prefix-list %s%s permit %s le %u\n", n->prefix.family==AF_INET?"ip":"ipv6",bname?bname:"NN",seqno, prefix,n->aggregateHi); }; } else { fprintf(f,"%s prefix-list %s%s permit %s\n", (n->prefix.family==AF_INET)?"ip":"ipv6",bname?bname:"NN",seqno, prefix); }; checkSon: if(n->son) bgpq3_print_cprefix(n->son,ff); }; void bgpq3_print_cprefixxr(struct sx_radix_node* n, void* ff) { char prefix[128]; FILE* f=(FILE*)ff; if(!f) f=stdout; if(n->isGlue) goto checkSon; sx_prefix_snprintf(&n->prefix,prefix,sizeof(prefix)); if(n->isAggregate) { if(n->aggregateLow>n->prefix.masklen) { fprintf(f,"%s%s ge %u le %u", needscomma?",\n ":" ", prefix, n->aggregateLow,n->aggregateHi); } else { fprintf(f,"%s%s le %u", needscomma?",\n ":" ", prefix, n->aggregateHi); }; } else { fprintf(f,"%s%s", needscomma?",\n ":" ", prefix); }; needscomma=1; checkSon: if(n->son) bgpq3_print_cprefixxr(n->son,ff); }; void bgpq3_print_hprefix(struct sx_radix_node* n, void* ff) { char prefix[128]; FILE* f=(FILE*)ff; if(!f) f=stdout; if(n->isGlue) goto checkSon; sx_prefix_snprintf_sep(&n->prefix,prefix,sizeof(prefix)," "); if(n->isAggregate) { if(n->aggregateLow>n->prefix.masklen) { fprintf(f,"ip %s-prefix %s permit %s greater-equal %u " "less-equal %u\n", n->prefix.family==AF_INET?"ip":"ipv6",bname?bname:"NN", prefix,n->aggregateLow,n->aggregateHi); } else { fprintf(f,"ip %s-prefix %s permit %s less-equal %u\n", n->prefix.family==AF_INET?"ip":"ipv6",bname?bname:"NN", prefix,n->aggregateHi); }; } else { fprintf(f,"ip %s-prefix %s permit %s\n", (n->prefix.family==AF_INET)?"ip":"ipv6",bname?bname:"NN", prefix); }; checkSon: if(n->son) bgpq3_print_hprefix(n->son,ff); }; void bgpq3_print_ceacl(struct sx_radix_node* n, void* ff) { char prefix[128]; FILE* f=(FILE*)ff; char* c; uint32_t netmask=0xfffffffful; if(!f) f=stdout; if(n->isGlue) goto checkSon; sx_prefix_snprintf(&n->prefix,prefix,sizeof(prefix)); c=strchr(prefix,'/'); if(c) *c=0; if(n->prefix.masklen==32) { netmask=0; } else { netmask<<=(32-n->prefix.masklen); netmask&=0xfffffffful; }; netmask=htonl(netmask); if(n->isAggregate) { unsigned long mask=0xfffffffful, wildaddr, wild2addr, wildmask; int masklen=n->aggregateLow; wildaddr=0xfffffffful>>n->prefix.masklen; if(n->aggregateHi==32) { wild2addr=0; } else { wild2addr=0xfffffffful>>n->aggregateHi; }; wildaddr=wildaddr&(~wild2addr); if(masklen==32) mask=0xfffffffful; else mask=0xfffffffful & (0xfffffffful<<(32-masklen)); if(n->aggregateHi==32) wild2addr=0; else wild2addr=0xfffffffful>>n->aggregateHi; wildmask=(0xfffffffful>>n->aggregateLow)&(~wild2addr); mask=htonl(mask); wildaddr=htonl(wildaddr); wildmask=htonl(wildmask); if(wildaddr) { fprintf(f," permit ip %s ", inet_ntoa(n->prefix.addr.addr)); fprintf(f,"%s ", inet_ntoa(*(struct in_addr*)&wildaddr)); } else { fprintf(f," permit ip host %s ",inet_ntoa(n->prefix.addr.addr)); }; if(wildmask) { fprintf(f,"%s ", inet_ntoa(*(struct in_addr*)&mask)); fprintf(f,"%s\n", inet_ntoa(*(struct in_addr*)&wildmask)); } else { fprintf(f,"host %s\n", inet_ntoa(*(struct in_addr*)&mask)); }; } else { fprintf(f," permit ip host %s host %s\n",prefix, inet_ntoa(*(struct in_addr*)&netmask)); }; checkSon: if(n->son) bgpq3_print_ceacl(n->son,ff); }; void bgpq3_print_nokia_ipfilter(struct sx_radix_node* n, void* ff) { char prefix[128]; FILE* f=(FILE*)ff; if(n->isGlue) goto checkSon; if(!f) f=stdout; sx_prefix_snprintf(&n->prefix,prefix,sizeof(prefix)); fprintf(f," prefix %s\n", prefix); checkSon: if(n->son) bgpq3_print_nokia_ipfilter(n->son, ff); }; void bgpq3_print_nokia_md_ipfilter(struct sx_radix_node* n, void* ff) { char prefix[128]; FILE* f=(FILE*)ff; if(n->isGlue) goto checkSon; if(!f) f=stdout; sx_prefix_snprintf(&n->prefix,prefix,sizeof(prefix)); fprintf(f," prefix %s { }\n", prefix); checkSon: if(n->son) bgpq3_print_nokia_md_ipfilter(n->son, ff); }; void bgpq3_print_nokia_prefix(struct sx_radix_node* n, void* ff) { char prefix[128]; FILE* f=(FILE*)ff; if(n->isGlue) goto checkSon; if(!f) f=stdout; sx_prefix_snprintf(&n->prefix,prefix,sizeof(prefix)); if(!n->isAggregate) { fprintf(f," prefix %s exact\n", prefix); } else { if(n->aggregateLow>n->prefix.masklen) { fprintf(f," prefix %s prefix-length-range %u-%u\n", prefix,n->aggregateLow,n->aggregateHi); } else { fprintf(f," prefix %s prefix-length-range %u-%u\n", prefix, n->prefix.masklen, n->aggregateHi); }; }; checkSon: if(n->son) bgpq3_print_nokia_prefix(n->son, ff); }; void bgpq3_print_nokia_md_prefix(struct sx_radix_node* n, void* ff) { char prefix[128]; FILE* f=(FILE*)ff; if(n->isGlue) goto checkSon; if(!f) f=stdout; sx_prefix_snprintf(&n->prefix,prefix,sizeof(prefix)); if(!n->isAggregate) { fprintf(f," prefix %s type exact {\n }\n", prefix); } else { if(n->aggregateLow>n->prefix.masklen) { fprintf(f," prefix %s type range {\n start-length %u\n" " end-length %u\n }\n", prefix,n->aggregateLow,n->aggregateHi); } else { fprintf(f," prefix %s type through {\n " "through-length %u\n }\n", prefix, n->aggregateHi); }; }; checkSon: if(n->son) bgpq3_print_nokia_md_prefix(n->son, ff); }; int bgpq3_print_juniper_prefixlist(FILE* f, struct bgpq_expander* b) { fprintf(f,"policy-options {\nreplace:\n prefix-list %s {\n", b->name?b->name:"NN"); sx_radix_tree_foreach(b->tree,bgpq3_print_jprefix,f); fprintf(f," }\n}\n"); return 0; }; int bgpq3_print_juniper_routefilter(FILE* f, struct bgpq_expander* b) { char* c=NULL; if(b->name && (c=strchr(b->name,'/'))) { *c=0; fprintf(f,"policy-options {\n policy-statement %s {\n term %s {\n" "replace:\n from {\n", b->name, c+1); if(b->match) fprintf(f," %s;\n",b->match); } else { fprintf(f,"policy-options {\n policy-statement %s { \n" "replace:\n from {\n", b->name?b->name:"NN"); if(b->match) fprintf(f," %s;\n",b->match); }; if(!sx_radix_tree_empty(b->tree)) { jrfilter_prefixed=1; sx_radix_tree_foreach(b->tree,bgpq3_print_jrfilter,f); } else { fprintf(f," route-filter %s/0 orlonger reject;\n", b->tree->family == AF_INET ? "0.0.0.0" : "::"); }; if(c) { fprintf(f, " }\n }\n }\n}\n"); } else { fprintf(f, " }\n }\n}\n"); }; return 0; }; int bgpq3_print_openbgpd_prefixlist(FILE* f, struct bgpq_expander* b) { bname=b->name ? b->name : "NN"; if (sx_radix_tree_empty(b->tree)) { fprintf(f, "# generated prefix-list %s (AS %u) is empty\n", bname, b->asnumber); if (!b->asnumber) fprintf(f, "# use -a to generate \"deny from ASN \" " "instead of this list\n"); }; if (!sx_radix_tree_empty(b->tree) || !b->asnumber) { if(b->name){ if(strcmp(b->name, "NN") != 0) { fprintf(f, "%s=\"", b->name); } } fprintf(f,"prefix { "); sx_radix_tree_foreach(b->tree,bgpq3_print_openbgpd_prefix,f); fprintf(f, "\n\t}"); if(b->name){ if(strcmp(b->name, "NN") != 0) { fprintf(f, "\""); } } fprintf(f, "\n"); } else { fprintf(f, "deny from AS %u\n", b->asnumber); }; return 0; }; int bgpq3_print_openbgpd_prefixset(FILE* f, struct bgpq_expander* b) { bname=b->name ? b->name : "NN"; fprintf(f,"prefix-set %s {", b->name); if (!sx_radix_tree_empty(b->tree)) sx_radix_tree_foreach(b->tree,bgpq3_print_openbgpd_prefix,f); fprintf(f, "\n}\n"); return 0; }; int bgpq3_print_cisco_prefixlist(FILE* f, struct bgpq_expander* b) { bname=b->name ? b->name : "NN"; seq=b->sequence; fprintf(f,"no %s prefix-list %s\n", (b->family==AF_INET)?"ip":"ipv6",bname); if (!sx_radix_tree_empty(b->tree)) { sx_radix_tree_foreach(b->tree,bgpq3_print_cprefix,f); } else { fprintf(f, "! generated prefix-list %s is empty\n", bname); fprintf(f, "%s prefix-list %s deny %s\n", (b->family==AF_INET) ? "ip" : "ipv6", bname, (b->family==AF_INET) ? "0.0.0.0/0" : "::/0"); }; return 0; }; int bgpq3_print_ciscoxr_prefixlist(FILE* f, struct bgpq_expander* b) { bname=b->name ? b->name : "NN"; fprintf(f,"no prefix-set %s\nprefix-set %s\n", bname, bname); sx_radix_tree_foreach(b->tree,bgpq3_print_cprefixxr,f); fprintf(f, "\nend-set\n"); return 0; }; int bgpq3_print_json_prefixlist(FILE* f, struct bgpq_expander* b) { fprintf(f,"{ \"%s\": [", b->name?b->name:"NN"); sx_radix_tree_foreach(b->tree,bgpq3_print_json_prefix,f); fprintf(f,"\n] }\n"); return 0; }; int bgpq3_print_bird_prefixlist(FILE* f, struct bgpq_expander* b) { if (!sx_radix_tree_empty(b->tree)) { fprintf(f,"%s = [", b->name?b->name:"NN"); sx_radix_tree_foreach(b->tree,bgpq3_print_bird_prefix,f); fprintf(f,"\n];\n"); } else { SX_DEBUG(debug_expander, "skip empty prefix-list in BIRD format\n"); }; return 0; }; int bgpq3_print_huawei_prefixlist(FILE* f, struct bgpq_expander* b) { bname=b->name ? b->name : "NN"; seq=b->sequence; fprintf(f,"undo ip %s-prefix %s\n", (b->family==AF_INET)?"ip":"ipv6",bname); if (!sx_radix_tree_empty(b->tree)) { sx_radix_tree_foreach(b->tree,bgpq3_print_hprefix,f); } else { fprintf(f, "ip %s-prefix %s deny %s\n", (b->family==AF_INET) ? "ip" : "ipv6", bname, (b->family==AF_INET) ? "0.0.0.0/0" : "::/0"); }; return 0; }; struct fpcbdata { FILE* f; struct bgpq_expander* b; }; void bgpq3_print_format_prefix(struct sx_radix_node* n, void* ff) { char prefix[128]; struct fpcbdata* fpc=(struct fpcbdata*)ff; FILE* f=fpc->f; struct bgpq_expander* b=fpc->b; if(n->isGlue) return; if(!f) f=stdout; memset(prefix, 0, sizeof(prefix)); sx_prefix_snprintf_fmt(&n->prefix, prefix, sizeof(prefix), b->name?b->name:"NN", b->format); fprintf(f, "%s", prefix); }; int bgpq3_print_format_prefixlist(FILE* f, struct bgpq_expander* b) { struct fpcbdata ff = {.f=f, .b=b}; sx_radix_tree_foreach(b->tree,bgpq3_print_format_prefix,&ff); if (strcmp(b->format+strlen(b->format-2), "\n")) fprintf(f, "\n"); return 0; }; int bgpq3_print_nokia_prefixlist(FILE* f, struct bgpq_expander* b) { bname=b->name ? b->name : "NN"; fprintf(f,"configure router policy-options\nbegin\nno prefix-list \"%s\"\n", bname); fprintf(f,"prefix-list \"%s\"\n", bname); sx_radix_tree_foreach(b->tree,bgpq3_print_nokia_prefix,f); fprintf(f,"exit\ncommit\n"); return 0; }; int bgpq3_print_cisco_eacl(FILE* f, struct bgpq_expander* b) { bname=b->name ? b->name : "NN"; fprintf(f,"no ip access-list extended %s\n", bname); if (!sx_radix_tree_empty(b->tree)) { fprintf(f,"ip access-list extended %s\n", bname); sx_radix_tree_foreach(b->tree,bgpq3_print_ceacl,f); } else { fprintf(f,"! generated access-list %s is empty\n", bname); fprintf(f,"ip access-list extended %s deny any any\n", bname); }; return 0; }; int bgpq3_print_nokia_ipprefixlist(FILE* f, struct bgpq_expander* b) { bname=b->name ? b->name : "NN"; fprintf(f,"configure filter match-list\nno %s-prefix-list \"%s\"\n", b->tree->family==AF_INET?"ip":"ipv6", bname); fprintf(f,"%s-prefix-list \"%s\" create\n", b->tree->family==AF_INET?"ip":"ipv6", bname); if (!sx_radix_tree_empty(b->tree)) { sx_radix_tree_foreach(b->tree,bgpq3_print_nokia_ipfilter,f); } else { fprintf(f,"# generated ip-prefix-list %s is empty\n", bname); }; fprintf(f,"exit\n"); return 0; }; int bgpq3_print_nokia_md_prefixlist(FILE* f, struct bgpq_expander* b) { bname=b->name ? b->name : "NN"; fprintf(f,"/configure filter match-list\ndelete %s-prefix-list \"%s\"\n", b->tree->family==AF_INET?"ip":"ipv6", bname); fprintf(f,"%s-prefix-list \"%s\" {\n", b->tree->family==AF_INET?"ip":"ipv6", bname); if (!sx_radix_tree_empty(b->tree)) { sx_radix_tree_foreach(b->tree,bgpq3_print_nokia_md_ipfilter,f); } else { fprintf(f,"# generated %s-prefix-list %s is empty\n", b->tree->family==AF_INET?"ip":"ipv6", bname); }; fprintf(f,"}\n"); return 0; }; int bgpq3_print_nokia_md_ipprefixlist(FILE* f, struct bgpq_expander* b) { bname=b->name ? b->name : "NN"; fprintf(f,"/configure policy-options\ndelete prefix-list \"%s\"\n", bname); fprintf(f,"prefix-list \"%s\" {\n", bname); if (!sx_radix_tree_empty(b->tree)) { sx_radix_tree_foreach(b->tree,bgpq3_print_nokia_md_prefix,f); }; fprintf(f,"}\n"); return 0; }; int bgpq3_print_prefixlist(FILE* f, struct bgpq_expander* b) { switch(b->vendor) { case V_JUNIPER: return bgpq3_print_juniper_prefixlist(f,b); case V_CISCO: return bgpq3_print_cisco_prefixlist(f,b); case V_CISCO_XR: return bgpq3_print_ciscoxr_prefixlist(f,b); case V_JSON: return bgpq3_print_json_prefixlist(f,b); case V_BIRD: return bgpq3_print_bird_prefixlist(f,b); case V_OPENBGPD: return bgpq3_print_openbgpd_prefixlist(f,b); case V_FORMAT: return bgpq3_print_format_prefixlist(f,b); case V_NOKIA: return bgpq3_print_nokia_prefixlist(f,b); case V_NOKIA_MD: return bgpq3_print_nokia_md_ipprefixlist(f,b); case V_HUAWEI: return bgpq3_print_huawei_prefixlist(f,b); }; return 0; }; int bgpq3_print_eacl(FILE* f, struct bgpq_expander* b) { switch(b->vendor) { case V_JUNIPER: return bgpq3_print_juniper_routefilter(f,b); case V_CISCO: return bgpq3_print_cisco_eacl(f,b); case V_CISCO_XR: sx_report(SX_FATAL, "unreachable point\n"); case V_JSON: sx_report(SX_FATAL, "unreachable point\n"); case V_BIRD: sx_report(SX_FATAL, "unreachable point\n"); case V_OPENBGPD: return bgpq3_print_openbgpd_prefixset(f,b); case V_FORMAT: sx_report(SX_FATAL, "unreachable point\n"); case V_NOKIA: return bgpq3_print_nokia_ipprefixlist(f,b); case V_NOKIA_MD: return bgpq3_print_nokia_md_prefixlist(f,b); case V_HUAWEI: return sx_report(SX_FATAL, "unreachable point\n"); }; return 0; }; int bgpq3_print_juniper_route_filter_list(FILE* f, struct bgpq_expander* b) { fprintf(f, "policy-options {\nreplace:\n route-filter-list %s {\n", b->name?b->name:"NN"); if (sx_radix_tree_empty(b->tree)) { fprintf(f, " route-filter %s/0 orlonger reject;\n", b->tree->family == AF_INET ? "0.0.0.0" : "::"); } else { jrfilter_prefixed=0; sx_radix_tree_foreach(b->tree,bgpq3_print_jrfilter,f); }; fprintf(f, " }\n}\n"); return 0; }; int bgpq3_print_route_filter_list(FILE* f, struct bgpq_expander* b) { switch(b->vendor) { case V_JUNIPER: return bgpq3_print_juniper_route_filter_list(f,b); default: sx_report(SX_FATAL, "unreachable point\n"); }; return 0; }; bgpq3-0.1.35/bgpq_expander.c000066400000000000000000000544011340020421000155650ustar00rootroot00000000000000#if HAVE_CONFIG_H #include "config.h" #endif #include #include #if HAVE_SYS_SELECT_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include "bgpq3.h" #include "sx_report.h" #include "sx_maxsockbuf.h" int debug_expander=0; int pipelining=1; int expand_as23456=0; int expand_special_asn=0; static inline int tentry_cmp(struct sx_tentry* a, struct sx_tentry* b) { return strcasecmp(a->text, b->text); }; RB_GENERATE(tentree, sx_tentry, entry, tentry_cmp); int bgpq_expander_init(struct bgpq_expander* b, int af) { if(!af) af=AF_INET; if(!b) return 0; memset(b,0,sizeof(struct bgpq_expander)); b->tree=sx_radix_tree_new(af); if(!b->tree) goto fixups; b->family=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="whois.radb.net"; b->port="43"; STAILQ_INIT(&b->wq); STAILQ_INIT(&b->rq); STAILQ_INIT(&b->rsets); STAILQ_INIT(&b->macroses); return 1; fixups: /* if(b->tree) XXXXXXXXXXXXX sx_radix_tree_destroy(b->tree); */ b->tree=NULL; free(b); return 0; }; int bgpq_expander_add_asset(struct bgpq_expander* b, char* as) { struct sx_slentry* le; if(!b || !as) return 0; le=sx_slentry_new(as); STAILQ_INSERT_TAIL(&b->macroses, le, next); return 1; }; int bgpq_expander_add_rset(struct bgpq_expander* b, char* rs) { struct sx_slentry* le; if(!b || !rs) return 0; le=sx_slentry_new(rs); if(!le) return 0; STAILQ_INSERT_TAIL(&b->rsets, le, next); return 1; }; int bgpq_expander_add_already(struct bgpq_expander* b, char* rs) { struct sx_tentry* le, lkey; lkey.text = rs; if (RB_FIND(tentree, &b->already, &lkey)) return 1; le = sx_tentry_new(rs); RB_INSERT(tentree, &b->already, le); return 1; }; int bgpq_expander_add_stop(struct bgpq_expander* b, char* rs) { struct sx_tentry* le, lkey; lkey.text = rs; if (RB_FIND(tentree, &b->stoplist, &lkey)) return 1; le = sx_tentry_new(rs); RB_INSERT(tentree, &b->stoplist, le); return 1; }; int bgpq_expander_add_as(struct bgpq_expander* b, char* as) { char* eoa; uint32_t asno; if(!b || !as) return 0; asno=strtoul(as+2,&eoa,10); if(eoa && (*eoa!='.' && *eoa!=0)) { sx_report(SX_ERROR,"Invalid symbol in AS number: '%c' in %s\n", *eoa, as); return 0; }; if(*eoa=='.' || asno>65535) { if(b->asn32 || b->generation>=T_PREFIXLIST) { uint32_t asn1; if(asno>65535) { asn1=asno%65536; asno/=65536; } else if(eoa && *(eoa+1)) { asn1=strtoul(eoa+1,&eoa,10); } else { sx_report(SX_ERROR, "Invalid AS number: '%s'\n", as); return 0; }; if(eoa && *eoa!=0) { sx_report(SX_ERROR,"Invalid symbol in AS number: '%c' in %s\n", *eoa, as); return 0; }; if(asn1>65535) { sx_report(SX_ERROR,"Invalid AS number in %s\n", as); return 0; }; if(!expand_special_asn && (((asno*65536+asn1)>=4200000000ul) || ((asno*65536+asn1)>=64496 && (asno*65536+asn1) <= 65551))) { return 0; }; if(!b->asn32s[asno]) { b->asn32s[asno]=malloc(8192); if(!b->asn32s[asno]) { 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[asno],0,8192); }; b->asn32s[asno][asn1/8]|=(0x80>>(asn1%8)); } else if(!b->asn32) { b->asn32s[0][23456/8]|=(0x80>>(23456%8)); }; return 1; }; if(asno<1 || asno>65535) { sx_report(SX_ERROR,"Invalid AS number in %s\n", as); return 0; }; if(asno==23456 && !expand_as23456) return 0; if(!expand_special_asn && (asno>=64496 && asno <= 65536)) return 0; b->asn32s[0][asno/8]|=(0x80>>(asno%8)); return 1; }; int bgpq_expander_add_prefix(struct bgpq_expander* b, char* prefix) { struct sx_prefix p; if(!sx_prefix_parse(&p,0,prefix)) { sx_report(SX_ERROR,"Unable to parse prefix %s\n", prefix); return 0; } else if(p.family!=b->family) { SX_DEBUG(debug_expander,"Ignoring prefix %s with wrong address family\n" ,prefix); return 0; }; if(b->maxlen && p.masklen>b->maxlen) { SX_DEBUG(debug_expander, "Ignoring prefix %s: masklen %i > max " "masklen %u\n", prefix, p.masklen, b->maxlen); return 0; }; sx_radix_tree_insert(b->tree,&p); return 1; }; int bgpq_expander_add_prefix_range(struct bgpq_expander* b, char* prefix) { return sx_prefix_range_parse(b->tree, b->family, b->maxlen, prefix); }; int bgpq_expanded_macro(char* as, struct bgpq_expander* ex, struct bgpq_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, ...); int bgpq_expand_irrd(struct bgpq_expander* b, int (*callback)(char*, struct bgpq_expander* b, struct bgpq_request* req), void* udata, char* fmt, ...); int bgpq_expanded_macro_limit(char* as, struct bgpq_expander* b, struct bgpq_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, ignore\n", as); return 0; }; if (RB_FIND(tentree, &b->stoplist, &tkey)) { SX_DEBUG(debug_expander>2,"%s is in the stoplist, ignore\n", as); return 0; }; if(!b->maxdepth || (b->cdepth + 1 < b->maxdepth && req->depth + 1 < b->maxdepth)) { bgpq_expander_add_already(b,as); if (pipelining) { struct bgpq_request* req1 = bgpq_pipeline(b, bgpq_expanded_macro_limit, NULL, "!i%s\n", as); req1->depth = req->depth+1; } else { b->cdepth++; bgpq_expand_irrd(b, bgpq_expanded_macro_limit, NULL, "!i%s\n", as); b->cdepth--; }; } else { SX_DEBUG(debug_expander>2, "ignoring %s at depth %i\n", as, b->cdepth?(b->cdepth+1):(req->depth+1)); }; } else if(!strncasecmp(as, "AS", 2)) { struct sx_tentry tkey = { .text = as }; if (RB_FIND(tentree, &b->stoplist, &tkey)) { SX_DEBUG(debug_expander>2,"%s is in the stoplist, ignore\n", as); return 0; }; if(bgpq_expander_add_as(b, as)) { SX_DEBUG(debug_expander>2, ".. added asn %s\n", as); } else { SX_DEBUG(debug_expander, ".. some error adding as %s (in " "response to %s)\n", as, req->request); }; } else if (!strcasecmp(as, "ANY")) { return 0; } else { sx_report(SX_ERROR, "unexpected object '%s' in expanded_macro_limit " "(in response to %s)\n", as, req->request); }; return 1; }; int bgpq_expanded_prefix(char* as, struct bgpq_expander* ex, struct bgpq_request* req __attribute__((unused))) { char* d = strchr(as, '^'); if (!d) bgpq_expander_add_prefix(ex,as); else bgpq_expander_add_prefix_range(ex,as); return 1; }; int bgpq_expanded_v6prefix(char* prefix, struct bgpq_expander* ex, struct bgpq_request* req) { char* d = strchr(prefix, '^'); if (!d) bgpq_expander_add_prefix(ex,prefix); else bgpq_expander_add_prefix_range(ex,prefix); return 1; }; 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) { struct bgpq_request* bp = malloc(sizeof(struct bgpq_request)); if (!bp) return NULL; memset(bp, 0, sizeof(struct bgpq_request)); bp->request = strdup(request); bp->offset = 0; bp->size = strlen(bp->request); bp->callback = callback; bp->udata = udata; return bp; }; static void bgpq_request_free(struct bgpq_request* req) { if (req->request) free(req->request); free(req); }; struct bgpq_request* bgpq_pipeline(struct bgpq_expander* b, int (*callback)(char*, struct bgpq_expander*, struct bgpq_request*), void* udata, char* fmt, ...) { char request[128]; int ret; struct bgpq_request* bp=NULL; va_list ap; va_start(ap,fmt); vsnprintf(request,sizeof(request),fmt,ap); va_end(ap); SX_DEBUG(debug_expander,"expander: sending %s", request); bp = bgpq_request_alloc(request, callback, udata); if(!bp) { sx_report(SX_FATAL,"Unable to allocate %lu bytes: %s\n", (unsigned long)sizeof(struct bgpq_request),strerror(errno)); exit(1); }; if (STAILQ_EMPTY(&b->wq)) { ret=write(b->fd, request, bp->size); if (ret < 0) { if (errno == EAGAIN) { STAILQ_INSERT_TAIL(&b->wq, bp, next); return bp; }; sx_report(SX_FATAL, "Error writing request: %s\n", strerror(errno)); }; bp->offset=ret; if (ret == bp->size) { STAILQ_INSERT_TAIL(&b->rq, bp, next); } else { STAILQ_INSERT_TAIL(&b->wq, bp, next); }; } else STAILQ_INSERT_TAIL(&b->wq, bp, next); return bp; }; static void bgpq_expander_invalidate_asn(struct bgpq_expander* b, const char* q) { 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); 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)); }; }; }; static void bgpq_write(struct bgpq_expander* b) { while(!STAILQ_EMPTY(&b->wq)) { struct bgpq_request* req = STAILQ_FIRST(&b->wq); int ret = write(b->fd, req->request+req->offset, req->size-req->offset); if (ret < 0) { if (errno == EAGAIN) return; sx_report(SX_FATAL, "error writing data: %s\n", strerror(errno)); }; if (ret == req->size - req->offset) { /* this request was dequeued */ STAILQ_REMOVE_HEAD(&b->wq, next); STAILQ_INSERT_TAIL(&b->rq, req, next); } else { req->offset += ret; break; }; }; }; static int bgpq_selread(struct bgpq_expander* b, char* buffer, int size) { fd_set rfd, wfd; int ret; struct timeval timeout = {10, 0}; repeat: FD_ZERO(&rfd); FD_SET(b->fd, &rfd); FD_ZERO(&wfd); if (!STAILQ_EMPTY(&b->wq)) FD_SET(b->fd, &wfd); ret = select(b->fd+1, &rfd, &wfd, NULL, &timeout); if (ret == 0) sx_report(SX_FATAL, "select timeout\n"); else if (ret == -1 && errno == EINTR) goto repeat; else if (ret == -1) sx_report(SX_FATAL, "select error %i: %s\n", errno, strerror(errno)); if (!STAILQ_EMPTY(&b->wq) && FD_ISSET(b->fd, &wfd)) bgpq_write(b); if (FD_ISSET(b->fd, &rfd)) return read(b->fd, buffer, size); goto repeat; }; int bgpq_read(struct bgpq_expander* b) { static char response[256]; static int off = 0; if (!STAILQ_EMPTY(&b->wq)) bgpq_write(b); while(!STAILQ_EMPTY(&b->rq)) { struct bgpq_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; repeat: ret = bgpq_selread(b, response+off, sizeof(response)-off); if (ret < 0) { if (errno == EAGAIN) goto repeat; sx_report(SX_FATAL,"Error reading data from IRRd: %s (dequeue)\n", strerror(errno)); } else if (ret == 0) { sx_report(SX_FATAL,"EOF from IRRd (dequeue)\n"); }; off += ret; if (!(cres=strchr(response, '\n'))) goto repeat; have: SX_DEBUG(debug_expander>5, "got response of %.*s\n", off, response); if(response[0]=='A') { char* eon, *c; unsigned long togot=strtoul(response+1,&eon,10); char* recvbuffer=malloc(togot+2); int offset = 0; if (!recvbuffer) { sx_report(SX_FATAL, "error allocating %lu bytes: %s\n", togot+2, strerror(errno)); }; memset(recvbuffer,0,togot+2); if(!eon || *eon!='\n') { sx_report(SX_ERROR,"A-code finished with wrong char '%c'(%s)\n", eon?*eon:'0',response); exit(1); }; if (off - ((eon+1) - response) > togot) { /* full response and more data is already in buffer */ memcpy(recvbuffer, eon+1, togot); offset = togot; memmove(response, eon+1+togot, off-((eon+1)-response)-togot); off -= togot + ((eon+1)-response); memset(response+off, 0, sizeof(response)-off); } else { /* response is not yet fully buffered */ memcpy(recvbuffer, eon+1, off - ((eon+1)-response)); offset = off - ((eon+1) - response); memset(response, 0, sizeof(response)); off = 0; }; SX_DEBUG(debug_expander>5, "starting read with ready '%.*s', waiting for %lu\n", offset, recvbuffer, togot-offset); if (off > 0) goto have3; if (offset == togot) goto reread2; reread: ret = bgpq_selread(b, recvbuffer+offset, togot-offset); if (ret < 0) { if (errno == EAGAIN) goto reread; sx_report(SX_FATAL,"Error reading IRRd: %s (dequeue, result)\n", strerror(errno)); } else if (ret == 0) { sx_report(SX_FATAL,"EOF from IRRd (dequeue, result)\n"); }; SX_DEBUG(debug_expander>5, "Read1: got '%.*s'\n", ret, recvbuffer+offset); offset+=ret; if(offset < togot) { SX_DEBUG(debug_expander>5, "expected %lu, got %lu expanding %s", togot, strlen(recvbuffer), req->request); goto reread; }; reread2: ret = bgpq_selread(b, response+off, sizeof(response) - off); if (ret < 0) { if (errno == EAGAIN) goto reread2; sx_report(SX_FATAL,"Error reading IRRd: %s (dequeue,final)\n", strerror(errno)); } else if (ret == 0) { sx_report(SX_FATAL,"EOF from IRRd (dequeue,final)\n"); }; SX_DEBUG(debug_expander>5, "Read2: got '%.*s'\n", ret, response+off); off+=ret; have3: if (!(cres = strchr(response, '\n'))) goto reread2; SX_DEBUG(debug_expander>=3,"Got %s (%lu bytes of %lu) in response " "to %sfinal code: %.*s",recvbuffer,strlen(recvbuffer),togot, req->request,off,response); for(c=recvbuffer; ccallback(c, b, req); c+=spn+1; }; assert(c == recvbuffer+togot); memset(recvbuffer,0,togot+2); free(recvbuffer); } else if(response[0]=='C') { /* No data */ SX_DEBUG(debug_expander,"No data expanding %s\n", req->request); if (b->validate_asns) bgpq_expander_invalidate_asn(b, req->request); } else if(response[0]=='D') { /* .... */ SX_DEBUG(debug_expander,"Key not found expanding %s\n", req->request); if (b->validate_asns) bgpq_expander_invalidate_asn(b, req->request); } else if(response[0]=='E') { sx_report(SX_ERROR, "Multiple keys expanding %s: %s\n", req->request, response); } else if(response[0]=='F') { sx_report(SX_ERROR, "Error expanding %s: %s\n", req->request, response); } else { sx_report(SX_ERROR,"Wrong reply: %s to %s\n", response, req->request); exit(1); }; memmove(response, cres+1, 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); STAILQ_REMOVE_HEAD(&b->rq, next); b->piped--; bgpq_request_free(req); }; return 0; }; int bgpq_expand_irrd(struct bgpq_expander* b, int (*callback)(char*, struct bgpq_expander*, struct bgpq_request* ), void* udata, char* fmt, ...) { char request[128], response[128]; va_list ap; int ret, off = 0; struct bgpq_request *req; va_start(ap,fmt); vsnprintf(request,sizeof(request),fmt,ap); va_end(ap); req = bgpq_request_alloc(request, callback, udata); SX_DEBUG(debug_expander,"expander: sending '%s'\n", request); ret=write(b->fd, request, strlen(request)); if(ret!=strlen(request)) { sx_report(SX_FATAL,"Partial write to IRRd, only %i bytes written: %s\n", ret, strerror(errno)); exit(1); }; memset(response,0,sizeof(response)); repeat: ret = bgpq_selread(b, response+off, sizeof(response)-off); if (ret < 0) { sx_report(SX_ERROR, "Error reading IRRd: %s\n", strerror(errno)); exit(1); } else if (ret == 0) { sx_report(SX_FATAL, "EOF reading IRRd\n"); exit(1); }; off += ret; if (strchr(response, '\n') == NULL) goto repeat; SX_DEBUG(debug_expander>2,"expander: initially got %lu bytes, '%s'\n", (unsigned long)strlen(response),response); if(response[0]=='A') { char* eon, *c; long togot=strtoul(response+1,&eon,10); char *recvbuffer = malloc(togot+2); int offset = 0; if (!recvbuffer) { sx_report(SX_FATAL, "Error allocating %lu bytes: %s\n", togot+2, strerror(errno)); }; if(eon && *eon!='\n') { sx_report(SX_ERROR,"A-code finised with wrong char '%c' (%s)\n", *eon,response); exit(1); }; if (off - ((eon+1)-response) > togot) { memcpy(recvbuffer, eon+1, togot); offset = togot; memmove(response, eon+1+togot, off - ((eon+1)-response) - togot); off -= togot + ((eon+1)-response); memset(response+off, 0, sizeof(response)-off); } else { memcpy(recvbuffer, eon+1, off - ((eon+1)-response)); offset = off - ((eon+1) - response); memset(response, 0, sizeof(response)); off = 0; }; if (off > 0) goto have3; if (offset == togot) goto reread2; reread: ret = bgpq_selread(b, recvbuffer+offset, togot-offset); if (ret == 0) { sx_report(SX_FATAL,"EOF from IRRd (expand,result)\n"); } else if (ret < 0) { sx_report(SX_FATAL,"Error reading IRRd: %s (expand,result)\n", strerror(errno)); }; offset += ret; if (offset < togot) goto reread; reread2: ret = bgpq_selread(b, response+off, sizeof(response)-off); if (ret < 0) { sx_report(SX_FATAL, "error reading IRRd: %s\n", strerror(errno)); exit(1); } else if (ret == 0) { sx_report(SX_FATAL, "eof reading IRRd\n"); exit(1); }; off += ret; have3: if (!strchr(response, '\n')) goto reread2; SX_DEBUG(debug_expander>2,"expander: final reply of %lu bytes, " "%.*sreturn code %.*s", (unsigned long)strlen(recvbuffer), offset, recvbuffer, off, response); for(c=recvbuffer; cvalidate_asns) bgpq_expander_invalidate_asn(b, request); } else if(response[0]=='D') { /* ... */ if (b->validate_asns) bgpq_expander_invalidate_asn(b, request); } else if(response[0]=='E') { /* XXXXXX */ } else if(response[0]=='F') { /* XXXXXX */ } else { sx_report(SX_ERROR,"Wrong reply: %s\n", response); exit(0); }; bgpq_request_free(req); return 0; }; int bgpq_expand(struct bgpq_expander* b) { int fd=-1, err, ret; struct sx_slentry* mc; struct addrinfo hints, *res=NULL, *rp; memset(&hints,0,sizeof(struct addrinfo)); hints.ai_socktype=SOCK_STREAM; err=getaddrinfo(b->server,b->port,&hints,&res); if(err) { sx_report(SX_ERROR,"Unable to resolve %s: %s\n", b->server, gai_strerror(err)); exit(1); }; for(rp=res; rp; rp=rp->ai_next) { fd=socket(rp->ai_family,rp->ai_socktype,0); if(fd==-1) { if(errno==EPROTONOSUPPORT || errno==EAFNOSUPPORT) continue; sx_report(SX_ERROR,"Unable to create socket: %s\n", strerror(errno)); exit(1); }; err=connect(fd,rp->ai_addr,rp->ai_addrlen); if(err) { shutdown(fd,SHUT_RDWR); close(fd); fd=-1; continue; }; err=sx_maxsockbuf(fd,SO_SNDBUF); if(err>0) { SX_DEBUG(debug_expander, "Acquired sendbuf of %i bytes\n", err); } else { shutdown(fd, SHUT_RDWR); close(fd); fd=-1; continue; }; break; }; freeaddrinfo(res); if(fd == -1) { /* all our attempts to connect failed */ sx_report(SX_ERROR,"All attempts to connect %s failed, last" " error: %s\n", b->server, strerror(errno)); exit(1); }; b->fd = fd; if((ret=write(fd, "!!\n", 3))!=3) { sx_report(SX_ERROR,"Partial write to IRRd: %i bytes, %s\n", ret, strerror(errno)); exit(1); }; if(b->sources && b->sources[0]!=0) { int slen = strlen(b->sources)+4; if (slen < 128) slen = 128; char sources[slen]; snprintf(sources,sizeof(sources),"!s%s\n", b->sources); SX_DEBUG(debug_expander,"Requesting sources %s", sources); write(fd, sources, strlen(sources)); memset(sources, 0, slen); read(fd, sources, slen); SX_DEBUG(debug_expander,"Got answer %s", sources); if(sources[0]!='C') { sx_report(SX_ERROR, "Invalid source(s) '%s': %s\n", b->sources, sources); exit(1); }; }; if(b->identify) { char ident[128]; snprintf(ident,sizeof(ident),"!n" PACKAGE_STRING "\n"); write(fd, ident, strlen(ident)); read(fd, ident, sizeof(ident)); }; if (pipelining) fcntl(fd, F_SETFL, O_NONBLOCK|(fcntl(fd, F_GETFL))); STAILQ_FOREACH(mc, &b->macroses, next) { if (!b->maxdepth && RB_EMPTY(&b->stoplist)) { bgpq_expand_irrd(b, bgpq_expanded_macro, b, "!i%s,1\n", mc->text); } else { bgpq_expander_add_already(b,mc->text); if (pipelining) { bgpq_pipeline(b, bgpq_expanded_macro_limit, NULL, "!i%s\n", mc->text); } else { bgpq_expand_irrd(b, bgpq_expanded_macro_limit, NULL, "!i%s\n", mc->text); }; }; }; if(pipelining) { if(!STAILQ_EMPTY(&b->wq)) bgpq_write(b); if (!STAILQ_EMPTY(&b->rq)) bgpq_read(b); }; if(b->generation>=T_PREFIXLIST || b->validate_asns) { uint32_t i, j, k; STAILQ_FOREACH(mc, &b->rsets, next) { if(b->family==AF_INET) { bgpq_expand_irrd(b, bgpq_expanded_prefix, NULL, "!i%s,1\n", mc->text); } else { bgpq_expand_irrd(b, bgpq_expanded_v6prefix, NULL, "!i%s,1\n", mc->text); }; }; for(k=0;kasn32s)/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); }; }; }; }; }; }; if(pipelining) { if(!STAILQ_EMPTY(&b->wq)) bgpq_write(b); if (!STAILQ_EMPTY(&b->rq)) bgpq_read(b); }; }; write(fd, "!q\n",3); shutdown(fd, SHUT_RDWR); close(fd); return 1; }; bgpq3-0.1.35/config.h.in000066400000000000000000000037151340020421000146270ustar00rootroot00000000000000/* config.h.in. Generated from configure.in by autoheader. */ /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `nsl' library (-lnsl). */ #undef HAVE_LIBNSL /* Define to 1 if you have the `socket' library (-lsocket). */ #undef HAVE_LIBSOCKET /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* sys/queue.h have STAILQ_ */ #undef HAVE_STAILQ_IN_SYS_QUEUE /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strlcpy' function. */ #undef HAVE_STRLCPY /* Define to 1 if you have the header file. */ #undef HAVE_SYS_CDEFS_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_QUEUE_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SELECT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TREE_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS bgpq3-0.1.35/configure000077500000000000000000004271151340020421000145170ustar00rootroot00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for bgpq3 0.1.35. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and snar@snar.spb.ru $0: about your system, including any error possibly output $0: before this message. Then install a modern shell, or $0: manually run the script under such a shell if you do $0: have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='bgpq3' PACKAGE_TARNAME='bgpq3' PACKAGE_VERSION='0.1.35' PACKAGE_STRING='bgpq3 0.1.35' PACKAGE_BUGREPORT='snar@snar.spb.ru' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS LIBOBJS MARKDOWN EGREP GREP CPP INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures bgpq3 0.1.35 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/bgpq3] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of bgpq3 0.1.35:";; esac cat <<\_ACEOF Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF bgpq3 configure 0.1.35 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## ------------------------------- ## ## Report this to snar@snar.spb.ru ## ## ------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by bgpq3 $as_me 0.1.35, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers config.h" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sys/cdefs.h sys/queue.h sys/tree.h sys/select.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for STAILQ_ interface in queue.h" >&5 $as_echo_n "checking for STAILQ_ interface in queue.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if HAVE_SYS_QUEUE_H #include #else #include "sys_queue.h" #endif struct blah { STAILQ_ENTRY(blah) next; }; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_STAILQ_IN_SYS_QUEUE 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext for ac_prog in markdown_py markdown2 markdown do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MARKDOWN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MARKDOWN"; then ac_cv_prog_MARKDOWN="$MARKDOWN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MARKDOWN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MARKDOWN=$ac_cv_prog_MARKDOWN if test -n "$MARKDOWN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MARKDOWN" >&5 $as_echo "$MARKDOWN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$MARKDOWN" && break done test -n "$MARKDOWN" || MARKDOWN="echo" for ac_func in strlcpy do : ac_fn_c_check_func "$LINENO" "strlcpy" "ac_cv_func_strlcpy" if test "x$ac_cv_func_strlcpy" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRLCPY 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5 $as_echo_n "checking for socket in -lsocket... " >&6; } if ${ac_cv_lib_socket_socket+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char socket (); int main () { return socket (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_socket_socket=yes else ac_cv_lib_socket_socket=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socket" >&5 $as_echo "$ac_cv_lib_socket_socket" >&6; } if test "x$ac_cv_lib_socket_socket" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBSOCKET 1 _ACEOF LIBS="-lsocket $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getaddrinfo in -lnsl" >&5 $as_echo_n "checking for getaddrinfo in -lnsl... " >&6; } if ${ac_cv_lib_nsl_getaddrinfo+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnsl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char getaddrinfo (); int main () { return getaddrinfo (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_nsl_getaddrinfo=yes else ac_cv_lib_nsl_getaddrinfo=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_getaddrinfo" >&5 $as_echo "$ac_cv_lib_nsl_getaddrinfo" >&6; } if test "x$ac_cv_lib_nsl_getaddrinfo" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBNSL 1 _ACEOF LIBS="-lnsl $LIBS" fi ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by bgpq3 $as_me 0.1.35, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ bgpq3 config.status 0.1.35 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi bgpq3-0.1.35/configure.in000066400000000000000000000012411340020421000151050ustar00rootroot00000000000000AC_INIT(bgpq3,0.1.35,snar@snar.spb.ru) AC_CONFIG_HEADER(config.h) AC_PROG_CC AC_PROG_INSTALL AC_CHECK_HEADERS([sys/cdefs.h sys/queue.h sys/tree.h sys/select.h]) AC_MSG_CHECKING([for STAILQ_ interface in queue.h]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ #if HAVE_SYS_QUEUE_H #include #else #include "sys_queue.h" #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_CHECK_FUNCS(strlcpy) AC_CHECK_LIB(socket,socket) AC_CHECK_LIB(nsl,getaddrinfo) AC_OUTPUT(Makefile) bgpq3-0.1.35/install-sh000077500000000000000000000127361340020421000146130ustar00rootroot00000000000000#!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: chmodcmd="" else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 bgpq3-0.1.35/readme.header000066400000000000000000000011661340020421000152110ustar00rootroot00000000000000 bgpq3-0.1.35/strlcpy.c000066400000000000000000000044561340020421000144530ustar00rootroot00000000000000/* $OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $ */ /* * Copyright (c) 1998 Todd C. Miller * 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 #include /* * 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 bgpq3-0.1.35/sx_maxsockbuf.c000066400000000000000000000036341340020421000156240ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #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>=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; }; bgpq3-0.1.35/sx_maxsockbuf.h000066400000000000000000000002471340020421000156260ustar00rootroot00000000000000#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 bgpq3-0.1.35/sx_prefix.c000066400000000000000000000726551340020421000147700ustar00rootroot00000000000000#if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include "sx_prefix.h" #include "sx_report.h" int debug_aggregation=0; extern int debug_expander; struct sx_prefix* sx_prefix_alloc(struct sx_prefix* p) { struct sx_prefix* sp=malloc(sizeof(struct sx_prefix)); if(!sp) return NULL; if(p) { *sp=*p; } else { memset(sp,0,sizeof(struct sx_prefix)); }; return sp; }; void sx_prefix_destroy(struct sx_prefix* p) { if(p) free(p); }; void sx_prefix_adjust_masklen(struct sx_prefix* p) { int nbytes=(p->family==AF_INET?4:16); 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; }; for(i=1;i<=8-p->masklen%8;i++) { p->addr.addrs[p->masklen/8]&=(0xff<addr.addrs, 0, sizeof(q->addr.addrs)); q->family=p->family; q->masklen=p->masklen; for(i=0;imasklen/8;i++) q->addr.addrs[i]=0xff; for(i=1;i<=p->masklen%8;i++) q->addr.addrs[p->masklen/8]|=(1<<(8-i)); }; void sx_prefix_imask(struct sx_prefix* p, struct sx_prefix* q) { int i; memset(q->addr.addrs, 0xff, sizeof(q->addr.addrs)); q->family=p->family; q->masklen=p->masklen; for(i=0;imasklen/8;i++) q->addr.addrs[i]=0; for(i=1;i<=p->masklen%8;i++) q->addr.addrs[p->masklen/8]&=~(1<<(8-i)); }; int sx_prefix_parse(struct sx_prefix* p, int af, char* text) { char* c=NULL; int masklen, ret; char mtext[INET6_ADDRSTRLEN+5]; strlcpy(mtext, text, sizeof(mtext)); c=strchr(mtext,'/'); if(c) { char* eod; *c=0; masklen=strtol(c+1,&eod,10); if(eod && eod[0] && !isspace(eod[0])) { *c='/'; sx_report(SX_ERROR,"Invalid masklen in prefix %s\n", text); goto fixups; }; } else { masklen=-1; }; if(!af) { if(strchr(mtext,':')) af=AF_INET6; else af=AF_INET; }; ret = inet_pton(af, mtext, &p->addr); if(ret != 1) { int aparts[4]; /* contrary to documentation (man inet_ntop on FreeBSD), addresses with leading zeros are not parsed correctly. Try to workaround this issue manually */ if (af==AF_INET && sscanf(mtext, "%i.%i.%i.%i", aparts, aparts+1, aparts+2, aparts+3) == 4 && aparts[0]>=0 && aparts[0]<256 && aparts[1]>=0 && aparts[1]<256 && aparts[2]>=0 && aparts[2]<256 && aparts[3]>=0 && aparts[3]<256) { p->addr.addr.s_addr = htonl((aparts[0]<<24) + (aparts[1]<<16) + (aparts[2]<<8) + aparts[3]); } else { if(c) *c='/'; sx_report(SX_ERROR,"Unable to parse prefix '%s', af=%i (%s), " "ret=%i\n", mtext, af, af==AF_INET ? "inet" : "inet6", ret); goto fixups; }; }; if(af==AF_INET) { if(masklen==-1) p->masklen=32; else { if(masklen<0 || masklen>32) { p->masklen=32; } else { p->masklen=masklen; }; }; } else if(af==AF_INET6) { if(masklen==-1) p->masklen=128; else { if(masklen<0 || masklen>128) { p->masklen=128; } else { p->masklen=masklen; }; }; } else { sx_report(SX_ERROR,"Invalid address family %i\n", af); goto fixups; }; p->family=af; sx_prefix_adjust_masklen(p); if(c) *c='/'; return 1; fixups: return 0; }; int sx_prefix_isbitset(struct sx_prefix* p, int n) { unsigned char s; /* bits outside the prefix considered unset */ if(p->family==AF_INET && (n<0 || n>32)) return 0; else if(p->family==AF_INET6 && (n<0 || n>128)) return 0; s=p->addr.addrs[(n-1)/8]; return (s&(0x80>>((n-1)%8)))?1:0; }; void sx_prefix_setbit(struct sx_prefix* p, int n) { unsigned char* s; if (p->family == AF_INET && (n<0 || n>32)) return; else if (p->family == AF_INET6 && (n<0 || n>128)) return; s=p->addr.addrs+(n-1)/8; (*s)|=0x80>>((n-1)%8); }; int sx_radix_tree_insert_specifics(struct sx_radix_tree* t, struct sx_prefix p, unsigned min, unsigned max) { if (p.masklen >= min) sx_radix_tree_insert(t, &p); if (p.masklen+1 > max) return 1; 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) { char* d=strchr(text, '^'); struct sx_prefix p; unsigned long min, max; if (!d || !d[1]) return 0; *d = 0; if (!sx_prefix_parse(&p, 0, text)) { sx_report(SX_ERROR, "Unable to parse prefix %s^%s\n", text, d+1); return 0; }; *d = '^'; if (af && p.family != af) { sx_report(SX_ERROR, "Ignoring prefix %s, wrong af %i\n", text, p.family); return 0; }; if (maxlen && p.masklen > maxlen) { SX_DEBUG(debug_expander, "Ignoring prefix %s, masklen %i > max " "masklen %u\n", text, p.masklen, maxlen); return 0; }; if (d[1] == '-') { min=p.masklen+1; max=maxlen; } else if (d[1] == '+') { min=p.masklen; max=maxlen; } else if (isdigit(d[1])) { 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) { sx_report(SX_ERROR, "Unable to parse prefix-range %s\n", text); return 0; }; } else { sx_report(SX_ERROR, "Invalid prefix-range %s\n", text); return 0; }; if (min < p.masklen) { sx_report(SX_ERROR, "Invalid prefix-range %s: min %lu < masklen %u\n", text, min, p.masklen); return 0; }; if (af == AF_INET && max > 32) { sx_report(SX_ERROR, "Invalid prefix-range %s: max %lu > 32\n", text, max); return 0; } else if (af == AF_INET6 && max > 128) { sx_report(SX_ERROR, "Invalid ipv6 prefix-range %s: max %lu > 128\n", text, max); return 0; }; if (max > maxlen) max = maxlen; SX_DEBUG(debug_expander, "parsed prefix-range %s as %lu-%lu (maxlen: %u)\n", text, min, max, maxlen); sx_radix_tree_insert_specifics(tree, p, min, max); return 1; }; struct sx_prefix* sx_prefix_new(int af, char* text) { struct sx_prefix* p=NULL; if(!text) return NULL; p=sx_prefix_alloc(NULL); if(!p) return NULL; if(!sx_prefix_parse(p,af,text)) { sx_prefix_destroy(p); return NULL; }; return p; }; int sx_prefix_fprint(FILE* f, struct sx_prefix* p) { char buffer[128]; if(!p) { fprintf(f?f:stdout,"(null)"); return 0; }; inet_ntop(p->family,&p->addr,buffer,sizeof(buffer)); return fprintf(f?f:stdout,"%s/%i",buffer,p->masklen); }; int sx_prefix_snprintf_sep(struct sx_prefix* p, char* rbuffer, int srb, char* sep) { char buffer[128]; if(!sep) sep="/"; if(!p) { snprintf(rbuffer,srb,"(null)"); return 0; }; inet_ntop(p->family,&p->addr,buffer,sizeof(buffer)); return snprintf(rbuffer,srb,"%s%s%i",buffer,sep,p->masklen); }; int sx_prefix_snprintf(struct sx_prefix* p, char* rbuffer, int srb) { return sx_prefix_snprintf_sep(p, rbuffer, srb, "/"); }; int sx_prefix_snprintf_fmt(struct sx_prefix* p, char* buffer, int size, const char* name, const char* format) { unsigned off=0; const char* c=format; struct sx_prefix q; while(*c) { if(*c=='%') { switch(*(c+1)) { case 'r': case 'n': inet_ntop(p->family,&p->addr,buffer+off,size-off); off=strlen(buffer); break; case 'l': off+=snprintf(buffer+off,size-off,"%i",p->masklen); break; case '%': buffer[off++]='%'; break; case 'N': off+=snprintf(buffer+off,size-off,"%s",name); break; case 'm': sx_prefix_mask(p, &q); inet_ntop(p->family,&q.addr,buffer+off,size-off); off=strlen(buffer); break; case 'i': sx_prefix_imask(p, &q); inet_ntop(p->family,&q.addr,buffer+off,size-off); off=strlen(buffer); break; default : sx_report(SX_ERROR, "Unknown format char '%c'\n", *(c+1)); return 0; }; c+=2; } else if (*c=='\\') { switch(*(c+1)) { case 'n': buffer[off++]='\n'; break; case 't': buffer[off++]='\t'; break; case '\\': buffer[off++]='\\'; break; default: buffer[off++]=*(c+1); break; }; c+=2; } else { buffer[off++]=*c; c++; }; }; return strlen(buffer); }; int sx_prefix_jsnprintf(struct sx_prefix* p, char* rbuffer, int srb) { char buffer[128]; if(!p) { snprintf(rbuffer,srb,"(null)"); return 0; }; inet_ntop(p->family,&p->addr,buffer,sizeof(buffer)); return snprintf(rbuffer,srb,"%s\\/%i",buffer,p->masklen); }; struct sx_radix_tree* sx_radix_tree_new(int af) { struct sx_radix_tree* rt=malloc(sizeof(struct sx_radix_tree)); if(!rt) { return NULL; }; memset(rt,0,sizeof(struct sx_radix_tree)); rt->family=af; return rt; }; int 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* rn=malloc(sizeof(struct sx_radix_node)); if(!rn) return NULL; memset(rn,0,sizeof(struct sx_radix_node)); if(prefix) { rn->prefix=*prefix; /* structure copy */ }; return rn; }; int sx_prefix_eqbits(struct sx_prefix* a, struct sx_prefix* b) { int i; int nbytes=(a->family==AF_INET?4:16); for(i=0;iaddr.addrs[i]==b->addr.addrs[i]) continue; else { int j; for(j=0;j<8 && i*8+j<=a->masklen && i*8+j<=b->masklen;j++) { if((a->addr.addrs[i]&(0x80>>j))!=(b->addr.addrs[i]&(0x80>>j))) return i*8+j; }; }; }; if(a->masklenmasklen) return a->masklen; return b->masklen; }; struct sx_prefix* sx_prefix_overlay(struct sx_prefix* p, int n) { struct sx_prefix* sp=sx_prefix_alloc(p); sp->masklen=n; sx_prefix_adjust_masklen(sp); return sp; }; void sx_radix_tree_unlink(struct sx_radix_tree* tree, struct sx_radix_node* node) { next: if(node->r && node->l) { node->isGlue=1; } else if(node->r) { if(node->parent) { if(node->parent->r==node) { node->parent->r=node->r; node->r->parent=node->parent; } else if(node->parent->l==node) { node->parent->l=node->r; node->r->parent=node->parent; } else { sx_report(SX_ERROR,"Unlinking node which is not descendant " "of its parent\n"); }; } else if(tree->head==node) { /* only one case, really */ tree->head=node->r; node->r->parent=NULL; } else { sx_report(SX_ERROR,"Unlinking node with no parent and not root\n"); }; return; } else if(node->l) { if(node->parent) { if(node->parent->r==node) { node->parent->r=node->l; node->l->parent=node->parent; } 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) { tree->head=node->l; node->l->parent=NULL; } else { sx_report(SX_ERROR,"Unlinking node with no parent and not root\n"); }; return; } else { /* the only case - node does not have descendants */ if(node->parent) { if(node->parent->l==node) node->parent->l=NULL; else if(node->parent->r==node) node->parent->r=NULL; else { sx_report(SX_ERROR,"Unlinking node which is not descendant " "of its parent\n"); }; if(node->parent->isGlue) { node=node->parent; goto next; }; } else if(tree->head==node) { tree->head=NULL; } else { sx_report(SX_ERROR,"Unlinking node with no parent and not root\n"); }; return; }; }; 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; if(!tree || !prefix) return NULL; if(tree->family!=prefix->family) return NULL; if(!tree->head) return NULL; chead=tree->head; next: eb=sx_prefix_eqbits(&chead->prefix,prefix); if(eb==chead->prefix.masklen && eb==prefix->masklen) { /* they are equal */ if(chead->isGlue) return candidate; return chead; } else if(ebprefix.masklen) { return candidate; } else if(ebmasklen) { /* it equals chead->masklen */ if(sx_prefix_isbitset(prefix,eb+1)) { if(chead->r) { if(!chead->isGlue) { candidate=chead; }; chead=chead->r; goto next; } else { if(chead->isGlue) return candidate; return chead; }; } else { if(chead->l) { if(!chead->isGlue) { candidate=chead; }; chead=chead->l; goto next; } else { if(chead->isGlue) return candidate; return chead; }; }; } else { 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, pbuffer, cbuffer); abort(); }; }; 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; if(!tree || !prefix) return NULL; if(tree->family!=prefix->family) { return NULL; }; if(!tree->head) { tree->head=sx_radix_node_new(prefix); return tree->head; }; candidate=&tree->head; chead=tree->head; next: eb=sx_prefix_eqbits(prefix,&chead->prefix); if(ebmasklen && ebprefix.masklen) { struct sx_prefix neoRoot=*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); if(!rn) { sx_report(SX_ERROR,"Unable to create node: %s\n", strerror(errno)); return NULL; }; if(sx_prefix_isbitset(prefix,eb+1)) { rn->l=chead; rn->r=ret; } else { rn->l=ret; rn->r=chead; }; rn->parent=chead->parent; chead->parent=rn; ret->parent=rn; rn->isGlue=1; *candidate=rn; return ret; } else if(eb==prefix->masklen && ebprefix.masklen) { struct sx_radix_node* ret=sx_radix_node_new(prefix); if(sx_prefix_isbitset(&chead->prefix,eb+1)) { ret->r=chead; } else { ret->l=chead; }; ret->parent=chead->parent; chead->parent=ret; *candidate=ret; return ret; } else if(eb==chead->prefix.masklen && ebmasklen) { if(sx_prefix_isbitset(prefix,eb+1)) { if(chead->r) { candidate=&chead->r; chead=chead->r; goto next; } else { chead->r=sx_radix_node_new(prefix); chead->r->parent=chead; return chead->r; }; } else { if(chead->l) { candidate=&chead->l; chead=chead->l; goto next; } else { chead->l=sx_radix_node_new(prefix); chead->l->parent=chead; return chead->l; }; }; } else if(eb==chead->prefix.masklen && eb==prefix->masklen) { /* equal routes... */ if(chead->isGlue) { chead->isGlue=0; }; return chead; } else { 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, pbuffer, cbuffer); abort(); }; }; void sx_radix_node_fprintf(struct sx_radix_node* node, void* udata) { FILE* out=(udata?udata:stdout); char buffer[128]; if(!node) { fprintf(out,"(null)\n"); } else { sx_prefix_snprintf(&node->prefix,buffer,sizeof(buffer)); fprintf(out,"%s %s\n", buffer, node->isGlue?"(glue)":""); }; }; int sx_radix_node_foreach(struct sx_radix_node* node, void (*func)(struct sx_radix_node*, void*), void* udata) { func(node,udata); if(node->l) sx_radix_node_foreach(node->l,func,udata); if(node->r) sx_radix_node_foreach(node->r,func,udata); return 0; }; int 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); return 0; }; int sx_radix_node_aggregate(struct sx_radix_node* node) { if(node->l) sx_radix_node_aggregate(node->l); if(node->r) sx_radix_node_aggregate(node->r); if(debug_aggregation) { printf("Aggregating on node: "); sx_prefix_fprint(stdout,&node->prefix); printf(" %s%s%u,%u\n", node->isGlue?"Glue ":"", node->isAggregate?"Aggregate ":"",node->aggregateLow, node->aggregateHi); if(node->r) { printf("R-Tree: "); sx_prefix_fprint(stdout,&node->r->prefix); printf(" %s%s%u,%u\n", (node->r->isGlue)?"Glue ":"", (node->r->isAggregate)?"Aggregate ":"", node->r->aggregateLow,node->r->aggregateHi); if(node->r->son) { printf("R-Son: "); sx_prefix_fprint(stdout,&node->r->son->prefix); printf(" %s%s%u,%u\n",node->r->son->isGlue?"Glue ":"", node->r->son->isAggregate?"Aggregate ":"", node->r->son->aggregateLow,node->r->son->aggregateHi); }; }; if(node->l) { printf("L-Tree: "); sx_prefix_fprint(stdout,&node->l->prefix); printf(" %s%s%u,%u\n",node->l->isGlue?"Glue ":"", node->l->isAggregate?"Aggregate ":"", node->l->aggregateLow,node->l->aggregateHi); if(node->l->son) { printf("L-Son: "); sx_prefix_fprint(stdout,&node->l->son->prefix); printf(" %s%s%u,%u\n",node->l->son->isGlue?"Glue ":"", node->l->son->isAggregate?"Aggregate ":"", node->l->son->aggregateLow,node->l->son->aggregateHi); }; }; }; if(node->r && node->l) { 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) { node->isAggregate=1; node->r->isGlue=1; node->l->isGlue=1; node->aggregateHi=node->r->prefix.masklen; if(node->isGlue) { node->isGlue=0; node->aggregateLow=node->r->prefix.masklen; } else { node->aggregateLow=node->prefix.masklen; }; }; if(node->r->son && node->l->son && node->r->son->isAggregate && node->l->son->isAggregate && node->r->son->aggregateHi==node->l->son->aggregateHi && node->r->son->aggregateLow==node->l->son->aggregateLow && node->r->prefix.masklen==node->prefix.masklen+1 && node->l->prefix.masklen==node->prefix.masklen+1) { node->son=sx_radix_node_new(&node->prefix); node->son->isGlue=0; node->son->isAggregate=1; node->son->aggregateHi=node->r->son->aggregateHi; node->son->aggregateLow=node->r->son->aggregateLow; node->r->son->isGlue=1; node->l->son->isGlue=1; }; } else if(node->r->isAggregate && node->l->isAggregate && node->r->aggregateHi==node->l->aggregateHi && node->r->aggregateLow==node->l->aggregateLow) { if(node->r->prefix.masklen==node->prefix.masklen+1 && node->l->prefix.masklen==node->prefix.masklen+1) { if(node->isGlue) { node->r->isGlue=1; node->l->isGlue=1; node->isAggregate=1; node->isGlue=0; node->aggregateHi=node->r->aggregateHi; node->aggregateLow=node->r->aggregateLow; } else if(node->r->prefix.masklen==node->r->aggregateLow) { node->r->isGlue=1; node->l->isGlue=1; node->isAggregate=1; node->aggregateHi=node->r->aggregateHi; node->aggregateLow=node->prefix.masklen; } else { node->son=sx_radix_node_new(&node->prefix); node->son->isGlue=0; node->son->isAggregate=1; node->son->aggregateHi=node->r->aggregateHi; node->son->aggregateLow=node->r->aggregateLow; node->r->isGlue=1; node->l->isGlue=1; if(node->r->son && node->l->son && node->r->son->aggregateHi==node->l->son->aggregateHi && node->r->son->aggregateLow==node->l->son->aggregateLow) { node->son->son=sx_radix_node_new(&node->prefix); node->son->son->isGlue=0; node->son->son->isAggregate=1; node->son->son->aggregateHi=node->r->son->aggregateHi; node->son->son->aggregateLow=node->r->son->aggregateLow; node->r->son->isGlue=1; node->l->son->isGlue=1; }; }; }; } else if(node->l->son && node->r->isAggregate && node->l->son->isAggregate && node->r->aggregateHi==node->l->son->aggregateHi && node->r->aggregateLow==node->l->son->aggregateLow) { if(node->r->prefix.masklen==node->prefix.masklen+1 && node->l->prefix.masklen==node->prefix.masklen+1) { if(node->isGlue) { node->r->isGlue=1; node->l->son->isGlue=1; node->isAggregate=1; node->isGlue=0; node->aggregateHi=node->r->aggregateHi; node->aggregateLow=node->r->aggregateLow; } else { node->son=sx_radix_node_new(&node->prefix); node->son->isGlue=0; node->son->isAggregate=1; node->son->aggregateHi=node->r->aggregateHi; node->son->aggregateLow=node->r->aggregateLow; node->r->isGlue=1; node->l->son->isGlue=1; }; }; } else if(node->r->son && node->l->isAggregate && node->r->son->isAggregate && 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) { if(node->isGlue) { node->l->isGlue=1; node->r->son->isGlue=1; node->isAggregate=1; node->isGlue=0; node->aggregateHi=node->l->aggregateHi; node->aggregateLow=node->l->aggregateLow; } else { node->son=sx_radix_node_new(&node->prefix); node->son->isGlue=0; node->son->isAggregate=1; node->son->aggregateHi=node->l->aggregateHi; node->son->aggregateLow=node->l->aggregateLow; node->l->isGlue=1; node->r->son->isGlue=1; }; }; }; }; return 0; }; int sx_radix_tree_aggregate(struct sx_radix_tree* tree) { if(tree && tree->head) return sx_radix_node_aggregate(tree->head); return 0; }; static void setGlueUpTo(struct sx_radix_node* node, void* 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) { if(!node->isGlue && node->prefix.masklenisAggregate=1; node->aggregateLow=node->prefix.masklen; node->aggregateHi=refine; if(node->l) { sx_radix_node_foreach(node->l, setGlueUpTo, &refine); sx_radix_node_refine(node->l, refine); }; if(node->r) { sx_radix_node_foreach(node->r, setGlueUpTo, &refine); sx_radix_node_refine(node->r, refine); }; } else if(!node->isGlue && node->prefix.masklen==refine) { /* not setting aggregate in this case */ if(node->l) sx_radix_node_refine(node->l, refine); if(node->r) sx_radix_node_refine(node->r, refine); } else if(node->isGlue) { if(node->r) sx_radix_node_refine(node->r, refine); if(node->l) sx_radix_node_refine(node->l, refine); } else { /* node->prefix.masklen > refine */ /* do nothing, should pass specifics 'as is'. Also, do not process any embedded routes, their masklen is bigger, too... node->isGlue=1; if(node->l) sx_radix_node_foreach(node->l, setGlue, NULL); if(node->r) sx_radix_node_foreach(node->r, setGlue, NULL); */ }; return 0; }; int sx_radix_tree_refine(struct sx_radix_tree* tree, unsigned refine) { if(tree && tree->head) return sx_radix_node_refine(tree->head, refine); return 0; }; static void setGlueFrom(struct sx_radix_node* node, void* udata) { unsigned refine=*(unsigned*)udata; if(node && node->prefix.masklen <= refine) { node->isGlue=1; }; }; static int sx_radix_node_refineLow(struct sx_radix_node* node, unsigned refineLow) { if(!node->isGlue && node->prefix.masklen<=refineLow) { if(!node->isAggregate) { node->isAggregate=1; node->aggregateLow=refineLow; if(node->prefix.family == AF_INET) { node->aggregateHi=32; } else { node->aggregateHi=128; } } else { node->aggregateLow=refineLow; }; if(node->l) { sx_radix_node_foreach(node->l, setGlueFrom, &refineLow); sx_radix_node_refineLow(node->l, refineLow); }; if(node->r) { sx_radix_node_foreach(node->r, setGlueFrom, &refineLow); sx_radix_node_refineLow(node->r, refineLow); }; } else if(!node->isGlue && node->prefix.masklen==refineLow) { /* not setting aggregate in this case */ if(node->l) sx_radix_node_refineLow(node->l, refineLow); if(node->r) sx_radix_node_refineLow(node->r, refineLow); } else if(node->isGlue) { if(node->r) sx_radix_node_refineLow(node->r, refineLow); if(node->l) sx_radix_node_refineLow(node->l, refineLow); } else { /* node->prefix.masklen > refine */ /* do nothing, should pass specifics 'as is'. Also, do not process any embedded routes, their masklen is bigger, too... node->isGlue=1; if(node->l) sx_radix_node_foreach(node->l, setGlue, NULL); if(node->r) sx_radix_node_foreach(node->r, setGlue, NULL); */ }; return 0; }; int sx_radix_tree_refineLow(struct sx_radix_tree* tree, unsigned refineLow) { if(tree && tree->head) return sx_radix_node_refineLow(tree->head, refineLow); return 0; }; #if SX_PTREE_TEST int main() { struct sx_prefix* p; int n; struct sx_radix_tree* tree; struct sx_radix_node* node; p=sx_prefix_new(0,"10.11.12.13/24"); sx_prefix_fprint(stdout,p); printf("\n"); p=sx_prefix_new(0,"10.11.12.13/33"); sx_prefix_fprint(stdout,p); printf("\n"); p=sx_prefix_new(0,"10.11.12.13/-133"); sx_prefix_fprint(stdout,p); printf("\n"); p=sx_prefix_new(AF_INET,"10.11.12.14/24"); sx_prefix_fprint(stdout,p); printf("\n"); p=sx_prefix_new(AF_INET,"10.11.12.14/33"); sx_prefix_fprint(stdout,p); printf("\n"); p=sx_prefix_new(AF_INET,"10.11.12.14/-133"); sx_prefix_fprint(stdout,p); printf("\n"); p=sx_prefix_new(AF_INET6,"10.11.12.15/24"); sx_prefix_fprint(stdout,p); printf("\n"); p=sx_prefix_new(AF_INET6,"10.11.12.15/33"); sx_prefix_fprint(stdout,p); printf("\n"); p=sx_prefix_new(AF_INET6,"10.11.12.15/-133"); sx_prefix_fprint(stdout,p); printf("\n"); p=sx_prefix_new(0,"2001:1b00::/24"); sx_prefix_fprint(stdout,p); printf("\n"); p=sx_prefix_new(0,"2001:1b00::/33"); sx_prefix_fprint(stdout,p); printf("\n"); p=sx_prefix_new(0,"2001:1b00::/-133"); sx_prefix_fprint(stdout,p); printf("\n"); p=sx_prefix_new(AF_INET6,"2001:1b01::/24"); sx_prefix_fprint(stdout,p); printf("\n"); p=sx_prefix_new(AF_INET6,"2001:1b01::/33"); sx_prefix_fprint(stdout,p); printf("\n"); p=sx_prefix_new(AF_INET6,"2001:1b01::/-133"); 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); 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 SX_TEST_EBITS("2001:1b00::/32","2001:1b01::/32",31); #endif p=sx_prefix_new(0,"10.11.12.255/32"); sx_prefix_fprint(stdout,p); printf("\n31'th bit is %i\n",sx_prefix_isbitset(p,31)); printf("32'th bit is %i\n",sx_prefix_isbitset(p,32)); printf("33'th bit is %i\n",sx_prefix_isbitset(p,33)); p=sx_prefix_new(0,"10.11.12.255/31"); sx_prefix_fprint(stdout,p); printf("\n31'th bit is %i\n",sx_prefix_isbitset(p,31)); printf("32'th bit is %i\n",sx_prefix_isbitset(p,32)); printf("33'th bit is %i\n",sx_prefix_isbitset(p,33)); p=sx_prefix_new(0,"10.11.12.255/30"); sx_prefix_fprint(stdout,p); printf("\n31'th bit is %i\n",sx_prefix_isbitset(p,31)); p=sx_prefix_new(0,"10.11.12.255/29"); sx_prefix_fprint(stdout,p); printf("\n"); p=sx_prefix_new(0,"10.11.12.255/28"); sx_prefix_fprint(stdout,p); printf("\n"); p=sx_prefix_new(0,"10.11.12.255/27"); sx_prefix_fprint(stdout,p); printf("\n"); p=sx_prefix_new(0,"10.11.12.255/26"); sx_prefix_fprint(stdout,p); printf("\n"); p=sx_prefix_new(0,"10.11.12.255/25"); sx_prefix_fprint(stdout,p); printf("\n25'th bit is %i\n",sx_prefix_isbitset(p,25)); p=sx_prefix_new(0,"10.11.12.255/24"); sx_prefix_fprint(stdout,p); printf("\n25'th bit is %i\n",sx_prefix_isbitset(p,25)); tree=sx_radix_tree_new(AF_INET); sx_radix_tree_insert(tree,sx_prefix_new(0,"81.9.100.10/32")); sx_radix_tree_insert(tree,sx_prefix_new(0,"217.170.80.83/32")); sx_radix_tree_foreach(tree,sx_radix_node_fprintf,NULL); tree=sx_radix_tree_new(AF_INET); sx_radix_tree_insert(tree,sx_prefix_new(0,"81.9.100.10/32")); sx_radix_tree_insert(tree,sx_prefix_new(0,"217.170.80.83/32")); sx_radix_tree_insert(tree,sx_prefix_new(0,"217.170.80.84/32")); sx_radix_tree_insert(tree,sx_prefix_new(0,"217.170.80.85/32")); sx_radix_tree_insert(tree,sx_prefix_new(0,"217.170.80.86/32")); sx_radix_tree_insert(tree,sx_prefix_new(0,"217.170.80.87/32")); sx_radix_tree_insert(tree,sx_prefix_new(0,"217.170.80.90/32")); sx_radix_tree_insert(tree,sx_prefix_new(0,"217.170.80.90/32")); sx_radix_tree_insert(tree,sx_prefix_new(0,"127.0.0.1/32")); sx_radix_tree_insert(tree,sx_prefix_new(0,"127.0.0.1/24")); sx_radix_tree_insert(tree,sx_prefix_new(0,"127.0.0.0/24")); sx_radix_tree_insert(tree,sx_prefix_new(0,"128.0.0.0/1")); sx_radix_tree_foreach(tree,sx_radix_node_fprintf,NULL); printf("lookup 1.1.1.1: "); node=sx_radix_tree_lookup(tree,sx_prefix_new(0,"1.1.1.1")); sx_radix_node_fprintf(node,NULL); printf("lookup 217.170.80.90: "); node=sx_radix_tree_lookup(tree,sx_prefix_new(0,"217.170.80.90")); sx_radix_node_fprintf(node,NULL); sx_radix_tree_unlink(tree,node); printf("lookup 217.170.80.90 after delete: "); node=sx_radix_tree_lookup(tree,sx_prefix_new(0,"217.170.80.90")); sx_radix_node_fprintf(node,NULL); sx_radix_tree_insert(tree,sx_prefix_new(0,"217.170.80.90/32")); printf("lookup 217.170.80.90 after reinsert: "); node=sx_radix_tree_lookup(tree,sx_prefix_new(0,"217.170.80.90")); sx_radix_node_fprintf(node,NULL); printf("lookup 217.170.80.81: "); node=sx_radix_tree_lookup(tree,sx_prefix_new(0,"217.170.80.81")); sx_radix_node_fprintf(node,NULL); printf("lookup 127.0.0.1/24: "); node=sx_radix_tree_lookup(tree,sx_prefix_new(0,"127.0.0.1/24")); sx_radix_node_fprintf(node,NULL); printf("lookup 127.0.0.1/26: "); node=sx_radix_tree_lookup(tree,sx_prefix_new(0,"127.0.0.1/26")); sx_radix_node_fprintf(node,NULL); printf("lookup 127.0.0.1/23: "); node=sx_radix_tree_lookup(tree,sx_prefix_new(0,"127.0.0.1/23")); sx_radix_node_fprintf(node,NULL); tree=sx_radix_tree_new(AF_INET6); sx_radix_tree_insert(tree,sx_prefix_new(0,"2100:1b00::/32")); sx_radix_tree_insert(tree,sx_prefix_new(0,"2100:1b01::/32")); sx_radix_tree_insert(tree,sx_prefix_new(0,"2100:1b00::/33")); sx_radix_tree_insert(tree,sx_prefix_new(0,"2100:1b00::1/128")); sx_radix_tree_foreach(tree,sx_radix_node_fprintf,NULL); return 0; }; #endif bgpq3-0.1.35/sx_prefix.h000066400000000000000000000052321340020421000147600ustar00rootroot00000000000000#ifndef _SX_PREFIX_H_ #define _SX_PREFIX_H_ #include #include #include #include typedef struct sx_prefix { int family; int masklen; union { struct in_addr addr; struct in6_addr addr6; unsigned char addrs[sizeof(struct in6_addr)]; } addr; } 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; } sx_radix_node_t; typedef struct sx_radix_tree { 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_prefix* sx_prefix_alloc(struct sx_prefix* p); void sx_prefix_destroy(struct sx_prefix* 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); #ifndef HAVE_STRLCPY size_t strlcpy(char* dst, const char* src, size_t size); #endif #endif bgpq3-0.1.35/sx_report.c000066400000000000000000000033441340020421000147730ustar00rootroot00000000000000#if HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include "sx_report.h" static int reportStderr=1; static char const* sx_report_name(sx_report_t t) { switch(t) { case SX_MISFEATURE: return "MISSING FEATURE:"; case SX_FATAL: return "FATAL ERROR:"; case SX_ERROR: return "ERROR:"; case SX_NOTICE: return "Notice:"; case SX_DEBUG: return "Debug:"; }; return "...... HMMMMM.... ERROR... \n"; }; int sx_report(sx_report_t t, char* fmt, ...) { char buffer[65536]; va_list ap; va_start(ap,fmt); vsnprintf(buffer,sizeof(buffer),fmt,ap); va_end(ap); if(reportStderr) { fputs(sx_report_name(t),stderr); fputs(buffer,stderr); } else { switch(t) { case SX_FATAL: syslog(LOG_ERR,"FATAL ERROR: %s", buffer); break; case SX_MISFEATURE: case SX_ERROR: syslog(LOG_ERR,"ERROR: %s", buffer); break; case SX_NOTICE: syslog(LOG_WARNING,"Notice: %s", buffer); break; case SX_DEBUG: syslog(LOG_DEBUG,"Debug: %s", buffer); break; }; }; if(t==SX_FATAL) exit(-1); return 0; }; int sx_debug(char const* const file, char const* const func, int const line, char* fmt, ...) { char buffer[65536]; char bline[65536]; va_list ap; va_start(ap,fmt); vsnprintf(buffer,sizeof(buffer),fmt,ap); va_end(ap); snprintf(bline,sizeof(bline),"DEBUG: %s:%i %s ", file, line, func); if(reportStderr) { fputs(bline,stderr); fputs(buffer,stderr); } else { syslog(LOG_DEBUG,"%s %s", bline, buffer); }; return 0; }; void sx_openlog(char* progname) { openlog(progname?progname:"",LOG_PID,LOG_DAEMON); reportStderr=0; }; bgpq3-0.1.35/sx_report.h000066400000000000000000000010161340020421000147720ustar00rootroot00000000000000#ifndef SX_REPORT_H_ #define SX_REPORT_H_ typedef enum { SX_DEBUG = 0, SX_NOTICE, SX_ERROR, SX_MISFEATURE, SX_FATAL } sx_report_t; /* opens syslog and disables logging to stderr */ void sx_openlog(char* progname); int sx_report(sx_report_t, char* fmt, ...) __attribute__ ((format (printf, 2, 3))); int sx_debug(char const* const, char const* const, int const, char* fmt, ...) __attribute__ ((format (printf, 4, 5))); #define SX_DEBUG(a,b,c...) if(a) sx_debug(__FILE__,__FUNCTION__,__LINE__,\ b, ## c); #endif bgpq3-0.1.35/sx_slentry.c000066400000000000000000000007621340020421000151610ustar00rootroot00000000000000 #include #include #include #include "sx_slentry.h" struct sx_slentry* sx_slentry_new(char* t) { struct sx_slentry* e=malloc(sizeof(struct sx_slentry)); if(!e) return NULL; memset(e,0,sizeof(struct sx_slentry)); if(t) e->text=strdup(t); return e; }; struct sx_tentry* sx_tentry_new(char* t) { 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; }; bgpq3-0.1.35/sx_slentry.h000066400000000000000000000007231340020421000151630ustar00rootroot00000000000000#ifndef SX_SLENTRY_H_ #define SX_SLENTRY_H_ #if HAVE_SYS_QUEUE_H && HAVE_STAILQ_IN_SYS_QUEUE #include #else #include "sys_queue.h" #endif #if HAVE_SYS_TREE_H #include #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 bgpq3-0.1.35/sys_queue.h000066400000000000000000000565021340020421000150010ustar00rootroot00000000000000/*- * 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 #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_ */ bgpq3-0.1.35/sys_tree.h000066400000000000000000000624071340020421000146150ustar00rootroot00000000000000/* $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 $ */ /*- * Copyright 2002 Niels Provos * 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 ``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. */ #ifndef _SYS_TREE_H_ #define _SYS_TREE_H_ #if HAVE_SYS_CDEFS_H #include #endif /* * This file defines data structures for different types of trees: * splay trees and red-black trees. * * A splay tree is a self-organizing data structure. Every operation * on the tree causes a splay to happen. The splay moves the requested * node to the root of the tree and partly rebalances it. * * This has the benefit that request locality causes faster lookups as * the requested nodes move to the top of the tree. On the other hand, * every lookup causes memory writes. * * The Balance Theorem bounds the total access time for m operations * and n inserts on an initially empty tree as O((m + n)lg n). The * amortized cost for a sequence of m accesses to a splay tree is O(lg n); * * A red-black tree is a binary search tree with the node color as an * extra attribute. It fulfills a set of conditions: * - every search path from the root to a leaf consists of the * same number of black nodes, * - each red node (except for the root) has a black parent, * - each leaf node is black. * * Every operation on a red-black tree is bounded as O(lg n). * The maximum height of a red-black tree is 2lg (n+1). */ #define SPLAY_HEAD(name, type) \ struct name { \ struct type *sph_root; /* root of the tree */ \ } #define SPLAY_INITIALIZER(root) \ { NULL } #define SPLAY_INIT(root) do { \ (root)->sph_root = NULL; \ } while (/*CONSTCOND*/ 0) #define SPLAY_ENTRY(type) \ struct { \ struct type *spe_left; /* left element */ \ struct type *spe_right; /* right element */ \ } #define SPLAY_LEFT(elm, field) (elm)->field.spe_left #define SPLAY_RIGHT(elm, field) (elm)->field.spe_right #define SPLAY_ROOT(head) (head)->sph_root #define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) /* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ #define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ (head)->sph_root = tmp; \ } while (/*CONSTCOND*/ 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) #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) #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) #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) /* Generates prototypes and inline functions */ #define SPLAY_PROTOTYPE(name, type, field, cmp) \ void name##_SPLAY(struct name *, struct type *); \ void name##_SPLAY_MINMAX(struct name *, int); \ 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 * \ name##_SPLAY_FIND(struct name *head, struct type *elm) \ { \ if (SPLAY_EMPTY(head)) \ return(NULL); \ name##_SPLAY(head, elm); \ if ((cmp)(elm, (head)->sph_root) == 0) \ return (head->sph_root); \ return (NULL); \ } \ \ static __inline struct type * \ name##_SPLAY_NEXT(struct name *head, struct type *elm) \ { \ name##_SPLAY(head, elm); \ if (SPLAY_RIGHT(elm, field) != NULL) { \ elm = SPLAY_RIGHT(elm, field); \ while (SPLAY_LEFT(elm, field) != NULL) { \ elm = SPLAY_LEFT(elm, field); \ } \ } else \ elm = NULL; \ return (elm); \ } \ \ static __inline struct type * \ name##_SPLAY_MIN_MAX(struct name *head, int val) \ { \ name##_SPLAY_MINMAX(head, val); \ return (SPLAY_ROOT(head)); \ } /* Main splay operation. * Moves node close to the key of elm to top */ #define SPLAY_GENERATE(name, type, field, cmp) \ struct type * \ name##_SPLAY_INSERT(struct name *head, struct type *elm) \ { \ if (SPLAY_EMPTY(head)) { \ SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ } else { \ int __comp; \ name##_SPLAY(head, elm); \ __comp = (cmp)(elm, (head)->sph_root); \ if(__comp < 0) { \ SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\ SPLAY_RIGHT(elm, field) = (head)->sph_root; \ SPLAY_LEFT((head)->sph_root, field) = NULL; \ } else if (__comp > 0) { \ SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\ SPLAY_LEFT(elm, field) = (head)->sph_root; \ SPLAY_RIGHT((head)->sph_root, field) = NULL; \ } else \ return ((head)->sph_root); \ } \ (head)->sph_root = (elm); \ return (NULL); \ } \ \ struct type * \ name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ { \ struct type *__tmp; \ if (SPLAY_EMPTY(head)) \ return (NULL); \ name##_SPLAY(head, elm); \ if ((cmp)(elm, (head)->sph_root) == 0) { \ if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\ } else { \ __tmp = SPLAY_RIGHT((head)->sph_root, field); \ (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\ name##_SPLAY(head, elm); \ SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ } \ return (elm); \ } \ return (NULL); \ } \ \ void \ name##_SPLAY(struct name *head, struct type *elm) \ { \ struct type __node, *__left, *__right, *__tmp; \ int __comp; \ \ SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ __left = __right = &__node; \ \ while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \ if (__comp < 0) { \ __tmp = SPLAY_LEFT((head)->sph_root, field); \ if (__tmp == NULL) \ break; \ if ((cmp)(elm, __tmp) < 0){ \ SPLAY_ROTATE_RIGHT(head, __tmp, field); \ if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ break; \ } \ SPLAY_LINKLEFT(head, __right, field); \ } else if (__comp > 0) { \ __tmp = SPLAY_RIGHT((head)->sph_root, field); \ if (__tmp == NULL) \ break; \ if ((cmp)(elm, __tmp) > 0){ \ SPLAY_ROTATE_LEFT(head, __tmp, field); \ if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ break; \ } \ SPLAY_LINKRIGHT(head, __left, field); \ } \ } \ SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ } \ \ /* Splay with either the minimum or the maximum element \ * Used to find minimum or maximum element in tree. \ */ \ void name##_SPLAY_MINMAX(struct name *head, int __comp) \ { \ struct type __node, *__left, *__right, *__tmp; \ \ SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ __left = __right = &__node; \ \ while (1) { \ if (__comp < 0) { \ __tmp = SPLAY_LEFT((head)->sph_root, field); \ if (__tmp == NULL) \ break; \ if (__comp < 0){ \ SPLAY_ROTATE_RIGHT(head, __tmp, field); \ if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ break; \ } \ SPLAY_LINKLEFT(head, __right, field); \ } else if (__comp > 0) { \ __tmp = SPLAY_RIGHT((head)->sph_root, field); \ if (__tmp == NULL) \ break; \ if (__comp > 0) { \ SPLAY_ROTATE_LEFT(head, __tmp, field); \ if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ break; \ } \ SPLAY_LINKRIGHT(head, __left, field); \ } \ } \ SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ } #define SPLAY_NEGINF -1 #define SPLAY_INF 1 #define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y) #define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) #define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) #define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) #define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) #define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) #define SPLAY_FOREACH(x, name, head) \ for ((x) = SPLAY_MIN(name, head); \ (x) != NULL; \ (x) = SPLAY_NEXT(name, head, x)) /* Macros that define a red-black tree */ #define RB_HEAD(name, type) \ struct name { \ struct type *rbh_root; /* root of the tree */ \ } #define RB_INITIALIZER(root) \ { NULL } #define RB_INIT(root) do { \ (root)->rbh_root = NULL; \ } while (/*CONSTCOND*/ 0) #define RB_BLACK 0 #define RB_RED 1 #define RB_ENTRY(type) \ struct { \ struct type *rbe_left; /* left element */ \ struct type *rbe_right; /* right element */ \ struct type *rbe_parent; /* parent element */ \ int rbe_color; /* node color */ \ } #define RB_LEFT(elm, field) (elm)->field.rbe_left #define RB_RIGHT(elm, field) (elm)->field.rbe_right #define RB_PARENT(elm, field) (elm)->field.rbe_parent #define RB_COLOR(elm, field) (elm)->field.rbe_color #define RB_ROOT(head) (head)->rbh_root #define RB_EMPTY(head) (RB_ROOT(head) == NULL) #define RB_SET(elm, parent, field) do { \ RB_PARENT(elm, field) = parent; \ RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ RB_COLOR(elm, field) = RB_RED; \ } while (/*CONSTCOND*/ 0) #define RB_SET_BLACKRED(black, red, field) do { \ RB_COLOR(black, field) = RB_BLACK; \ RB_COLOR(red, field) = RB_RED; \ } while (/*CONSTCOND*/ 0) #ifndef RB_AUGMENT #define RB_AUGMENT(x) do {} while (0) #endif #define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ (tmp) = RB_RIGHT(elm, field); \ if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \ RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ } \ RB_AUGMENT(elm); \ if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \ if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ else \ RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ } else \ (head)->rbh_root = (tmp); \ RB_LEFT(tmp, field) = (elm); \ RB_PARENT(elm, field) = (tmp); \ RB_AUGMENT(tmp); \ if ((RB_PARENT(tmp, field))) \ RB_AUGMENT(RB_PARENT(tmp, field)); \ } while (/*CONSTCOND*/ 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) { \ RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ } \ RB_AUGMENT(elm); \ if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \ if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ else \ RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ } else \ (head)->rbh_root = (tmp); \ RB_RIGHT(tmp, field) = (elm); \ RB_PARENT(elm, field) = (tmp); \ RB_AUGMENT(tmp); \ if ((RB_PARENT(tmp, field))) \ RB_AUGMENT(RB_PARENT(tmp, field)); \ } while (/*CONSTCOND*/ 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) #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 *);\ attr struct type *name##_RB_REMOVE(struct name *, struct type *); \ attr struct type *name##_RB_INSERT(struct name *, struct type *); \ attr struct type *name##_RB_FIND(struct name *, struct type *); \ attr struct type *name##_RB_NFIND(struct name *, struct type *); \ attr struct type *name##_RB_NEXT(struct type *); \ attr struct type *name##_RB_PREV(struct type *); \ attr struct type *name##_RB_MINMAX(struct name *, int); \ \ /* Main rb operation. * Moves node close to the key of elm to top */ #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) #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 && \ RB_COLOR(parent, field) == RB_RED) { \ gparent = RB_PARENT(parent, field); \ if (parent == RB_LEFT(gparent, field)) { \ tmp = RB_RIGHT(gparent, field); \ if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ RB_COLOR(tmp, field) = RB_BLACK; \ RB_SET_BLACKRED(parent, gparent, field);\ elm = gparent; \ continue; \ } \ if (RB_RIGHT(parent, field) == elm) { \ RB_ROTATE_LEFT(head, parent, tmp, field);\ tmp = parent; \ parent = elm; \ elm = tmp; \ } \ RB_SET_BLACKRED(parent, gparent, field); \ RB_ROTATE_RIGHT(head, gparent, tmp, field); \ } else { \ tmp = RB_LEFT(gparent, field); \ if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ RB_COLOR(tmp, field) = RB_BLACK; \ RB_SET_BLACKRED(parent, gparent, field);\ elm = gparent; \ continue; \ } \ if (RB_LEFT(parent, field) == elm) { \ RB_ROTATE_RIGHT(head, parent, tmp, field);\ tmp = parent; \ parent = elm; \ elm = tmp; \ } \ RB_SET_BLACKRED(parent, gparent, field); \ RB_ROTATE_LEFT(head, gparent, tmp, field); \ } \ } \ RB_COLOR(head->rbh_root, field) = RB_BLACK; \ } \ \ attr void \ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \ { \ struct type *tmp; \ while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ elm != RB_ROOT(head)) { \ if (RB_LEFT(parent, field) == elm) { \ tmp = RB_RIGHT(parent, field); \ if (RB_COLOR(tmp, field) == RB_RED) { \ RB_SET_BLACKRED(tmp, parent, field); \ RB_ROTATE_LEFT(head, parent, tmp, field);\ tmp = RB_RIGHT(parent, field); \ } \ if ((RB_LEFT(tmp, field) == NULL || \ RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ (RB_RIGHT(tmp, field) == NULL || \ RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ RB_COLOR(tmp, field) = RB_RED; \ elm = parent; \ parent = RB_PARENT(elm, field); \ } else { \ 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) \ RB_COLOR(oleft, field) = RB_BLACK;\ RB_COLOR(tmp, field) = RB_RED; \ RB_ROTATE_RIGHT(head, tmp, oleft, field);\ tmp = RB_RIGHT(parent, field); \ } \ RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ RB_COLOR(parent, field) = RB_BLACK; \ if (RB_RIGHT(tmp, field)) \ RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\ RB_ROTATE_LEFT(head, parent, tmp, field);\ elm = RB_ROOT(head); \ break; \ } \ } else { \ tmp = RB_LEFT(parent, field); \ if (RB_COLOR(tmp, field) == RB_RED) { \ RB_SET_BLACKRED(tmp, parent, field); \ RB_ROTATE_RIGHT(head, parent, tmp, field);\ tmp = RB_LEFT(parent, field); \ } \ if ((RB_LEFT(tmp, field) == NULL || \ RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ (RB_RIGHT(tmp, field) == NULL || \ RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ RB_COLOR(tmp, field) = RB_RED; \ elm = parent; \ parent = RB_PARENT(elm, field); \ } else { \ 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) \ RB_COLOR(oright, field) = RB_BLACK;\ RB_COLOR(tmp, field) = RB_RED; \ RB_ROTATE_LEFT(head, tmp, oright, field);\ tmp = RB_LEFT(parent, field); \ } \ RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ RB_COLOR(parent, field) = RB_BLACK; \ if (RB_LEFT(tmp, field)) \ RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\ RB_ROTATE_RIGHT(head, parent, tmp, field);\ elm = RB_ROOT(head); \ break; \ } \ } \ } \ if (elm) \ RB_COLOR(elm, field) = RB_BLACK; \ } \ \ attr struct type * \ name##_RB_REMOVE(struct name *head, struct type *elm) \ { \ struct type *child, *parent, *old = elm; \ int color; \ if (RB_LEFT(elm, field) == NULL) \ child = RB_RIGHT(elm, field); \ else if (RB_RIGHT(elm, field) == NULL) \ child = RB_LEFT(elm, field); \ else { \ struct type *left; \ elm = RB_RIGHT(elm, field); \ while ((left = RB_LEFT(elm, field)) != NULL) \ elm = left; \ child = RB_RIGHT(elm, field); \ parent = RB_PARENT(elm, field); \ color = RB_COLOR(elm, field); \ if (child) \ RB_PARENT(child, field) = parent; \ if (parent) { \ if (RB_LEFT(parent, field) == elm) \ RB_LEFT(parent, field) = child; \ else \ RB_RIGHT(parent, field) = child; \ RB_AUGMENT(parent); \ } else \ RB_ROOT(head) = child; \ if (RB_PARENT(elm, field) == old) \ parent = elm; \ (elm)->field = (old)->field; \ if (RB_PARENT(old, field)) { \ if (RB_LEFT(RB_PARENT(old, field), field) == old)\ RB_LEFT(RB_PARENT(old, field), field) = elm;\ else \ RB_RIGHT(RB_PARENT(old, field), field) = elm;\ RB_AUGMENT(RB_PARENT(old, field)); \ } else \ RB_ROOT(head) = elm; \ RB_PARENT(RB_LEFT(old, field), field) = elm; \ if (RB_RIGHT(old, field)) \ RB_PARENT(RB_RIGHT(old, field), field) = elm; \ if (parent) { \ left = parent; \ do { \ RB_AUGMENT(left); \ } while ((left = RB_PARENT(left, field)) != NULL); \ } \ goto color; \ } \ parent = RB_PARENT(elm, field); \ color = RB_COLOR(elm, field); \ if (child) \ RB_PARENT(child, field) = parent; \ if (parent) { \ if (RB_LEFT(parent, field) == elm) \ RB_LEFT(parent, field) = child; \ else \ RB_RIGHT(parent, field) = child; \ RB_AUGMENT(parent); \ } else \ RB_ROOT(head) = child; \ color: \ if (color == RB_BLACK) \ name##_RB_REMOVE_COLOR(head, parent, child); \ return (old); \ } \ \ /* Inserts a node into the RB tree */ \ attr struct type * \ name##_RB_INSERT(struct name *head, struct type *elm) \ { \ struct type *tmp; \ struct type *parent = NULL; \ int comp = 0; \ tmp = RB_ROOT(head); \ while (tmp) { \ parent = tmp; \ comp = (cmp)(elm, parent); \ if (comp < 0) \ tmp = RB_LEFT(tmp, field); \ else if (comp > 0) \ tmp = RB_RIGHT(tmp, field); \ else \ return (tmp); \ } \ RB_SET(elm, parent, field); \ if (parent != NULL) { \ if (comp < 0) \ RB_LEFT(parent, field) = elm; \ else \ RB_RIGHT(parent, field) = elm; \ RB_AUGMENT(parent); \ } else \ RB_ROOT(head) = elm; \ name##_RB_INSERT_COLOR(head, elm); \ return (NULL); \ } \ \ /* Finds the node with the same key as elm */ \ attr struct type * \ name##_RB_FIND(struct name *head, struct type *elm) \ { \ struct type *tmp = RB_ROOT(head); \ int comp; \ while (tmp) { \ comp = cmp(elm, tmp); \ if (comp < 0) \ tmp = RB_LEFT(tmp, field); \ else if (comp > 0) \ tmp = RB_RIGHT(tmp, field); \ else \ return (tmp); \ } \ return (NULL); \ } \ \ /* Finds the first node greater than or equal to the search key */ \ attr struct type * \ name##_RB_NFIND(struct name *head, struct type *elm) \ { \ struct type *tmp = RB_ROOT(head); \ struct type *res = NULL; \ int comp; \ while (tmp) { \ comp = cmp(elm, tmp); \ if (comp < 0) { \ res = tmp; \ tmp = RB_LEFT(tmp, field); \ } \ else if (comp > 0) \ tmp = RB_RIGHT(tmp, field); \ else \ return (tmp); \ } \ return (res); \ } \ \ /* ARGSUSED */ \ attr struct type * \ name##_RB_NEXT(struct type *elm) \ { \ if (RB_RIGHT(elm, field)) { \ elm = RB_RIGHT(elm, field); \ while (RB_LEFT(elm, field)) \ elm = RB_LEFT(elm, field); \ } else { \ if (RB_PARENT(elm, field) && \ (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ elm = RB_PARENT(elm, field); \ else { \ while (RB_PARENT(elm, field) && \ (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\ elm = RB_PARENT(elm, field); \ elm = RB_PARENT(elm, field); \ } \ } \ return (elm); \ } \ \ /* ARGSUSED */ \ attr struct type * \ name##_RB_PREV(struct type *elm) \ { \ if (RB_LEFT(elm, field)) { \ elm = RB_LEFT(elm, field); \ while (RB_RIGHT(elm, field)) \ elm = RB_RIGHT(elm, field); \ } else { \ if (RB_PARENT(elm, field) && \ (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \ elm = RB_PARENT(elm, field); \ else { \ while (RB_PARENT(elm, field) && \ (elm == RB_LEFT(RB_PARENT(elm, field), field)))\ elm = RB_PARENT(elm, field); \ elm = RB_PARENT(elm, field); \ } \ } \ return (elm); \ } \ \ attr struct type * \ name##_RB_MINMAX(struct name *head, int val) \ { \ struct type *tmp = RB_ROOT(head); \ struct type *parent = NULL; \ while (tmp) { \ parent = tmp; \ if (val < 0) \ tmp = RB_LEFT(tmp, field); \ else \ tmp = RB_RIGHT(tmp, field); \ } \ return (parent); \ } #define RB_NEGINF -1 #define RB_INF 1 #define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) #define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) #define RB_FIND(name, x, y) name##_RB_FIND(x, y) #define RB_NFIND(name, x, y) name##_RB_NFIND(x, y) #define RB_NEXT(name, x, y) name##_RB_NEXT(y) #define RB_PREV(name, x, y) name##_RB_PREV(y) #define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) #define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) #define RB_FOREACH(x, name, head) \ for ((x) = RB_MIN(name, head); \ (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) = (y)) #define RB_FOREACH_REVERSE(x, name, head) \ for ((x) = RB_MAX(name, head); \ (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) = (y)) #endif /* _SYS_TREE_H_ */