jcs's openbsd hax
openbsd

import NSD 4.11.0, ok florian phessler

sthen c19d6275 4888f666

+23733 -11
+1 -1
usr.sbin/nsd/buffer.c
··· 41 41 } 42 42 43 43 void 44 - buffer_create_from(buffer_type *buffer, void *data, size_t size) 44 + buffer_create_from(buffer_type *buffer, const void *data, size_t size) 45 45 { 46 46 assert(data); 47 47
+3 -10
usr.sbin/nsd/ipc.h
··· 27 27 { 28 28 struct nsd *nsd; 29 29 struct nsd_child *child; 30 - int child_num; 31 - 32 - /* pointer to the socket, as it may change if it is restarted */ 33 - int *xfrd_sock; 34 - struct buffer *packet; 35 - int forward_mode; 36 - size_t got_bytes; 37 - uint16_t total_bytes; 38 - uint32_t acl_num; 39 - int32_t acl_xfr; 40 30 }; 41 31 42 32 /* ··· 83 73 * Handle interprocess communication with parent process, read and write. 84 74 */ 85 75 void xfrd_handle_ipc(int fd, short event, void* arg); 76 + 77 + /* receive incoming notifies received by and from the serve processes */ 78 + void xfrd_handle_notify(int fd, short event, void* arg); 86 79 87 80 /* check if all children have exited in an orderly fashion and set mode */ 88 81 void parent_check_all_children_exited(struct nsd* nsd);
+61
usr.sbin/nsd/simdzone/CHANGELOG.md
··· 1 + # Changelog 2 + 3 + All notable changes to simdzone will be documented in this file. 4 + 5 + The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0), 6 + and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 + 8 + ## [0.2.0] - 2024-12-12 9 + 10 + ### Added 11 + 12 + - Add semantic checks for DS and ZONEMD digests (NLnetLabs/nsd#205). 13 + - Support registering a callback for $INCLUDE entries (NLnetLabs/nsd#229). 14 + - Add tls-supported-groups SvcParam support. 15 + - Check iana registries for unimplemented (new) RR types and SvcParamKeys. 16 + - Add support for NINFO, RKEY, RESINFO, WALLET, CLA and TA RR types. 17 + 18 + ### Fixed 19 + 20 + - Prepend -march to CFLAGS to fix architecture detection (NLnetLabs/nsd#372). 21 + - Fix propagation of implicit TTLs (NLnetLabs/nsd#375). 22 + - Fix detection of Westmere architecture by checking for CLMUL too. 23 + - Fix compilation on NetBSD (#233). 24 + - Fix reading specialized symbolic links (NLnetLabs/nsd#380). 25 + 26 + ## [0.1.1] - 2024-07-19 27 + 28 + ### Added 29 + 30 + - Test to verify configure.ac and Makefile.in are correct. 31 + - Add support for reading from stdin if filename is "-". 32 + - Add support for building with Oracle Developer Studio 12.6. 33 + - Add support for "time" service for Well-Know Services (WKS) RR. 34 + 35 + ### Fixed 36 + 37 + - Fix makefile dependencies. 38 + - Fix makefile to use source directory for build dependencies. 39 + - Fix changelog to reflect v0.1.0 release. 40 + - Update makefile to not use target-specific variables. 41 + - Fix makefile clean targets. 42 + - Fix state keeping in fallback scanner for contiguous and quoted. 43 + - Fix bug in name scanner. 44 + - Fix type mnemonic parsing in fallback parser. 45 + - Fix endian.h to include machine/endian.h on OpenBSD releases before 5.6. 46 + - Fix use after free on buffer resize. 47 + - Fix parsing of numeric protocols in WKS RRs. 48 + - Make devclean target depend on realclean target. 49 + - Fix detection of AVX2 support by checking generic AVX support by the 50 + processor and operating system (#222). 51 + 52 + ### Changed 53 + 54 + - Make relative includes relative to current working directory. 55 + - Split Autoconf and CMake compiler tests for supported SIMD instructions. 56 + 57 + ## [0.1.0] - 2024-04-16 58 + 59 + ### Added 60 + 61 + - Initial release.
+75
usr.sbin/nsd/simdzone/CONTRIBUTING.md
··· 1 + # Contributing to simdzone 2 + 3 + The simdzone library is open source and made available under the permissive 4 + 3-clause BSD license. 5 + 6 + Contributions are very welcome! 7 + 8 + > The original specification in [RFC1035][1] is rather ambiguous and does not 9 + > cover additions from later RFCs. See [SYNTAX.md](SYNTAX.md) for a quick 10 + > summary of the format and interpretation in simdzone. 11 + 12 + [1]: https://datatracker.ietf.org/doc/html/rfc1035#section-5 13 + 14 + ## Reference data 15 + 16 + 1. [Zone Data for .se and .nu][2] can be obtained via a DNS zone transfer. 17 + 18 + 2. The [Centralized Zone Data Service (CZDS)][3] provides access to zone data 19 + for participating gTLDs. 20 + 21 + > Downloading zone data via the browser can be problematic. The 22 + > [The CZDS API client in Java][4] can be used as a workaround. 23 + 24 + 3. The *Hint and Zone Files* can be obtained from Internet Assigned Numbers 25 + Authority (IANA) [Root Zone Management][5] page. 26 + 27 + [2]: https://internetstiftelsen.se/en/zone-data/ 28 + [3]: https://czds.icann.org/ 29 + [4]: https://github.com/icann/czds-api-client-java/ 30 + [5]: https://www.iana.org/domains/root 31 + 32 + ## Source layout 33 + 34 + `include` contains only headers required for consumption of the library. 35 + 36 + `src` contains the implementation and internal headers. 37 + 38 + The layout of `src` is (of course) inspired by the layout in simdjson. The 39 + structure is intentionally simple and without (too much) hierarchy, but as 40 + simdzone has very architecture specific code to maximize performance, there 41 + are some caveats. 42 + 43 + Processors may support multiple instruction sets. e.g. x86\_64 may support 44 + SSE4.2, AVX2 and AVX-512 instruction sets depending on the processor family. 45 + The preferred implementation is automatically selected at runtime. As a result, 46 + code may need to be compiled more than once. To improve code reuse, shared 47 + logic resides in headers rather than source files and is declared static to 48 + avoid name clashes. Bits and pieces are then mixed and matched in a 49 + `src/<arch>/parser.c` compilation target to allow for multiple implementations 50 + to co-exist. 51 + 52 + Sources and headers common to all architectures that do not implement parsing 53 + for a specific data-type reside directly under `src`. Code specific to an 54 + architecture resides in a directory under `src`, e.g. `haswell` or `fallback`. 55 + `src/generic` contains scanner and parser code common to all implementations, 56 + but leans towards code shared by SIMD implementations. 57 + 58 + For example, SIMD-optimized scanner code resides in `src/generic/scanner.h`, 59 + abstractions for intrinsics reside in e.g. `src/haswell/simd.h` and `lex(...)`, 60 + which is used by all implementations, is implemented in `src/lexer.h`. 61 + A fallback scanner is implemented in `src/fallback/scanner.h`. 62 + 63 + A SIMD-optimized type parser is implemented in `src/generic/type.h`, a fallback 64 + type parser is implemented in `src/fallback/type.h`. Future versions are 65 + expected to add more optimized parsers for specific data types, even parsers 66 + that are tied to a specific instruction set. The layout accommodates these 67 + scenarios. e.g. an AVX2 optimized parser may reside in `src/haswell/<type>.h`, 68 + an SSE4.2 optimized parser may reside in `src/westmere/<type>.h`, etc. 69 + 70 + ## Symbol visibility 71 + 72 + All exported symbols, identifiers, etc must be prefixed with `zone_`, or 73 + `ZONE_` for macros. Non-exported symbols are generally not prefixed. e.g. 74 + `lex(...)` and `scan(...)` are declared static and as such are not required to 75 + be prefixed.
+311
usr.sbin/nsd/simdzone/FORMAT.md
··· 1 + # Zone files 2 + 3 + Zone files are text files that contain resource records (RRs) in text form. 4 + Zones can be defined by expressing them in the form of a list of RRs. 5 + 6 + Zone files were originally specified in RFC1035 Section 5, but the DNS 7 + has seen many additions since and the specification is rather ambiguous. 8 + Consequently, various name servers implement slightly different dialects. This 9 + document aims to clarify the format by listing (some of) the relevant 10 + specifications and then proceed to explain why certain design decisions were 11 + made in simdzone. 12 + 13 + * [RFC 1034 Section 3.6.1][rfc1034#3.6.1] 14 + * [RFC 1035 Section 5][rfc1035#5] 15 + * [RFC 2065 Section 4.5][rfc2065#4.5] 16 + * [RFC 2181 Section 8][rfc2181#8] 17 + * [RFC 2308 Section 4][rfc2308#4] 18 + * [RFC 3597 Section 5][rfc3597#5] 19 + * [RFC 9460 Section 2.1][rfc9460#2.1] 20 + 21 + 22 + ## Clarification (work-in-progress) 23 + 24 + > NOTE: BIND behavior is more-or-less considered the de facto standard. 25 + 26 + Historically, master files where edited by hand, which is reflected in the 27 + syntax. Consider the format a tabular serialization format with provisions 28 + for convenient editing. i.e. the owner, class and ttl fields may be omitted 29 + (provided the line starts with \<blank\> for the owner) and $INCLUDE directives 30 + can be used for templating. 31 + 32 + The format is NOT context-free. The field following the owner (if specified) 33 + may represent either a type, class or ttl and a symbolic constant, e.g. A 34 + or NS, may have a different meaning if specified as an RDATA field. 35 + 36 + The DNS is intentionally extensible. The specification is not explicit about 37 + how that affects syntax, but it explains why no specific notation for 38 + data-types can be enforced by RFC 1035. To make it easier for data-types to 39 + be added at a later stage the syntax cannot enforce a certain notation (or 40 + the scanner would need to be revised). Consequently, the scanner only 41 + identifies items (or fields) and structural characters, which can be 42 + expressed as either a contiguous set of characters without interior spaces, 43 + or as a quoted string. 44 + 45 + The format allows for including structural characters in fields by means of 46 + escaping the actual character or enclosing the field in quotes. The example 47 + provided by the specification here is using ASCII dots in domain name labels. 48 + The dot is normally a label separator, replaced by the length of the label 49 + on the wire. If a domain name includes an actual ASCII dot, the character 50 + must be escaped in the textual representation (`\X` or `\DDD`). 51 + 52 + Note that ASCII dot characters strictly speaking do not have to be escaped 53 + in a quoted string. RFC 1035 clearly states labels in domain names are 54 + expressed as character strings. However, behavior differs across 55 + implementations, so support for quoted labels is best dropped (see below). 56 + 57 + RFC 1035 states both \<contiguous\> and \<quoted\> are \<character-string\>. 58 + Meaning, items can be either \<contiguous\> or \<quoted\>. Wether a specific 59 + item is interpreted as a \<character-string\> depends on type of value for 60 + that item. E.g., TTLs are decimal integers and therefore cannot be expressed 61 + as \<quoted\> as it is not a \<character-string\>. Similarly, base64 62 + sequences are encoded binary blobs, not \<character-string\>s and therefore 63 + cannot be expressed as such. Escape sequences are valid only in 64 + \<character-string\>s. 65 + 66 + * Mnemonics are NOT character strings. 67 + 68 + > BIND does not accept quoted fields for A or NS RDATA. TTL values in SOA 69 + > RDATA, base64 Signature in DNSKEY RDATA, as well as type, class and TTL 70 + > header fields all result in a syntax error too if quoted. 71 + 72 + * Some integer fields allow for using mnemonics too. E.g., the algorithm 73 + field in RRSIG records. 74 + 75 + * RFC 1035 states: A freestanding @ denotes the current origin. 76 + There has been discussion in which locations @ is interpreted as the origin. 77 + e.g. how is a freestanding @ be interpreted in the RDATA section of a TXT RR. 78 + Note that there is no mention of text expansion in the original text. A 79 + freestanding @ denotes the origin. As such, it stands to reason that it's 80 + use is limited to locations where domain names are expressed, which also 81 + happens to be the most practical way to implement the functionality. 82 + 83 + > This also seems to be the behavior that other name servers implement (at 84 + > least BIND and PowerDNS). The BIND manual states: "When used in the label 85 + > (or name) field, the asperand or at-sign (@) symbol represents the current 86 + > origin. At the start of the zone file, it is the \<zone\_name\>, followed 87 + > by a trailing dot (.). 88 + 89 + > It may also make sense to interpret a quoted freestanding @ differently 90 + > than a non-quoted one. At least, BIND throws an error if a quoted 91 + > freestanding @ is encountered in the RDATA sections for CNAME and NS RRs. 92 + > However, a quoted freestanding @ is accepted and interpreted as origin 93 + > if specified as the OWNER. 94 + 95 + > Found mentions of what happens when a zone that uses freestanding @ in 96 + > RDATA is written to disk. Of course, this particular scenario rarely occurs 97 + > as it does not need to be written to disk when loaded on a primary and no 98 + > file exists if received over AXFR/IXFR. However, it may make sense to 99 + > implement optimistic compression of this form, and make it configurable. 100 + 101 + * Class and type names are mutually exclusive in practice. 102 + RFC1035 states: The RR begins with optional TTL and class fields, ... 103 + Therefore, if a type name matches a class name, the parser cannot distinguish 104 + between the two in text representation and must resort to generic notation 105 + (RFC3597) or, depending on the RDATA format for the record type, a 106 + look-ahead may be sufficient. Realistically, it is highly likely that because 107 + of this, no type name will ever match a class name. 108 + 109 + > This means both can reside in the same table. 110 + 111 + * The encoding is non-ASCII. Some characters have special meaning, but users 112 + are technically allowed to put in non-printable octets outside the ASCII 113 + range without custom encoding. Of course, this rarely occurs in practice 114 + and users are encouraged to use the \DDD encoding for "special". 115 + 116 + * Parenthesis may not be nested. 117 + 118 + * $ORIGIN must be an absolute domain. 119 + 120 + * Escape sequences must NOT be unescaped in the scanner as is common with 121 + programming languages like C that have a preprocessor. Instead, the 122 + original text is necessary in the parsing stage to distinguish between 123 + label separators (dots). 124 + 125 + * RFC 1035 specifies that the current origin should be restored after an 126 + $INCLUDE, but it is silent on whether the current domain name should also be 127 + restored. BIND 9 restores both of them. This could be construed as a 128 + deviation from RFC 1035, a feature, or both. 129 + 130 + * RFC 1035 states: and text literals can contain CRLF within the text. 131 + BIND, however, does not allow newlines in text (escaped or not). For 132 + performance reasons, we may adopt the same behavior as that would relieve 133 + the need to keep track of possibly embedded newlines. 134 + 135 + * From: http://www.zytrax.com/books/dns/ch8/include.html (mentioned in chat) 136 + > Source states: The RFC is silent on the topic of embedded `$INCLUDE`s in 137 + > `$INCLUDE`d files - BIND 9 documentation is similarly silent. Assume they 138 + > are not permitted. 139 + 140 + All implementations, including BIND, allow for embedded `$INCLUDE`s. 141 + The current implementation is such that (embedded) includes are allowed by 142 + default. However, `$INCLUDE` directives can be disabled, which is useful 143 + when parsing from an untrusted source. There is also protection against 144 + cyclic includes. 145 + 146 + > There is no maximum to the amount of embedded includes (yet). NSD limits 147 + > the number of includes to 10 by default (compile option). For security, it 148 + > must be possible to set a hard limit. 149 + 150 + * Default values for TTLs can be quite complicated. 151 + 152 + A [commit to ldns](https://github.com/NLnetLabs/ldns/commit/cb101c9) by 153 + @wtoorop nicely sums it up in code. 154 + 155 + RFC 1035 section 5.1: 156 + > Omitted class and TTL values are default to the last explicitly stated 157 + > values. 158 + 159 + This behavior is updated by RFC 2308 section 4: 160 + > All resource records appearing after the directive, and which do not 161 + > explicitly include a TTL value, have their TTL set to the TTL given 162 + > in the $TTL directive. SIG records without a explicit TTL get their 163 + > TTL from the "original TTL" of the SIG record [RFC 2065 Section 4.5]. 164 + 165 + The TTL rules for `SIG` RRs stated in RFC 2065 Section 4.5: 166 + > If the original TTL, which applies to the type signed, is the same as 167 + > the TTL of the SIG RR itself, it may be omitted. The date field 168 + > which follows it is larger than the maximum possible TTL so there is 169 + > no ambiguity. 170 + 171 + The same applies applies to `RRSIG` RRs, although not stated as explicitly 172 + in RFC 4034 Section 3: 173 + > The TTL value of an RRSIG RR MUST match the TTL value of the RRset it 174 + > covers. This is an exception to the [RFC2181] rules for TTL values 175 + > of individual RRs within a RRset: individual RRSIG RRs with the same 176 + > owner name will have different TTL values if the RRsets they cover 177 + > have different TTL values. 178 + 179 + Logic spanning RRs must not be handled during deserialization. The order in 180 + which RRs appear in the zone file is not relevant and keeping a possibly 181 + infinite backlog of RRs to handle it "automatically" is inefficient. As 182 + the name server retains RRs in a database already it seems most elegant to 183 + signal the TTL value was omitted and a default was used so that it may be 184 + updated in some post processing step. 185 + 186 + [RFC 2181 Section 8][rfc2181#8] contains additional notes on the maximum 187 + value for TTLs. During deserialization, any value exceeding 2147483647 is 188 + considered an error in primary mode, or a warning in secondary mode. 189 + [RFC 8767 Section 4][rfc8767#4] updates the text, but the update does not 190 + update handling during deserialization. 191 + 192 + [RFC 2181 Section 5][rfc2181#5.2] states the TTLs of all RRs in an RRSet 193 + must be the same. As with default values for `SIG` and `RRSIG` RRs, this 194 + must NOT be handled during deserialization. Presumably, the application 195 + should transparently fix TTLs (NLnetLabs/nsd#178). 196 + 197 + * Do NOT allow for quoted labels in domain names. 198 + [RFC 1035 Section 5][rfc1035#5] states: 199 + > The labels in the domain name are expressed as character strings and 200 + > separated by dots. 201 + 202 + [RFC 1035 section 5][rfc1035#5] states: 203 + > \<character-string\> is expressed in one or two ways: as a contiguous set 204 + > of characters without interior spaces, or as string beginning with a " and 205 + > ending with a ". 206 + 207 + However, quoted labels in domain names are very uncommon and implementations 208 + handle quoted names both in OWNER and RDATA very differently. The Flex+Bison 209 + based parser used in NSD before was the only parser that got it right. 210 + 211 + * BIND 212 + * owner: yes, interpreted as quoted 213 + ``` 214 + dig @127.0.0.1 A quoted.example.com. 215 + ``` 216 + ``` 217 + quoted.example.com. xxx IN A x.x.x.x 218 + ``` 219 + * rdata: no, syntax error (even with `check-names master ignored;`) 220 + * Knot 221 + * owner: no, syntax error 222 + * rdata: no, syntax error 223 + * PowerDNS 224 + * owner: no, not interpreted as quoted 225 + ``` 226 + pdnsutil list-zone example.com. 227 + ``` 228 + ``` 229 + "quoted".example.com xxx IN A x.x.x.x 230 + ``` 231 + * rdata: no, not interpreted as quoted 232 + ``` 233 + dig @127.0.0.1 NS example.com. 234 + ``` 235 + ``` 236 + example.com. xxx IN NS \"quoted.example.com.\".example.com. 237 + ``` 238 + 239 + > [libzscanner](https://github.com/CZ-NIC/knot/tree/master/src/libzscanner), 240 + > the (standalone) zone parser used by Knot seems mosts consistent. 241 + 242 + Drop support for quoted labels or domain names for consistent behavior. 243 + 244 + * Should any domain names that are not valid host names as specified by 245 + RFC 1123 section 2, i.e. use characters not in the preferred naming syntax 246 + as specified by RFC 1035 section 2.3.1, be accepted? RFC 2181 section 11 is 247 + very specific on this topic, but it merely states that labels may contain 248 + characters outside the set on the wire, it does not address what is, or is 249 + not, allowed in zone files. 250 + 251 + BIND's zone parser throws a syntax error for any name that is not a valid 252 + hostname unless `check-names master ignored;` is specified. Knot 253 + additionally accepts `-`, `_` and `/` according to 254 + [NOTES](https://github.com/CZ-NIC/knot/blob/master/src/libzscanner/NOTES). 255 + 256 + * [RFC1035 Section 2.3.1][rfc1035#2.3.1] 257 + * [RFC1123 Section 2][rfc1123#2] 258 + * [RFC2181 Section 11][rfc2181#11] 259 + 260 + * RFC 1035 specifies two control directives "$INCLUDE" and "$ORIGIN". RFC 2308 261 + specifies the "$TTL" directive. BIND additionally implements the "$DATE" and 262 + "$GENERATE" directives. Since "$" (dollar sign) is not reserved, both 263 + "$DATE" and "$GENERATE" (and "$TTL" before RFC2308) are considered valid 264 + domain names in other implementations (based on what is accepted for domain 265 + names, see earlier points). It seems "$" is better considered a reserved 266 + character (possibly limiting its special status to the start of the 267 + line), to allow for reliable extensibility in the future. 268 + 269 + > BIND seems to already throw an error if "$" is encountered, see 270 + > `lib/dns/master.c`. Presumably, the "$DATE" directive is written when the 271 + > zone is written to disk(?) In the code it is referred to as 272 + > __dump_time__ and later used to calculate __ttl_offset__. 273 + 274 + * BIND10 had a nice writeup on zone files, kindly provided by Shane Kerr. 275 + [Zone File Loading Requirements on Wayback Machine](https://web.archive.org/web/20140928215002/http://bind10.isc.org:80/wiki/ZoneLoadingRequirements) 276 + 277 + * `TYPE0` is sometimes used for debugging and therefore may occur in type 278 + bitmaps or as unknown RR type. 279 + 280 + * `pdns/master/regression-tests/zones/test.com` contains regression tests 281 + that may be useful for testing simdzone. 282 + 283 + * Some implementations (Knot, possibly PowerDNS) will silently split-up 284 + strings longer than 255 characters. Others (BIND, simdzone) will throw a 285 + syntax error. 286 + 287 + * How do we handle the corner case where the first record does not have a TTL 288 + when the file does not define a zone? (from @shane-kerr). 289 + 290 + At this point in time, the application provides a default TTL value before 291 + parsing. Whether that is the right approach is unclear, but it is what NSD 292 + did before. 293 + 294 + * Leading zeroes in integers appear to be allowed judging by the zone file 295 + generated for the [socket10kxfr][socket10kxfr.pre#L64] test in NSD. BIND 296 + and Knot parsed it without problems too. 297 + 298 + [rfc1034#3.6.1]: https://datatracker.ietf.org/doc/html/rfc1034#section-3.6.1 299 + [rfc1035#5]: https://datatracker.ietf.org/doc/html/rfc1035#section-5 300 + [rfc1035#2.3.1]: https://datatracker.ietf.org/doc/html/rfc1035#section-2.3.1 301 + [rfc1123#2]: https://datatracker.ietf.org/doc/html/rfc1123#section-2 302 + [rfc2065#4.5]: https://datatracker.ietf.org/doc/html/rfc2065#section-4.5 303 + [rfc2181#5.2]: https://datatracker.ietf.org/doc/html/rfc2181#section-5.2 304 + [rfc2181#8]: https://datatracker.ietf.org/doc/html/rfc2181#section-8 305 + [rfc2181#11]: https://datatracker.ietf.org/doc/html/rfc2181#section-11 306 + [rfc2308#4]: https://datatracker.ietf.org/doc/html/rfc2308#section-4 307 + [rfc3597#5]: https://datatracker.ietf.org/doc/html/rfc3597#section-5 308 + [rfc8767#4]: https://www.rfc-editor.org/rfc/rfc8767#section-4 309 + [rfc9460#2.1]: https://datatracker.ietf.org/doc/html/rfc9460#section-2.1 310 + 311 + [socket10kxfr.pre#L64]: https://github.com/NLnetLabs/nsd/blob/86a6961f2ca64f169d7beece0ed8a5e1dd1cd302/tpkg/long/socket10kxfr.tdir/socket10kxfr.pre#L64
+29
usr.sbin/nsd/simdzone/LICENSE
··· 1 + BSD 3-Clause License 2 + 3 + Copyright (c) 2022, NLnet Labs. 4 + All rights reserved. 5 + 6 + Redistribution and use in source and binary forms, with or without 7 + modification, are permitted provided that the following conditions are met: 8 + 9 + 1. Redistributions of source code must retain the above copyright notice, this 10 + list of conditions and the following disclaimer. 11 + 12 + 2. Redistributions in binary form must reproduce the above copyright notice, 13 + this list of conditions and the following disclaimer in the documentation 14 + and/or other materials provided with the distribution. 15 + 16 + 3. Neither the name of the copyright holder nor the names of its 17 + contributors may be used to endorse or promote products derived from 18 + this software without specific prior written permission. 19 + 20 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+84
usr.sbin/nsd/simdzone/Makefile.in
··· 1 + # 2 + # Makefile.in -- one file to make them all 3 + # 4 + # Copyright (c) 2022-2024, NLnet Labs. All rights reserved. 5 + # 6 + # SPDX-License-Identifier: BSD-3-Clause 7 + # 8 + WESTMERE = @HAVE_WESTMERE@ 9 + HASWELL = @HAVE_HASWELL@ 10 + 11 + CC = @CC@ 12 + CPPFLAGS = @CPPFLAGS@ -I$(SOURCE)/include -I$(SOURCE)/src -I. 13 + CFLAGS = @CFLAGS@ 14 + DEPFLAGS = @DEPFLAGS@ 15 + VPATH = @srcdir@ 16 + 17 + SOURCE = @srcdir@ 18 + 19 + SOURCES = src/zone.c src/fallback/parser.c 20 + OBJECTS = $(SOURCES:.c=.o) 21 + 22 + WESTMERE_SOURCES = src/westmere/parser.c 23 + WESTMERE_OBJECTS = $(WESTMERE_SOURCES:.c=.o) 24 + 25 + HASWELL_SOURCES = src/haswell/parser.c 26 + HASWELL_OBJECTS = $(HASWELL_SOURCES:.c=.o) 27 + 28 + NO_OBJECTS = 29 + 30 + DEPENDS = $(SOURCES:.c=.d) $(WESTMERE_SOURCES:.c=.d) $(HASWELL_SOURCES:.c=.d) 31 + 32 + # The export header automatically defines visibility macros. These macros are 33 + # required for standalone builds on Windows. I.e., exported functions must be 34 + # declared with __declspec(dllexport) for dynamic link libraries (.dll) and 35 + # __declspec(dllimport) for statically linked libraries (.lib). Define dummy 36 + # macros for compatibility. 37 + EXPORT_HEADER = include/zone/export.h 38 + 39 + .PHONY: all clean 40 + 41 + all: libzone.a 42 + 43 + clean: 44 + @rm -f .depend 45 + @rm -f libzone.a $(OBJECTS) $(EXPORT_HEADER) 46 + 47 + distclean: clean 48 + @rm -f Makefile config.h config.log config.status 49 + 50 + realclean: distclean 51 + @rm -rf autom4te* 52 + 53 + maintainer-clean: realclean 54 + 55 + devclean: realclean 56 + @rm -rf config.h.in configure 57 + 58 + libzone.a: $(OBJECTS) $($(WESTMERE)_OBJECTS) $($(HASWELL)_OBJECTS) 59 + $(AR) rcs libzone.a $(OBJECTS) $($(WESTMERE)_OBJECTS) $($(HASWELL)_OBJECTS) 60 + 61 + $(EXPORT_HEADER): 62 + @mkdir -p include/zone 63 + @echo "#define ZONE_EXPORT" > $(EXPORT_HEADER) 64 + 65 + $(WESTMERE_OBJECTS): $(EXPORT_HEADER) .depend 66 + @mkdir -p src/westmere 67 + $(CC) $(DEPFLAGS) $(CPPFLAGS) $(CFLAGS) -march=westmere -o $@ -c $(SOURCE)/$(@:.o=.c) 68 + 69 + $(HASWELL_OBJECTS): $(EXPORT_HEADER) .depend 70 + @mkdir -p src/haswell 71 + $(CC) $(DEPFLAGS) $(CPPFLAGS) $(CFLAGS) -march=haswell -o $@ -c $(SOURCE)/$(@:.o=.c) 72 + 73 + $(OBJECTS): $(EXPORT_HEADER) .depend 74 + @mkdir -p src/fallback 75 + $(CC) $(DEPFLAGS) $(CPPFLAGS) $(CFLAGS) -o $@ -c $(SOURCE)/$(@:.o=.c) 76 + @touch $@ 77 + 78 + .depend: 79 + @cat /dev/null > $@ 80 + @for x in $(DEPENDS:.d=); do echo "$${x}.o: $(SOURCE)/$${x}.c $${x}.d" >> $@; done 81 + 82 + -include .depend 83 + $(DEPENDS): 84 + -include $(DEPENDS)
+95
usr.sbin/nsd/simdzone/README.md
··· 1 + ![Build Status](https://github.com/NLnetLabs/simdzone/actions/workflows/build-test.yml/badge.svg) 2 + [![Coverity Status](https://scan.coverity.com/projects/27509/badge.svg)](https://scan.coverity.com/projects/nlnetlabs-simdzone) 3 + [![Mastodon Follow](https://img.shields.io/mastodon/follow/109262826617293067?domain=https%3A%2F%2Ffosstodon.org&style=social)](https://fosstodon.org/@nlnetlabs) 4 + 5 + # simdzone: Parsing zone files really fast 6 + 7 + Fast and standards compliant DNS presentation format parser. 8 + 9 + DNS resource records (RRs) can be expressed in text form using the 10 + presentation format. The format is most frequently used to define a zone in 11 + master files, more commonly known as zone files, and is best considered a 12 + tabular serialization format with provisions for convenient editing. 13 + 14 + The format is originally defined in [RFC1035 section 5][rfc1035-section-5] and 15 + [RFC1034 section 3.6.1][rfc1034-section-3-6-1], but as the DNS is 16 + intentionally extensible, the format has been extended over time too. 17 + 18 + This project provides a lightning fast presentation format deserializer (and 19 + serializer eventually) for other projects to leverage. Learn more about 20 + simdzone by reading the [documentation](https://simdzone.docs.nlnetlabs.nl/). 21 + 22 + ## Research paper 23 + 24 + * Jeroen Koekkoek and Daniel Lemire, [Parsing Millions of DNS Records per Second](https://arxiv.org/abs/2411.12035), Software: Practice and Experience (to appear) 25 + 26 + 27 + 28 + 29 + ## Motivation 30 + Zone files can become quite large (.com ~24G, .se ~1.3G) and the parser in 31 + NSD left something to be desired. simdjson demonstrates that applying SIMD 32 + instructions for parsing structured text can significantly boost performance. 33 + simdzone, whose name is a play on [simdjson][simdjson], aims to achieve a 34 + similar performance boost for parsing zone data. 35 + 36 + > Currently SSE4.2 and AVX2 are supported, a fallback is used otherwise. 37 + 38 + > simdzone copies some code from the [simdjson][simdjson] project, with 39 + > permission to use and distribute it under the terms of 40 + > [The 3-Clause BSD License][bsd-3-clause]. 41 + 42 + [rfc1035-section-5]: https://datatracker.ietf.org/doc/html/rfc1035#section-5 43 + [rfc1034-section-3-6-1]: https://datatracker.ietf.org/doc/html/rfc1034#section-3.6.1 44 + [nsd]: https://nlnetlabs.nl/projects/nsd/about/ 45 + [simdjson]: https://github.com/simdjson/simdjson 46 + [bsd-3-clause]: https://opensource.org/license/bsd-3-clause/ 47 + 48 + ## Results 49 + Running `zone-bench` on my system (Intel Core i7-1065G7) against an older 50 + `.com` zone file of 12482791271 bytes under Linux (Fedora 39). 51 + 52 + clang version 17.0.6, release mode: 53 + ``` 54 + $ time ./zone-bench parse ../../zones/com.zone 55 + Selected target haswell 56 + Parsed 341535548 records 57 + 58 + real 0m13.533s 59 + user 0m12.355s 60 + sys 0m1.160s 61 + ``` 62 + 63 + There are bound to be bugs and quite possibly smarter ways of implementing 64 + some operations, but the results are promising. 65 + 66 + ## Compiling 67 + Make sure the following tools are installed: 68 + * C toolchain (the set of tools to compile C code) 69 + * [cmocka](https://cmocka.org/) (if configured with `-DBUILD_TESTING=on`) 70 + * [Doxygen](https://www.doxygen.nl/) (if configured with `-DBUILD_DOCUMENTATION=on`) 71 + * [Sphinx](https://www.sphinx-doc.org/en/master/) (if configured with `-DBUILD_DOCUMENTATION=on`) 72 + 73 + To compile in release mode: 74 + ``` 75 + $ cd zone-parser 76 + $ mkdir build 77 + $ cd build 78 + $ cmake -DCMAKE_BUILD_TYPE=Release .. 79 + $ cmake --build . 80 + ``` 81 + 82 + To compile in debug mode with testing: 83 + ``` 84 + $ cd zone-parser 85 + $ mkdir build 86 + $ cd build 87 + $ cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=on .. 88 + $ cmake --build . 89 + ``` 90 + 91 + ## Contributing 92 + Contributions in any way, shape or form are very welcome! Please see 93 + [CONTRIBUTING.md](CONTRIBUTING.md) to find out how you can help. 94 + 95 + Design decisions and notes on the [FORMAT](FORMAT.md).
+78
usr.sbin/nsd/simdzone/compat/getopt.c
··· 1 + #include <stdio.h> 2 + #include <string.h> 3 + #include "getopt.h" 4 + 5 + /* 6 + * Here's something you've all been waiting for: the AT&T public domain 7 + * source for getopt(3). It is the code which was given out at the 1985 8 + * UNIFORUM conference in Dallas. I obtained it by electronic mail 9 + * directly from AT&T. The people there assure me that it is indeed 10 + * in the public domain. 11 + * 12 + * There is no manual page. That is because the one they gave out at 13 + * UNIFORUM was slightly different from the current System V Release 2 14 + * manual page. The difference apparently involved a note about the 15 + * famous rules 5 and 6, recommending using white space between an option 16 + * and its first argument, and not grouping options that have arguments. 17 + * Getopt itself is currently lenient about both of these things White 18 + * space is allowed, but not mandatory, and the last option in a group can 19 + * have an argument. That particular version of the man page evidently 20 + * has no official existence, and my source at AT&T did not send a copy. 21 + * The current SVR2 man page reflects the actual behavior of this getopt. 22 + * However, I am not about to post a copy of anything licensed by AT&T. 23 + */ 24 + 25 + #define ERR(szz,czz) if(opterr){fprintf(stderr,"%s%s%c\n",argv[0],szz,czz);} 26 + 27 + int opterr = 1; 28 + int optind = 1; 29 + int optopt; 30 + char *optarg; 31 + 32 + int 33 + getopt( 34 + int argc, 35 + char **argv, 36 + const char *opts) 37 + { 38 + static int sp = 1; 39 + register int c; 40 + register char *cp; 41 + 42 + if (sp == 1) { 43 + if (optind >= argc || 44 + argv[optind][0] != '-' || argv[optind][1] == '\0') 45 + return (EOF); 46 + else if (strcmp(argv[optind], "--") == 0) { 47 + optind++; 48 + return (EOF); 49 + } 50 + } 51 + optopt = c = argv[optind][sp]; 52 + if (c == ':' || (cp = strchr(opts, c)) == NULL) { 53 + ERR(": illegal option -- ", c); 54 + if (argv[optind][++sp] == '\0') { 55 + optind++; 56 + sp = 1; 57 + } 58 + return ('?'); 59 + } 60 + if (*++cp == ':') { 61 + if (argv[optind][sp + 1] != '\0') 62 + optarg = &argv[optind++][sp + 1]; 63 + else if (++optind >= argc) { 64 + ERR(": option requires an argument -- ", c); 65 + sp = 1; 66 + return ('?'); 67 + } else 68 + optarg = argv[optind++]; 69 + sp = 1; 70 + } else { 71 + if (argv[optind][++sp] == '\0') { 72 + sp = 1; 73 + optind++; 74 + } 75 + optarg = NULL; 76 + } 77 + return (c); 78 + }
+19
usr.sbin/nsd/simdzone/compat/getopt.h
··· 1 + /* 2 + * getopt.h -- getopt definitions for platform that are missing unistd.h 3 + * 4 + * Copyright (c) 2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef GETOPT_H 10 + #define GETOPT_H 11 + 12 + extern int opterr; 13 + extern int optind; 14 + extern int optopt; 15 + extern char *optarg; 16 + 17 + int getopt(int argc, char **argv, const char *opts); 18 + 19 + #endif /* GETOPT_H */
+1754
usr.sbin/nsd/simdzone/config.guess
··· 1 + #! /bin/sh 2 + # Attempt to guess a canonical system name. 3 + # Copyright 1992-2022 Free Software Foundation, Inc. 4 + 5 + # shellcheck disable=SC2006,SC2268 # see below for rationale 6 + 7 + timestamp='2022-01-09' 8 + 9 + # This file is free software; you can redistribute it and/or modify it 10 + # under the terms of the GNU General Public License as published by 11 + # the Free Software Foundation, either version 3 of the License, or 12 + # (at your option) any later version. 13 + # 14 + # This program is distributed in the hope that it will be useful, but 15 + # WITHOUT ANY WARRANTY; without even the implied warranty of 16 + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 + # General Public License for more details. 18 + # 19 + # You should have received a copy of the GNU General Public License 20 + # along with this program; if not, see <https://www.gnu.org/licenses/>. 21 + # 22 + # As a special exception to the GNU General Public License, if you 23 + # distribute this file as part of a program that contains a 24 + # configuration script generated by Autoconf, you may include it under 25 + # the same distribution terms that you use for the rest of that 26 + # program. This Exception is an additional permission under section 7 27 + # of the GNU General Public License, version 3 ("GPLv3"). 28 + # 29 + # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. 30 + # 31 + # You can get the latest version of this script from: 32 + # https://git.savannah.gnu.org/cgit/config.git/plain/config.guess 33 + # 34 + # Please send patches to <config-patches@gnu.org>. 35 + 36 + 37 + # The "shellcheck disable" line above the timestamp inhibits complaints 38 + # about features and limitations of the classic Bourne shell that were 39 + # superseded or lifted in POSIX. However, this script identifies a wide 40 + # variety of pre-POSIX systems that do not have POSIX shells at all, and 41 + # even some reasonably current systems (Solaris 10 as case-in-point) still 42 + # have a pre-POSIX /bin/sh. 43 + 44 + 45 + me=`echo "$0" | sed -e 's,.*/,,'` 46 + 47 + usage="\ 48 + Usage: $0 [OPTION] 49 + 50 + Output the configuration name of the system \`$me' is run on. 51 + 52 + Options: 53 + -h, --help print this help, then exit 54 + -t, --time-stamp print date of last modification, then exit 55 + -v, --version print version number, then exit 56 + 57 + Report bugs and patches to <config-patches@gnu.org>." 58 + 59 + version="\ 60 + GNU config.guess ($timestamp) 61 + 62 + Originally written by Per Bothner. 63 + Copyright 1992-2022 Free Software Foundation, Inc. 64 + 65 + This is free software; see the source for copying conditions. There is NO 66 + warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." 67 + 68 + help=" 69 + Try \`$me --help' for more information." 70 + 71 + # Parse command line 72 + while test $# -gt 0 ; do 73 + case $1 in 74 + --time-stamp | --time* | -t ) 75 + echo "$timestamp" ; exit ;; 76 + --version | -v ) 77 + echo "$version" ; exit ;; 78 + --help | --h* | -h ) 79 + echo "$usage"; exit ;; 80 + -- ) # Stop option processing 81 + shift; break ;; 82 + - ) # Use stdin as input. 83 + break ;; 84 + -* ) 85 + echo "$me: invalid option $1$help" >&2 86 + exit 1 ;; 87 + * ) 88 + break ;; 89 + esac 90 + done 91 + 92 + if test $# != 0; then 93 + echo "$me: too many arguments$help" >&2 94 + exit 1 95 + fi 96 + 97 + # Just in case it came from the environment. 98 + GUESS= 99 + 100 + # CC_FOR_BUILD -- compiler used by this script. Note that the use of a 101 + # compiler to aid in system detection is discouraged as it requires 102 + # temporary files to be created and, as you can see below, it is a 103 + # headache to deal with in a portable fashion. 104 + 105 + # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still 106 + # use `HOST_CC' if defined, but it is deprecated. 107 + 108 + # Portable tmp directory creation inspired by the Autoconf team. 109 + 110 + tmp= 111 + # shellcheck disable=SC2172 112 + trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 113 + 114 + set_cc_for_build() { 115 + # prevent multiple calls if $tmp is already set 116 + test "$tmp" && return 0 117 + : "${TMPDIR=/tmp}" 118 + # shellcheck disable=SC2039,SC3028 119 + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || 120 + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || 121 + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || 122 + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } 123 + dummy=$tmp/dummy 124 + case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in 125 + ,,) echo "int x;" > "$dummy.c" 126 + for driver in cc gcc c89 c99 ; do 127 + if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then 128 + CC_FOR_BUILD=$driver 129 + break 130 + fi 131 + done 132 + if test x"$CC_FOR_BUILD" = x ; then 133 + CC_FOR_BUILD=no_compiler_found 134 + fi 135 + ;; 136 + ,,*) CC_FOR_BUILD=$CC ;; 137 + ,*,*) CC_FOR_BUILD=$HOST_CC ;; 138 + esac 139 + } 140 + 141 + # This is needed to find uname on a Pyramid OSx when run in the BSD universe. 142 + # (ghazi@noc.rutgers.edu 1994-08-24) 143 + if test -f /.attbin/uname ; then 144 + PATH=$PATH:/.attbin ; export PATH 145 + fi 146 + 147 + UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown 148 + UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown 149 + UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown 150 + UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown 151 + 152 + case $UNAME_SYSTEM in 153 + Linux|GNU|GNU/*) 154 + LIBC=unknown 155 + 156 + set_cc_for_build 157 + cat <<-EOF > "$dummy.c" 158 + #include <features.h> 159 + #if defined(__UCLIBC__) 160 + LIBC=uclibc 161 + #elif defined(__dietlibc__) 162 + LIBC=dietlibc 163 + #elif defined(__GLIBC__) 164 + LIBC=gnu 165 + #else 166 + #include <stdarg.h> 167 + /* First heuristic to detect musl libc. */ 168 + #ifdef __DEFINED_va_list 169 + LIBC=musl 170 + #endif 171 + #endif 172 + EOF 173 + cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` 174 + eval "$cc_set_libc" 175 + 176 + # Second heuristic to detect musl libc. 177 + if [ "$LIBC" = unknown ] && 178 + command -v ldd >/dev/null && 179 + ldd --version 2>&1 | grep -q ^musl; then 180 + LIBC=musl 181 + fi 182 + 183 + # If the system lacks a compiler, then just pick glibc. 184 + # We could probably try harder. 185 + if [ "$LIBC" = unknown ]; then 186 + LIBC=gnu 187 + fi 188 + ;; 189 + esac 190 + 191 + # Note: order is significant - the case branches are not exclusive. 192 + 193 + case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in 194 + *:NetBSD:*:*) 195 + # NetBSD (nbsd) targets should (where applicable) match one or 196 + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, 197 + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently 198 + # switched to ELF, *-*-netbsd* would select the old 199 + # object file format. This provides both forward 200 + # compatibility and a consistent mechanism for selecting the 201 + # object file format. 202 + # 203 + # Note: NetBSD doesn't particularly care about the vendor 204 + # portion of the name. We always set it to "unknown". 205 + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ 206 + /sbin/sysctl -n hw.machine_arch 2>/dev/null || \ 207 + /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \ 208 + echo unknown)` 209 + case $UNAME_MACHINE_ARCH in 210 + aarch64eb) machine=aarch64_be-unknown ;; 211 + armeb) machine=armeb-unknown ;; 212 + arm*) machine=arm-unknown ;; 213 + sh3el) machine=shl-unknown ;; 214 + sh3eb) machine=sh-unknown ;; 215 + sh5el) machine=sh5le-unknown ;; 216 + earmv*) 217 + arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` 218 + endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` 219 + machine=${arch}${endian}-unknown 220 + ;; 221 + *) machine=$UNAME_MACHINE_ARCH-unknown ;; 222 + esac 223 + # The Operating System including object format, if it has switched 224 + # to ELF recently (or will in the future) and ABI. 225 + case $UNAME_MACHINE_ARCH in 226 + earm*) 227 + os=netbsdelf 228 + ;; 229 + arm*|i386|m68k|ns32k|sh3*|sparc|vax) 230 + set_cc_for_build 231 + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ 232 + | grep -q __ELF__ 233 + then 234 + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). 235 + # Return netbsd for either. FIX? 236 + os=netbsd 237 + else 238 + os=netbsdelf 239 + fi 240 + ;; 241 + *) 242 + os=netbsd 243 + ;; 244 + esac 245 + # Determine ABI tags. 246 + case $UNAME_MACHINE_ARCH in 247 + earm*) 248 + expr='s/^earmv[0-9]/-eabi/;s/eb$//' 249 + abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` 250 + ;; 251 + esac 252 + # The OS release 253 + # Debian GNU/NetBSD machines have a different userland, and 254 + # thus, need a distinct triplet. However, they do not need 255 + # kernel version information, so it can be replaced with a 256 + # suitable tag, in the style of linux-gnu. 257 + case $UNAME_VERSION in 258 + Debian*) 259 + release='-gnu' 260 + ;; 261 + *) 262 + release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` 263 + ;; 264 + esac 265 + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: 266 + # contains redundant information, the shorter form: 267 + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. 268 + GUESS=$machine-${os}${release}${abi-} 269 + ;; 270 + *:Bitrig:*:*) 271 + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` 272 + GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE 273 + ;; 274 + *:OpenBSD:*:*) 275 + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` 276 + GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE 277 + ;; 278 + *:SecBSD:*:*) 279 + UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'` 280 + GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE 281 + ;; 282 + *:LibertyBSD:*:*) 283 + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` 284 + GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE 285 + ;; 286 + *:MidnightBSD:*:*) 287 + GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE 288 + ;; 289 + *:ekkoBSD:*:*) 290 + GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE 291 + ;; 292 + *:SolidBSD:*:*) 293 + GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE 294 + ;; 295 + *:OS108:*:*) 296 + GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE 297 + ;; 298 + macppc:MirBSD:*:*) 299 + GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE 300 + ;; 301 + *:MirBSD:*:*) 302 + GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE 303 + ;; 304 + *:Sortix:*:*) 305 + GUESS=$UNAME_MACHINE-unknown-sortix 306 + ;; 307 + *:Twizzler:*:*) 308 + GUESS=$UNAME_MACHINE-unknown-twizzler 309 + ;; 310 + *:Redox:*:*) 311 + GUESS=$UNAME_MACHINE-unknown-redox 312 + ;; 313 + mips:OSF1:*.*) 314 + GUESS=mips-dec-osf1 315 + ;; 316 + alpha:OSF1:*:*) 317 + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. 318 + trap '' 0 319 + case $UNAME_RELEASE in 320 + *4.0) 321 + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` 322 + ;; 323 + *5.*) 324 + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` 325 + ;; 326 + esac 327 + # According to Compaq, /usr/sbin/psrinfo has been available on 328 + # OSF/1 and Tru64 systems produced since 1995. I hope that 329 + # covers most systems running today. This code pipes the CPU 330 + # types through head -n 1, so we only detect the type of CPU 0. 331 + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` 332 + case $ALPHA_CPU_TYPE in 333 + "EV4 (21064)") 334 + UNAME_MACHINE=alpha ;; 335 + "EV4.5 (21064)") 336 + UNAME_MACHINE=alpha ;; 337 + "LCA4 (21066/21068)") 338 + UNAME_MACHINE=alpha ;; 339 + "EV5 (21164)") 340 + UNAME_MACHINE=alphaev5 ;; 341 + "EV5.6 (21164A)") 342 + UNAME_MACHINE=alphaev56 ;; 343 + "EV5.6 (21164PC)") 344 + UNAME_MACHINE=alphapca56 ;; 345 + "EV5.7 (21164PC)") 346 + UNAME_MACHINE=alphapca57 ;; 347 + "EV6 (21264)") 348 + UNAME_MACHINE=alphaev6 ;; 349 + "EV6.7 (21264A)") 350 + UNAME_MACHINE=alphaev67 ;; 351 + "EV6.8CB (21264C)") 352 + UNAME_MACHINE=alphaev68 ;; 353 + "EV6.8AL (21264B)") 354 + UNAME_MACHINE=alphaev68 ;; 355 + "EV6.8CX (21264D)") 356 + UNAME_MACHINE=alphaev68 ;; 357 + "EV6.9A (21264/EV69A)") 358 + UNAME_MACHINE=alphaev69 ;; 359 + "EV7 (21364)") 360 + UNAME_MACHINE=alphaev7 ;; 361 + "EV7.9 (21364A)") 362 + UNAME_MACHINE=alphaev79 ;; 363 + esac 364 + # A Pn.n version is a patched version. 365 + # A Vn.n version is a released version. 366 + # A Tn.n version is a released field test version. 367 + # A Xn.n version is an unreleased experimental baselevel. 368 + # 1.2 uses "1.2" for uname -r. 369 + OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` 370 + GUESS=$UNAME_MACHINE-dec-osf$OSF_REL 371 + ;; 372 + Amiga*:UNIX_System_V:4.0:*) 373 + GUESS=m68k-unknown-sysv4 374 + ;; 375 + *:[Aa]miga[Oo][Ss]:*:*) 376 + GUESS=$UNAME_MACHINE-unknown-amigaos 377 + ;; 378 + *:[Mm]orph[Oo][Ss]:*:*) 379 + GUESS=$UNAME_MACHINE-unknown-morphos 380 + ;; 381 + *:OS/390:*:*) 382 + GUESS=i370-ibm-openedition 383 + ;; 384 + *:z/VM:*:*) 385 + GUESS=s390-ibm-zvmoe 386 + ;; 387 + *:OS400:*:*) 388 + GUESS=powerpc-ibm-os400 389 + ;; 390 + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) 391 + GUESS=arm-acorn-riscix$UNAME_RELEASE 392 + ;; 393 + arm*:riscos:*:*|arm*:RISCOS:*:*) 394 + GUESS=arm-unknown-riscos 395 + ;; 396 + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) 397 + GUESS=hppa1.1-hitachi-hiuxmpp 398 + ;; 399 + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) 400 + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. 401 + case `(/bin/universe) 2>/dev/null` in 402 + att) GUESS=pyramid-pyramid-sysv3 ;; 403 + *) GUESS=pyramid-pyramid-bsd ;; 404 + esac 405 + ;; 406 + NILE*:*:*:dcosx) 407 + GUESS=pyramid-pyramid-svr4 408 + ;; 409 + DRS?6000:unix:4.0:6*) 410 + GUESS=sparc-icl-nx6 411 + ;; 412 + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) 413 + case `/usr/bin/uname -p` in 414 + sparc) GUESS=sparc-icl-nx7 ;; 415 + esac 416 + ;; 417 + s390x:SunOS:*:*) 418 + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` 419 + GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL 420 + ;; 421 + sun4H:SunOS:5.*:*) 422 + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` 423 + GUESS=sparc-hal-solaris2$SUN_REL 424 + ;; 425 + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) 426 + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` 427 + GUESS=sparc-sun-solaris2$SUN_REL 428 + ;; 429 + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) 430 + GUESS=i386-pc-auroraux$UNAME_RELEASE 431 + ;; 432 + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) 433 + set_cc_for_build 434 + SUN_ARCH=i386 435 + # If there is a compiler, see if it is configured for 64-bit objects. 436 + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. 437 + # This test works for both compilers. 438 + if test "$CC_FOR_BUILD" != no_compiler_found; then 439 + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ 440 + (CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \ 441 + grep IS_64BIT_ARCH >/dev/null 442 + then 443 + SUN_ARCH=x86_64 444 + fi 445 + fi 446 + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` 447 + GUESS=$SUN_ARCH-pc-solaris2$SUN_REL 448 + ;; 449 + sun4*:SunOS:6*:*) 450 + # According to config.sub, this is the proper way to canonicalize 451 + # SunOS6. Hard to guess exactly what SunOS6 will be like, but 452 + # it's likely to be more like Solaris than SunOS4. 453 + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` 454 + GUESS=sparc-sun-solaris3$SUN_REL 455 + ;; 456 + sun4*:SunOS:*:*) 457 + case `/usr/bin/arch -k` in 458 + Series*|S4*) 459 + UNAME_RELEASE=`uname -v` 460 + ;; 461 + esac 462 + # Japanese Language versions have a version number like `4.1.3-JL'. 463 + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'` 464 + GUESS=sparc-sun-sunos$SUN_REL 465 + ;; 466 + sun3*:SunOS:*:*) 467 + GUESS=m68k-sun-sunos$UNAME_RELEASE 468 + ;; 469 + sun*:*:4.2BSD:*) 470 + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` 471 + test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 472 + case `/bin/arch` in 473 + sun3) 474 + GUESS=m68k-sun-sunos$UNAME_RELEASE 475 + ;; 476 + sun4) 477 + GUESS=sparc-sun-sunos$UNAME_RELEASE 478 + ;; 479 + esac 480 + ;; 481 + aushp:SunOS:*:*) 482 + GUESS=sparc-auspex-sunos$UNAME_RELEASE 483 + ;; 484 + # The situation for MiNT is a little confusing. The machine name 485 + # can be virtually everything (everything which is not 486 + # "atarist" or "atariste" at least should have a processor 487 + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" 488 + # to the lowercase version "mint" (or "freemint"). Finally 489 + # the system name "TOS" denotes a system which is actually not 490 + # MiNT. But MiNT is downward compatible to TOS, so this should 491 + # be no problem. 492 + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) 493 + GUESS=m68k-atari-mint$UNAME_RELEASE 494 + ;; 495 + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) 496 + GUESS=m68k-atari-mint$UNAME_RELEASE 497 + ;; 498 + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) 499 + GUESS=m68k-atari-mint$UNAME_RELEASE 500 + ;; 501 + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) 502 + GUESS=m68k-milan-mint$UNAME_RELEASE 503 + ;; 504 + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) 505 + GUESS=m68k-hades-mint$UNAME_RELEASE 506 + ;; 507 + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) 508 + GUESS=m68k-unknown-mint$UNAME_RELEASE 509 + ;; 510 + m68k:machten:*:*) 511 + GUESS=m68k-apple-machten$UNAME_RELEASE 512 + ;; 513 + powerpc:machten:*:*) 514 + GUESS=powerpc-apple-machten$UNAME_RELEASE 515 + ;; 516 + RISC*:Mach:*:*) 517 + GUESS=mips-dec-mach_bsd4.3 518 + ;; 519 + RISC*:ULTRIX:*:*) 520 + GUESS=mips-dec-ultrix$UNAME_RELEASE 521 + ;; 522 + VAX*:ULTRIX*:*:*) 523 + GUESS=vax-dec-ultrix$UNAME_RELEASE 524 + ;; 525 + 2020:CLIX:*:* | 2430:CLIX:*:*) 526 + GUESS=clipper-intergraph-clix$UNAME_RELEASE 527 + ;; 528 + mips:*:*:UMIPS | mips:*:*:RISCos) 529 + set_cc_for_build 530 + sed 's/^ //' << EOF > "$dummy.c" 531 + #ifdef __cplusplus 532 + #include <stdio.h> /* for printf() prototype */ 533 + int main (int argc, char *argv[]) { 534 + #else 535 + int main (argc, argv) int argc; char *argv[]; { 536 + #endif 537 + #if defined (host_mips) && defined (MIPSEB) 538 + #if defined (SYSTYPE_SYSV) 539 + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); 540 + #endif 541 + #if defined (SYSTYPE_SVR4) 542 + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); 543 + #endif 544 + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) 545 + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); 546 + #endif 547 + #endif 548 + exit (-1); 549 + } 550 + EOF 551 + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && 552 + dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && 553 + SYSTEM_NAME=`"$dummy" "$dummyarg"` && 554 + { echo "$SYSTEM_NAME"; exit; } 555 + GUESS=mips-mips-riscos$UNAME_RELEASE 556 + ;; 557 + Motorola:PowerMAX_OS:*:*) 558 + GUESS=powerpc-motorola-powermax 559 + ;; 560 + Motorola:*:4.3:PL8-*) 561 + GUESS=powerpc-harris-powermax 562 + ;; 563 + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) 564 + GUESS=powerpc-harris-powermax 565 + ;; 566 + Night_Hawk:Power_UNIX:*:*) 567 + GUESS=powerpc-harris-powerunix 568 + ;; 569 + m88k:CX/UX:7*:*) 570 + GUESS=m88k-harris-cxux7 571 + ;; 572 + m88k:*:4*:R4*) 573 + GUESS=m88k-motorola-sysv4 574 + ;; 575 + m88k:*:3*:R3*) 576 + GUESS=m88k-motorola-sysv3 577 + ;; 578 + AViiON:dgux:*:*) 579 + # DG/UX returns AViiON for all architectures 580 + UNAME_PROCESSOR=`/usr/bin/uname -p` 581 + if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110 582 + then 583 + if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \ 584 + test "$TARGET_BINARY_INTERFACE"x = x 585 + then 586 + GUESS=m88k-dg-dgux$UNAME_RELEASE 587 + else 588 + GUESS=m88k-dg-dguxbcs$UNAME_RELEASE 589 + fi 590 + else 591 + GUESS=i586-dg-dgux$UNAME_RELEASE 592 + fi 593 + ;; 594 + M88*:DolphinOS:*:*) # DolphinOS (SVR3) 595 + GUESS=m88k-dolphin-sysv3 596 + ;; 597 + M88*:*:R3*:*) 598 + # Delta 88k system running SVR3 599 + GUESS=m88k-motorola-sysv3 600 + ;; 601 + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) 602 + GUESS=m88k-tektronix-sysv3 603 + ;; 604 + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) 605 + GUESS=m68k-tektronix-bsd 606 + ;; 607 + *:IRIX*:*:*) 608 + IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'` 609 + GUESS=mips-sgi-irix$IRIX_REL 610 + ;; 611 + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. 612 + GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id 613 + ;; # Note that: echo "'`uname -s`'" gives 'AIX ' 614 + i*86:AIX:*:*) 615 + GUESS=i386-ibm-aix 616 + ;; 617 + ia64:AIX:*:*) 618 + if test -x /usr/bin/oslevel ; then 619 + IBM_REV=`/usr/bin/oslevel` 620 + else 621 + IBM_REV=$UNAME_VERSION.$UNAME_RELEASE 622 + fi 623 + GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV 624 + ;; 625 + *:AIX:2:3) 626 + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then 627 + set_cc_for_build 628 + sed 's/^ //' << EOF > "$dummy.c" 629 + #include <sys/systemcfg.h> 630 + 631 + main() 632 + { 633 + if (!__power_pc()) 634 + exit(1); 635 + puts("powerpc-ibm-aix3.2.5"); 636 + exit(0); 637 + } 638 + EOF 639 + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` 640 + then 641 + GUESS=$SYSTEM_NAME 642 + else 643 + GUESS=rs6000-ibm-aix3.2.5 644 + fi 645 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then 646 + GUESS=rs6000-ibm-aix3.2.4 647 + else 648 + GUESS=rs6000-ibm-aix3.2 649 + fi 650 + ;; 651 + *:AIX:*:[4567]) 652 + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` 653 + if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then 654 + IBM_ARCH=rs6000 655 + else 656 + IBM_ARCH=powerpc 657 + fi 658 + if test -x /usr/bin/lslpp ; then 659 + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \ 660 + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` 661 + else 662 + IBM_REV=$UNAME_VERSION.$UNAME_RELEASE 663 + fi 664 + GUESS=$IBM_ARCH-ibm-aix$IBM_REV 665 + ;; 666 + *:AIX:*:*) 667 + GUESS=rs6000-ibm-aix 668 + ;; 669 + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) 670 + GUESS=romp-ibm-bsd4.4 671 + ;; 672 + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and 673 + GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to 674 + ;; # report: romp-ibm BSD 4.3 675 + *:BOSX:*:*) 676 + GUESS=rs6000-bull-bosx 677 + ;; 678 + DPX/2?00:B.O.S.:*:*) 679 + GUESS=m68k-bull-sysv3 680 + ;; 681 + 9000/[34]??:4.3bsd:1.*:*) 682 + GUESS=m68k-hp-bsd 683 + ;; 684 + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) 685 + GUESS=m68k-hp-bsd4.4 686 + ;; 687 + 9000/[34678]??:HP-UX:*:*) 688 + HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` 689 + case $UNAME_MACHINE in 690 + 9000/31?) HP_ARCH=m68000 ;; 691 + 9000/[34]??) HP_ARCH=m68k ;; 692 + 9000/[678][0-9][0-9]) 693 + if test -x /usr/bin/getconf; then 694 + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` 695 + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` 696 + case $sc_cpu_version in 697 + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 698 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 699 + 532) # CPU_PA_RISC2_0 700 + case $sc_kernel_bits in 701 + 32) HP_ARCH=hppa2.0n ;; 702 + 64) HP_ARCH=hppa2.0w ;; 703 + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 704 + esac ;; 705 + esac 706 + fi 707 + if test "$HP_ARCH" = ""; then 708 + set_cc_for_build 709 + sed 's/^ //' << EOF > "$dummy.c" 710 + 711 + #define _HPUX_SOURCE 712 + #include <stdlib.h> 713 + #include <unistd.h> 714 + 715 + int main () 716 + { 717 + #if defined(_SC_KERNEL_BITS) 718 + long bits = sysconf(_SC_KERNEL_BITS); 719 + #endif 720 + long cpu = sysconf (_SC_CPU_VERSION); 721 + 722 + switch (cpu) 723 + { 724 + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; 725 + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; 726 + case CPU_PA_RISC2_0: 727 + #if defined(_SC_KERNEL_BITS) 728 + switch (bits) 729 + { 730 + case 64: puts ("hppa2.0w"); break; 731 + case 32: puts ("hppa2.0n"); break; 732 + default: puts ("hppa2.0"); break; 733 + } break; 734 + #else /* !defined(_SC_KERNEL_BITS) */ 735 + puts ("hppa2.0"); break; 736 + #endif 737 + default: puts ("hppa1.0"); break; 738 + } 739 + exit (0); 740 + } 741 + EOF 742 + (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` 743 + test -z "$HP_ARCH" && HP_ARCH=hppa 744 + fi ;; 745 + esac 746 + if test "$HP_ARCH" = hppa2.0w 747 + then 748 + set_cc_for_build 749 + 750 + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating 751 + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler 752 + # generating 64-bit code. GNU and HP use different nomenclature: 753 + # 754 + # $ CC_FOR_BUILD=cc ./config.guess 755 + # => hppa2.0w-hp-hpux11.23 756 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess 757 + # => hppa64-hp-hpux11.23 758 + 759 + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | 760 + grep -q __LP64__ 761 + then 762 + HP_ARCH=hppa2.0w 763 + else 764 + HP_ARCH=hppa64 765 + fi 766 + fi 767 + GUESS=$HP_ARCH-hp-hpux$HPUX_REV 768 + ;; 769 + ia64:HP-UX:*:*) 770 + HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` 771 + GUESS=ia64-hp-hpux$HPUX_REV 772 + ;; 773 + 3050*:HI-UX:*:*) 774 + set_cc_for_build 775 + sed 's/^ //' << EOF > "$dummy.c" 776 + #include <unistd.h> 777 + int 778 + main () 779 + { 780 + long cpu = sysconf (_SC_CPU_VERSION); 781 + /* The order matters, because CPU_IS_HP_MC68K erroneously returns 782 + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct 783 + results, however. */ 784 + if (CPU_IS_PA_RISC (cpu)) 785 + { 786 + switch (cpu) 787 + { 788 + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; 789 + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; 790 + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; 791 + default: puts ("hppa-hitachi-hiuxwe2"); break; 792 + } 793 + } 794 + else if (CPU_IS_HP_MC68K (cpu)) 795 + puts ("m68k-hitachi-hiuxwe2"); 796 + else puts ("unknown-hitachi-hiuxwe2"); 797 + exit (0); 798 + } 799 + EOF 800 + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && 801 + { echo "$SYSTEM_NAME"; exit; } 802 + GUESS=unknown-hitachi-hiuxwe2 803 + ;; 804 + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) 805 + GUESS=hppa1.1-hp-bsd 806 + ;; 807 + 9000/8??:4.3bsd:*:*) 808 + GUESS=hppa1.0-hp-bsd 809 + ;; 810 + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) 811 + GUESS=hppa1.0-hp-mpeix 812 + ;; 813 + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) 814 + GUESS=hppa1.1-hp-osf 815 + ;; 816 + hp8??:OSF1:*:*) 817 + GUESS=hppa1.0-hp-osf 818 + ;; 819 + i*86:OSF1:*:*) 820 + if test -x /usr/sbin/sysversion ; then 821 + GUESS=$UNAME_MACHINE-unknown-osf1mk 822 + else 823 + GUESS=$UNAME_MACHINE-unknown-osf1 824 + fi 825 + ;; 826 + parisc*:Lites*:*:*) 827 + GUESS=hppa1.1-hp-lites 828 + ;; 829 + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) 830 + GUESS=c1-convex-bsd 831 + ;; 832 + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) 833 + if getsysinfo -f scalar_acc 834 + then echo c32-convex-bsd 835 + else echo c2-convex-bsd 836 + fi 837 + exit ;; 838 + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) 839 + GUESS=c34-convex-bsd 840 + ;; 841 + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) 842 + GUESS=c38-convex-bsd 843 + ;; 844 + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) 845 + GUESS=c4-convex-bsd 846 + ;; 847 + CRAY*Y-MP:*:*:*) 848 + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` 849 + GUESS=ymp-cray-unicos$CRAY_REL 850 + ;; 851 + CRAY*[A-Z]90:*:*:*) 852 + echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ 853 + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ 854 + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ 855 + -e 's/\.[^.]*$/.X/' 856 + exit ;; 857 + CRAY*TS:*:*:*) 858 + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` 859 + GUESS=t90-cray-unicos$CRAY_REL 860 + ;; 861 + CRAY*T3E:*:*:*) 862 + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` 863 + GUESS=alphaev5-cray-unicosmk$CRAY_REL 864 + ;; 865 + CRAY*SV1:*:*:*) 866 + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` 867 + GUESS=sv1-cray-unicos$CRAY_REL 868 + ;; 869 + *:UNICOS/mp:*:*) 870 + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` 871 + GUESS=craynv-cray-unicosmp$CRAY_REL 872 + ;; 873 + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) 874 + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` 875 + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` 876 + FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` 877 + GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} 878 + ;; 879 + 5000:UNIX_System_V:4.*:*) 880 + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` 881 + FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` 882 + GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} 883 + ;; 884 + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) 885 + GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE 886 + ;; 887 + sparc*:BSD/OS:*:*) 888 + GUESS=sparc-unknown-bsdi$UNAME_RELEASE 889 + ;; 890 + *:BSD/OS:*:*) 891 + GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE 892 + ;; 893 + arm:FreeBSD:*:*) 894 + UNAME_PROCESSOR=`uname -p` 895 + set_cc_for_build 896 + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ 897 + | grep -q __ARM_PCS_VFP 898 + then 899 + FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` 900 + GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi 901 + else 902 + FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` 903 + GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf 904 + fi 905 + ;; 906 + *:FreeBSD:*:*) 907 + UNAME_PROCESSOR=`/usr/bin/uname -p` 908 + case $UNAME_PROCESSOR in 909 + amd64) 910 + UNAME_PROCESSOR=x86_64 ;; 911 + i386) 912 + UNAME_PROCESSOR=i586 ;; 913 + esac 914 + FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` 915 + GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL 916 + ;; 917 + i*:CYGWIN*:*) 918 + GUESS=$UNAME_MACHINE-pc-cygwin 919 + ;; 920 + *:MINGW64*:*) 921 + GUESS=$UNAME_MACHINE-pc-mingw64 922 + ;; 923 + *:MINGW*:*) 924 + GUESS=$UNAME_MACHINE-pc-mingw32 925 + ;; 926 + *:MSYS*:*) 927 + GUESS=$UNAME_MACHINE-pc-msys 928 + ;; 929 + i*:PW*:*) 930 + GUESS=$UNAME_MACHINE-pc-pw32 931 + ;; 932 + *:SerenityOS:*:*) 933 + GUESS=$UNAME_MACHINE-pc-serenity 934 + ;; 935 + *:Interix*:*) 936 + case $UNAME_MACHINE in 937 + x86) 938 + GUESS=i586-pc-interix$UNAME_RELEASE 939 + ;; 940 + authenticamd | genuineintel | EM64T) 941 + GUESS=x86_64-unknown-interix$UNAME_RELEASE 942 + ;; 943 + IA64) 944 + GUESS=ia64-unknown-interix$UNAME_RELEASE 945 + ;; 946 + esac ;; 947 + i*:UWIN*:*) 948 + GUESS=$UNAME_MACHINE-pc-uwin 949 + ;; 950 + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) 951 + GUESS=x86_64-pc-cygwin 952 + ;; 953 + prep*:SunOS:5.*:*) 954 + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` 955 + GUESS=powerpcle-unknown-solaris2$SUN_REL 956 + ;; 957 + *:GNU:*:*) 958 + # the GNU system 959 + GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'` 960 + GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'` 961 + GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL 962 + ;; 963 + *:GNU/*:*:*) 964 + # other systems with GNU libc and userland 965 + GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"` 966 + GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` 967 + GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC 968 + ;; 969 + *:Minix:*:*) 970 + GUESS=$UNAME_MACHINE-unknown-minix 971 + ;; 972 + aarch64:Linux:*:*) 973 + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC 974 + ;; 975 + aarch64_be:Linux:*:*) 976 + UNAME_MACHINE=aarch64_be 977 + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC 978 + ;; 979 + alpha:Linux:*:*) 980 + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in 981 + EV5) UNAME_MACHINE=alphaev5 ;; 982 + EV56) UNAME_MACHINE=alphaev56 ;; 983 + PCA56) UNAME_MACHINE=alphapca56 ;; 984 + PCA57) UNAME_MACHINE=alphapca56 ;; 985 + EV6) UNAME_MACHINE=alphaev6 ;; 986 + EV67) UNAME_MACHINE=alphaev67 ;; 987 + EV68*) UNAME_MACHINE=alphaev68 ;; 988 + esac 989 + objdump --private-headers /bin/sh | grep -q ld.so.1 990 + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi 991 + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC 992 + ;; 993 + arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*) 994 + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC 995 + ;; 996 + arm*:Linux:*:*) 997 + set_cc_for_build 998 + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ 999 + | grep -q __ARM_EABI__ 1000 + then 1001 + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC 1002 + else 1003 + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ 1004 + | grep -q __ARM_PCS_VFP 1005 + then 1006 + GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi 1007 + else 1008 + GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf 1009 + fi 1010 + fi 1011 + ;; 1012 + avr32*:Linux:*:*) 1013 + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC 1014 + ;; 1015 + cris:Linux:*:*) 1016 + GUESS=$UNAME_MACHINE-axis-linux-$LIBC 1017 + ;; 1018 + crisv32:Linux:*:*) 1019 + GUESS=$UNAME_MACHINE-axis-linux-$LIBC 1020 + ;; 1021 + e2k:Linux:*:*) 1022 + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC 1023 + ;; 1024 + frv:Linux:*:*) 1025 + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC 1026 + ;; 1027 + hexagon:Linux:*:*) 1028 + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC 1029 + ;; 1030 + i*86:Linux:*:*) 1031 + GUESS=$UNAME_MACHINE-pc-linux-$LIBC 1032 + ;; 1033 + ia64:Linux:*:*) 1034 + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC 1035 + ;; 1036 + k1om:Linux:*:*) 1037 + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC 1038 + ;; 1039 + loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*) 1040 + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC 1041 + ;; 1042 + m32r*:Linux:*:*) 1043 + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC 1044 + ;; 1045 + m68*:Linux:*:*) 1046 + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC 1047 + ;; 1048 + mips:Linux:*:* | mips64:Linux:*:*) 1049 + set_cc_for_build 1050 + IS_GLIBC=0 1051 + test x"${LIBC}" = xgnu && IS_GLIBC=1 1052 + sed 's/^ //' << EOF > "$dummy.c" 1053 + #undef CPU 1054 + #undef mips 1055 + #undef mipsel 1056 + #undef mips64 1057 + #undef mips64el 1058 + #if ${IS_GLIBC} && defined(_ABI64) 1059 + LIBCABI=gnuabi64 1060 + #else 1061 + #if ${IS_GLIBC} && defined(_ABIN32) 1062 + LIBCABI=gnuabin32 1063 + #else 1064 + LIBCABI=${LIBC} 1065 + #endif 1066 + #endif 1067 + 1068 + #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 1069 + CPU=mipsisa64r6 1070 + #else 1071 + #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 1072 + CPU=mipsisa32r6 1073 + #else 1074 + #if defined(__mips64) 1075 + CPU=mips64 1076 + #else 1077 + CPU=mips 1078 + #endif 1079 + #endif 1080 + #endif 1081 + 1082 + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) 1083 + MIPS_ENDIAN=el 1084 + #else 1085 + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) 1086 + MIPS_ENDIAN= 1087 + #else 1088 + MIPS_ENDIAN= 1089 + #endif 1090 + #endif 1091 + EOF 1092 + cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'` 1093 + eval "$cc_set_vars" 1094 + test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } 1095 + ;; 1096 + mips64el:Linux:*:*) 1097 + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC 1098 + ;; 1099 + openrisc*:Linux:*:*) 1100 + GUESS=or1k-unknown-linux-$LIBC 1101 + ;; 1102 + or32:Linux:*:* | or1k*:Linux:*:*) 1103 + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC 1104 + ;; 1105 + padre:Linux:*:*) 1106 + GUESS=sparc-unknown-linux-$LIBC 1107 + ;; 1108 + parisc64:Linux:*:* | hppa64:Linux:*:*) 1109 + GUESS=hppa64-unknown-linux-$LIBC 1110 + ;; 1111 + parisc:Linux:*:* | hppa:Linux:*:*) 1112 + # Look for CPU level 1113 + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in 1114 + PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;; 1115 + PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;; 1116 + *) GUESS=hppa-unknown-linux-$LIBC ;; 1117 + esac 1118 + ;; 1119 + ppc64:Linux:*:*) 1120 + GUESS=powerpc64-unknown-linux-$LIBC 1121 + ;; 1122 + ppc:Linux:*:*) 1123 + GUESS=powerpc-unknown-linux-$LIBC 1124 + ;; 1125 + ppc64le:Linux:*:*) 1126 + GUESS=powerpc64le-unknown-linux-$LIBC 1127 + ;; 1128 + ppcle:Linux:*:*) 1129 + GUESS=powerpcle-unknown-linux-$LIBC 1130 + ;; 1131 + riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*) 1132 + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC 1133 + ;; 1134 + s390:Linux:*:* | s390x:Linux:*:*) 1135 + GUESS=$UNAME_MACHINE-ibm-linux-$LIBC 1136 + ;; 1137 + sh64*:Linux:*:*) 1138 + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC 1139 + ;; 1140 + sh*:Linux:*:*) 1141 + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC 1142 + ;; 1143 + sparc:Linux:*:* | sparc64:Linux:*:*) 1144 + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC 1145 + ;; 1146 + tile*:Linux:*:*) 1147 + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC 1148 + ;; 1149 + vax:Linux:*:*) 1150 + GUESS=$UNAME_MACHINE-dec-linux-$LIBC 1151 + ;; 1152 + x86_64:Linux:*:*) 1153 + set_cc_for_build 1154 + LIBCABI=$LIBC 1155 + if test "$CC_FOR_BUILD" != no_compiler_found; then 1156 + if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \ 1157 + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ 1158 + grep IS_X32 >/dev/null 1159 + then 1160 + LIBCABI=${LIBC}x32 1161 + fi 1162 + fi 1163 + GUESS=$UNAME_MACHINE-pc-linux-$LIBCABI 1164 + ;; 1165 + xtensa*:Linux:*:*) 1166 + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC 1167 + ;; 1168 + i*86:DYNIX/ptx:4*:*) 1169 + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. 1170 + # earlier versions are messed up and put the nodename in both 1171 + # sysname and nodename. 1172 + GUESS=i386-sequent-sysv4 1173 + ;; 1174 + i*86:UNIX_SV:4.2MP:2.*) 1175 + # Unixware is an offshoot of SVR4, but it has its own version 1176 + # number series starting with 2... 1177 + # I am not positive that other SVR4 systems won't match this, 1178 + # I just have to hope. -- rms. 1179 + # Use sysv4.2uw... so that sysv4* matches it. 1180 + GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION 1181 + ;; 1182 + i*86:OS/2:*:*) 1183 + # If we were able to find `uname', then EMX Unix compatibility 1184 + # is probably installed. 1185 + GUESS=$UNAME_MACHINE-pc-os2-emx 1186 + ;; 1187 + i*86:XTS-300:*:STOP) 1188 + GUESS=$UNAME_MACHINE-unknown-stop 1189 + ;; 1190 + i*86:atheos:*:*) 1191 + GUESS=$UNAME_MACHINE-unknown-atheos 1192 + ;; 1193 + i*86:syllable:*:*) 1194 + GUESS=$UNAME_MACHINE-pc-syllable 1195 + ;; 1196 + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) 1197 + GUESS=i386-unknown-lynxos$UNAME_RELEASE 1198 + ;; 1199 + i*86:*DOS:*:*) 1200 + GUESS=$UNAME_MACHINE-pc-msdosdjgpp 1201 + ;; 1202 + i*86:*:4.*:*) 1203 + UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` 1204 + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then 1205 + GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL 1206 + else 1207 + GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL 1208 + fi 1209 + ;; 1210 + i*86:*:5:[678]*) 1211 + # UnixWare 7.x, OpenUNIX and OpenServer 6. 1212 + case `/bin/uname -X | grep "^Machine"` in 1213 + *486*) UNAME_MACHINE=i486 ;; 1214 + *Pentium) UNAME_MACHINE=i586 ;; 1215 + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; 1216 + esac 1217 + GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} 1218 + ;; 1219 + i*86:*:3.2:*) 1220 + if test -f /usr/options/cb.name; then 1221 + UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` 1222 + GUESS=$UNAME_MACHINE-pc-isc$UNAME_REL 1223 + elif /bin/uname -X 2>/dev/null >/dev/null ; then 1224 + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` 1225 + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 1226 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ 1227 + && UNAME_MACHINE=i586 1228 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ 1229 + && UNAME_MACHINE=i686 1230 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ 1231 + && UNAME_MACHINE=i686 1232 + GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL 1233 + else 1234 + GUESS=$UNAME_MACHINE-pc-sysv32 1235 + fi 1236 + ;; 1237 + pc:*:*:*) 1238 + # Left here for compatibility: 1239 + # uname -m prints for DJGPP always 'pc', but it prints nothing about 1240 + # the processor, so we play safe by assuming i586. 1241 + # Note: whatever this is, it MUST be the same as what config.sub 1242 + # prints for the "djgpp" host, or else GDB configure will decide that 1243 + # this is a cross-build. 1244 + GUESS=i586-pc-msdosdjgpp 1245 + ;; 1246 + Intel:Mach:3*:*) 1247 + GUESS=i386-pc-mach3 1248 + ;; 1249 + paragon:*:*:*) 1250 + GUESS=i860-intel-osf1 1251 + ;; 1252 + i860:*:4.*:*) # i860-SVR4 1253 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then 1254 + GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4 1255 + else # Add other i860-SVR4 vendors below as they are discovered. 1256 + GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4 1257 + fi 1258 + ;; 1259 + mini*:CTIX:SYS*5:*) 1260 + # "miniframe" 1261 + GUESS=m68010-convergent-sysv 1262 + ;; 1263 + mc68k:UNIX:SYSTEM5:3.51m) 1264 + GUESS=m68k-convergent-sysv 1265 + ;; 1266 + M680?0:D-NIX:5.3:*) 1267 + GUESS=m68k-diab-dnix 1268 + ;; 1269 + M68*:*:R3V[5678]*:*) 1270 + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 1271 + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) 1272 + OS_REL='' 1273 + test -r /etc/.relid \ 1274 + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` 1275 + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ 1276 + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } 1277 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ 1278 + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; 1279 + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) 1280 + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ 1281 + && { echo i486-ncr-sysv4; exit; } ;; 1282 + NCR*:*:4.2:* | MPRAS*:*:4.2:*) 1283 + OS_REL='.3' 1284 + test -r /etc/.relid \ 1285 + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` 1286 + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ 1287 + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } 1288 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ 1289 + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } 1290 + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ 1291 + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; 1292 + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) 1293 + GUESS=m68k-unknown-lynxos$UNAME_RELEASE 1294 + ;; 1295 + mc68030:UNIX_System_V:4.*:*) 1296 + GUESS=m68k-atari-sysv4 1297 + ;; 1298 + TSUNAMI:LynxOS:2.*:*) 1299 + GUESS=sparc-unknown-lynxos$UNAME_RELEASE 1300 + ;; 1301 + rs6000:LynxOS:2.*:*) 1302 + GUESS=rs6000-unknown-lynxos$UNAME_RELEASE 1303 + ;; 1304 + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) 1305 + GUESS=powerpc-unknown-lynxos$UNAME_RELEASE 1306 + ;; 1307 + SM[BE]S:UNIX_SV:*:*) 1308 + GUESS=mips-dde-sysv$UNAME_RELEASE 1309 + ;; 1310 + RM*:ReliantUNIX-*:*:*) 1311 + GUESS=mips-sni-sysv4 1312 + ;; 1313 + RM*:SINIX-*:*:*) 1314 + GUESS=mips-sni-sysv4 1315 + ;; 1316 + *:SINIX-*:*:*) 1317 + if uname -p 2>/dev/null >/dev/null ; then 1318 + UNAME_MACHINE=`(uname -p) 2>/dev/null` 1319 + GUESS=$UNAME_MACHINE-sni-sysv4 1320 + else 1321 + GUESS=ns32k-sni-sysv 1322 + fi 1323 + ;; 1324 + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort 1325 + # says <Richard.M.Bartel@ccMail.Census.GOV> 1326 + GUESS=i586-unisys-sysv4 1327 + ;; 1328 + *:UNIX_System_V:4*:FTX*) 1329 + # From Gerald Hewes <hewes@openmarket.com>. 1330 + # How about differentiating between stratus architectures? -djm 1331 + GUESS=hppa1.1-stratus-sysv4 1332 + ;; 1333 + *:*:*:FTX*) 1334 + # From seanf@swdc.stratus.com. 1335 + GUESS=i860-stratus-sysv4 1336 + ;; 1337 + i*86:VOS:*:*) 1338 + # From Paul.Green@stratus.com. 1339 + GUESS=$UNAME_MACHINE-stratus-vos 1340 + ;; 1341 + *:VOS:*:*) 1342 + # From Paul.Green@stratus.com. 1343 + GUESS=hppa1.1-stratus-vos 1344 + ;; 1345 + mc68*:A/UX:*:*) 1346 + GUESS=m68k-apple-aux$UNAME_RELEASE 1347 + ;; 1348 + news*:NEWS-OS:6*:*) 1349 + GUESS=mips-sony-newsos6 1350 + ;; 1351 + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) 1352 + if test -d /usr/nec; then 1353 + GUESS=mips-nec-sysv$UNAME_RELEASE 1354 + else 1355 + GUESS=mips-unknown-sysv$UNAME_RELEASE 1356 + fi 1357 + ;; 1358 + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. 1359 + GUESS=powerpc-be-beos 1360 + ;; 1361 + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. 1362 + GUESS=powerpc-apple-beos 1363 + ;; 1364 + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. 1365 + GUESS=i586-pc-beos 1366 + ;; 1367 + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. 1368 + GUESS=i586-pc-haiku 1369 + ;; 1370 + x86_64:Haiku:*:*) 1371 + GUESS=x86_64-unknown-haiku 1372 + ;; 1373 + SX-4:SUPER-UX:*:*) 1374 + GUESS=sx4-nec-superux$UNAME_RELEASE 1375 + ;; 1376 + SX-5:SUPER-UX:*:*) 1377 + GUESS=sx5-nec-superux$UNAME_RELEASE 1378 + ;; 1379 + SX-6:SUPER-UX:*:*) 1380 + GUESS=sx6-nec-superux$UNAME_RELEASE 1381 + ;; 1382 + SX-7:SUPER-UX:*:*) 1383 + GUESS=sx7-nec-superux$UNAME_RELEASE 1384 + ;; 1385 + SX-8:SUPER-UX:*:*) 1386 + GUESS=sx8-nec-superux$UNAME_RELEASE 1387 + ;; 1388 + SX-8R:SUPER-UX:*:*) 1389 + GUESS=sx8r-nec-superux$UNAME_RELEASE 1390 + ;; 1391 + SX-ACE:SUPER-UX:*:*) 1392 + GUESS=sxace-nec-superux$UNAME_RELEASE 1393 + ;; 1394 + Power*:Rhapsody:*:*) 1395 + GUESS=powerpc-apple-rhapsody$UNAME_RELEASE 1396 + ;; 1397 + *:Rhapsody:*:*) 1398 + GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE 1399 + ;; 1400 + arm64:Darwin:*:*) 1401 + GUESS=aarch64-apple-darwin$UNAME_RELEASE 1402 + ;; 1403 + *:Darwin:*:*) 1404 + UNAME_PROCESSOR=`uname -p` 1405 + case $UNAME_PROCESSOR in 1406 + unknown) UNAME_PROCESSOR=powerpc ;; 1407 + esac 1408 + if command -v xcode-select > /dev/null 2> /dev/null && \ 1409 + ! xcode-select --print-path > /dev/null 2> /dev/null ; then 1410 + # Avoid executing cc if there is no toolchain installed as 1411 + # cc will be a stub that puts up a graphical alert 1412 + # prompting the user to install developer tools. 1413 + CC_FOR_BUILD=no_compiler_found 1414 + else 1415 + set_cc_for_build 1416 + fi 1417 + if test "$CC_FOR_BUILD" != no_compiler_found; then 1418 + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ 1419 + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ 1420 + grep IS_64BIT_ARCH >/dev/null 1421 + then 1422 + case $UNAME_PROCESSOR in 1423 + i386) UNAME_PROCESSOR=x86_64 ;; 1424 + powerpc) UNAME_PROCESSOR=powerpc64 ;; 1425 + esac 1426 + fi 1427 + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc 1428 + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ 1429 + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ 1430 + grep IS_PPC >/dev/null 1431 + then 1432 + UNAME_PROCESSOR=powerpc 1433 + fi 1434 + elif test "$UNAME_PROCESSOR" = i386 ; then 1435 + # uname -m returns i386 or x86_64 1436 + UNAME_PROCESSOR=$UNAME_MACHINE 1437 + fi 1438 + GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE 1439 + ;; 1440 + *:procnto*:*:* | *:QNX:[0123456789]*:*) 1441 + UNAME_PROCESSOR=`uname -p` 1442 + if test "$UNAME_PROCESSOR" = x86; then 1443 + UNAME_PROCESSOR=i386 1444 + UNAME_MACHINE=pc 1445 + fi 1446 + GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE 1447 + ;; 1448 + *:QNX:*:4*) 1449 + GUESS=i386-pc-qnx 1450 + ;; 1451 + NEO-*:NONSTOP_KERNEL:*:*) 1452 + GUESS=neo-tandem-nsk$UNAME_RELEASE 1453 + ;; 1454 + NSE-*:NONSTOP_KERNEL:*:*) 1455 + GUESS=nse-tandem-nsk$UNAME_RELEASE 1456 + ;; 1457 + NSR-*:NONSTOP_KERNEL:*:*) 1458 + GUESS=nsr-tandem-nsk$UNAME_RELEASE 1459 + ;; 1460 + NSV-*:NONSTOP_KERNEL:*:*) 1461 + GUESS=nsv-tandem-nsk$UNAME_RELEASE 1462 + ;; 1463 + NSX-*:NONSTOP_KERNEL:*:*) 1464 + GUESS=nsx-tandem-nsk$UNAME_RELEASE 1465 + ;; 1466 + *:NonStop-UX:*:*) 1467 + GUESS=mips-compaq-nonstopux 1468 + ;; 1469 + BS2000:POSIX*:*:*) 1470 + GUESS=bs2000-siemens-sysv 1471 + ;; 1472 + DS/*:UNIX_System_V:*:*) 1473 + GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE 1474 + ;; 1475 + *:Plan9:*:*) 1476 + # "uname -m" is not consistent, so use $cputype instead. 386 1477 + # is converted to i386 for consistency with other x86 1478 + # operating systems. 1479 + if test "${cputype-}" = 386; then 1480 + UNAME_MACHINE=i386 1481 + elif test "x${cputype-}" != x; then 1482 + UNAME_MACHINE=$cputype 1483 + fi 1484 + GUESS=$UNAME_MACHINE-unknown-plan9 1485 + ;; 1486 + *:TOPS-10:*:*) 1487 + GUESS=pdp10-unknown-tops10 1488 + ;; 1489 + *:TENEX:*:*) 1490 + GUESS=pdp10-unknown-tenex 1491 + ;; 1492 + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) 1493 + GUESS=pdp10-dec-tops20 1494 + ;; 1495 + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) 1496 + GUESS=pdp10-xkl-tops20 1497 + ;; 1498 + *:TOPS-20:*:*) 1499 + GUESS=pdp10-unknown-tops20 1500 + ;; 1501 + *:ITS:*:*) 1502 + GUESS=pdp10-unknown-its 1503 + ;; 1504 + SEI:*:*:SEIUX) 1505 + GUESS=mips-sei-seiux$UNAME_RELEASE 1506 + ;; 1507 + *:DragonFly:*:*) 1508 + DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` 1509 + GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL 1510 + ;; 1511 + *:*VMS:*:*) 1512 + UNAME_MACHINE=`(uname -p) 2>/dev/null` 1513 + case $UNAME_MACHINE in 1514 + A*) GUESS=alpha-dec-vms ;; 1515 + I*) GUESS=ia64-dec-vms ;; 1516 + V*) GUESS=vax-dec-vms ;; 1517 + esac ;; 1518 + *:XENIX:*:SysV) 1519 + GUESS=i386-pc-xenix 1520 + ;; 1521 + i*86:skyos:*:*) 1522 + SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'` 1523 + GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL 1524 + ;; 1525 + i*86:rdos:*:*) 1526 + GUESS=$UNAME_MACHINE-pc-rdos 1527 + ;; 1528 + i*86:Fiwix:*:*) 1529 + GUESS=$UNAME_MACHINE-pc-fiwix 1530 + ;; 1531 + *:AROS:*:*) 1532 + GUESS=$UNAME_MACHINE-unknown-aros 1533 + ;; 1534 + x86_64:VMkernel:*:*) 1535 + GUESS=$UNAME_MACHINE-unknown-esx 1536 + ;; 1537 + amd64:Isilon\ OneFS:*:*) 1538 + GUESS=x86_64-unknown-onefs 1539 + ;; 1540 + *:Unleashed:*:*) 1541 + GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE 1542 + ;; 1543 + esac 1544 + 1545 + # Do we have a guess based on uname results? 1546 + if test "x$GUESS" != x; then 1547 + echo "$GUESS" 1548 + exit 1549 + fi 1550 + 1551 + # No uname command or uname output not recognized. 1552 + set_cc_for_build 1553 + cat > "$dummy.c" <<EOF 1554 + #ifdef _SEQUENT_ 1555 + #include <sys/types.h> 1556 + #include <sys/utsname.h> 1557 + #endif 1558 + #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) 1559 + #if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) 1560 + #include <signal.h> 1561 + #if defined(_SIZE_T_) || defined(SIGLOST) 1562 + #include <sys/utsname.h> 1563 + #endif 1564 + #endif 1565 + #endif 1566 + main () 1567 + { 1568 + #if defined (sony) 1569 + #if defined (MIPSEB) 1570 + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, 1571 + I don't know.... */ 1572 + printf ("mips-sony-bsd\n"); exit (0); 1573 + #else 1574 + #include <sys/param.h> 1575 + printf ("m68k-sony-newsos%s\n", 1576 + #ifdef NEWSOS4 1577 + "4" 1578 + #else 1579 + "" 1580 + #endif 1581 + ); exit (0); 1582 + #endif 1583 + #endif 1584 + 1585 + #if defined (NeXT) 1586 + #if !defined (__ARCHITECTURE__) 1587 + #define __ARCHITECTURE__ "m68k" 1588 + #endif 1589 + int version; 1590 + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; 1591 + if (version < 4) 1592 + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); 1593 + else 1594 + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); 1595 + exit (0); 1596 + #endif 1597 + 1598 + #if defined (MULTIMAX) || defined (n16) 1599 + #if defined (UMAXV) 1600 + printf ("ns32k-encore-sysv\n"); exit (0); 1601 + #else 1602 + #if defined (CMU) 1603 + printf ("ns32k-encore-mach\n"); exit (0); 1604 + #else 1605 + printf ("ns32k-encore-bsd\n"); exit (0); 1606 + #endif 1607 + #endif 1608 + #endif 1609 + 1610 + #if defined (__386BSD__) 1611 + printf ("i386-pc-bsd\n"); exit (0); 1612 + #endif 1613 + 1614 + #if defined (sequent) 1615 + #if defined (i386) 1616 + printf ("i386-sequent-dynix\n"); exit (0); 1617 + #endif 1618 + #if defined (ns32000) 1619 + printf ("ns32k-sequent-dynix\n"); exit (0); 1620 + #endif 1621 + #endif 1622 + 1623 + #if defined (_SEQUENT_) 1624 + struct utsname un; 1625 + 1626 + uname(&un); 1627 + if (strncmp(un.version, "V2", 2) == 0) { 1628 + printf ("i386-sequent-ptx2\n"); exit (0); 1629 + } 1630 + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ 1631 + printf ("i386-sequent-ptx1\n"); exit (0); 1632 + } 1633 + printf ("i386-sequent-ptx\n"); exit (0); 1634 + #endif 1635 + 1636 + #if defined (vax) 1637 + #if !defined (ultrix) 1638 + #include <sys/param.h> 1639 + #if defined (BSD) 1640 + #if BSD == 43 1641 + printf ("vax-dec-bsd4.3\n"); exit (0); 1642 + #else 1643 + #if BSD == 199006 1644 + printf ("vax-dec-bsd4.3reno\n"); exit (0); 1645 + #else 1646 + printf ("vax-dec-bsd\n"); exit (0); 1647 + #endif 1648 + #endif 1649 + #else 1650 + printf ("vax-dec-bsd\n"); exit (0); 1651 + #endif 1652 + #else 1653 + #if defined(_SIZE_T_) || defined(SIGLOST) 1654 + struct utsname un; 1655 + uname (&un); 1656 + printf ("vax-dec-ultrix%s\n", un.release); exit (0); 1657 + #else 1658 + printf ("vax-dec-ultrix\n"); exit (0); 1659 + #endif 1660 + #endif 1661 + #endif 1662 + #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) 1663 + #if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) 1664 + #if defined(_SIZE_T_) || defined(SIGLOST) 1665 + struct utsname *un; 1666 + uname (&un); 1667 + printf ("mips-dec-ultrix%s\n", un.release); exit (0); 1668 + #else 1669 + printf ("mips-dec-ultrix\n"); exit (0); 1670 + #endif 1671 + #endif 1672 + #endif 1673 + 1674 + #if defined (alliant) && defined (i860) 1675 + printf ("i860-alliant-bsd\n"); exit (0); 1676 + #endif 1677 + 1678 + exit (1); 1679 + } 1680 + EOF 1681 + 1682 + $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` && 1683 + { echo "$SYSTEM_NAME"; exit; } 1684 + 1685 + # Apollos put the system type in the environment. 1686 + test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } 1687 + 1688 + echo "$0: unable to guess system type" >&2 1689 + 1690 + case $UNAME_MACHINE:$UNAME_SYSTEM in 1691 + mips:Linux | mips64:Linux) 1692 + # If we got here on MIPS GNU/Linux, output extra information. 1693 + cat >&2 <<EOF 1694 + 1695 + NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize 1696 + the system type. Please install a C compiler and try again. 1697 + EOF 1698 + ;; 1699 + esac 1700 + 1701 + cat >&2 <<EOF 1702 + 1703 + This script (version $timestamp), has failed to recognize the 1704 + operating system you are using. If your script is old, overwrite *all* 1705 + copies of config.guess and config.sub with the latest versions from: 1706 + 1707 + https://git.savannah.gnu.org/cgit/config.git/plain/config.guess 1708 + and 1709 + https://git.savannah.gnu.org/cgit/config.git/plain/config.sub 1710 + EOF 1711 + 1712 + our_year=`echo $timestamp | sed 's,-.*,,'` 1713 + thisyear=`date +%Y` 1714 + # shellcheck disable=SC2003 1715 + script_age=`expr "$thisyear" - "$our_year"` 1716 + if test "$script_age" -lt 3 ; then 1717 + cat >&2 <<EOF 1718 + 1719 + If $0 has already been updated, send the following data and any 1720 + information you think might be pertinent to config-patches@gnu.org to 1721 + provide the necessary information to handle your system. 1722 + 1723 + config.guess timestamp = $timestamp 1724 + 1725 + uname -m = `(uname -m) 2>/dev/null || echo unknown` 1726 + uname -r = `(uname -r) 2>/dev/null || echo unknown` 1727 + uname -s = `(uname -s) 2>/dev/null || echo unknown` 1728 + uname -v = `(uname -v) 2>/dev/null || echo unknown` 1729 + 1730 + /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` 1731 + /bin/uname -X = `(/bin/uname -X) 2>/dev/null` 1732 + 1733 + hostinfo = `(hostinfo) 2>/dev/null` 1734 + /bin/universe = `(/bin/universe) 2>/dev/null` 1735 + /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` 1736 + /bin/arch = `(/bin/arch) 2>/dev/null` 1737 + /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` 1738 + /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` 1739 + 1740 + UNAME_MACHINE = "$UNAME_MACHINE" 1741 + UNAME_RELEASE = "$UNAME_RELEASE" 1742 + UNAME_SYSTEM = "$UNAME_SYSTEM" 1743 + UNAME_VERSION = "$UNAME_VERSION" 1744 + EOF 1745 + fi 1746 + 1747 + exit 1 1748 + 1749 + # Local variables: 1750 + # eval: (add-hook 'before-save-hook 'time-stamp) 1751 + # time-stamp-start: "timestamp='" 1752 + # time-stamp-format: "%:y-%02m-%02d" 1753 + # time-stamp-end: "'" 1754 + # End:
+85
usr.sbin/nsd/simdzone/config.h.in
··· 1 + /* config.h.in. Generated from configure.ac by autoheader. */ 2 + 3 + /* Define to 1 if you have the declaration of `bswap16', and to 0 if you 4 + don't. */ 5 + #undef HAVE_DECL_BSWAP16 6 + 7 + /* Define to 1 if you have the declaration of `bswap32', and to 0 if you 8 + don't. */ 9 + #undef HAVE_DECL_BSWAP32 10 + 11 + /* Define to 1 if you have the declaration of `bswap64', and to 0 if you 12 + don't. */ 13 + #undef HAVE_DECL_BSWAP64 14 + 15 + /* Define to 1 if you have the <endian.h> header file. */ 16 + #undef HAVE_ENDIAN_H 17 + 18 + /* Wether or not to compile support for AVX2 */ 19 + #undef HAVE_HASWELL 20 + 21 + /* Define to 1 if you have the <inttypes.h> header file. */ 22 + #undef HAVE_INTTYPES_H 23 + 24 + /* Define to 1 if you have the `realpath' function. */ 25 + #undef HAVE_REALPATH 26 + 27 + /* Define to 1 if you have the <stdint.h> header file. */ 28 + #undef HAVE_STDINT_H 29 + 30 + /* Define to 1 if you have the <stdio.h> header file. */ 31 + #undef HAVE_STDIO_H 32 + 33 + /* Define to 1 if you have the <stdlib.h> header file. */ 34 + #undef HAVE_STDLIB_H 35 + 36 + /* Define to 1 if you have the <strings.h> header file. */ 37 + #undef HAVE_STRINGS_H 38 + 39 + /* Define to 1 if you have the <string.h> header file. */ 40 + #undef HAVE_STRING_H 41 + 42 + /* Define to 1 if you have the <sys/endian.h> header file. */ 43 + #undef HAVE_SYS_ENDIAN_H 44 + 45 + /* Define to 1 if you have the <sys/stat.h> header file. */ 46 + #undef HAVE_SYS_STAT_H 47 + 48 + /* Define to 1 if you have the <sys/types.h> header file. */ 49 + #undef HAVE_SYS_TYPES_H 50 + 51 + /* Define to 1 if you have the <unistd.h> header file. */ 52 + #undef HAVE_UNISTD_H 53 + 54 + /* Wether or not to compile support for SSE4.2 */ 55 + #undef HAVE_WESTMERE 56 + 57 + /* Define to the address where bug reports for this package should be sent. */ 58 + #undef PACKAGE_BUGREPORT 59 + 60 + /* Define to the full name of this package. */ 61 + #undef PACKAGE_NAME 62 + 63 + /* Define to the full name and version of this package. */ 64 + #undef PACKAGE_STRING 65 + 66 + /* Define to the one symbol short name of this package. */ 67 + #undef PACKAGE_TARNAME 68 + 69 + /* Define to the home page for this package. */ 70 + #undef PACKAGE_URL 71 + 72 + /* Define to the version of this package. */ 73 + #undef PACKAGE_VERSION 74 + 75 + /* Define to 1 if all of the C90 standard headers exist (not just the ones 76 + required in a freestanding environment). This macro is provided for 77 + backward compatibility; new code need not use it. */ 78 + #undef STDC_HEADERS 79 + 80 + 81 + /* Defines _XOPEN_SOURCE and _POSIX_C_SOURCE implicitly in features.h */ 82 + #ifndef _DEFAULT_SOURCE 83 + # define _DEFAULT_SOURCE 1 84 + #endif 85 +
+1890
usr.sbin/nsd/simdzone/config.sub
··· 1 + #! /bin/sh 2 + # Configuration validation subroutine script. 3 + # Copyright 1992-2022 Free Software Foundation, Inc. 4 + 5 + # shellcheck disable=SC2006,SC2268 # see below for rationale 6 + 7 + timestamp='2022-01-03' 8 + 9 + # This file is free software; you can redistribute it and/or modify it 10 + # under the terms of the GNU General Public License as published by 11 + # the Free Software Foundation, either version 3 of the License, or 12 + # (at your option) any later version. 13 + # 14 + # This program is distributed in the hope that it will be useful, but 15 + # WITHOUT ANY WARRANTY; without even the implied warranty of 16 + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 + # General Public License for more details. 18 + # 19 + # You should have received a copy of the GNU General Public License 20 + # along with this program; if not, see <https://www.gnu.org/licenses/>. 21 + # 22 + # As a special exception to the GNU General Public License, if you 23 + # distribute this file as part of a program that contains a 24 + # configuration script generated by Autoconf, you may include it under 25 + # the same distribution terms that you use for the rest of that 26 + # program. This Exception is an additional permission under section 7 27 + # of the GNU General Public License, version 3 ("GPLv3"). 28 + 29 + 30 + # Please send patches to <config-patches@gnu.org>. 31 + # 32 + # Configuration subroutine to validate and canonicalize a configuration type. 33 + # Supply the specified configuration type as an argument. 34 + # If it is invalid, we print an error message on stderr and exit with code 1. 35 + # Otherwise, we print the canonical config type on stdout and succeed. 36 + 37 + # You can get the latest version of this script from: 38 + # https://git.savannah.gnu.org/cgit/config.git/plain/config.sub 39 + 40 + # This file is supposed to be the same for all GNU packages 41 + # and recognize all the CPU types, system types and aliases 42 + # that are meaningful with *any* GNU software. 43 + # Each package is responsible for reporting which valid configurations 44 + # it does not support. The user should be able to distinguish 45 + # a failure to support a valid configuration from a meaningless 46 + # configuration. 47 + 48 + # The goal of this file is to map all the various variations of a given 49 + # machine specification into a single specification in the form: 50 + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM 51 + # or in some cases, the newer four-part form: 52 + # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM 53 + # It is wrong to echo any other type of specification. 54 + 55 + # The "shellcheck disable" line above the timestamp inhibits complaints 56 + # about features and limitations of the classic Bourne shell that were 57 + # superseded or lifted in POSIX. However, this script identifies a wide 58 + # variety of pre-POSIX systems that do not have POSIX shells at all, and 59 + # even some reasonably current systems (Solaris 10 as case-in-point) still 60 + # have a pre-POSIX /bin/sh. 61 + 62 + me=`echo "$0" | sed -e 's,.*/,,'` 63 + 64 + usage="\ 65 + Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS 66 + 67 + Canonicalize a configuration name. 68 + 69 + Options: 70 + -h, --help print this help, then exit 71 + -t, --time-stamp print date of last modification, then exit 72 + -v, --version print version number, then exit 73 + 74 + Report bugs and patches to <config-patches@gnu.org>." 75 + 76 + version="\ 77 + GNU config.sub ($timestamp) 78 + 79 + Copyright 1992-2022 Free Software Foundation, Inc. 80 + 81 + This is free software; see the source for copying conditions. There is NO 82 + warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." 83 + 84 + help=" 85 + Try \`$me --help' for more information." 86 + 87 + # Parse command line 88 + while test $# -gt 0 ; do 89 + case $1 in 90 + --time-stamp | --time* | -t ) 91 + echo "$timestamp" ; exit ;; 92 + --version | -v ) 93 + echo "$version" ; exit ;; 94 + --help | --h* | -h ) 95 + echo "$usage"; exit ;; 96 + -- ) # Stop option processing 97 + shift; break ;; 98 + - ) # Use stdin as input. 99 + break ;; 100 + -* ) 101 + echo "$me: invalid option $1$help" >&2 102 + exit 1 ;; 103 + 104 + *local*) 105 + # First pass through any local machine types. 106 + echo "$1" 107 + exit ;; 108 + 109 + * ) 110 + break ;; 111 + esac 112 + done 113 + 114 + case $# in 115 + 0) echo "$me: missing argument$help" >&2 116 + exit 1;; 117 + 1) ;; 118 + *) echo "$me: too many arguments$help" >&2 119 + exit 1;; 120 + esac 121 + 122 + # Split fields of configuration type 123 + # shellcheck disable=SC2162 124 + saved_IFS=$IFS 125 + IFS="-" read field1 field2 field3 field4 <<EOF 126 + $1 127 + EOF 128 + IFS=$saved_IFS 129 + 130 + # Separate into logical components for further validation 131 + case $1 in 132 + *-*-*-*-*) 133 + echo Invalid configuration \`"$1"\': more than four components >&2 134 + exit 1 135 + ;; 136 + *-*-*-*) 137 + basic_machine=$field1-$field2 138 + basic_os=$field3-$field4 139 + ;; 140 + *-*-*) 141 + # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two 142 + # parts 143 + maybe_os=$field2-$field3 144 + case $maybe_os in 145 + nto-qnx* | linux-* | uclinux-uclibc* \ 146 + | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ 147 + | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ 148 + | storm-chaos* | os2-emx* | rtmk-nova*) 149 + basic_machine=$field1 150 + basic_os=$maybe_os 151 + ;; 152 + android-linux) 153 + basic_machine=$field1-unknown 154 + basic_os=linux-android 155 + ;; 156 + *) 157 + basic_machine=$field1-$field2 158 + basic_os=$field3 159 + ;; 160 + esac 161 + ;; 162 + *-*) 163 + # A lone config we happen to match not fitting any pattern 164 + case $field1-$field2 in 165 + decstation-3100) 166 + basic_machine=mips-dec 167 + basic_os= 168 + ;; 169 + *-*) 170 + # Second component is usually, but not always the OS 171 + case $field2 in 172 + # Prevent following clause from handling this valid os 173 + sun*os*) 174 + basic_machine=$field1 175 + basic_os=$field2 176 + ;; 177 + zephyr*) 178 + basic_machine=$field1-unknown 179 + basic_os=$field2 180 + ;; 181 + # Manufacturers 182 + dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ 183 + | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ 184 + | unicom* | ibm* | next | hp | isi* | apollo | altos* \ 185 + | convergent* | ncr* | news | 32* | 3600* | 3100* \ 186 + | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ 187 + | ultra | tti* | harris | dolphin | highlevel | gould \ 188 + | cbm | ns | masscomp | apple | axis | knuth | cray \ 189 + | microblaze* | sim | cisco \ 190 + | oki | wec | wrs | winbond) 191 + basic_machine=$field1-$field2 192 + basic_os= 193 + ;; 194 + *) 195 + basic_machine=$field1 196 + basic_os=$field2 197 + ;; 198 + esac 199 + ;; 200 + esac 201 + ;; 202 + *) 203 + # Convert single-component short-hands not valid as part of 204 + # multi-component configurations. 205 + case $field1 in 206 + 386bsd) 207 + basic_machine=i386-pc 208 + basic_os=bsd 209 + ;; 210 + a29khif) 211 + basic_machine=a29k-amd 212 + basic_os=udi 213 + ;; 214 + adobe68k) 215 + basic_machine=m68010-adobe 216 + basic_os=scout 217 + ;; 218 + alliant) 219 + basic_machine=fx80-alliant 220 + basic_os= 221 + ;; 222 + altos | altos3068) 223 + basic_machine=m68k-altos 224 + basic_os= 225 + ;; 226 + am29k) 227 + basic_machine=a29k-none 228 + basic_os=bsd 229 + ;; 230 + amdahl) 231 + basic_machine=580-amdahl 232 + basic_os=sysv 233 + ;; 234 + amiga) 235 + basic_machine=m68k-unknown 236 + basic_os= 237 + ;; 238 + amigaos | amigados) 239 + basic_machine=m68k-unknown 240 + basic_os=amigaos 241 + ;; 242 + amigaunix | amix) 243 + basic_machine=m68k-unknown 244 + basic_os=sysv4 245 + ;; 246 + apollo68) 247 + basic_machine=m68k-apollo 248 + basic_os=sysv 249 + ;; 250 + apollo68bsd) 251 + basic_machine=m68k-apollo 252 + basic_os=bsd 253 + ;; 254 + aros) 255 + basic_machine=i386-pc 256 + basic_os=aros 257 + ;; 258 + aux) 259 + basic_machine=m68k-apple 260 + basic_os=aux 261 + ;; 262 + balance) 263 + basic_machine=ns32k-sequent 264 + basic_os=dynix 265 + ;; 266 + blackfin) 267 + basic_machine=bfin-unknown 268 + basic_os=linux 269 + ;; 270 + cegcc) 271 + basic_machine=arm-unknown 272 + basic_os=cegcc 273 + ;; 274 + convex-c1) 275 + basic_machine=c1-convex 276 + basic_os=bsd 277 + ;; 278 + convex-c2) 279 + basic_machine=c2-convex 280 + basic_os=bsd 281 + ;; 282 + convex-c32) 283 + basic_machine=c32-convex 284 + basic_os=bsd 285 + ;; 286 + convex-c34) 287 + basic_machine=c34-convex 288 + basic_os=bsd 289 + ;; 290 + convex-c38) 291 + basic_machine=c38-convex 292 + basic_os=bsd 293 + ;; 294 + cray) 295 + basic_machine=j90-cray 296 + basic_os=unicos 297 + ;; 298 + crds | unos) 299 + basic_machine=m68k-crds 300 + basic_os= 301 + ;; 302 + da30) 303 + basic_machine=m68k-da30 304 + basic_os= 305 + ;; 306 + decstation | pmax | pmin | dec3100 | decstatn) 307 + basic_machine=mips-dec 308 + basic_os= 309 + ;; 310 + delta88) 311 + basic_machine=m88k-motorola 312 + basic_os=sysv3 313 + ;; 314 + dicos) 315 + basic_machine=i686-pc 316 + basic_os=dicos 317 + ;; 318 + djgpp) 319 + basic_machine=i586-pc 320 + basic_os=msdosdjgpp 321 + ;; 322 + ebmon29k) 323 + basic_machine=a29k-amd 324 + basic_os=ebmon 325 + ;; 326 + es1800 | OSE68k | ose68k | ose | OSE) 327 + basic_machine=m68k-ericsson 328 + basic_os=ose 329 + ;; 330 + gmicro) 331 + basic_machine=tron-gmicro 332 + basic_os=sysv 333 + ;; 334 + go32) 335 + basic_machine=i386-pc 336 + basic_os=go32 337 + ;; 338 + h8300hms) 339 + basic_machine=h8300-hitachi 340 + basic_os=hms 341 + ;; 342 + h8300xray) 343 + basic_machine=h8300-hitachi 344 + basic_os=xray 345 + ;; 346 + h8500hms) 347 + basic_machine=h8500-hitachi 348 + basic_os=hms 349 + ;; 350 + harris) 351 + basic_machine=m88k-harris 352 + basic_os=sysv3 353 + ;; 354 + hp300 | hp300hpux) 355 + basic_machine=m68k-hp 356 + basic_os=hpux 357 + ;; 358 + hp300bsd) 359 + basic_machine=m68k-hp 360 + basic_os=bsd 361 + ;; 362 + hppaosf) 363 + basic_machine=hppa1.1-hp 364 + basic_os=osf 365 + ;; 366 + hppro) 367 + basic_machine=hppa1.1-hp 368 + basic_os=proelf 369 + ;; 370 + i386mach) 371 + basic_machine=i386-mach 372 + basic_os=mach 373 + ;; 374 + isi68 | isi) 375 + basic_machine=m68k-isi 376 + basic_os=sysv 377 + ;; 378 + m68knommu) 379 + basic_machine=m68k-unknown 380 + basic_os=linux 381 + ;; 382 + magnum | m3230) 383 + basic_machine=mips-mips 384 + basic_os=sysv 385 + ;; 386 + merlin) 387 + basic_machine=ns32k-utek 388 + basic_os=sysv 389 + ;; 390 + mingw64) 391 + basic_machine=x86_64-pc 392 + basic_os=mingw64 393 + ;; 394 + mingw32) 395 + basic_machine=i686-pc 396 + basic_os=mingw32 397 + ;; 398 + mingw32ce) 399 + basic_machine=arm-unknown 400 + basic_os=mingw32ce 401 + ;; 402 + monitor) 403 + basic_machine=m68k-rom68k 404 + basic_os=coff 405 + ;; 406 + morphos) 407 + basic_machine=powerpc-unknown 408 + basic_os=morphos 409 + ;; 410 + moxiebox) 411 + basic_machine=moxie-unknown 412 + basic_os=moxiebox 413 + ;; 414 + msdos) 415 + basic_machine=i386-pc 416 + basic_os=msdos 417 + ;; 418 + msys) 419 + basic_machine=i686-pc 420 + basic_os=msys 421 + ;; 422 + mvs) 423 + basic_machine=i370-ibm 424 + basic_os=mvs 425 + ;; 426 + nacl) 427 + basic_machine=le32-unknown 428 + basic_os=nacl 429 + ;; 430 + ncr3000) 431 + basic_machine=i486-ncr 432 + basic_os=sysv4 433 + ;; 434 + netbsd386) 435 + basic_machine=i386-pc 436 + basic_os=netbsd 437 + ;; 438 + netwinder) 439 + basic_machine=armv4l-rebel 440 + basic_os=linux 441 + ;; 442 + news | news700 | news800 | news900) 443 + basic_machine=m68k-sony 444 + basic_os=newsos 445 + ;; 446 + news1000) 447 + basic_machine=m68030-sony 448 + basic_os=newsos 449 + ;; 450 + necv70) 451 + basic_machine=v70-nec 452 + basic_os=sysv 453 + ;; 454 + nh3000) 455 + basic_machine=m68k-harris 456 + basic_os=cxux 457 + ;; 458 + nh[45]000) 459 + basic_machine=m88k-harris 460 + basic_os=cxux 461 + ;; 462 + nindy960) 463 + basic_machine=i960-intel 464 + basic_os=nindy 465 + ;; 466 + mon960) 467 + basic_machine=i960-intel 468 + basic_os=mon960 469 + ;; 470 + nonstopux) 471 + basic_machine=mips-compaq 472 + basic_os=nonstopux 473 + ;; 474 + os400) 475 + basic_machine=powerpc-ibm 476 + basic_os=os400 477 + ;; 478 + OSE68000 | ose68000) 479 + basic_machine=m68000-ericsson 480 + basic_os=ose 481 + ;; 482 + os68k) 483 + basic_machine=m68k-none 484 + basic_os=os68k 485 + ;; 486 + paragon) 487 + basic_machine=i860-intel 488 + basic_os=osf 489 + ;; 490 + parisc) 491 + basic_machine=hppa-unknown 492 + basic_os=linux 493 + ;; 494 + psp) 495 + basic_machine=mipsallegrexel-sony 496 + basic_os=psp 497 + ;; 498 + pw32) 499 + basic_machine=i586-unknown 500 + basic_os=pw32 501 + ;; 502 + rdos | rdos64) 503 + basic_machine=x86_64-pc 504 + basic_os=rdos 505 + ;; 506 + rdos32) 507 + basic_machine=i386-pc 508 + basic_os=rdos 509 + ;; 510 + rom68k) 511 + basic_machine=m68k-rom68k 512 + basic_os=coff 513 + ;; 514 + sa29200) 515 + basic_machine=a29k-amd 516 + basic_os=udi 517 + ;; 518 + sei) 519 + basic_machine=mips-sei 520 + basic_os=seiux 521 + ;; 522 + sequent) 523 + basic_machine=i386-sequent 524 + basic_os= 525 + ;; 526 + sps7) 527 + basic_machine=m68k-bull 528 + basic_os=sysv2 529 + ;; 530 + st2000) 531 + basic_machine=m68k-tandem 532 + basic_os= 533 + ;; 534 + stratus) 535 + basic_machine=i860-stratus 536 + basic_os=sysv4 537 + ;; 538 + sun2) 539 + basic_machine=m68000-sun 540 + basic_os= 541 + ;; 542 + sun2os3) 543 + basic_machine=m68000-sun 544 + basic_os=sunos3 545 + ;; 546 + sun2os4) 547 + basic_machine=m68000-sun 548 + basic_os=sunos4 549 + ;; 550 + sun3) 551 + basic_machine=m68k-sun 552 + basic_os= 553 + ;; 554 + sun3os3) 555 + basic_machine=m68k-sun 556 + basic_os=sunos3 557 + ;; 558 + sun3os4) 559 + basic_machine=m68k-sun 560 + basic_os=sunos4 561 + ;; 562 + sun4) 563 + basic_machine=sparc-sun 564 + basic_os= 565 + ;; 566 + sun4os3) 567 + basic_machine=sparc-sun 568 + basic_os=sunos3 569 + ;; 570 + sun4os4) 571 + basic_machine=sparc-sun 572 + basic_os=sunos4 573 + ;; 574 + sun4sol2) 575 + basic_machine=sparc-sun 576 + basic_os=solaris2 577 + ;; 578 + sun386 | sun386i | roadrunner) 579 + basic_machine=i386-sun 580 + basic_os= 581 + ;; 582 + sv1) 583 + basic_machine=sv1-cray 584 + basic_os=unicos 585 + ;; 586 + symmetry) 587 + basic_machine=i386-sequent 588 + basic_os=dynix 589 + ;; 590 + t3e) 591 + basic_machine=alphaev5-cray 592 + basic_os=unicos 593 + ;; 594 + t90) 595 + basic_machine=t90-cray 596 + basic_os=unicos 597 + ;; 598 + toad1) 599 + basic_machine=pdp10-xkl 600 + basic_os=tops20 601 + ;; 602 + tpf) 603 + basic_machine=s390x-ibm 604 + basic_os=tpf 605 + ;; 606 + udi29k) 607 + basic_machine=a29k-amd 608 + basic_os=udi 609 + ;; 610 + ultra3) 611 + basic_machine=a29k-nyu 612 + basic_os=sym1 613 + ;; 614 + v810 | necv810) 615 + basic_machine=v810-nec 616 + basic_os=none 617 + ;; 618 + vaxv) 619 + basic_machine=vax-dec 620 + basic_os=sysv 621 + ;; 622 + vms) 623 + basic_machine=vax-dec 624 + basic_os=vms 625 + ;; 626 + vsta) 627 + basic_machine=i386-pc 628 + basic_os=vsta 629 + ;; 630 + vxworks960) 631 + basic_machine=i960-wrs 632 + basic_os=vxworks 633 + ;; 634 + vxworks68) 635 + basic_machine=m68k-wrs 636 + basic_os=vxworks 637 + ;; 638 + vxworks29k) 639 + basic_machine=a29k-wrs 640 + basic_os=vxworks 641 + ;; 642 + xbox) 643 + basic_machine=i686-pc 644 + basic_os=mingw32 645 + ;; 646 + ymp) 647 + basic_machine=ymp-cray 648 + basic_os=unicos 649 + ;; 650 + *) 651 + basic_machine=$1 652 + basic_os= 653 + ;; 654 + esac 655 + ;; 656 + esac 657 + 658 + # Decode 1-component or ad-hoc basic machines 659 + case $basic_machine in 660 + # Here we handle the default manufacturer of certain CPU types. It is in 661 + # some cases the only manufacturer, in others, it is the most popular. 662 + w89k) 663 + cpu=hppa1.1 664 + vendor=winbond 665 + ;; 666 + op50n) 667 + cpu=hppa1.1 668 + vendor=oki 669 + ;; 670 + op60c) 671 + cpu=hppa1.1 672 + vendor=oki 673 + ;; 674 + ibm*) 675 + cpu=i370 676 + vendor=ibm 677 + ;; 678 + orion105) 679 + cpu=clipper 680 + vendor=highlevel 681 + ;; 682 + mac | mpw | mac-mpw) 683 + cpu=m68k 684 + vendor=apple 685 + ;; 686 + pmac | pmac-mpw) 687 + cpu=powerpc 688 + vendor=apple 689 + ;; 690 + 691 + # Recognize the various machine names and aliases which stand 692 + # for a CPU type and a company and sometimes even an OS. 693 + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) 694 + cpu=m68000 695 + vendor=att 696 + ;; 697 + 3b*) 698 + cpu=we32k 699 + vendor=att 700 + ;; 701 + bluegene*) 702 + cpu=powerpc 703 + vendor=ibm 704 + basic_os=cnk 705 + ;; 706 + decsystem10* | dec10*) 707 + cpu=pdp10 708 + vendor=dec 709 + basic_os=tops10 710 + ;; 711 + decsystem20* | dec20*) 712 + cpu=pdp10 713 + vendor=dec 714 + basic_os=tops20 715 + ;; 716 + delta | 3300 | motorola-3300 | motorola-delta \ 717 + | 3300-motorola | delta-motorola) 718 + cpu=m68k 719 + vendor=motorola 720 + ;; 721 + dpx2*) 722 + cpu=m68k 723 + vendor=bull 724 + basic_os=sysv3 725 + ;; 726 + encore | umax | mmax) 727 + cpu=ns32k 728 + vendor=encore 729 + ;; 730 + elxsi) 731 + cpu=elxsi 732 + vendor=elxsi 733 + basic_os=${basic_os:-bsd} 734 + ;; 735 + fx2800) 736 + cpu=i860 737 + vendor=alliant 738 + ;; 739 + genix) 740 + cpu=ns32k 741 + vendor=ns 742 + ;; 743 + h3050r* | hiux*) 744 + cpu=hppa1.1 745 + vendor=hitachi 746 + basic_os=hiuxwe2 747 + ;; 748 + hp3k9[0-9][0-9] | hp9[0-9][0-9]) 749 + cpu=hppa1.0 750 + vendor=hp 751 + ;; 752 + hp9k2[0-9][0-9] | hp9k31[0-9]) 753 + cpu=m68000 754 + vendor=hp 755 + ;; 756 + hp9k3[2-9][0-9]) 757 + cpu=m68k 758 + vendor=hp 759 + ;; 760 + hp9k6[0-9][0-9] | hp6[0-9][0-9]) 761 + cpu=hppa1.0 762 + vendor=hp 763 + ;; 764 + hp9k7[0-79][0-9] | hp7[0-79][0-9]) 765 + cpu=hppa1.1 766 + vendor=hp 767 + ;; 768 + hp9k78[0-9] | hp78[0-9]) 769 + # FIXME: really hppa2.0-hp 770 + cpu=hppa1.1 771 + vendor=hp 772 + ;; 773 + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) 774 + # FIXME: really hppa2.0-hp 775 + cpu=hppa1.1 776 + vendor=hp 777 + ;; 778 + hp9k8[0-9][13679] | hp8[0-9][13679]) 779 + cpu=hppa1.1 780 + vendor=hp 781 + ;; 782 + hp9k8[0-9][0-9] | hp8[0-9][0-9]) 783 + cpu=hppa1.0 784 + vendor=hp 785 + ;; 786 + i*86v32) 787 + cpu=`echo "$1" | sed -e 's/86.*/86/'` 788 + vendor=pc 789 + basic_os=sysv32 790 + ;; 791 + i*86v4*) 792 + cpu=`echo "$1" | sed -e 's/86.*/86/'` 793 + vendor=pc 794 + basic_os=sysv4 795 + ;; 796 + i*86v) 797 + cpu=`echo "$1" | sed -e 's/86.*/86/'` 798 + vendor=pc 799 + basic_os=sysv 800 + ;; 801 + i*86sol2) 802 + cpu=`echo "$1" | sed -e 's/86.*/86/'` 803 + vendor=pc 804 + basic_os=solaris2 805 + ;; 806 + j90 | j90-cray) 807 + cpu=j90 808 + vendor=cray 809 + basic_os=${basic_os:-unicos} 810 + ;; 811 + iris | iris4d) 812 + cpu=mips 813 + vendor=sgi 814 + case $basic_os in 815 + irix*) 816 + ;; 817 + *) 818 + basic_os=irix4 819 + ;; 820 + esac 821 + ;; 822 + miniframe) 823 + cpu=m68000 824 + vendor=convergent 825 + ;; 826 + *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) 827 + cpu=m68k 828 + vendor=atari 829 + basic_os=mint 830 + ;; 831 + news-3600 | risc-news) 832 + cpu=mips 833 + vendor=sony 834 + basic_os=newsos 835 + ;; 836 + next | m*-next) 837 + cpu=m68k 838 + vendor=next 839 + case $basic_os in 840 + openstep*) 841 + ;; 842 + nextstep*) 843 + ;; 844 + ns2*) 845 + basic_os=nextstep2 846 + ;; 847 + *) 848 + basic_os=nextstep3 849 + ;; 850 + esac 851 + ;; 852 + np1) 853 + cpu=np1 854 + vendor=gould 855 + ;; 856 + op50n-* | op60c-*) 857 + cpu=hppa1.1 858 + vendor=oki 859 + basic_os=proelf 860 + ;; 861 + pa-hitachi) 862 + cpu=hppa1.1 863 + vendor=hitachi 864 + basic_os=hiuxwe2 865 + ;; 866 + pbd) 867 + cpu=sparc 868 + vendor=tti 869 + ;; 870 + pbb) 871 + cpu=m68k 872 + vendor=tti 873 + ;; 874 + pc532) 875 + cpu=ns32k 876 + vendor=pc532 877 + ;; 878 + pn) 879 + cpu=pn 880 + vendor=gould 881 + ;; 882 + power) 883 + cpu=power 884 + vendor=ibm 885 + ;; 886 + ps2) 887 + cpu=i386 888 + vendor=ibm 889 + ;; 890 + rm[46]00) 891 + cpu=mips 892 + vendor=siemens 893 + ;; 894 + rtpc | rtpc-*) 895 + cpu=romp 896 + vendor=ibm 897 + ;; 898 + sde) 899 + cpu=mipsisa32 900 + vendor=sde 901 + basic_os=${basic_os:-elf} 902 + ;; 903 + simso-wrs) 904 + cpu=sparclite 905 + vendor=wrs 906 + basic_os=vxworks 907 + ;; 908 + tower | tower-32) 909 + cpu=m68k 910 + vendor=ncr 911 + ;; 912 + vpp*|vx|vx-*) 913 + cpu=f301 914 + vendor=fujitsu 915 + ;; 916 + w65) 917 + cpu=w65 918 + vendor=wdc 919 + ;; 920 + w89k-*) 921 + cpu=hppa1.1 922 + vendor=winbond 923 + basic_os=proelf 924 + ;; 925 + none) 926 + cpu=none 927 + vendor=none 928 + ;; 929 + leon|leon[3-9]) 930 + cpu=sparc 931 + vendor=$basic_machine 932 + ;; 933 + leon-*|leon[3-9]-*) 934 + cpu=sparc 935 + vendor=`echo "$basic_machine" | sed 's/-.*//'` 936 + ;; 937 + 938 + *-*) 939 + # shellcheck disable=SC2162 940 + saved_IFS=$IFS 941 + IFS="-" read cpu vendor <<EOF 942 + $basic_machine 943 + EOF 944 + IFS=$saved_IFS 945 + ;; 946 + # We use `pc' rather than `unknown' 947 + # because (1) that's what they normally are, and 948 + # (2) the word "unknown" tends to confuse beginning users. 949 + i*86 | x86_64) 950 + cpu=$basic_machine 951 + vendor=pc 952 + ;; 953 + # These rules are duplicated from below for sake of the special case above; 954 + # i.e. things that normalized to x86 arches should also default to "pc" 955 + pc98) 956 + cpu=i386 957 + vendor=pc 958 + ;; 959 + x64 | amd64) 960 + cpu=x86_64 961 + vendor=pc 962 + ;; 963 + # Recognize the basic CPU types without company name. 964 + *) 965 + cpu=$basic_machine 966 + vendor=unknown 967 + ;; 968 + esac 969 + 970 + unset -v basic_machine 971 + 972 + # Decode basic machines in the full and proper CPU-Company form. 973 + case $cpu-$vendor in 974 + # Here we handle the default manufacturer of certain CPU types in canonical form. It is in 975 + # some cases the only manufacturer, in others, it is the most popular. 976 + craynv-unknown) 977 + vendor=cray 978 + basic_os=${basic_os:-unicosmp} 979 + ;; 980 + c90-unknown | c90-cray) 981 + vendor=cray 982 + basic_os=${Basic_os:-unicos} 983 + ;; 984 + fx80-unknown) 985 + vendor=alliant 986 + ;; 987 + romp-unknown) 988 + vendor=ibm 989 + ;; 990 + mmix-unknown) 991 + vendor=knuth 992 + ;; 993 + microblaze-unknown | microblazeel-unknown) 994 + vendor=xilinx 995 + ;; 996 + rs6000-unknown) 997 + vendor=ibm 998 + ;; 999 + vax-unknown) 1000 + vendor=dec 1001 + ;; 1002 + pdp11-unknown) 1003 + vendor=dec 1004 + ;; 1005 + we32k-unknown) 1006 + vendor=att 1007 + ;; 1008 + cydra-unknown) 1009 + vendor=cydrome 1010 + ;; 1011 + i370-ibm*) 1012 + vendor=ibm 1013 + ;; 1014 + orion-unknown) 1015 + vendor=highlevel 1016 + ;; 1017 + xps-unknown | xps100-unknown) 1018 + cpu=xps100 1019 + vendor=honeywell 1020 + ;; 1021 + 1022 + # Here we normalize CPU types with a missing or matching vendor 1023 + armh-unknown | armh-alt) 1024 + cpu=armv7l 1025 + vendor=alt 1026 + basic_os=${basic_os:-linux-gnueabihf} 1027 + ;; 1028 + dpx20-unknown | dpx20-bull) 1029 + cpu=rs6000 1030 + vendor=bull 1031 + basic_os=${basic_os:-bosx} 1032 + ;; 1033 + 1034 + # Here we normalize CPU types irrespective of the vendor 1035 + amd64-*) 1036 + cpu=x86_64 1037 + ;; 1038 + blackfin-*) 1039 + cpu=bfin 1040 + basic_os=linux 1041 + ;; 1042 + c54x-*) 1043 + cpu=tic54x 1044 + ;; 1045 + c55x-*) 1046 + cpu=tic55x 1047 + ;; 1048 + c6x-*) 1049 + cpu=tic6x 1050 + ;; 1051 + e500v[12]-*) 1052 + cpu=powerpc 1053 + basic_os=${basic_os}"spe" 1054 + ;; 1055 + mips3*-*) 1056 + cpu=mips64 1057 + ;; 1058 + ms1-*) 1059 + cpu=mt 1060 + ;; 1061 + m68knommu-*) 1062 + cpu=m68k 1063 + basic_os=linux 1064 + ;; 1065 + m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*) 1066 + cpu=s12z 1067 + ;; 1068 + openrisc-*) 1069 + cpu=or32 1070 + ;; 1071 + parisc-*) 1072 + cpu=hppa 1073 + basic_os=linux 1074 + ;; 1075 + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) 1076 + cpu=i586 1077 + ;; 1078 + pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*) 1079 + cpu=i686 1080 + ;; 1081 + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) 1082 + cpu=i686 1083 + ;; 1084 + pentium4-*) 1085 + cpu=i786 1086 + ;; 1087 + pc98-*) 1088 + cpu=i386 1089 + ;; 1090 + ppc-* | ppcbe-*) 1091 + cpu=powerpc 1092 + ;; 1093 + ppcle-* | powerpclittle-*) 1094 + cpu=powerpcle 1095 + ;; 1096 + ppc64-*) 1097 + cpu=powerpc64 1098 + ;; 1099 + ppc64le-* | powerpc64little-*) 1100 + cpu=powerpc64le 1101 + ;; 1102 + sb1-*) 1103 + cpu=mipsisa64sb1 1104 + ;; 1105 + sb1el-*) 1106 + cpu=mipsisa64sb1el 1107 + ;; 1108 + sh5e[lb]-*) 1109 + cpu=`echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/'` 1110 + ;; 1111 + spur-*) 1112 + cpu=spur 1113 + ;; 1114 + strongarm-* | thumb-*) 1115 + cpu=arm 1116 + ;; 1117 + tx39-*) 1118 + cpu=mipstx39 1119 + ;; 1120 + tx39el-*) 1121 + cpu=mipstx39el 1122 + ;; 1123 + x64-*) 1124 + cpu=x86_64 1125 + ;; 1126 + xscale-* | xscalee[bl]-*) 1127 + cpu=`echo "$cpu" | sed 's/^xscale/arm/'` 1128 + ;; 1129 + arm64-* | aarch64le-*) 1130 + cpu=aarch64 1131 + ;; 1132 + 1133 + # Recognize the canonical CPU Types that limit and/or modify the 1134 + # company names they are paired with. 1135 + cr16-*) 1136 + basic_os=${basic_os:-elf} 1137 + ;; 1138 + crisv32-* | etraxfs*-*) 1139 + cpu=crisv32 1140 + vendor=axis 1141 + ;; 1142 + cris-* | etrax*-*) 1143 + cpu=cris 1144 + vendor=axis 1145 + ;; 1146 + crx-*) 1147 + basic_os=${basic_os:-elf} 1148 + ;; 1149 + neo-tandem) 1150 + cpu=neo 1151 + vendor=tandem 1152 + ;; 1153 + nse-tandem) 1154 + cpu=nse 1155 + vendor=tandem 1156 + ;; 1157 + nsr-tandem) 1158 + cpu=nsr 1159 + vendor=tandem 1160 + ;; 1161 + nsv-tandem) 1162 + cpu=nsv 1163 + vendor=tandem 1164 + ;; 1165 + nsx-tandem) 1166 + cpu=nsx 1167 + vendor=tandem 1168 + ;; 1169 + mipsallegrexel-sony) 1170 + cpu=mipsallegrexel 1171 + vendor=sony 1172 + ;; 1173 + tile*-*) 1174 + basic_os=${basic_os:-linux-gnu} 1175 + ;; 1176 + 1177 + *) 1178 + # Recognize the canonical CPU types that are allowed with any 1179 + # company name. 1180 + case $cpu in 1181 + 1750a | 580 \ 1182 + | a29k \ 1183 + | aarch64 | aarch64_be \ 1184 + | abacus \ 1185 + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \ 1186 + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \ 1187 + | alphapca5[67] | alpha64pca5[67] \ 1188 + | am33_2.0 \ 1189 + | amdgcn \ 1190 + | arc | arceb | arc32 | arc64 \ 1191 + | arm | arm[lb]e | arme[lb] | armv* \ 1192 + | avr | avr32 \ 1193 + | asmjs \ 1194 + | ba \ 1195 + | be32 | be64 \ 1196 + | bfin | bpf | bs2000 \ 1197 + | c[123]* | c30 | [cjt]90 | c4x \ 1198 + | c8051 | clipper | craynv | csky | cydra \ 1199 + | d10v | d30v | dlx | dsp16xx \ 1200 + | e2k | elxsi | epiphany \ 1201 + | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \ 1202 + | h8300 | h8500 \ 1203 + | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ 1204 + | hexagon \ 1205 + | i370 | i*86 | i860 | i960 | ia16 | ia64 \ 1206 + | ip2k | iq2000 \ 1207 + | k1om \ 1208 + | le32 | le64 \ 1209 + | lm32 \ 1210 + | loongarch32 | loongarch64 | loongarchx32 \ 1211 + | m32c | m32r | m32rle \ 1212 + | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \ 1213 + | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \ 1214 + | m88110 | m88k | maxq | mb | mcore | mep | metag \ 1215 + | microblaze | microblazeel \ 1216 + | mips | mipsbe | mipseb | mipsel | mipsle \ 1217 + | mips16 \ 1218 + | mips64 | mips64eb | mips64el \ 1219 + | mips64octeon | mips64octeonel \ 1220 + | mips64orion | mips64orionel \ 1221 + | mips64r5900 | mips64r5900el \ 1222 + | mips64vr | mips64vrel \ 1223 + | mips64vr4100 | mips64vr4100el \ 1224 + | mips64vr4300 | mips64vr4300el \ 1225 + | mips64vr5000 | mips64vr5000el \ 1226 + | mips64vr5900 | mips64vr5900el \ 1227 + | mipsisa32 | mipsisa32el \ 1228 + | mipsisa32r2 | mipsisa32r2el \ 1229 + | mipsisa32r3 | mipsisa32r3el \ 1230 + | mipsisa32r5 | mipsisa32r5el \ 1231 + | mipsisa32r6 | mipsisa32r6el \ 1232 + | mipsisa64 | mipsisa64el \ 1233 + | mipsisa64r2 | mipsisa64r2el \ 1234 + | mipsisa64r3 | mipsisa64r3el \ 1235 + | mipsisa64r5 | mipsisa64r5el \ 1236 + | mipsisa64r6 | mipsisa64r6el \ 1237 + | mipsisa64sb1 | mipsisa64sb1el \ 1238 + | mipsisa64sr71k | mipsisa64sr71kel \ 1239 + | mipsr5900 | mipsr5900el \ 1240 + | mipstx39 | mipstx39el \ 1241 + | mmix \ 1242 + | mn10200 | mn10300 \ 1243 + | moxie \ 1244 + | mt \ 1245 + | msp430 \ 1246 + | nds32 | nds32le | nds32be \ 1247 + | nfp \ 1248 + | nios | nios2 | nios2eb | nios2el \ 1249 + | none | np1 | ns16k | ns32k | nvptx \ 1250 + | open8 \ 1251 + | or1k* \ 1252 + | or32 \ 1253 + | orion \ 1254 + | picochip \ 1255 + | pdp10 | pdp11 | pj | pjl | pn | power \ 1256 + | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \ 1257 + | pru \ 1258 + | pyramid \ 1259 + | riscv | riscv32 | riscv32be | riscv64 | riscv64be \ 1260 + | rl78 | romp | rs6000 | rx \ 1261 + | s390 | s390x \ 1262 + | score \ 1263 + | sh | shl \ 1264 + | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \ 1265 + | sh[1234]e[lb] | sh[12345][lb]e | sh[23]ele | sh64 | sh64le \ 1266 + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \ 1267 + | sparclite \ 1268 + | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \ 1269 + | spu \ 1270 + | tahoe \ 1271 + | thumbv7* \ 1272 + | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \ 1273 + | tron \ 1274 + | ubicom32 \ 1275 + | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \ 1276 + | vax \ 1277 + | visium \ 1278 + | w65 \ 1279 + | wasm32 | wasm64 \ 1280 + | we32k \ 1281 + | x86 | x86_64 | xc16x | xgate | xps100 \ 1282 + | xstormy16 | xtensa* \ 1283 + | ymp \ 1284 + | z8k | z80) 1285 + ;; 1286 + 1287 + *) 1288 + echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2 1289 + exit 1 1290 + ;; 1291 + esac 1292 + ;; 1293 + esac 1294 + 1295 + # Here we canonicalize certain aliases for manufacturers. 1296 + case $vendor in 1297 + digital*) 1298 + vendor=dec 1299 + ;; 1300 + commodore*) 1301 + vendor=cbm 1302 + ;; 1303 + *) 1304 + ;; 1305 + esac 1306 + 1307 + # Decode manufacturer-specific aliases for certain operating systems. 1308 + 1309 + if test x$basic_os != x 1310 + then 1311 + 1312 + # First recognize some ad-hoc cases, or perhaps split kernel-os, or else just 1313 + # set os. 1314 + case $basic_os in 1315 + gnu/linux*) 1316 + kernel=linux 1317 + os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'` 1318 + ;; 1319 + os2-emx) 1320 + kernel=os2 1321 + os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'` 1322 + ;; 1323 + nto-qnx*) 1324 + kernel=nto 1325 + os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'` 1326 + ;; 1327 + *-*) 1328 + # shellcheck disable=SC2162 1329 + saved_IFS=$IFS 1330 + IFS="-" read kernel os <<EOF 1331 + $basic_os 1332 + EOF 1333 + IFS=$saved_IFS 1334 + ;; 1335 + # Default OS when just kernel was specified 1336 + nto*) 1337 + kernel=nto 1338 + os=`echo "$basic_os" | sed -e 's|nto|qnx|'` 1339 + ;; 1340 + linux*) 1341 + kernel=linux 1342 + os=`echo "$basic_os" | sed -e 's|linux|gnu|'` 1343 + ;; 1344 + *) 1345 + kernel= 1346 + os=$basic_os 1347 + ;; 1348 + esac 1349 + 1350 + # Now, normalize the OS (knowing we just have one component, it's not a kernel, 1351 + # etc.) 1352 + case $os in 1353 + # First match some system type aliases that might get confused 1354 + # with valid system types. 1355 + # solaris* is a basic system type, with this one exception. 1356 + auroraux) 1357 + os=auroraux 1358 + ;; 1359 + bluegene*) 1360 + os=cnk 1361 + ;; 1362 + solaris1 | solaris1.*) 1363 + os=`echo "$os" | sed -e 's|solaris1|sunos4|'` 1364 + ;; 1365 + solaris) 1366 + os=solaris2 1367 + ;; 1368 + unixware*) 1369 + os=sysv4.2uw 1370 + ;; 1371 + # es1800 is here to avoid being matched by es* (a different OS) 1372 + es1800*) 1373 + os=ose 1374 + ;; 1375 + # Some version numbers need modification 1376 + chorusos*) 1377 + os=chorusos 1378 + ;; 1379 + isc) 1380 + os=isc2.2 1381 + ;; 1382 + sco6) 1383 + os=sco5v6 1384 + ;; 1385 + sco5) 1386 + os=sco3.2v5 1387 + ;; 1388 + sco4) 1389 + os=sco3.2v4 1390 + ;; 1391 + sco3.2.[4-9]*) 1392 + os=`echo "$os" | sed -e 's/sco3.2./sco3.2v/'` 1393 + ;; 1394 + sco*v* | scout) 1395 + # Don't match below 1396 + ;; 1397 + sco*) 1398 + os=sco3.2v2 1399 + ;; 1400 + psos*) 1401 + os=psos 1402 + ;; 1403 + qnx*) 1404 + os=qnx 1405 + ;; 1406 + hiux*) 1407 + os=hiuxwe2 1408 + ;; 1409 + lynx*178) 1410 + os=lynxos178 1411 + ;; 1412 + lynx*5) 1413 + os=lynxos5 1414 + ;; 1415 + lynxos*) 1416 + # don't get caught up in next wildcard 1417 + ;; 1418 + lynx*) 1419 + os=lynxos 1420 + ;; 1421 + mac[0-9]*) 1422 + os=`echo "$os" | sed -e 's|mac|macos|'` 1423 + ;; 1424 + opened*) 1425 + os=openedition 1426 + ;; 1427 + os400*) 1428 + os=os400 1429 + ;; 1430 + sunos5*) 1431 + os=`echo "$os" | sed -e 's|sunos5|solaris2|'` 1432 + ;; 1433 + sunos6*) 1434 + os=`echo "$os" | sed -e 's|sunos6|solaris3|'` 1435 + ;; 1436 + wince*) 1437 + os=wince 1438 + ;; 1439 + utek*) 1440 + os=bsd 1441 + ;; 1442 + dynix*) 1443 + os=bsd 1444 + ;; 1445 + acis*) 1446 + os=aos 1447 + ;; 1448 + atheos*) 1449 + os=atheos 1450 + ;; 1451 + syllable*) 1452 + os=syllable 1453 + ;; 1454 + 386bsd) 1455 + os=bsd 1456 + ;; 1457 + ctix* | uts*) 1458 + os=sysv 1459 + ;; 1460 + nova*) 1461 + os=rtmk-nova 1462 + ;; 1463 + ns2) 1464 + os=nextstep2 1465 + ;; 1466 + # Preserve the version number of sinix5. 1467 + sinix5.*) 1468 + os=`echo "$os" | sed -e 's|sinix|sysv|'` 1469 + ;; 1470 + sinix*) 1471 + os=sysv4 1472 + ;; 1473 + tpf*) 1474 + os=tpf 1475 + ;; 1476 + triton*) 1477 + os=sysv3 1478 + ;; 1479 + oss*) 1480 + os=sysv3 1481 + ;; 1482 + svr4*) 1483 + os=sysv4 1484 + ;; 1485 + svr3) 1486 + os=sysv3 1487 + ;; 1488 + sysvr4) 1489 + os=sysv4 1490 + ;; 1491 + ose*) 1492 + os=ose 1493 + ;; 1494 + *mint | mint[0-9]* | *MiNT | MiNT[0-9]*) 1495 + os=mint 1496 + ;; 1497 + dicos*) 1498 + os=dicos 1499 + ;; 1500 + pikeos*) 1501 + # Until real need of OS specific support for 1502 + # particular features comes up, bare metal 1503 + # configurations are quite functional. 1504 + case $cpu in 1505 + arm*) 1506 + os=eabi 1507 + ;; 1508 + *) 1509 + os=elf 1510 + ;; 1511 + esac 1512 + ;; 1513 + *) 1514 + # No normalization, but not necessarily accepted, that comes below. 1515 + ;; 1516 + esac 1517 + 1518 + else 1519 + 1520 + # Here we handle the default operating systems that come with various machines. 1521 + # The value should be what the vendor currently ships out the door with their 1522 + # machine or put another way, the most popular os provided with the machine. 1523 + 1524 + # Note that if you're going to try to match "-MANUFACTURER" here (say, 1525 + # "-sun"), then you have to tell the case statement up towards the top 1526 + # that MANUFACTURER isn't an operating system. Otherwise, code above 1527 + # will signal an error saying that MANUFACTURER isn't an operating 1528 + # system, and we'll never get to this point. 1529 + 1530 + kernel= 1531 + case $cpu-$vendor in 1532 + score-*) 1533 + os=elf 1534 + ;; 1535 + spu-*) 1536 + os=elf 1537 + ;; 1538 + *-acorn) 1539 + os=riscix1.2 1540 + ;; 1541 + arm*-rebel) 1542 + kernel=linux 1543 + os=gnu 1544 + ;; 1545 + arm*-semi) 1546 + os=aout 1547 + ;; 1548 + c4x-* | tic4x-*) 1549 + os=coff 1550 + ;; 1551 + c8051-*) 1552 + os=elf 1553 + ;; 1554 + clipper-intergraph) 1555 + os=clix 1556 + ;; 1557 + hexagon-*) 1558 + os=elf 1559 + ;; 1560 + tic54x-*) 1561 + os=coff 1562 + ;; 1563 + tic55x-*) 1564 + os=coff 1565 + ;; 1566 + tic6x-*) 1567 + os=coff 1568 + ;; 1569 + # This must come before the *-dec entry. 1570 + pdp10-*) 1571 + os=tops20 1572 + ;; 1573 + pdp11-*) 1574 + os=none 1575 + ;; 1576 + *-dec | vax-*) 1577 + os=ultrix4.2 1578 + ;; 1579 + m68*-apollo) 1580 + os=domain 1581 + ;; 1582 + i386-sun) 1583 + os=sunos4.0.2 1584 + ;; 1585 + m68000-sun) 1586 + os=sunos3 1587 + ;; 1588 + m68*-cisco) 1589 + os=aout 1590 + ;; 1591 + mep-*) 1592 + os=elf 1593 + ;; 1594 + mips*-cisco) 1595 + os=elf 1596 + ;; 1597 + mips*-*) 1598 + os=elf 1599 + ;; 1600 + or32-*) 1601 + os=coff 1602 + ;; 1603 + *-tti) # must be before sparc entry or we get the wrong os. 1604 + os=sysv3 1605 + ;; 1606 + sparc-* | *-sun) 1607 + os=sunos4.1.1 1608 + ;; 1609 + pru-*) 1610 + os=elf 1611 + ;; 1612 + *-be) 1613 + os=beos 1614 + ;; 1615 + *-ibm) 1616 + os=aix 1617 + ;; 1618 + *-knuth) 1619 + os=mmixware 1620 + ;; 1621 + *-wec) 1622 + os=proelf 1623 + ;; 1624 + *-winbond) 1625 + os=proelf 1626 + ;; 1627 + *-oki) 1628 + os=proelf 1629 + ;; 1630 + *-hp) 1631 + os=hpux 1632 + ;; 1633 + *-hitachi) 1634 + os=hiux 1635 + ;; 1636 + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) 1637 + os=sysv 1638 + ;; 1639 + *-cbm) 1640 + os=amigaos 1641 + ;; 1642 + *-dg) 1643 + os=dgux 1644 + ;; 1645 + *-dolphin) 1646 + os=sysv3 1647 + ;; 1648 + m68k-ccur) 1649 + os=rtu 1650 + ;; 1651 + m88k-omron*) 1652 + os=luna 1653 + ;; 1654 + *-next) 1655 + os=nextstep 1656 + ;; 1657 + *-sequent) 1658 + os=ptx 1659 + ;; 1660 + *-crds) 1661 + os=unos 1662 + ;; 1663 + *-ns) 1664 + os=genix 1665 + ;; 1666 + i370-*) 1667 + os=mvs 1668 + ;; 1669 + *-gould) 1670 + os=sysv 1671 + ;; 1672 + *-highlevel) 1673 + os=bsd 1674 + ;; 1675 + *-encore) 1676 + os=bsd 1677 + ;; 1678 + *-sgi) 1679 + os=irix 1680 + ;; 1681 + *-siemens) 1682 + os=sysv4 1683 + ;; 1684 + *-masscomp) 1685 + os=rtu 1686 + ;; 1687 + f30[01]-fujitsu | f700-fujitsu) 1688 + os=uxpv 1689 + ;; 1690 + *-rom68k) 1691 + os=coff 1692 + ;; 1693 + *-*bug) 1694 + os=coff 1695 + ;; 1696 + *-apple) 1697 + os=macos 1698 + ;; 1699 + *-atari*) 1700 + os=mint 1701 + ;; 1702 + *-wrs) 1703 + os=vxworks 1704 + ;; 1705 + *) 1706 + os=none 1707 + ;; 1708 + esac 1709 + 1710 + fi 1711 + 1712 + # Now, validate our (potentially fixed-up) OS. 1713 + case $os in 1714 + # Sometimes we do "kernel-libc", so those need to count as OSes. 1715 + musl* | newlib* | relibc* | uclibc*) 1716 + ;; 1717 + # Likewise for "kernel-abi" 1718 + eabi* | gnueabi*) 1719 + ;; 1720 + # VxWorks passes extra cpu info in the 4th filed. 1721 + simlinux | simwindows | spe) 1722 + ;; 1723 + # Now accept the basic system types. 1724 + # The portable systems comes first. 1725 + # Each alternative MUST end in a * to match a version number. 1726 + gnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \ 1727 + | *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \ 1728 + | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \ 1729 + | sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \ 1730 + | hiux* | abug | nacl* | netware* | windows* \ 1731 + | os9* | macos* | osx* | ios* \ 1732 + | mpw* | magic* | mmixware* | mon960* | lnews* \ 1733 + | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \ 1734 + | aos* | aros* | cloudabi* | sortix* | twizzler* \ 1735 + | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \ 1736 + | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \ 1737 + | mirbsd* | netbsd* | dicos* | openedition* | ose* \ 1738 + | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \ 1739 + | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \ 1740 + | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \ 1741 + | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \ 1742 + | udi* | lites* | ieee* | go32* | aux* | hcos* \ 1743 + | chorusrdb* | cegcc* | glidix* | serenity* \ 1744 + | cygwin* | msys* | pe* | moss* | proelf* | rtems* \ 1745 + | midipix* | mingw32* | mingw64* | mint* \ 1746 + | uxpv* | beos* | mpeix* | udk* | moxiebox* \ 1747 + | interix* | uwin* | mks* | rhapsody* | darwin* \ 1748 + | openstep* | oskit* | conix* | pw32* | nonstopux* \ 1749 + | storm-chaos* | tops10* | tenex* | tops20* | its* \ 1750 + | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \ 1751 + | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \ 1752 + | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \ 1753 + | skyos* | haiku* | rdos* | toppers* | drops* | es* \ 1754 + | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ 1755 + | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ 1756 + | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \ 1757 + | fiwix* ) 1758 + ;; 1759 + # This one is extra strict with allowed versions 1760 + sco3.2v2 | sco3.2v[4-9]* | sco5v6*) 1761 + # Don't forget version if it is 3.2v4 or newer. 1762 + ;; 1763 + none) 1764 + ;; 1765 + *) 1766 + echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2 1767 + exit 1 1768 + ;; 1769 + esac 1770 + 1771 + # As a final step for OS-related things, validate the OS-kernel combination 1772 + # (given a valid OS), if there is a kernel. 1773 + case $kernel-$os in 1774 + linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \ 1775 + | linux-musl* | linux-relibc* | linux-uclibc* ) 1776 + ;; 1777 + uclinux-uclibc* ) 1778 + ;; 1779 + -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* ) 1780 + # These are just libc implementations, not actual OSes, and thus 1781 + # require a kernel. 1782 + echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 1783 + exit 1 1784 + ;; 1785 + kfreebsd*-gnu* | kopensolaris*-gnu*) 1786 + ;; 1787 + vxworks-simlinux | vxworks-simwindows | vxworks-spe) 1788 + ;; 1789 + nto-qnx*) 1790 + ;; 1791 + os2-emx) 1792 + ;; 1793 + *-eabi* | *-gnueabi*) 1794 + ;; 1795 + -*) 1796 + # Blank kernel with real OS is always fine. 1797 + ;; 1798 + *-*) 1799 + echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2 1800 + exit 1 1801 + ;; 1802 + esac 1803 + 1804 + # Here we handle the case where we know the os, and the CPU type, but not the 1805 + # manufacturer. We pick the logical manufacturer. 1806 + case $vendor in 1807 + unknown) 1808 + case $cpu-$os in 1809 + *-riscix*) 1810 + vendor=acorn 1811 + ;; 1812 + *-sunos*) 1813 + vendor=sun 1814 + ;; 1815 + *-cnk* | *-aix*) 1816 + vendor=ibm 1817 + ;; 1818 + *-beos*) 1819 + vendor=be 1820 + ;; 1821 + *-hpux*) 1822 + vendor=hp 1823 + ;; 1824 + *-mpeix*) 1825 + vendor=hp 1826 + ;; 1827 + *-hiux*) 1828 + vendor=hitachi 1829 + ;; 1830 + *-unos*) 1831 + vendor=crds 1832 + ;; 1833 + *-dgux*) 1834 + vendor=dg 1835 + ;; 1836 + *-luna*) 1837 + vendor=omron 1838 + ;; 1839 + *-genix*) 1840 + vendor=ns 1841 + ;; 1842 + *-clix*) 1843 + vendor=intergraph 1844 + ;; 1845 + *-mvs* | *-opened*) 1846 + vendor=ibm 1847 + ;; 1848 + *-os400*) 1849 + vendor=ibm 1850 + ;; 1851 + s390-* | s390x-*) 1852 + vendor=ibm 1853 + ;; 1854 + *-ptx*) 1855 + vendor=sequent 1856 + ;; 1857 + *-tpf*) 1858 + vendor=ibm 1859 + ;; 1860 + *-vxsim* | *-vxworks* | *-windiss*) 1861 + vendor=wrs 1862 + ;; 1863 + *-aux*) 1864 + vendor=apple 1865 + ;; 1866 + *-hms*) 1867 + vendor=hitachi 1868 + ;; 1869 + *-mpw* | *-macos*) 1870 + vendor=apple 1871 + ;; 1872 + *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*) 1873 + vendor=atari 1874 + ;; 1875 + *-vos*) 1876 + vendor=stratus 1877 + ;; 1878 + esac 1879 + ;; 1880 + esac 1881 + 1882 + echo "$cpu-$vendor-${kernel:+$kernel-}$os" 1883 + exit 1884 + 1885 + # Local variables: 1886 + # eval: (add-hook 'before-save-hook 'time-stamp) 1887 + # time-stamp-start: "timestamp='" 1888 + # time-stamp-format: "%:y-%02m-%02d" 1889 + # time-stamp-end: "'" 1890 + # End:
+5370
usr.sbin/nsd/simdzone/configure
··· 1 + #! /bin/sh 2 + # Guess values for system-dependent variables and create Makefiles. 3 + # Generated by GNU Autoconf 2.71 for simdzone 0.2.0. 4 + # 5 + # Report bugs to <https://github.com/NLnetLabs/simdzone/issues>. 6 + # 7 + # 8 + # Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation, 9 + # Inc. 10 + # 11 + # 12 + # This configure script is free software; the Free Software Foundation 13 + # gives unlimited permission to copy, distribute and modify it. 14 + ## -------------------- ## 15 + ## M4sh Initialization. ## 16 + ## -------------------- ## 17 + 18 + # Be more Bourne compatible 19 + DUALCASE=1; export DUALCASE # for MKS sh 20 + as_nop=: 21 + if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 22 + then : 23 + emulate sh 24 + NULLCMD=: 25 + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which 26 + # is contrary to our usage. Disable this feature. 27 + alias -g '${1+"$@"}'='"$@"' 28 + setopt NO_GLOB_SUBST 29 + else $as_nop 30 + case `(set -o) 2>/dev/null` in #( 31 + *posix*) : 32 + set -o posix ;; #( 33 + *) : 34 + ;; 35 + esac 36 + fi 37 + 38 + 39 + 40 + # Reset variables that may have inherited troublesome values from 41 + # the environment. 42 + 43 + # IFS needs to be set, to space, tab, and newline, in precisely that order. 44 + # (If _AS_PATH_WALK were called with IFS unset, it would have the 45 + # side effect of setting IFS to empty, thus disabling word splitting.) 46 + # Quoting is to prevent editors from complaining about space-tab. 47 + as_nl=' 48 + ' 49 + export as_nl 50 + IFS=" "" $as_nl" 51 + 52 + PS1='$ ' 53 + PS2='> ' 54 + PS4='+ ' 55 + 56 + # Ensure predictable behavior from utilities with locale-dependent output. 57 + LC_ALL=C 58 + export LC_ALL 59 + LANGUAGE=C 60 + export LANGUAGE 61 + 62 + # We cannot yet rely on "unset" to work, but we need these variables 63 + # to be unset--not just set to an empty or harmless value--now, to 64 + # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct 65 + # also avoids known problems related to "unset" and subshell syntax 66 + # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). 67 + for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH 68 + do eval test \${$as_var+y} \ 69 + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : 70 + done 71 + 72 + # Ensure that fds 0, 1, and 2 are open. 73 + if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi 74 + if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi 75 + if (exec 3>&2) ; then :; else exec 2>/dev/null; fi 76 + 77 + # The user is always right. 78 + if ${PATH_SEPARATOR+false} :; then 79 + PATH_SEPARATOR=: 80 + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { 81 + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || 82 + PATH_SEPARATOR=';' 83 + } 84 + fi 85 + 86 + 87 + # Find who we are. Look in the path if we contain no directory separator. 88 + as_myself= 89 + case $0 in #(( 90 + *[\\/]* ) as_myself=$0 ;; 91 + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR 92 + for as_dir in $PATH 93 + do 94 + IFS=$as_save_IFS 95 + case $as_dir in #((( 96 + '') as_dir=./ ;; 97 + */) ;; 98 + *) as_dir=$as_dir/ ;; 99 + esac 100 + test -r "$as_dir$0" && as_myself=$as_dir$0 && break 101 + done 102 + IFS=$as_save_IFS 103 + 104 + ;; 105 + esac 106 + # We did not find ourselves, most probably we were run as `sh COMMAND' 107 + # in which case we are not to be found in the path. 108 + if test "x$as_myself" = x; then 109 + as_myself=$0 110 + fi 111 + if test ! -f "$as_myself"; then 112 + printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 113 + exit 1 114 + fi 115 + 116 + 117 + # Use a proper internal environment variable to ensure we don't fall 118 + # into an infinite loop, continuously re-executing ourselves. 119 + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then 120 + _as_can_reexec=no; export _as_can_reexec; 121 + # We cannot yet assume a decent shell, so we have to provide a 122 + # neutralization value for shells without unset; and this also 123 + # works around shells that cannot unset nonexistent variables. 124 + # Preserve -v and -x to the replacement shell. 125 + BASH_ENV=/dev/null 126 + ENV=/dev/null 127 + (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV 128 + case $- in # (((( 129 + *v*x* | *x*v* ) as_opts=-vx ;; 130 + *v* ) as_opts=-v ;; 131 + *x* ) as_opts=-x ;; 132 + * ) as_opts= ;; 133 + esac 134 + exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} 135 + # Admittedly, this is quite paranoid, since all the known shells bail 136 + # out after a failed `exec'. 137 + printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 138 + exit 255 139 + fi 140 + # We don't want this to propagate to other subprocesses. 141 + { _as_can_reexec=; unset _as_can_reexec;} 142 + if test "x$CONFIG_SHELL" = x; then 143 + as_bourne_compatible="as_nop=: 144 + if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 145 + then : 146 + emulate sh 147 + NULLCMD=: 148 + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which 149 + # is contrary to our usage. Disable this feature. 150 + alias -g '\${1+\"\$@\"}'='\"\$@\"' 151 + setopt NO_GLOB_SUBST 152 + else \$as_nop 153 + case \`(set -o) 2>/dev/null\` in #( 154 + *posix*) : 155 + set -o posix ;; #( 156 + *) : 157 + ;; 158 + esac 159 + fi 160 + " 161 + as_required="as_fn_return () { (exit \$1); } 162 + as_fn_success () { as_fn_return 0; } 163 + as_fn_failure () { as_fn_return 1; } 164 + as_fn_ret_success () { return 0; } 165 + as_fn_ret_failure () { return 1; } 166 + 167 + exitcode=0 168 + as_fn_success || { exitcode=1; echo as_fn_success failed.; } 169 + as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } 170 + as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } 171 + as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } 172 + if ( set x; as_fn_ret_success y && test x = \"\$1\" ) 173 + then : 174 + 175 + else \$as_nop 176 + exitcode=1; echo positional parameters were not saved. 177 + fi 178 + test x\$exitcode = x0 || exit 1 179 + blah=\$(echo \$(echo blah)) 180 + test x\"\$blah\" = xblah || exit 1 181 + test -x / || exit 1" 182 + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO 183 + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO 184 + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && 185 + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" 186 + if (eval "$as_required") 2>/dev/null 187 + then : 188 + as_have_required=yes 189 + else $as_nop 190 + as_have_required=no 191 + fi 192 + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null 193 + then : 194 + 195 + else $as_nop 196 + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR 197 + as_found=false 198 + for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH 199 + do 200 + IFS=$as_save_IFS 201 + case $as_dir in #((( 202 + '') as_dir=./ ;; 203 + */) ;; 204 + *) as_dir=$as_dir/ ;; 205 + esac 206 + as_found=: 207 + case $as_dir in #( 208 + /*) 209 + for as_base in sh bash ksh sh5; do 210 + # Try only shells that exist, to save several forks. 211 + as_shell=$as_dir$as_base 212 + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && 213 + as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null 214 + then : 215 + CONFIG_SHELL=$as_shell as_have_required=yes 216 + if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null 217 + then : 218 + break 2 219 + fi 220 + fi 221 + done;; 222 + esac 223 + as_found=false 224 + done 225 + IFS=$as_save_IFS 226 + if $as_found 227 + then : 228 + 229 + else $as_nop 230 + if { test -f "$SHELL" || test -f "$SHELL.exe"; } && 231 + as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null 232 + then : 233 + CONFIG_SHELL=$SHELL as_have_required=yes 234 + fi 235 + fi 236 + 237 + 238 + if test "x$CONFIG_SHELL" != x 239 + then : 240 + export CONFIG_SHELL 241 + # We cannot yet assume a decent shell, so we have to provide a 242 + # neutralization value for shells without unset; and this also 243 + # works around shells that cannot unset nonexistent variables. 244 + # Preserve -v and -x to the replacement shell. 245 + BASH_ENV=/dev/null 246 + ENV=/dev/null 247 + (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV 248 + case $- in # (((( 249 + *v*x* | *x*v* ) as_opts=-vx ;; 250 + *v* ) as_opts=-v ;; 251 + *x* ) as_opts=-x ;; 252 + * ) as_opts= ;; 253 + esac 254 + exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} 255 + # Admittedly, this is quite paranoid, since all the known shells bail 256 + # out after a failed `exec'. 257 + printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 258 + exit 255 259 + fi 260 + 261 + if test x$as_have_required = xno 262 + then : 263 + printf "%s\n" "$0: This script requires a shell more modern than all" 264 + printf "%s\n" "$0: the shells that I found on your system." 265 + if test ${ZSH_VERSION+y} ; then 266 + printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should" 267 + printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later." 268 + else 269 + printf "%s\n" "$0: Please tell bug-autoconf@gnu.org and 270 + $0: https://github.com/NLnetLabs/simdzone/issues about your 271 + $0: system, including any error possibly output before this 272 + $0: message. Then install a modern shell, or manually run 273 + $0: the script under such a shell if you do have one." 274 + fi 275 + exit 1 276 + fi 277 + fi 278 + fi 279 + SHELL=${CONFIG_SHELL-/bin/sh} 280 + export SHELL 281 + # Unset more variables known to interfere with behavior of common tools. 282 + CLICOLOR_FORCE= GREP_OPTIONS= 283 + unset CLICOLOR_FORCE GREP_OPTIONS 284 + 285 + ## --------------------- ## 286 + ## M4sh Shell Functions. ## 287 + ## --------------------- ## 288 + # as_fn_unset VAR 289 + # --------------- 290 + # Portably unset VAR. 291 + as_fn_unset () 292 + { 293 + { eval $1=; unset $1;} 294 + } 295 + as_unset=as_fn_unset 296 + 297 + 298 + # as_fn_set_status STATUS 299 + # ----------------------- 300 + # Set $? to STATUS, without forking. 301 + as_fn_set_status () 302 + { 303 + return $1 304 + } # as_fn_set_status 305 + 306 + # as_fn_exit STATUS 307 + # ----------------- 308 + # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. 309 + as_fn_exit () 310 + { 311 + set +e 312 + as_fn_set_status $1 313 + exit $1 314 + } # as_fn_exit 315 + # as_fn_nop 316 + # --------- 317 + # Do nothing but, unlike ":", preserve the value of $?. 318 + as_fn_nop () 319 + { 320 + return $? 321 + } 322 + as_nop=as_fn_nop 323 + 324 + # as_fn_mkdir_p 325 + # ------------- 326 + # Create "$as_dir" as a directory, including parents if necessary. 327 + as_fn_mkdir_p () 328 + { 329 + 330 + case $as_dir in #( 331 + -*) as_dir=./$as_dir;; 332 + esac 333 + test -d "$as_dir" || eval $as_mkdir_p || { 334 + as_dirs= 335 + while :; do 336 + case $as_dir in #( 337 + *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( 338 + *) as_qdir=$as_dir;; 339 + esac 340 + as_dirs="'$as_qdir' $as_dirs" 341 + as_dir=`$as_dirname -- "$as_dir" || 342 + $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ 343 + X"$as_dir" : 'X\(//\)[^/]' \| \ 344 + X"$as_dir" : 'X\(//\)$' \| \ 345 + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || 346 + printf "%s\n" X"$as_dir" | 347 + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ 348 + s//\1/ 349 + q 350 + } 351 + /^X\(\/\/\)[^/].*/{ 352 + s//\1/ 353 + q 354 + } 355 + /^X\(\/\/\)$/{ 356 + s//\1/ 357 + q 358 + } 359 + /^X\(\/\).*/{ 360 + s//\1/ 361 + q 362 + } 363 + s/.*/./; q'` 364 + test -d "$as_dir" && break 365 + done 366 + test -z "$as_dirs" || eval "mkdir $as_dirs" 367 + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" 368 + 369 + 370 + } # as_fn_mkdir_p 371 + 372 + # as_fn_executable_p FILE 373 + # ----------------------- 374 + # Test if FILE is an executable regular file. 375 + as_fn_executable_p () 376 + { 377 + test -f "$1" && test -x "$1" 378 + } # as_fn_executable_p 379 + # as_fn_append VAR VALUE 380 + # ---------------------- 381 + # Append the text in VALUE to the end of the definition contained in VAR. Take 382 + # advantage of any shell optimizations that allow amortized linear growth over 383 + # repeated appends, instead of the typical quadratic growth present in naive 384 + # implementations. 385 + if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null 386 + then : 387 + eval 'as_fn_append () 388 + { 389 + eval $1+=\$2 390 + }' 391 + else $as_nop 392 + as_fn_append () 393 + { 394 + eval $1=\$$1\$2 395 + } 396 + fi # as_fn_append 397 + 398 + # as_fn_arith ARG... 399 + # ------------------ 400 + # Perform arithmetic evaluation on the ARGs, and store the result in the 401 + # global $as_val. Take advantage of shells that can avoid forks. The arguments 402 + # must be portable across $(()) and expr. 403 + if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null 404 + then : 405 + eval 'as_fn_arith () 406 + { 407 + as_val=$(( $* )) 408 + }' 409 + else $as_nop 410 + as_fn_arith () 411 + { 412 + as_val=`expr "$@" || test $? -eq 1` 413 + } 414 + fi # as_fn_arith 415 + 416 + # as_fn_nop 417 + # --------- 418 + # Do nothing but, unlike ":", preserve the value of $?. 419 + as_fn_nop () 420 + { 421 + return $? 422 + } 423 + as_nop=as_fn_nop 424 + 425 + # as_fn_error STATUS ERROR [LINENO LOG_FD] 426 + # ---------------------------------------- 427 + # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are 428 + # provided, also output the error to LOG_FD, referencing LINENO. Then exit the 429 + # script with STATUS, using 1 if that was 0. 430 + as_fn_error () 431 + { 432 + as_status=$1; test $as_status -eq 0 && as_status=1 433 + if test "$4"; then 434 + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack 435 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 436 + fi 437 + printf "%s\n" "$as_me: error: $2" >&2 438 + as_fn_exit $as_status 439 + } # as_fn_error 440 + 441 + if expr a : '\(a\)' >/dev/null 2>&1 && 442 + test "X`expr 00001 : '.*\(...\)'`" = X001; then 443 + as_expr=expr 444 + else 445 + as_expr=false 446 + fi 447 + 448 + if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then 449 + as_basename=basename 450 + else 451 + as_basename=false 452 + fi 453 + 454 + if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then 455 + as_dirname=dirname 456 + else 457 + as_dirname=false 458 + fi 459 + 460 + as_me=`$as_basename -- "$0" || 461 + $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ 462 + X"$0" : 'X\(//\)$' \| \ 463 + X"$0" : 'X\(/\)' \| . 2>/dev/null || 464 + printf "%s\n" X/"$0" | 465 + sed '/^.*\/\([^/][^/]*\)\/*$/{ 466 + s//\1/ 467 + q 468 + } 469 + /^X\/\(\/\/\)$/{ 470 + s//\1/ 471 + q 472 + } 473 + /^X\/\(\/\).*/{ 474 + s//\1/ 475 + q 476 + } 477 + s/.*/./; q'` 478 + 479 + # Avoid depending upon Character Ranges. 480 + as_cr_letters='abcdefghijklmnopqrstuvwxyz' 481 + as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' 482 + as_cr_Letters=$as_cr_letters$as_cr_LETTERS 483 + as_cr_digits='0123456789' 484 + as_cr_alnum=$as_cr_Letters$as_cr_digits 485 + 486 + 487 + as_lineno_1=$LINENO as_lineno_1a=$LINENO 488 + as_lineno_2=$LINENO as_lineno_2a=$LINENO 489 + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && 490 + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { 491 + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) 492 + sed -n ' 493 + p 494 + /[$]LINENO/= 495 + ' <$as_myself | 496 + sed ' 497 + s/[$]LINENO.*/&-/ 498 + t lineno 499 + b 500 + :lineno 501 + N 502 + :loop 503 + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ 504 + t loop 505 + s/-\n.*// 506 + ' >$as_me.lineno && 507 + chmod +x "$as_me.lineno" || 508 + { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } 509 + 510 + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have 511 + # already done that, so ensure we don't try to do so again and fall 512 + # in an infinite loop. This has already happened in practice. 513 + _as_can_reexec=no; export _as_can_reexec 514 + # Don't try to exec as it changes $[0], causing all sort of problems 515 + # (the dirname of $[0] is not the place where we might find the 516 + # original and so on. Autoconf is especially sensitive to this). 517 + . "./$as_me.lineno" 518 + # Exit status is that of the last command. 519 + exit 520 + } 521 + 522 + 523 + # Determine whether it's possible to make 'echo' print without a newline. 524 + # These variables are no longer used directly by Autoconf, but are AC_SUBSTed 525 + # for compatibility with existing Makefiles. 526 + ECHO_C= ECHO_N= ECHO_T= 527 + case `echo -n x` in #((((( 528 + -n*) 529 + case `echo 'xy\c'` in 530 + *c*) ECHO_T=' ';; # ECHO_T is single tab character. 531 + xy) ECHO_C='\c';; 532 + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null 533 + ECHO_T=' ';; 534 + esac;; 535 + *) 536 + ECHO_N='-n';; 537 + esac 538 + 539 + # For backward compatibility with old third-party macros, we provide 540 + # the shell variables $as_echo and $as_echo_n. New code should use 541 + # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. 542 + as_echo='printf %s\n' 543 + as_echo_n='printf %s' 544 + 545 + 546 + rm -f conf$$ conf$$.exe conf$$.file 547 + if test -d conf$$.dir; then 548 + rm -f conf$$.dir/conf$$.file 549 + else 550 + rm -f conf$$.dir 551 + mkdir conf$$.dir 2>/dev/null 552 + fi 553 + if (echo >conf$$.file) 2>/dev/null; then 554 + if ln -s conf$$.file conf$$ 2>/dev/null; then 555 + as_ln_s='ln -s' 556 + # ... but there are two gotchas: 557 + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. 558 + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. 559 + # In both cases, we have to default to `cp -pR'. 560 + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || 561 + as_ln_s='cp -pR' 562 + elif ln conf$$.file conf$$ 2>/dev/null; then 563 + as_ln_s=ln 564 + else 565 + as_ln_s='cp -pR' 566 + fi 567 + else 568 + as_ln_s='cp -pR' 569 + fi 570 + rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file 571 + rmdir conf$$.dir 2>/dev/null 572 + 573 + if mkdir -p . 2>/dev/null; then 574 + as_mkdir_p='mkdir -p "$as_dir"' 575 + else 576 + test -d ./-p && rmdir ./-p 577 + as_mkdir_p=false 578 + fi 579 + 580 + as_test_x='test -x' 581 + as_executable_p=as_fn_executable_p 582 + 583 + # Sed expression to map a string onto a valid CPP name. 584 + as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" 585 + 586 + # Sed expression to map a string onto a valid variable name. 587 + as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" 588 + 589 + 590 + test -n "$DJDIR" || exec 7<&0 </dev/null 591 + exec 6>&1 592 + 593 + # Name of the host. 594 + # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, 595 + # so uname gets run too. 596 + ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` 597 + 598 + # 599 + # Initializations. 600 + # 601 + ac_default_prefix=/usr/local 602 + ac_clean_files= 603 + ac_config_libobj_dir=. 604 + LIBOBJS= 605 + cross_compiling=no 606 + subdirs= 607 + MFLAGS= 608 + MAKEFLAGS= 609 + 610 + # Identity of this package. 611 + PACKAGE_NAME='simdzone' 612 + PACKAGE_TARNAME='simdzone' 613 + PACKAGE_VERSION='0.2.0' 614 + PACKAGE_STRING='simdzone 0.2.0' 615 + PACKAGE_BUGREPORT='https://github.com/NLnetLabs/simdzone/issues' 616 + PACKAGE_URL='' 617 + 618 + # Factoring default headers for most tests. 619 + ac_includes_default="\ 620 + #include <stddef.h> 621 + #ifdef HAVE_STDIO_H 622 + # include <stdio.h> 623 + #endif 624 + #ifdef HAVE_STDLIB_H 625 + # include <stdlib.h> 626 + #endif 627 + #ifdef HAVE_STRING_H 628 + # include <string.h> 629 + #endif 630 + #ifdef HAVE_INTTYPES_H 631 + # include <inttypes.h> 632 + #endif 633 + #ifdef HAVE_STDINT_H 634 + # include <stdint.h> 635 + #endif 636 + #ifdef HAVE_STRINGS_H 637 + # include <strings.h> 638 + #endif 639 + #ifdef HAVE_SYS_TYPES_H 640 + # include <sys/types.h> 641 + #endif 642 + #ifdef HAVE_SYS_STAT_H 643 + # include <sys/stat.h> 644 + #endif 645 + #ifdef HAVE_UNISTD_H 646 + # include <unistd.h> 647 + #endif" 648 + 649 + ac_header_c_list= 650 + ac_subst_vars='LTLIBOBJS 651 + LIBOBJS 652 + HAVE_HASWELL 653 + HAVE_WESTMERE 654 + HAVE_ENDIAN_H 655 + target_os 656 + target_vendor 657 + target_cpu 658 + target 659 + host_os 660 + host_vendor 661 + host_cpu 662 + host 663 + build_os 664 + build_vendor 665 + build_cpu 666 + build 667 + DEPFLAGS 668 + OBJEXT 669 + EXEEXT 670 + ac_ct_CC 671 + CPPFLAGS 672 + LDFLAGS 673 + CFLAGS 674 + CC 675 + target_alias 676 + host_alias 677 + build_alias 678 + LIBS 679 + ECHO_T 680 + ECHO_N 681 + ECHO_C 682 + DEFS 683 + mandir 684 + localedir 685 + libdir 686 + psdir 687 + pdfdir 688 + dvidir 689 + htmldir 690 + infodir 691 + docdir 692 + oldincludedir 693 + includedir 694 + runstatedir 695 + localstatedir 696 + sharedstatedir 697 + sysconfdir 698 + datadir 699 + datarootdir 700 + libexecdir 701 + sbindir 702 + bindir 703 + program_transform_name 704 + prefix 705 + exec_prefix 706 + PACKAGE_URL 707 + PACKAGE_BUGREPORT 708 + PACKAGE_STRING 709 + PACKAGE_VERSION 710 + PACKAGE_TARNAME 711 + PACKAGE_NAME 712 + PATH_SEPARATOR 713 + SHELL' 714 + ac_subst_files='' 715 + ac_user_opts=' 716 + enable_option_checking 717 + enable_westmere 718 + enable_haswell 719 + ' 720 + ac_precious_vars='build_alias 721 + host_alias 722 + target_alias 723 + CC 724 + CFLAGS 725 + LDFLAGS 726 + LIBS 727 + CPPFLAGS' 728 + 729 + 730 + # Initialize some variables set by options. 731 + ac_init_help= 732 + ac_init_version=false 733 + ac_unrecognized_opts= 734 + ac_unrecognized_sep= 735 + # The variables have the same names as the options, with 736 + # dashes changed to underlines. 737 + cache_file=/dev/null 738 + exec_prefix=NONE 739 + no_create= 740 + no_recursion= 741 + prefix=NONE 742 + program_prefix=NONE 743 + program_suffix=NONE 744 + program_transform_name=s,x,x, 745 + silent= 746 + site= 747 + srcdir= 748 + verbose= 749 + x_includes=NONE 750 + x_libraries=NONE 751 + 752 + # Installation directory options. 753 + # These are left unexpanded so users can "make install exec_prefix=/foo" 754 + # and all the variables that are supposed to be based on exec_prefix 755 + # by default will actually change. 756 + # Use braces instead of parens because sh, perl, etc. also accept them. 757 + # (The list follows the same order as the GNU Coding Standards.) 758 + bindir='${exec_prefix}/bin' 759 + sbindir='${exec_prefix}/sbin' 760 + libexecdir='${exec_prefix}/libexec' 761 + datarootdir='${prefix}/share' 762 + datadir='${datarootdir}' 763 + sysconfdir='${prefix}/etc' 764 + sharedstatedir='${prefix}/com' 765 + localstatedir='${prefix}/var' 766 + runstatedir='${localstatedir}/run' 767 + includedir='${prefix}/include' 768 + oldincludedir='/usr/include' 769 + docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' 770 + infodir='${datarootdir}/info' 771 + htmldir='${docdir}' 772 + dvidir='${docdir}' 773 + pdfdir='${docdir}' 774 + psdir='${docdir}' 775 + libdir='${exec_prefix}/lib' 776 + localedir='${datarootdir}/locale' 777 + mandir='${datarootdir}/man' 778 + 779 + ac_prev= 780 + ac_dashdash= 781 + for ac_option 782 + do 783 + # If the previous option needs an argument, assign it. 784 + if test -n "$ac_prev"; then 785 + eval $ac_prev=\$ac_option 786 + ac_prev= 787 + continue 788 + fi 789 + 790 + case $ac_option in 791 + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; 792 + *=) ac_optarg= ;; 793 + *) ac_optarg=yes ;; 794 + esac 795 + 796 + case $ac_dashdash$ac_option in 797 + --) 798 + ac_dashdash=yes ;; 799 + 800 + -bindir | --bindir | --bindi | --bind | --bin | --bi) 801 + ac_prev=bindir ;; 802 + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) 803 + bindir=$ac_optarg ;; 804 + 805 + -build | --build | --buil | --bui | --bu) 806 + ac_prev=build_alias ;; 807 + -build=* | --build=* | --buil=* | --bui=* | --bu=*) 808 + build_alias=$ac_optarg ;; 809 + 810 + -cache-file | --cache-file | --cache-fil | --cache-fi \ 811 + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) 812 + ac_prev=cache_file ;; 813 + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ 814 + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) 815 + cache_file=$ac_optarg ;; 816 + 817 + --config-cache | -C) 818 + cache_file=config.cache ;; 819 + 820 + -datadir | --datadir | --datadi | --datad) 821 + ac_prev=datadir ;; 822 + -datadir=* | --datadir=* | --datadi=* | --datad=*) 823 + datadir=$ac_optarg ;; 824 + 825 + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ 826 + | --dataroo | --dataro | --datar) 827 + ac_prev=datarootdir ;; 828 + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ 829 + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) 830 + datarootdir=$ac_optarg ;; 831 + 832 + -disable-* | --disable-*) 833 + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` 834 + # Reject names that are not valid shell variable names. 835 + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && 836 + as_fn_error $? "invalid feature name: \`$ac_useropt'" 837 + ac_useropt_orig=$ac_useropt 838 + ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` 839 + case $ac_user_opts in 840 + *" 841 + "enable_$ac_useropt" 842 + "*) ;; 843 + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" 844 + ac_unrecognized_sep=', ';; 845 + esac 846 + eval enable_$ac_useropt=no ;; 847 + 848 + -docdir | --docdir | --docdi | --doc | --do) 849 + ac_prev=docdir ;; 850 + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) 851 + docdir=$ac_optarg ;; 852 + 853 + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) 854 + ac_prev=dvidir ;; 855 + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) 856 + dvidir=$ac_optarg ;; 857 + 858 + -enable-* | --enable-*) 859 + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` 860 + # Reject names that are not valid shell variable names. 861 + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && 862 + as_fn_error $? "invalid feature name: \`$ac_useropt'" 863 + ac_useropt_orig=$ac_useropt 864 + ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` 865 + case $ac_user_opts in 866 + *" 867 + "enable_$ac_useropt" 868 + "*) ;; 869 + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" 870 + ac_unrecognized_sep=', ';; 871 + esac 872 + eval enable_$ac_useropt=\$ac_optarg ;; 873 + 874 + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ 875 + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ 876 + | --exec | --exe | --ex) 877 + ac_prev=exec_prefix ;; 878 + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ 879 + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ 880 + | --exec=* | --exe=* | --ex=*) 881 + exec_prefix=$ac_optarg ;; 882 + 883 + -gas | --gas | --ga | --g) 884 + # Obsolete; use --with-gas. 885 + with_gas=yes ;; 886 + 887 + -help | --help | --hel | --he | -h) 888 + ac_init_help=long ;; 889 + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) 890 + ac_init_help=recursive ;; 891 + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) 892 + ac_init_help=short ;; 893 + 894 + -host | --host | --hos | --ho) 895 + ac_prev=host_alias ;; 896 + -host=* | --host=* | --hos=* | --ho=*) 897 + host_alias=$ac_optarg ;; 898 + 899 + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) 900 + ac_prev=htmldir ;; 901 + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ 902 + | --ht=*) 903 + htmldir=$ac_optarg ;; 904 + 905 + -includedir | --includedir | --includedi | --included | --include \ 906 + | --includ | --inclu | --incl | --inc) 907 + ac_prev=includedir ;; 908 + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ 909 + | --includ=* | --inclu=* | --incl=* | --inc=*) 910 + includedir=$ac_optarg ;; 911 + 912 + -infodir | --infodir | --infodi | --infod | --info | --inf) 913 + ac_prev=infodir ;; 914 + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) 915 + infodir=$ac_optarg ;; 916 + 917 + -libdir | --libdir | --libdi | --libd) 918 + ac_prev=libdir ;; 919 + -libdir=* | --libdir=* | --libdi=* | --libd=*) 920 + libdir=$ac_optarg ;; 921 + 922 + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ 923 + | --libexe | --libex | --libe) 924 + ac_prev=libexecdir ;; 925 + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ 926 + | --libexe=* | --libex=* | --libe=*) 927 + libexecdir=$ac_optarg ;; 928 + 929 + -localedir | --localedir | --localedi | --localed | --locale) 930 + ac_prev=localedir ;; 931 + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) 932 + localedir=$ac_optarg ;; 933 + 934 + -localstatedir | --localstatedir | --localstatedi | --localstated \ 935 + | --localstate | --localstat | --localsta | --localst | --locals) 936 + ac_prev=localstatedir ;; 937 + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ 938 + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) 939 + localstatedir=$ac_optarg ;; 940 + 941 + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) 942 + ac_prev=mandir ;; 943 + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) 944 + mandir=$ac_optarg ;; 945 + 946 + -nfp | --nfp | --nf) 947 + # Obsolete; use --without-fp. 948 + with_fp=no ;; 949 + 950 + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ 951 + | --no-cr | --no-c | -n) 952 + no_create=yes ;; 953 + 954 + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ 955 + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) 956 + no_recursion=yes ;; 957 + 958 + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ 959 + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ 960 + | --oldin | --oldi | --old | --ol | --o) 961 + ac_prev=oldincludedir ;; 962 + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ 963 + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ 964 + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) 965 + oldincludedir=$ac_optarg ;; 966 + 967 + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) 968 + ac_prev=prefix ;; 969 + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) 970 + prefix=$ac_optarg ;; 971 + 972 + -program-prefix | --program-prefix | --program-prefi | --program-pref \ 973 + | --program-pre | --program-pr | --program-p) 974 + ac_prev=program_prefix ;; 975 + -program-prefix=* | --program-prefix=* | --program-prefi=* \ 976 + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) 977 + program_prefix=$ac_optarg ;; 978 + 979 + -program-suffix | --program-suffix | --program-suffi | --program-suff \ 980 + | --program-suf | --program-su | --program-s) 981 + ac_prev=program_suffix ;; 982 + -program-suffix=* | --program-suffix=* | --program-suffi=* \ 983 + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) 984 + program_suffix=$ac_optarg ;; 985 + 986 + -program-transform-name | --program-transform-name \ 987 + | --program-transform-nam | --program-transform-na \ 988 + | --program-transform-n | --program-transform- \ 989 + | --program-transform | --program-transfor \ 990 + | --program-transfo | --program-transf \ 991 + | --program-trans | --program-tran \ 992 + | --progr-tra | --program-tr | --program-t) 993 + ac_prev=program_transform_name ;; 994 + -program-transform-name=* | --program-transform-name=* \ 995 + | --program-transform-nam=* | --program-transform-na=* \ 996 + | --program-transform-n=* | --program-transform-=* \ 997 + | --program-transform=* | --program-transfor=* \ 998 + | --program-transfo=* | --program-transf=* \ 999 + | --program-trans=* | --program-tran=* \ 1000 + | --progr-tra=* | --program-tr=* | --program-t=*) 1001 + program_transform_name=$ac_optarg ;; 1002 + 1003 + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) 1004 + ac_prev=pdfdir ;; 1005 + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) 1006 + pdfdir=$ac_optarg ;; 1007 + 1008 + -psdir | --psdir | --psdi | --psd | --ps) 1009 + ac_prev=psdir ;; 1010 + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) 1011 + psdir=$ac_optarg ;; 1012 + 1013 + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ 1014 + | -silent | --silent | --silen | --sile | --sil) 1015 + silent=yes ;; 1016 + 1017 + -runstatedir | --runstatedir | --runstatedi | --runstated \ 1018 + | --runstate | --runstat | --runsta | --runst | --runs \ 1019 + | --run | --ru | --r) 1020 + ac_prev=runstatedir ;; 1021 + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ 1022 + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ 1023 + | --run=* | --ru=* | --r=*) 1024 + runstatedir=$ac_optarg ;; 1025 + 1026 + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) 1027 + ac_prev=sbindir ;; 1028 + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ 1029 + | --sbi=* | --sb=*) 1030 + sbindir=$ac_optarg ;; 1031 + 1032 + -sharedstatedir | --sharedstatedir | --sharedstatedi \ 1033 + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ 1034 + | --sharedst | --shareds | --shared | --share | --shar \ 1035 + | --sha | --sh) 1036 + ac_prev=sharedstatedir ;; 1037 + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ 1038 + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ 1039 + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ 1040 + | --sha=* | --sh=*) 1041 + sharedstatedir=$ac_optarg ;; 1042 + 1043 + -site | --site | --sit) 1044 + ac_prev=site ;; 1045 + -site=* | --site=* | --sit=*) 1046 + site=$ac_optarg ;; 1047 + 1048 + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) 1049 + ac_prev=srcdir ;; 1050 + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) 1051 + srcdir=$ac_optarg ;; 1052 + 1053 + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ 1054 + | --syscon | --sysco | --sysc | --sys | --sy) 1055 + ac_prev=sysconfdir ;; 1056 + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ 1057 + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) 1058 + sysconfdir=$ac_optarg ;; 1059 + 1060 + -target | --target | --targe | --targ | --tar | --ta | --t) 1061 + ac_prev=target_alias ;; 1062 + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) 1063 + target_alias=$ac_optarg ;; 1064 + 1065 + -v | -verbose | --verbose | --verbos | --verbo | --verb) 1066 + verbose=yes ;; 1067 + 1068 + -version | --version | --versio | --versi | --vers | -V) 1069 + ac_init_version=: ;; 1070 + 1071 + -with-* | --with-*) 1072 + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` 1073 + # Reject names that are not valid shell variable names. 1074 + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && 1075 + as_fn_error $? "invalid package name: \`$ac_useropt'" 1076 + ac_useropt_orig=$ac_useropt 1077 + ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` 1078 + case $ac_user_opts in 1079 + *" 1080 + "with_$ac_useropt" 1081 + "*) ;; 1082 + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" 1083 + ac_unrecognized_sep=', ';; 1084 + esac 1085 + eval with_$ac_useropt=\$ac_optarg ;; 1086 + 1087 + -without-* | --without-*) 1088 + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` 1089 + # Reject names that are not valid shell variable names. 1090 + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && 1091 + as_fn_error $? "invalid package name: \`$ac_useropt'" 1092 + ac_useropt_orig=$ac_useropt 1093 + ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` 1094 + case $ac_user_opts in 1095 + *" 1096 + "with_$ac_useropt" 1097 + "*) ;; 1098 + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" 1099 + ac_unrecognized_sep=', ';; 1100 + esac 1101 + eval with_$ac_useropt=no ;; 1102 + 1103 + --x) 1104 + # Obsolete; use --with-x. 1105 + with_x=yes ;; 1106 + 1107 + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ 1108 + | --x-incl | --x-inc | --x-in | --x-i) 1109 + ac_prev=x_includes ;; 1110 + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ 1111 + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) 1112 + x_includes=$ac_optarg ;; 1113 + 1114 + -x-libraries | --x-libraries | --x-librarie | --x-librari \ 1115 + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) 1116 + ac_prev=x_libraries ;; 1117 + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ 1118 + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) 1119 + x_libraries=$ac_optarg ;; 1120 + 1121 + -*) as_fn_error $? "unrecognized option: \`$ac_option' 1122 + Try \`$0 --help' for more information" 1123 + ;; 1124 + 1125 + *=*) 1126 + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` 1127 + # Reject names that are not valid shell variable names. 1128 + case $ac_envvar in #( 1129 + '' | [0-9]* | *[!_$as_cr_alnum]* ) 1130 + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; 1131 + esac 1132 + eval $ac_envvar=\$ac_optarg 1133 + export $ac_envvar ;; 1134 + 1135 + *) 1136 + # FIXME: should be removed in autoconf 3.0. 1137 + printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2 1138 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && 1139 + printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2 1140 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" 1141 + ;; 1142 + 1143 + esac 1144 + done 1145 + 1146 + if test -n "$ac_prev"; then 1147 + ac_option=--`echo $ac_prev | sed 's/_/-/g'` 1148 + as_fn_error $? "missing argument to $ac_option" 1149 + fi 1150 + 1151 + if test -n "$ac_unrecognized_opts"; then 1152 + case $enable_option_checking in 1153 + no) ;; 1154 + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; 1155 + *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; 1156 + esac 1157 + fi 1158 + 1159 + # Check all directory arguments for consistency. 1160 + for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ 1161 + datadir sysconfdir sharedstatedir localstatedir includedir \ 1162 + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ 1163 + libdir localedir mandir runstatedir 1164 + do 1165 + eval ac_val=\$$ac_var 1166 + # Remove trailing slashes. 1167 + case $ac_val in 1168 + */ ) 1169 + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` 1170 + eval $ac_var=\$ac_val;; 1171 + esac 1172 + # Be sure to have absolute directory names. 1173 + case $ac_val in 1174 + [\\/$]* | ?:[\\/]* ) continue;; 1175 + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; 1176 + esac 1177 + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" 1178 + done 1179 + 1180 + # There might be people who depend on the old broken behavior: `$host' 1181 + # used to hold the argument of --host etc. 1182 + # FIXME: To remove some day. 1183 + build=$build_alias 1184 + host=$host_alias 1185 + target=$target_alias 1186 + 1187 + # FIXME: To remove some day. 1188 + if test "x$host_alias" != x; then 1189 + if test "x$build_alias" = x; then 1190 + cross_compiling=maybe 1191 + elif test "x$build_alias" != "x$host_alias"; then 1192 + cross_compiling=yes 1193 + fi 1194 + fi 1195 + 1196 + ac_tool_prefix= 1197 + test -n "$host_alias" && ac_tool_prefix=$host_alias- 1198 + 1199 + test "$silent" = yes && exec 6>/dev/null 1200 + 1201 + 1202 + ac_pwd=`pwd` && test -n "$ac_pwd" && 1203 + ac_ls_di=`ls -di .` && 1204 + ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || 1205 + as_fn_error $? "working directory cannot be determined" 1206 + test "X$ac_ls_di" = "X$ac_pwd_ls_di" || 1207 + as_fn_error $? "pwd does not report name of working directory" 1208 + 1209 + 1210 + # Find the source files, if location was not specified. 1211 + if test -z "$srcdir"; then 1212 + ac_srcdir_defaulted=yes 1213 + # Try the directory containing this script, then the parent directory. 1214 + ac_confdir=`$as_dirname -- "$as_myself" || 1215 + $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ 1216 + X"$as_myself" : 'X\(//\)[^/]' \| \ 1217 + X"$as_myself" : 'X\(//\)$' \| \ 1218 + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || 1219 + printf "%s\n" X"$as_myself" | 1220 + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ 1221 + s//\1/ 1222 + q 1223 + } 1224 + /^X\(\/\/\)[^/].*/{ 1225 + s//\1/ 1226 + q 1227 + } 1228 + /^X\(\/\/\)$/{ 1229 + s//\1/ 1230 + q 1231 + } 1232 + /^X\(\/\).*/{ 1233 + s//\1/ 1234 + q 1235 + } 1236 + s/.*/./; q'` 1237 + srcdir=$ac_confdir 1238 + if test ! -r "$srcdir/$ac_unique_file"; then 1239 + srcdir=.. 1240 + fi 1241 + else 1242 + ac_srcdir_defaulted=no 1243 + fi 1244 + if test ! -r "$srcdir/$ac_unique_file"; then 1245 + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." 1246 + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" 1247 + fi 1248 + ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" 1249 + ac_abs_confdir=`( 1250 + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" 1251 + pwd)` 1252 + # When building in place, set srcdir=. 1253 + if test "$ac_abs_confdir" = "$ac_pwd"; then 1254 + srcdir=. 1255 + fi 1256 + # Remove unnecessary trailing slashes from srcdir. 1257 + # Double slashes in file names in object file debugging info 1258 + # mess up M-x gdb in Emacs. 1259 + case $srcdir in 1260 + */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; 1261 + esac 1262 + for ac_var in $ac_precious_vars; do 1263 + eval ac_env_${ac_var}_set=\${${ac_var}+set} 1264 + eval ac_env_${ac_var}_value=\$${ac_var} 1265 + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} 1266 + eval ac_cv_env_${ac_var}_value=\$${ac_var} 1267 + done 1268 + 1269 + # 1270 + # Report the --help message. 1271 + # 1272 + if test "$ac_init_help" = "long"; then 1273 + # Omit some internal or obsolete options to make the list less imposing. 1274 + # This message is too long to be a string in the A/UX 3.1 sh. 1275 + cat <<_ACEOF 1276 + \`configure' configures simdzone 0.2.0 to adapt to many kinds of systems. 1277 + 1278 + Usage: $0 [OPTION]... [VAR=VALUE]... 1279 + 1280 + To assign environment variables (e.g., CC, CFLAGS...), specify them as 1281 + VAR=VALUE. See below for descriptions of some of the useful variables. 1282 + 1283 + Defaults for the options are specified in brackets. 1284 + 1285 + Configuration: 1286 + -h, --help display this help and exit 1287 + --help=short display options specific to this package 1288 + --help=recursive display the short help of all the included packages 1289 + -V, --version display version information and exit 1290 + -q, --quiet, --silent do not print \`checking ...' messages 1291 + --cache-file=FILE cache test results in FILE [disabled] 1292 + -C, --config-cache alias for \`--cache-file=config.cache' 1293 + -n, --no-create do not create output files 1294 + --srcdir=DIR find the sources in DIR [configure dir or \`..'] 1295 + 1296 + Installation directories: 1297 + --prefix=PREFIX install architecture-independent files in PREFIX 1298 + [$ac_default_prefix] 1299 + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX 1300 + [PREFIX] 1301 + 1302 + By default, \`make install' will install all the files in 1303 + \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify 1304 + an installation prefix other than \`$ac_default_prefix' using \`--prefix', 1305 + for instance \`--prefix=\$HOME'. 1306 + 1307 + For better control, use the options below. 1308 + 1309 + Fine tuning of the installation directories: 1310 + --bindir=DIR user executables [EPREFIX/bin] 1311 + --sbindir=DIR system admin executables [EPREFIX/sbin] 1312 + --libexecdir=DIR program executables [EPREFIX/libexec] 1313 + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] 1314 + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] 1315 + --localstatedir=DIR modifiable single-machine data [PREFIX/var] 1316 + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] 1317 + --libdir=DIR object code libraries [EPREFIX/lib] 1318 + --includedir=DIR C header files [PREFIX/include] 1319 + --oldincludedir=DIR C header files for non-gcc [/usr/include] 1320 + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] 1321 + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] 1322 + --infodir=DIR info documentation [DATAROOTDIR/info] 1323 + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] 1324 + --mandir=DIR man documentation [DATAROOTDIR/man] 1325 + --docdir=DIR documentation root [DATAROOTDIR/doc/simdzone] 1326 + --htmldir=DIR html documentation [DOCDIR] 1327 + --dvidir=DIR dvi documentation [DOCDIR] 1328 + --pdfdir=DIR pdf documentation [DOCDIR] 1329 + --psdir=DIR ps documentation [DOCDIR] 1330 + _ACEOF 1331 + 1332 + cat <<\_ACEOF 1333 + 1334 + System types: 1335 + --build=BUILD configure for building on BUILD [guessed] 1336 + --host=HOST cross-compile to build programs to run on HOST [BUILD] 1337 + --target=TARGET configure for building compilers for TARGET [HOST] 1338 + _ACEOF 1339 + fi 1340 + 1341 + if test -n "$ac_init_help"; then 1342 + case $ac_init_help in 1343 + short | recursive ) echo "Configuration of simdzone 0.2.0:";; 1344 + esac 1345 + cat <<\_ACEOF 1346 + 1347 + Optional Features: 1348 + --disable-option-checking ignore unrecognized --enable/--with options 1349 + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) 1350 + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] 1351 + --disable-westmere Disable Westmere (SSE4.2) kernel 1352 + --disable-haswell Disable Haswell (AVX2) kernel 1353 + 1354 + Some influential environment variables: 1355 + CC C compiler command 1356 + CFLAGS C compiler flags 1357 + LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a 1358 + nonstandard directory <lib dir> 1359 + LIBS libraries to pass to the linker, e.g. -l<library> 1360 + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if 1361 + you have headers in a nonstandard directory <include dir> 1362 + 1363 + Use these variables to override the choices made by `configure' or to help 1364 + it to find libraries and programs with nonstandard names/locations. 1365 + 1366 + Report bugs to <https://github.com/NLnetLabs/simdzone/issues>. 1367 + _ACEOF 1368 + ac_status=$? 1369 + fi 1370 + 1371 + if test "$ac_init_help" = "recursive"; then 1372 + # If there are subdirs, report their specific --help. 1373 + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue 1374 + test -d "$ac_dir" || 1375 + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || 1376 + continue 1377 + ac_builddir=. 1378 + 1379 + case "$ac_dir" in 1380 + .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; 1381 + *) 1382 + ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` 1383 + # A ".." for each directory in $ac_dir_suffix. 1384 + ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` 1385 + case $ac_top_builddir_sub in 1386 + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; 1387 + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; 1388 + esac ;; 1389 + esac 1390 + ac_abs_top_builddir=$ac_pwd 1391 + ac_abs_builddir=$ac_pwd$ac_dir_suffix 1392 + # for backward compatibility: 1393 + ac_top_builddir=$ac_top_build_prefix 1394 + 1395 + case $srcdir in 1396 + .) # We are building in place. 1397 + ac_srcdir=. 1398 + ac_top_srcdir=$ac_top_builddir_sub 1399 + ac_abs_top_srcdir=$ac_pwd ;; 1400 + [\\/]* | ?:[\\/]* ) # Absolute name. 1401 + ac_srcdir=$srcdir$ac_dir_suffix; 1402 + ac_top_srcdir=$srcdir 1403 + ac_abs_top_srcdir=$srcdir ;; 1404 + *) # Relative name. 1405 + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix 1406 + ac_top_srcdir=$ac_top_build_prefix$srcdir 1407 + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; 1408 + esac 1409 + ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix 1410 + 1411 + cd "$ac_dir" || { ac_status=$?; continue; } 1412 + # Check for configure.gnu first; this name is used for a wrapper for 1413 + # Metaconfig's "Configure" on case-insensitive file systems. 1414 + if test -f "$ac_srcdir/configure.gnu"; then 1415 + echo && 1416 + $SHELL "$ac_srcdir/configure.gnu" --help=recursive 1417 + elif test -f "$ac_srcdir/configure"; then 1418 + echo && 1419 + $SHELL "$ac_srcdir/configure" --help=recursive 1420 + else 1421 + printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2 1422 + fi || ac_status=$? 1423 + cd "$ac_pwd" || { ac_status=$?; break; } 1424 + done 1425 + fi 1426 + 1427 + test -n "$ac_init_help" && exit $ac_status 1428 + if $ac_init_version; then 1429 + cat <<\_ACEOF 1430 + simdzone configure 0.2.0 1431 + generated by GNU Autoconf 2.71 1432 + 1433 + Copyright (C) 2021 Free Software Foundation, Inc. 1434 + This configure script is free software; the Free Software Foundation 1435 + gives unlimited permission to copy, distribute and modify it. 1436 + _ACEOF 1437 + exit 1438 + fi 1439 + 1440 + ## ------------------------ ## 1441 + ## Autoconf initialization. ## 1442 + ## ------------------------ ## 1443 + 1444 + # ac_fn_c_try_compile LINENO 1445 + # -------------------------- 1446 + # Try to compile conftest.$ac_ext, and return whether this succeeded. 1447 + ac_fn_c_try_compile () 1448 + { 1449 + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack 1450 + rm -f conftest.$ac_objext conftest.beam 1451 + if { { ac_try="$ac_compile" 1452 + case "(($ac_try" in 1453 + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; 1454 + *) ac_try_echo=$ac_try;; 1455 + esac 1456 + eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" 1457 + printf "%s\n" "$ac_try_echo"; } >&5 1458 + (eval "$ac_compile") 2>conftest.err 1459 + ac_status=$? 1460 + if test -s conftest.err; then 1461 + grep -v '^ *+' conftest.err >conftest.er1 1462 + cat conftest.er1 >&5 1463 + mv -f conftest.er1 conftest.err 1464 + fi 1465 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 1466 + test $ac_status = 0; } && { 1467 + test -z "$ac_c_werror_flag" || 1468 + test ! -s conftest.err 1469 + } && test -s conftest.$ac_objext 1470 + then : 1471 + ac_retval=0 1472 + else $as_nop 1473 + printf "%s\n" "$as_me: failed program was:" >&5 1474 + sed 's/^/| /' conftest.$ac_ext >&5 1475 + 1476 + ac_retval=1 1477 + fi 1478 + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno 1479 + as_fn_set_status $ac_retval 1480 + 1481 + } # ac_fn_c_try_compile 1482 + 1483 + # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES 1484 + # ------------------------------------------------------- 1485 + # Tests whether HEADER exists and can be compiled using the include files in 1486 + # INCLUDES, setting the cache variable VAR accordingly. 1487 + ac_fn_c_check_header_compile () 1488 + { 1489 + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack 1490 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 1491 + printf %s "checking for $2... " >&6; } 1492 + if eval test \${$3+y} 1493 + then : 1494 + printf %s "(cached) " >&6 1495 + else $as_nop 1496 + cat confdefs.h - <<_ACEOF >conftest.$ac_ext 1497 + /* end confdefs.h. */ 1498 + $4 1499 + #include <$2> 1500 + _ACEOF 1501 + if ac_fn_c_try_compile "$LINENO" 1502 + then : 1503 + eval "$3=yes" 1504 + else $as_nop 1505 + eval "$3=no" 1506 + fi 1507 + rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext 1508 + fi 1509 + eval ac_res=\$$3 1510 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 1511 + printf "%s\n" "$ac_res" >&6; } 1512 + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno 1513 + 1514 + } # ac_fn_c_check_header_compile 1515 + 1516 + # ac_fn_check_decl LINENO SYMBOL VAR INCLUDES EXTRA-OPTIONS FLAG-VAR 1517 + # ------------------------------------------------------------------ 1518 + # Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR 1519 + # accordingly. Pass EXTRA-OPTIONS to the compiler, using FLAG-VAR. 1520 + ac_fn_check_decl () 1521 + { 1522 + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack 1523 + as_decl_name=`echo $2|sed 's/ *(.*//'` 1524 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 1525 + printf %s "checking whether $as_decl_name is declared... " >&6; } 1526 + if eval test \${$3+y} 1527 + then : 1528 + printf %s "(cached) " >&6 1529 + else $as_nop 1530 + as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` 1531 + eval ac_save_FLAGS=\$$6 1532 + as_fn_append $6 " $5" 1533 + cat confdefs.h - <<_ACEOF >conftest.$ac_ext 1534 + /* end confdefs.h. */ 1535 + $4 1536 + int 1537 + main (void) 1538 + { 1539 + #ifndef $as_decl_name 1540 + #ifdef __cplusplus 1541 + (void) $as_decl_use; 1542 + #else 1543 + (void) $as_decl_name; 1544 + #endif 1545 + #endif 1546 + 1547 + ; 1548 + return 0; 1549 + } 1550 + _ACEOF 1551 + if ac_fn_c_try_compile "$LINENO" 1552 + then : 1553 + eval "$3=yes" 1554 + else $as_nop 1555 + eval "$3=no" 1556 + fi 1557 + rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext 1558 + eval $6=\$ac_save_FLAGS 1559 + 1560 + fi 1561 + eval ac_res=\$$3 1562 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 1563 + printf "%s\n" "$ac_res" >&6; } 1564 + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno 1565 + 1566 + } # ac_fn_check_decl 1567 + 1568 + # ac_fn_c_try_link LINENO 1569 + # ----------------------- 1570 + # Try to link conftest.$ac_ext, and return whether this succeeded. 1571 + ac_fn_c_try_link () 1572 + { 1573 + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack 1574 + rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext 1575 + if { { ac_try="$ac_link" 1576 + case "(($ac_try" in 1577 + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; 1578 + *) ac_try_echo=$ac_try;; 1579 + esac 1580 + eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" 1581 + printf "%s\n" "$ac_try_echo"; } >&5 1582 + (eval "$ac_link") 2>conftest.err 1583 + ac_status=$? 1584 + if test -s conftest.err; then 1585 + grep -v '^ *+' conftest.err >conftest.er1 1586 + cat conftest.er1 >&5 1587 + mv -f conftest.er1 conftest.err 1588 + fi 1589 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 1590 + test $ac_status = 0; } && { 1591 + test -z "$ac_c_werror_flag" || 1592 + test ! -s conftest.err 1593 + } && test -s conftest$ac_exeext && { 1594 + test "$cross_compiling" = yes || 1595 + test -x conftest$ac_exeext 1596 + } 1597 + then : 1598 + ac_retval=0 1599 + else $as_nop 1600 + printf "%s\n" "$as_me: failed program was:" >&5 1601 + sed 's/^/| /' conftest.$ac_ext >&5 1602 + 1603 + ac_retval=1 1604 + fi 1605 + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information 1606 + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would 1607 + # interfere with the next link command; also delete a directory that is 1608 + # left behind by Apple's compiler. We do this before executing the actions. 1609 + rm -rf conftest.dSYM conftest_ipa8_conftest.oo 1610 + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno 1611 + as_fn_set_status $ac_retval 1612 + 1613 + } # ac_fn_c_try_link 1614 + 1615 + # ac_fn_c_check_func LINENO FUNC VAR 1616 + # ---------------------------------- 1617 + # Tests whether FUNC exists, setting the cache variable VAR accordingly 1618 + ac_fn_c_check_func () 1619 + { 1620 + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack 1621 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 1622 + printf %s "checking for $2... " >&6; } 1623 + if eval test \${$3+y} 1624 + then : 1625 + printf %s "(cached) " >&6 1626 + else $as_nop 1627 + cat confdefs.h - <<_ACEOF >conftest.$ac_ext 1628 + /* end confdefs.h. */ 1629 + /* Define $2 to an innocuous variant, in case <limits.h> declares $2. 1630 + For example, HP-UX 11i <limits.h> declares gettimeofday. */ 1631 + #define $2 innocuous_$2 1632 + 1633 + /* System header to define __stub macros and hopefully few prototypes, 1634 + which can conflict with char $2 (); below. */ 1635 + 1636 + #include <limits.h> 1637 + #undef $2 1638 + 1639 + /* Override any GCC internal prototype to avoid an error. 1640 + Use char because int might match the return type of a GCC 1641 + builtin and then its argument prototype would still apply. */ 1642 + #ifdef __cplusplus 1643 + extern "C" 1644 + #endif 1645 + char $2 (); 1646 + /* The GNU C library defines this for functions which it implements 1647 + to always fail with ENOSYS. Some functions are actually named 1648 + something starting with __ and the normal name is an alias. */ 1649 + #if defined __stub_$2 || defined __stub___$2 1650 + choke me 1651 + #endif 1652 + 1653 + int 1654 + main (void) 1655 + { 1656 + return $2 (); 1657 + ; 1658 + return 0; 1659 + } 1660 + _ACEOF 1661 + if ac_fn_c_try_link "$LINENO" 1662 + then : 1663 + eval "$3=yes" 1664 + else $as_nop 1665 + eval "$3=no" 1666 + fi 1667 + rm -f core conftest.err conftest.$ac_objext conftest.beam \ 1668 + conftest$ac_exeext conftest.$ac_ext 1669 + fi 1670 + eval ac_res=\$$3 1671 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 1672 + printf "%s\n" "$ac_res" >&6; } 1673 + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno 1674 + 1675 + } # ac_fn_c_check_func 1676 + ac_configure_args_raw= 1677 + for ac_arg 1678 + do 1679 + case $ac_arg in 1680 + *\'*) 1681 + ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; 1682 + esac 1683 + as_fn_append ac_configure_args_raw " '$ac_arg'" 1684 + done 1685 + 1686 + case $ac_configure_args_raw in 1687 + *$as_nl*) 1688 + ac_safe_unquote= ;; 1689 + *) 1690 + ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab. 1691 + ac_unsafe_a="$ac_unsafe_z#~" 1692 + ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g" 1693 + ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;; 1694 + esac 1695 + 1696 + cat >config.log <<_ACEOF 1697 + This file contains any messages produced by compilers while 1698 + running configure, to aid debugging if configure makes a mistake. 1699 + 1700 + It was created by simdzone $as_me 0.2.0, which was 1701 + generated by GNU Autoconf 2.71. Invocation command line was 1702 + 1703 + $ $0$ac_configure_args_raw 1704 + 1705 + _ACEOF 1706 + exec 5>>config.log 1707 + { 1708 + cat <<_ASUNAME 1709 + ## --------- ## 1710 + ## Platform. ## 1711 + ## --------- ## 1712 + 1713 + hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` 1714 + uname -m = `(uname -m) 2>/dev/null || echo unknown` 1715 + uname -r = `(uname -r) 2>/dev/null || echo unknown` 1716 + uname -s = `(uname -s) 2>/dev/null || echo unknown` 1717 + uname -v = `(uname -v) 2>/dev/null || echo unknown` 1718 + 1719 + /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` 1720 + /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` 1721 + 1722 + /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` 1723 + /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` 1724 + /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` 1725 + /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` 1726 + /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` 1727 + /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` 1728 + /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` 1729 + 1730 + _ASUNAME 1731 + 1732 + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR 1733 + for as_dir in $PATH 1734 + do 1735 + IFS=$as_save_IFS 1736 + case $as_dir in #((( 1737 + '') as_dir=./ ;; 1738 + */) ;; 1739 + *) as_dir=$as_dir/ ;; 1740 + esac 1741 + printf "%s\n" "PATH: $as_dir" 1742 + done 1743 + IFS=$as_save_IFS 1744 + 1745 + } >&5 1746 + 1747 + cat >&5 <<_ACEOF 1748 + 1749 + 1750 + ## ----------- ## 1751 + ## Core tests. ## 1752 + ## ----------- ## 1753 + 1754 + _ACEOF 1755 + 1756 + 1757 + # Keep a trace of the command line. 1758 + # Strip out --no-create and --no-recursion so they do not pile up. 1759 + # Strip out --silent because we don't want to record it for future runs. 1760 + # Also quote any args containing shell meta-characters. 1761 + # Make two passes to allow for proper duplicate-argument suppression. 1762 + ac_configure_args= 1763 + ac_configure_args0= 1764 + ac_configure_args1= 1765 + ac_must_keep_next=false 1766 + for ac_pass in 1 2 1767 + do 1768 + for ac_arg 1769 + do 1770 + case $ac_arg in 1771 + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; 1772 + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ 1773 + | -silent | --silent | --silen | --sile | --sil) 1774 + continue ;; 1775 + *\'*) 1776 + ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; 1777 + esac 1778 + case $ac_pass in 1779 + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 1780 + 2) 1781 + as_fn_append ac_configure_args1 " '$ac_arg'" 1782 + if test $ac_must_keep_next = true; then 1783 + ac_must_keep_next=false # Got value, back to normal. 1784 + else 1785 + case $ac_arg in 1786 + *=* | --config-cache | -C | -disable-* | --disable-* \ 1787 + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ 1788 + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ 1789 + | -with-* | --with-* | -without-* | --without-* | --x) 1790 + case "$ac_configure_args0 " in 1791 + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; 1792 + esac 1793 + ;; 1794 + -* ) ac_must_keep_next=true ;; 1795 + esac 1796 + fi 1797 + as_fn_append ac_configure_args " '$ac_arg'" 1798 + ;; 1799 + esac 1800 + done 1801 + done 1802 + { ac_configure_args0=; unset ac_configure_args0;} 1803 + { ac_configure_args1=; unset ac_configure_args1;} 1804 + 1805 + # When interrupted or exit'd, cleanup temporary files, and complete 1806 + # config.log. We remove comments because anyway the quotes in there 1807 + # would cause problems or look ugly. 1808 + # WARNING: Use '\'' to represent an apostrophe within the trap. 1809 + # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. 1810 + trap 'exit_status=$? 1811 + # Sanitize IFS. 1812 + IFS=" "" $as_nl" 1813 + # Save into config.log some information that might help in debugging. 1814 + { 1815 + echo 1816 + 1817 + printf "%s\n" "## ---------------- ## 1818 + ## Cache variables. ## 1819 + ## ---------------- ##" 1820 + echo 1821 + # The following way of writing the cache mishandles newlines in values, 1822 + ( 1823 + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do 1824 + eval ac_val=\$$ac_var 1825 + case $ac_val in #( 1826 + *${as_nl}*) 1827 + case $ac_var in #( 1828 + *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 1829 + printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; 1830 + esac 1831 + case $ac_var in #( 1832 + _ | IFS | as_nl) ;; #( 1833 + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( 1834 + *) { eval $ac_var=; unset $ac_var;} ;; 1835 + esac ;; 1836 + esac 1837 + done 1838 + (set) 2>&1 | 1839 + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( 1840 + *${as_nl}ac_space=\ *) 1841 + sed -n \ 1842 + "s/'\''/'\''\\\\'\'''\''/g; 1843 + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" 1844 + ;; #( 1845 + *) 1846 + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" 1847 + ;; 1848 + esac | 1849 + sort 1850 + ) 1851 + echo 1852 + 1853 + printf "%s\n" "## ----------------- ## 1854 + ## Output variables. ## 1855 + ## ----------------- ##" 1856 + echo 1857 + for ac_var in $ac_subst_vars 1858 + do 1859 + eval ac_val=\$$ac_var 1860 + case $ac_val in 1861 + *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; 1862 + esac 1863 + printf "%s\n" "$ac_var='\''$ac_val'\''" 1864 + done | sort 1865 + echo 1866 + 1867 + if test -n "$ac_subst_files"; then 1868 + printf "%s\n" "## ------------------- ## 1869 + ## File substitutions. ## 1870 + ## ------------------- ##" 1871 + echo 1872 + for ac_var in $ac_subst_files 1873 + do 1874 + eval ac_val=\$$ac_var 1875 + case $ac_val in 1876 + *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; 1877 + esac 1878 + printf "%s\n" "$ac_var='\''$ac_val'\''" 1879 + done | sort 1880 + echo 1881 + fi 1882 + 1883 + if test -s confdefs.h; then 1884 + printf "%s\n" "## ----------- ## 1885 + ## confdefs.h. ## 1886 + ## ----------- ##" 1887 + echo 1888 + cat confdefs.h 1889 + echo 1890 + fi 1891 + test "$ac_signal" != 0 && 1892 + printf "%s\n" "$as_me: caught signal $ac_signal" 1893 + printf "%s\n" "$as_me: exit $exit_status" 1894 + } >&5 1895 + rm -f core *.core core.conftest.* && 1896 + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && 1897 + exit $exit_status 1898 + ' 0 1899 + for ac_signal in 1 2 13 15; do 1900 + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal 1901 + done 1902 + ac_signal=0 1903 + 1904 + # confdefs.h avoids OS command line length limits that DEFS can exceed. 1905 + rm -f -r conftest* confdefs.h 1906 + 1907 + printf "%s\n" "/* confdefs.h */" > confdefs.h 1908 + 1909 + # Predefined preprocessor variables. 1910 + 1911 + printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h 1912 + 1913 + printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h 1914 + 1915 + printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h 1916 + 1917 + printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h 1918 + 1919 + printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h 1920 + 1921 + printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h 1922 + 1923 + 1924 + # Let the site file select an alternate cache file if it wants to. 1925 + # Prefer an explicitly selected file to automatically selected ones. 1926 + if test -n "$CONFIG_SITE"; then 1927 + ac_site_files="$CONFIG_SITE" 1928 + elif test "x$prefix" != xNONE; then 1929 + ac_site_files="$prefix/share/config.site $prefix/etc/config.site" 1930 + else 1931 + ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" 1932 + fi 1933 + 1934 + for ac_site_file in $ac_site_files 1935 + do 1936 + case $ac_site_file in #( 1937 + */*) : 1938 + ;; #( 1939 + *) : 1940 + ac_site_file=./$ac_site_file ;; 1941 + esac 1942 + if test -f "$ac_site_file" && test -r "$ac_site_file"; then 1943 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 1944 + printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;} 1945 + sed 's/^/| /' "$ac_site_file" >&5 1946 + . "$ac_site_file" \ 1947 + || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 1948 + printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} 1949 + as_fn_error $? "failed to load site script $ac_site_file 1950 + See \`config.log' for more details" "$LINENO" 5; } 1951 + fi 1952 + done 1953 + 1954 + if test -r "$cache_file"; then 1955 + # Some versions of bash will fail to source /dev/null (special files 1956 + # actually), so we avoid doing that. DJGPP emulates it as a regular file. 1957 + if test /dev/null != "$cache_file" && test -f "$cache_file"; then 1958 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 1959 + printf "%s\n" "$as_me: loading cache $cache_file" >&6;} 1960 + case $cache_file in 1961 + [\\/]* | ?:[\\/]* ) . "$cache_file";; 1962 + *) . "./$cache_file";; 1963 + esac 1964 + fi 1965 + else 1966 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 1967 + printf "%s\n" "$as_me: creating cache $cache_file" >&6;} 1968 + >$cache_file 1969 + fi 1970 + 1971 + # Test code for whether the C compiler supports C89 (global declarations) 1972 + ac_c_conftest_c89_globals=' 1973 + /* Does the compiler advertise C89 conformance? 1974 + Do not test the value of __STDC__, because some compilers set it to 0 1975 + while being otherwise adequately conformant. */ 1976 + #if !defined __STDC__ 1977 + # error "Compiler does not advertise C89 conformance" 1978 + #endif 1979 + 1980 + #include <stddef.h> 1981 + #include <stdarg.h> 1982 + struct stat; 1983 + /* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */ 1984 + struct buf { int x; }; 1985 + struct buf * (*rcsopen) (struct buf *, struct stat *, int); 1986 + static char *e (p, i) 1987 + char **p; 1988 + int i; 1989 + { 1990 + return p[i]; 1991 + } 1992 + static char *f (char * (*g) (char **, int), char **p, ...) 1993 + { 1994 + char *s; 1995 + va_list v; 1996 + va_start (v,p); 1997 + s = g (p, va_arg (v,int)); 1998 + va_end (v); 1999 + return s; 2000 + } 2001 + 2002 + /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has 2003 + function prototypes and stuff, but not \xHH hex character constants. 2004 + These do not provoke an error unfortunately, instead are silently treated 2005 + as an "x". The following induces an error, until -std is added to get 2006 + proper ANSI mode. Curiously \x00 != x always comes out true, for an 2007 + array size at least. It is necessary to write \x00 == 0 to get something 2008 + that is true only with -std. */ 2009 + int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1]; 2010 + 2011 + /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters 2012 + inside strings and character constants. */ 2013 + #define FOO(x) '\''x'\'' 2014 + int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1]; 2015 + 2016 + int test (int i, double x); 2017 + struct s1 {int (*f) (int a);}; 2018 + struct s2 {int (*f) (double a);}; 2019 + int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int), 2020 + int, int);' 2021 + 2022 + # Test code for whether the C compiler supports C89 (body of main). 2023 + ac_c_conftest_c89_main=' 2024 + ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]); 2025 + ' 2026 + 2027 + # Test code for whether the C compiler supports C99 (global declarations) 2028 + ac_c_conftest_c99_globals=' 2029 + // Does the compiler advertise C99 conformance? 2030 + #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L 2031 + # error "Compiler does not advertise C99 conformance" 2032 + #endif 2033 + 2034 + #include <stdbool.h> 2035 + extern int puts (const char *); 2036 + extern int printf (const char *, ...); 2037 + extern int dprintf (int, const char *, ...); 2038 + extern void *malloc (size_t); 2039 + 2040 + // Check varargs macros. These examples are taken from C99 6.10.3.5. 2041 + // dprintf is used instead of fprintf to avoid needing to declare 2042 + // FILE and stderr. 2043 + #define debug(...) dprintf (2, __VA_ARGS__) 2044 + #define showlist(...) puts (#__VA_ARGS__) 2045 + #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) 2046 + static void 2047 + test_varargs_macros (void) 2048 + { 2049 + int x = 1234; 2050 + int y = 5678; 2051 + debug ("Flag"); 2052 + debug ("X = %d\n", x); 2053 + showlist (The first, second, and third items.); 2054 + report (x>y, "x is %d but y is %d", x, y); 2055 + } 2056 + 2057 + // Check long long types. 2058 + #define BIG64 18446744073709551615ull 2059 + #define BIG32 4294967295ul 2060 + #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) 2061 + #if !BIG_OK 2062 + #error "your preprocessor is broken" 2063 + #endif 2064 + #if BIG_OK 2065 + #else 2066 + #error "your preprocessor is broken" 2067 + #endif 2068 + static long long int bignum = -9223372036854775807LL; 2069 + static unsigned long long int ubignum = BIG64; 2070 + 2071 + struct incomplete_array 2072 + { 2073 + int datasize; 2074 + double data[]; 2075 + }; 2076 + 2077 + struct named_init { 2078 + int number; 2079 + const wchar_t *name; 2080 + double average; 2081 + }; 2082 + 2083 + typedef const char *ccp; 2084 + 2085 + static inline int 2086 + test_restrict (ccp restrict text) 2087 + { 2088 + // See if C++-style comments work. 2089 + // Iterate through items via the restricted pointer. 2090 + // Also check for declarations in for loops. 2091 + for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i) 2092 + continue; 2093 + return 0; 2094 + } 2095 + 2096 + // Check varargs and va_copy. 2097 + static bool 2098 + test_varargs (const char *format, ...) 2099 + { 2100 + va_list args; 2101 + va_start (args, format); 2102 + va_list args_copy; 2103 + va_copy (args_copy, args); 2104 + 2105 + const char *str = ""; 2106 + int number = 0; 2107 + float fnumber = 0; 2108 + 2109 + while (*format) 2110 + { 2111 + switch (*format++) 2112 + { 2113 + case '\''s'\'': // string 2114 + str = va_arg (args_copy, const char *); 2115 + break; 2116 + case '\''d'\'': // int 2117 + number = va_arg (args_copy, int); 2118 + break; 2119 + case '\''f'\'': // float 2120 + fnumber = va_arg (args_copy, double); 2121 + break; 2122 + default: 2123 + break; 2124 + } 2125 + } 2126 + va_end (args_copy); 2127 + va_end (args); 2128 + 2129 + return *str && number && fnumber; 2130 + } 2131 + ' 2132 + 2133 + # Test code for whether the C compiler supports C99 (body of main). 2134 + ac_c_conftest_c99_main=' 2135 + // Check bool. 2136 + _Bool success = false; 2137 + success |= (argc != 0); 2138 + 2139 + // Check restrict. 2140 + if (test_restrict ("String literal") == 0) 2141 + success = true; 2142 + char *restrict newvar = "Another string"; 2143 + 2144 + // Check varargs. 2145 + success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234); 2146 + test_varargs_macros (); 2147 + 2148 + // Check flexible array members. 2149 + struct incomplete_array *ia = 2150 + malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); 2151 + ia->datasize = 10; 2152 + for (int i = 0; i < ia->datasize; ++i) 2153 + ia->data[i] = i * 1.234; 2154 + 2155 + // Check named initializers. 2156 + struct named_init ni = { 2157 + .number = 34, 2158 + .name = L"Test wide string", 2159 + .average = 543.34343, 2160 + }; 2161 + 2162 + ni.number = 58; 2163 + 2164 + int dynamic_array[ni.number]; 2165 + dynamic_array[0] = argv[0][0]; 2166 + dynamic_array[ni.number - 1] = 543; 2167 + 2168 + // work around unused variable warnings 2169 + ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\'' 2170 + || dynamic_array[ni.number - 1] != 543); 2171 + ' 2172 + 2173 + # Test code for whether the C compiler supports C11 (global declarations) 2174 + ac_c_conftest_c11_globals=' 2175 + // Does the compiler advertise C11 conformance? 2176 + #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L 2177 + # error "Compiler does not advertise C11 conformance" 2178 + #endif 2179 + 2180 + // Check _Alignas. 2181 + char _Alignas (double) aligned_as_double; 2182 + char _Alignas (0) no_special_alignment; 2183 + extern char aligned_as_int; 2184 + char _Alignas (0) _Alignas (int) aligned_as_int; 2185 + 2186 + // Check _Alignof. 2187 + enum 2188 + { 2189 + int_alignment = _Alignof (int), 2190 + int_array_alignment = _Alignof (int[100]), 2191 + char_alignment = _Alignof (char) 2192 + }; 2193 + _Static_assert (0 < -_Alignof (int), "_Alignof is signed"); 2194 + 2195 + // Check _Noreturn. 2196 + int _Noreturn does_not_return (void) { for (;;) continue; } 2197 + 2198 + // Check _Static_assert. 2199 + struct test_static_assert 2200 + { 2201 + int x; 2202 + _Static_assert (sizeof (int) <= sizeof (long int), 2203 + "_Static_assert does not work in struct"); 2204 + long int y; 2205 + }; 2206 + 2207 + // Check UTF-8 literals. 2208 + #define u8 syntax error! 2209 + char const utf8_literal[] = u8"happens to be ASCII" "another string"; 2210 + 2211 + // Check duplicate typedefs. 2212 + typedef long *long_ptr; 2213 + typedef long int *long_ptr; 2214 + typedef long_ptr long_ptr; 2215 + 2216 + // Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1. 2217 + struct anonymous 2218 + { 2219 + union { 2220 + struct { int i; int j; }; 2221 + struct { int k; long int l; } w; 2222 + }; 2223 + int m; 2224 + } v1; 2225 + ' 2226 + 2227 + # Test code for whether the C compiler supports C11 (body of main). 2228 + ac_c_conftest_c11_main=' 2229 + _Static_assert ((offsetof (struct anonymous, i) 2230 + == offsetof (struct anonymous, w.k)), 2231 + "Anonymous union alignment botch"); 2232 + v1.i = 2; 2233 + v1.w.k = 5; 2234 + ok |= v1.i != 5; 2235 + ' 2236 + 2237 + # Test code for whether the C compiler supports C11 (complete). 2238 + ac_c_conftest_c11_program="${ac_c_conftest_c89_globals} 2239 + ${ac_c_conftest_c99_globals} 2240 + ${ac_c_conftest_c11_globals} 2241 + 2242 + int 2243 + main (int argc, char **argv) 2244 + { 2245 + int ok = 0; 2246 + ${ac_c_conftest_c89_main} 2247 + ${ac_c_conftest_c99_main} 2248 + ${ac_c_conftest_c11_main} 2249 + return ok; 2250 + } 2251 + " 2252 + 2253 + # Test code for whether the C compiler supports C99 (complete). 2254 + ac_c_conftest_c99_program="${ac_c_conftest_c89_globals} 2255 + ${ac_c_conftest_c99_globals} 2256 + 2257 + int 2258 + main (int argc, char **argv) 2259 + { 2260 + int ok = 0; 2261 + ${ac_c_conftest_c89_main} 2262 + ${ac_c_conftest_c99_main} 2263 + return ok; 2264 + } 2265 + " 2266 + 2267 + # Test code for whether the C compiler supports C89 (complete). 2268 + ac_c_conftest_c89_program="${ac_c_conftest_c89_globals} 2269 + 2270 + int 2271 + main (int argc, char **argv) 2272 + { 2273 + int ok = 0; 2274 + ${ac_c_conftest_c89_main} 2275 + return ok; 2276 + } 2277 + " 2278 + 2279 + as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H" 2280 + as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H" 2281 + as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H" 2282 + as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H" 2283 + as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H" 2284 + as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H" 2285 + as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H" 2286 + as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H" 2287 + as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H" 2288 + 2289 + # Auxiliary files required by this configure script. 2290 + ac_aux_files="config.guess config.sub" 2291 + 2292 + # Locations in which to look for auxiliary files. 2293 + ac_aux_dir_candidates="${srcdir}${PATH_SEPARATOR}${srcdir}/..${PATH_SEPARATOR}${srcdir}/../.." 2294 + 2295 + # Search for a directory containing all of the required auxiliary files, 2296 + # $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates. 2297 + # If we don't find one directory that contains all the files we need, 2298 + # we report the set of missing files from the *first* directory in 2299 + # $ac_aux_dir_candidates and give up. 2300 + ac_missing_aux_files="" 2301 + ac_first_candidate=: 2302 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5 2303 + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR 2304 + as_found=false 2305 + for as_dir in $ac_aux_dir_candidates 2306 + do 2307 + IFS=$as_save_IFS 2308 + case $as_dir in #((( 2309 + '') as_dir=./ ;; 2310 + */) ;; 2311 + *) as_dir=$as_dir/ ;; 2312 + esac 2313 + as_found=: 2314 + 2315 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5 2316 + ac_aux_dir_found=yes 2317 + ac_install_sh= 2318 + for ac_aux in $ac_aux_files 2319 + do 2320 + # As a special case, if "install-sh" is required, that requirement 2321 + # can be satisfied by any of "install-sh", "install.sh", or "shtool", 2322 + # and $ac_install_sh is set appropriately for whichever one is found. 2323 + if test x"$ac_aux" = x"install-sh" 2324 + then 2325 + if test -f "${as_dir}install-sh"; then 2326 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5 2327 + ac_install_sh="${as_dir}install-sh -c" 2328 + elif test -f "${as_dir}install.sh"; then 2329 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5 2330 + ac_install_sh="${as_dir}install.sh -c" 2331 + elif test -f "${as_dir}shtool"; then 2332 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5 2333 + ac_install_sh="${as_dir}shtool install -c" 2334 + else 2335 + ac_aux_dir_found=no 2336 + if $ac_first_candidate; then 2337 + ac_missing_aux_files="${ac_missing_aux_files} install-sh" 2338 + else 2339 + break 2340 + fi 2341 + fi 2342 + else 2343 + if test -f "${as_dir}${ac_aux}"; then 2344 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5 2345 + else 2346 + ac_aux_dir_found=no 2347 + if $ac_first_candidate; then 2348 + ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}" 2349 + else 2350 + break 2351 + fi 2352 + fi 2353 + fi 2354 + done 2355 + if test "$ac_aux_dir_found" = yes; then 2356 + ac_aux_dir="$as_dir" 2357 + break 2358 + fi 2359 + ac_first_candidate=false 2360 + 2361 + as_found=false 2362 + done 2363 + IFS=$as_save_IFS 2364 + if $as_found 2365 + then : 2366 + 2367 + else $as_nop 2368 + as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5 2369 + fi 2370 + 2371 + 2372 + # These three variables are undocumented and unsupported, 2373 + # and are intended to be withdrawn in a future Autoconf release. 2374 + # They can cause serious problems if a builder's source tree is in a directory 2375 + # whose full name contains unusual characters. 2376 + if test -f "${ac_aux_dir}config.guess"; then 2377 + ac_config_guess="$SHELL ${ac_aux_dir}config.guess" 2378 + fi 2379 + if test -f "${ac_aux_dir}config.sub"; then 2380 + ac_config_sub="$SHELL ${ac_aux_dir}config.sub" 2381 + fi 2382 + if test -f "$ac_aux_dir/configure"; then 2383 + ac_configure="$SHELL ${ac_aux_dir}configure" 2384 + fi 2385 + 2386 + # Check that the precious variables saved in the cache have kept the same 2387 + # value. 2388 + ac_cache_corrupted=false 2389 + for ac_var in $ac_precious_vars; do 2390 + eval ac_old_set=\$ac_cv_env_${ac_var}_set 2391 + eval ac_new_set=\$ac_env_${ac_var}_set 2392 + eval ac_old_val=\$ac_cv_env_${ac_var}_value 2393 + eval ac_new_val=\$ac_env_${ac_var}_value 2394 + case $ac_old_set,$ac_new_set in 2395 + set,) 2396 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 2397 + printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} 2398 + ac_cache_corrupted=: ;; 2399 + ,set) 2400 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 2401 + printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} 2402 + ac_cache_corrupted=: ;; 2403 + ,);; 2404 + *) 2405 + if test "x$ac_old_val" != "x$ac_new_val"; then 2406 + # differences in whitespace do not lead to failure. 2407 + ac_old_val_w=`echo x $ac_old_val` 2408 + ac_new_val_w=`echo x $ac_new_val` 2409 + if test "$ac_old_val_w" != "$ac_new_val_w"; then 2410 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 2411 + printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} 2412 + ac_cache_corrupted=: 2413 + else 2414 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 2415 + printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} 2416 + eval $ac_var=\$ac_old_val 2417 + fi 2418 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 2419 + printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;} 2420 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 2421 + printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;} 2422 + fi;; 2423 + esac 2424 + # Pass precious variables to config.status. 2425 + if test "$ac_new_set" = set; then 2426 + case $ac_new_val in 2427 + *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; 2428 + *) ac_arg=$ac_var=$ac_new_val ;; 2429 + esac 2430 + case " $ac_configure_args " in 2431 + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. 2432 + *) as_fn_append ac_configure_args " '$ac_arg'" ;; 2433 + esac 2434 + fi 2435 + done 2436 + if $ac_cache_corrupted; then 2437 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 2438 + printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} 2439 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 2440 + printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;} 2441 + as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file' 2442 + and start over" "$LINENO" 5 2443 + fi 2444 + ## -------------------- ## 2445 + ## Main body of script. ## 2446 + ## -------------------- ## 2447 + 2448 + ac_ext=c 2449 + ac_cpp='$CPP $CPPFLAGS' 2450 + ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' 2451 + ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' 2452 + ac_compiler_gnu=$ac_cv_c_compiler_gnu 2453 + 2454 + 2455 + 2456 + ac_config_headers="$ac_config_headers config.h" 2457 + 2458 + ac_config_files="$ac_config_files Makefile" 2459 + 2460 + 2461 + # =========================================================================== 2462 + # https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html 2463 + # =========================================================================== 2464 + # 2465 + # SYNOPSIS 2466 + # 2467 + # AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) 2468 + # 2469 + # DESCRIPTION 2470 + # 2471 + # Check whether the given FLAG works with the current language's compiler 2472 + # or gives an error. (Warnings, however, are ignored) 2473 + # 2474 + # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on 2475 + # success/failure. 2476 + # 2477 + # If EXTRA-FLAGS is defined, it is added to the current language's default 2478 + # flags (e.g. CFLAGS) when the check is done. The check is thus made with 2479 + # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to 2480 + # force the compiler to issue an error when a bad flag is given. 2481 + # 2482 + # INPUT gives an alternative input source to AC_COMPILE_IFELSE. 2483 + # 2484 + # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this 2485 + # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. 2486 + # 2487 + # LICENSE 2488 + # 2489 + # Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de> 2490 + # Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com> 2491 + # 2492 + # Copying and distribution of this file, with or without modification, are 2493 + # permitted in any medium without royalty provided the copyright notice 2494 + # and this notice are preserved. This file is offered as-is, without any 2495 + # warranty. 2496 + 2497 + #serial 6 2498 + 2499 + 2500 + 2501 + 2502 + 2503 + 2504 + 2505 + 2506 + 2507 + 2508 + 2509 + ac_ext=c 2510 + ac_cpp='$CPP $CPPFLAGS' 2511 + ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' 2512 + ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' 2513 + ac_compiler_gnu=$ac_cv_c_compiler_gnu 2514 + if test -n "$ac_tool_prefix"; then 2515 + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. 2516 + set dummy ${ac_tool_prefix}gcc; ac_word=$2 2517 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 2518 + printf %s "checking for $ac_word... " >&6; } 2519 + if test ${ac_cv_prog_CC+y} 2520 + then : 2521 + printf %s "(cached) " >&6 2522 + else $as_nop 2523 + if test -n "$CC"; then 2524 + ac_cv_prog_CC="$CC" # Let the user override the test. 2525 + else 2526 + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR 2527 + for as_dir in $PATH 2528 + do 2529 + IFS=$as_save_IFS 2530 + case $as_dir in #((( 2531 + '') as_dir=./ ;; 2532 + */) ;; 2533 + *) as_dir=$as_dir/ ;; 2534 + esac 2535 + for ac_exec_ext in '' $ac_executable_extensions; do 2536 + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then 2537 + ac_cv_prog_CC="${ac_tool_prefix}gcc" 2538 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 2539 + break 2 2540 + fi 2541 + done 2542 + done 2543 + IFS=$as_save_IFS 2544 + 2545 + fi 2546 + fi 2547 + CC=$ac_cv_prog_CC 2548 + if test -n "$CC"; then 2549 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 2550 + printf "%s\n" "$CC" >&6; } 2551 + else 2552 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 2553 + printf "%s\n" "no" >&6; } 2554 + fi 2555 + 2556 + 2557 + fi 2558 + if test -z "$ac_cv_prog_CC"; then 2559 + ac_ct_CC=$CC 2560 + # Extract the first word of "gcc", so it can be a program name with args. 2561 + set dummy gcc; ac_word=$2 2562 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 2563 + printf %s "checking for $ac_word... " >&6; } 2564 + if test ${ac_cv_prog_ac_ct_CC+y} 2565 + then : 2566 + printf %s "(cached) " >&6 2567 + else $as_nop 2568 + if test -n "$ac_ct_CC"; then 2569 + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. 2570 + else 2571 + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR 2572 + for as_dir in $PATH 2573 + do 2574 + IFS=$as_save_IFS 2575 + case $as_dir in #((( 2576 + '') as_dir=./ ;; 2577 + */) ;; 2578 + *) as_dir=$as_dir/ ;; 2579 + esac 2580 + for ac_exec_ext in '' $ac_executable_extensions; do 2581 + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then 2582 + ac_cv_prog_ac_ct_CC="gcc" 2583 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 2584 + break 2 2585 + fi 2586 + done 2587 + done 2588 + IFS=$as_save_IFS 2589 + 2590 + fi 2591 + fi 2592 + ac_ct_CC=$ac_cv_prog_ac_ct_CC 2593 + if test -n "$ac_ct_CC"; then 2594 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 2595 + printf "%s\n" "$ac_ct_CC" >&6; } 2596 + else 2597 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 2598 + printf "%s\n" "no" >&6; } 2599 + fi 2600 + 2601 + if test "x$ac_ct_CC" = x; then 2602 + CC="" 2603 + else 2604 + case $cross_compiling:$ac_tool_warned in 2605 + yes:) 2606 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 2607 + printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} 2608 + ac_tool_warned=yes ;; 2609 + esac 2610 + CC=$ac_ct_CC 2611 + fi 2612 + else 2613 + CC="$ac_cv_prog_CC" 2614 + fi 2615 + 2616 + if test -z "$CC"; then 2617 + if test -n "$ac_tool_prefix"; then 2618 + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. 2619 + set dummy ${ac_tool_prefix}cc; ac_word=$2 2620 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 2621 + printf %s "checking for $ac_word... " >&6; } 2622 + if test ${ac_cv_prog_CC+y} 2623 + then : 2624 + printf %s "(cached) " >&6 2625 + else $as_nop 2626 + if test -n "$CC"; then 2627 + ac_cv_prog_CC="$CC" # Let the user override the test. 2628 + else 2629 + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR 2630 + for as_dir in $PATH 2631 + do 2632 + IFS=$as_save_IFS 2633 + case $as_dir in #((( 2634 + '') as_dir=./ ;; 2635 + */) ;; 2636 + *) as_dir=$as_dir/ ;; 2637 + esac 2638 + for ac_exec_ext in '' $ac_executable_extensions; do 2639 + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then 2640 + ac_cv_prog_CC="${ac_tool_prefix}cc" 2641 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 2642 + break 2 2643 + fi 2644 + done 2645 + done 2646 + IFS=$as_save_IFS 2647 + 2648 + fi 2649 + fi 2650 + CC=$ac_cv_prog_CC 2651 + if test -n "$CC"; then 2652 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 2653 + printf "%s\n" "$CC" >&6; } 2654 + else 2655 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 2656 + printf "%s\n" "no" >&6; } 2657 + fi 2658 + 2659 + 2660 + fi 2661 + fi 2662 + if test -z "$CC"; then 2663 + # Extract the first word of "cc", so it can be a program name with args. 2664 + set dummy cc; ac_word=$2 2665 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 2666 + printf %s "checking for $ac_word... " >&6; } 2667 + if test ${ac_cv_prog_CC+y} 2668 + then : 2669 + printf %s "(cached) " >&6 2670 + else $as_nop 2671 + if test -n "$CC"; then 2672 + ac_cv_prog_CC="$CC" # Let the user override the test. 2673 + else 2674 + ac_prog_rejected=no 2675 + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR 2676 + for as_dir in $PATH 2677 + do 2678 + IFS=$as_save_IFS 2679 + case $as_dir in #((( 2680 + '') as_dir=./ ;; 2681 + */) ;; 2682 + *) as_dir=$as_dir/ ;; 2683 + esac 2684 + for ac_exec_ext in '' $ac_executable_extensions; do 2685 + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then 2686 + if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then 2687 + ac_prog_rejected=yes 2688 + continue 2689 + fi 2690 + ac_cv_prog_CC="cc" 2691 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 2692 + break 2 2693 + fi 2694 + done 2695 + done 2696 + IFS=$as_save_IFS 2697 + 2698 + if test $ac_prog_rejected = yes; then 2699 + # We found a bogon in the path, so make sure we never use it. 2700 + set dummy $ac_cv_prog_CC 2701 + shift 2702 + if test $# != 0; then 2703 + # We chose a different compiler from the bogus one. 2704 + # However, it has the same basename, so the bogon will be chosen 2705 + # first if we set CC to just the basename; use the full file name. 2706 + shift 2707 + ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@" 2708 + fi 2709 + fi 2710 + fi 2711 + fi 2712 + CC=$ac_cv_prog_CC 2713 + if test -n "$CC"; then 2714 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 2715 + printf "%s\n" "$CC" >&6; } 2716 + else 2717 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 2718 + printf "%s\n" "no" >&6; } 2719 + fi 2720 + 2721 + 2722 + fi 2723 + if test -z "$CC"; then 2724 + if test -n "$ac_tool_prefix"; then 2725 + for ac_prog in cl.exe 2726 + do 2727 + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. 2728 + set dummy $ac_tool_prefix$ac_prog; ac_word=$2 2729 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 2730 + printf %s "checking for $ac_word... " >&6; } 2731 + if test ${ac_cv_prog_CC+y} 2732 + then : 2733 + printf %s "(cached) " >&6 2734 + else $as_nop 2735 + if test -n "$CC"; then 2736 + ac_cv_prog_CC="$CC" # Let the user override the test. 2737 + else 2738 + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR 2739 + for as_dir in $PATH 2740 + do 2741 + IFS=$as_save_IFS 2742 + case $as_dir in #((( 2743 + '') as_dir=./ ;; 2744 + */) ;; 2745 + *) as_dir=$as_dir/ ;; 2746 + esac 2747 + for ac_exec_ext in '' $ac_executable_extensions; do 2748 + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then 2749 + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" 2750 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 2751 + break 2 2752 + fi 2753 + done 2754 + done 2755 + IFS=$as_save_IFS 2756 + 2757 + fi 2758 + fi 2759 + CC=$ac_cv_prog_CC 2760 + if test -n "$CC"; then 2761 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 2762 + printf "%s\n" "$CC" >&6; } 2763 + else 2764 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 2765 + printf "%s\n" "no" >&6; } 2766 + fi 2767 + 2768 + 2769 + test -n "$CC" && break 2770 + done 2771 + fi 2772 + if test -z "$CC"; then 2773 + ac_ct_CC=$CC 2774 + for ac_prog in cl.exe 2775 + do 2776 + # Extract the first word of "$ac_prog", so it can be a program name with args. 2777 + set dummy $ac_prog; ac_word=$2 2778 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 2779 + printf %s "checking for $ac_word... " >&6; } 2780 + if test ${ac_cv_prog_ac_ct_CC+y} 2781 + then : 2782 + printf %s "(cached) " >&6 2783 + else $as_nop 2784 + if test -n "$ac_ct_CC"; then 2785 + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. 2786 + else 2787 + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR 2788 + for as_dir in $PATH 2789 + do 2790 + IFS=$as_save_IFS 2791 + case $as_dir in #((( 2792 + '') as_dir=./ ;; 2793 + */) ;; 2794 + *) as_dir=$as_dir/ ;; 2795 + esac 2796 + for ac_exec_ext in '' $ac_executable_extensions; do 2797 + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then 2798 + ac_cv_prog_ac_ct_CC="$ac_prog" 2799 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 2800 + break 2 2801 + fi 2802 + done 2803 + done 2804 + IFS=$as_save_IFS 2805 + 2806 + fi 2807 + fi 2808 + ac_ct_CC=$ac_cv_prog_ac_ct_CC 2809 + if test -n "$ac_ct_CC"; then 2810 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 2811 + printf "%s\n" "$ac_ct_CC" >&6; } 2812 + else 2813 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 2814 + printf "%s\n" "no" >&6; } 2815 + fi 2816 + 2817 + 2818 + test -n "$ac_ct_CC" && break 2819 + done 2820 + 2821 + if test "x$ac_ct_CC" = x; then 2822 + CC="" 2823 + else 2824 + case $cross_compiling:$ac_tool_warned in 2825 + yes:) 2826 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 2827 + printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} 2828 + ac_tool_warned=yes ;; 2829 + esac 2830 + CC=$ac_ct_CC 2831 + fi 2832 + fi 2833 + 2834 + fi 2835 + if test -z "$CC"; then 2836 + if test -n "$ac_tool_prefix"; then 2837 + # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args. 2838 + set dummy ${ac_tool_prefix}clang; ac_word=$2 2839 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 2840 + printf %s "checking for $ac_word... " >&6; } 2841 + if test ${ac_cv_prog_CC+y} 2842 + then : 2843 + printf %s "(cached) " >&6 2844 + else $as_nop 2845 + if test -n "$CC"; then 2846 + ac_cv_prog_CC="$CC" # Let the user override the test. 2847 + else 2848 + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR 2849 + for as_dir in $PATH 2850 + do 2851 + IFS=$as_save_IFS 2852 + case $as_dir in #((( 2853 + '') as_dir=./ ;; 2854 + */) ;; 2855 + *) as_dir=$as_dir/ ;; 2856 + esac 2857 + for ac_exec_ext in '' $ac_executable_extensions; do 2858 + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then 2859 + ac_cv_prog_CC="${ac_tool_prefix}clang" 2860 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 2861 + break 2 2862 + fi 2863 + done 2864 + done 2865 + IFS=$as_save_IFS 2866 + 2867 + fi 2868 + fi 2869 + CC=$ac_cv_prog_CC 2870 + if test -n "$CC"; then 2871 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 2872 + printf "%s\n" "$CC" >&6; } 2873 + else 2874 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 2875 + printf "%s\n" "no" >&6; } 2876 + fi 2877 + 2878 + 2879 + fi 2880 + if test -z "$ac_cv_prog_CC"; then 2881 + ac_ct_CC=$CC 2882 + # Extract the first word of "clang", so it can be a program name with args. 2883 + set dummy clang; ac_word=$2 2884 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 2885 + printf %s "checking for $ac_word... " >&6; } 2886 + if test ${ac_cv_prog_ac_ct_CC+y} 2887 + then : 2888 + printf %s "(cached) " >&6 2889 + else $as_nop 2890 + if test -n "$ac_ct_CC"; then 2891 + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. 2892 + else 2893 + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR 2894 + for as_dir in $PATH 2895 + do 2896 + IFS=$as_save_IFS 2897 + case $as_dir in #((( 2898 + '') as_dir=./ ;; 2899 + */) ;; 2900 + *) as_dir=$as_dir/ ;; 2901 + esac 2902 + for ac_exec_ext in '' $ac_executable_extensions; do 2903 + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then 2904 + ac_cv_prog_ac_ct_CC="clang" 2905 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 2906 + break 2 2907 + fi 2908 + done 2909 + done 2910 + IFS=$as_save_IFS 2911 + 2912 + fi 2913 + fi 2914 + ac_ct_CC=$ac_cv_prog_ac_ct_CC 2915 + if test -n "$ac_ct_CC"; then 2916 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 2917 + printf "%s\n" "$ac_ct_CC" >&6; } 2918 + else 2919 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 2920 + printf "%s\n" "no" >&6; } 2921 + fi 2922 + 2923 + if test "x$ac_ct_CC" = x; then 2924 + CC="" 2925 + else 2926 + case $cross_compiling:$ac_tool_warned in 2927 + yes:) 2928 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 2929 + printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} 2930 + ac_tool_warned=yes ;; 2931 + esac 2932 + CC=$ac_ct_CC 2933 + fi 2934 + else 2935 + CC="$ac_cv_prog_CC" 2936 + fi 2937 + 2938 + fi 2939 + 2940 + 2941 + test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 2942 + printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} 2943 + as_fn_error $? "no acceptable C compiler found in \$PATH 2944 + See \`config.log' for more details" "$LINENO" 5; } 2945 + 2946 + # Provide some information about the compiler. 2947 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 2948 + set X $ac_compile 2949 + ac_compiler=$2 2950 + for ac_option in --version -v -V -qversion -version; do 2951 + { { ac_try="$ac_compiler $ac_option >&5" 2952 + case "(($ac_try" in 2953 + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; 2954 + *) ac_try_echo=$ac_try;; 2955 + esac 2956 + eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" 2957 + printf "%s\n" "$ac_try_echo"; } >&5 2958 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err 2959 + ac_status=$? 2960 + if test -s conftest.err; then 2961 + sed '10a\ 2962 + ... rest of stderr output deleted ... 2963 + 10q' conftest.err >conftest.er1 2964 + cat conftest.er1 >&5 2965 + fi 2966 + rm -f conftest.er1 conftest.err 2967 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 2968 + test $ac_status = 0; } 2969 + done 2970 + 2971 + cat confdefs.h - <<_ACEOF >conftest.$ac_ext 2972 + /* end confdefs.h. */ 2973 + 2974 + int 2975 + main (void) 2976 + { 2977 + 2978 + ; 2979 + return 0; 2980 + } 2981 + _ACEOF 2982 + ac_clean_files_save=$ac_clean_files 2983 + ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" 2984 + # Try to create an executable without -o first, disregard a.out. 2985 + # It will help us diagnose broken compilers, and finding out an intuition 2986 + # of exeext. 2987 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 2988 + printf %s "checking whether the C compiler works... " >&6; } 2989 + ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'` 2990 + 2991 + # The possible output files: 2992 + ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" 2993 + 2994 + ac_rmfiles= 2995 + for ac_file in $ac_files 2996 + do 2997 + case $ac_file in 2998 + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; 2999 + * ) ac_rmfiles="$ac_rmfiles $ac_file";; 3000 + esac 3001 + done 3002 + rm -f $ac_rmfiles 3003 + 3004 + if { { ac_try="$ac_link_default" 3005 + case "(($ac_try" in 3006 + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; 3007 + *) ac_try_echo=$ac_try;; 3008 + esac 3009 + eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" 3010 + printf "%s\n" "$ac_try_echo"; } >&5 3011 + (eval "$ac_link_default") 2>&5 3012 + ac_status=$? 3013 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 3014 + test $ac_status = 0; } 3015 + then : 3016 + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. 3017 + # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' 3018 + # in a Makefile. We should not override ac_cv_exeext if it was cached, 3019 + # so that the user can short-circuit this test for compilers unknown to 3020 + # Autoconf. 3021 + for ac_file in $ac_files '' 3022 + do 3023 + test -f "$ac_file" || continue 3024 + case $ac_file in 3025 + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) 3026 + ;; 3027 + [ab].out ) 3028 + # We found the default executable, but exeext='' is most 3029 + # certainly right. 3030 + break;; 3031 + *.* ) 3032 + if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no; 3033 + then :; else 3034 + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` 3035 + fi 3036 + # We set ac_cv_exeext here because the later test for it is not 3037 + # safe: cross compilers may not add the suffix if given an `-o' 3038 + # argument, so we may need to know it at that point already. 3039 + # Even if this section looks crufty: it has the advantage of 3040 + # actually working. 3041 + break;; 3042 + * ) 3043 + break;; 3044 + esac 3045 + done 3046 + test "$ac_cv_exeext" = no && ac_cv_exeext= 3047 + 3048 + else $as_nop 3049 + ac_file='' 3050 + fi 3051 + if test -z "$ac_file" 3052 + then : 3053 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 3054 + printf "%s\n" "no" >&6; } 3055 + printf "%s\n" "$as_me: failed program was:" >&5 3056 + sed 's/^/| /' conftest.$ac_ext >&5 3057 + 3058 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 3059 + printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} 3060 + as_fn_error 77 "C compiler cannot create executables 3061 + See \`config.log' for more details" "$LINENO" 5; } 3062 + else $as_nop 3063 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 3064 + printf "%s\n" "yes" >&6; } 3065 + fi 3066 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 3067 + printf %s "checking for C compiler default output file name... " >&6; } 3068 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 3069 + printf "%s\n" "$ac_file" >&6; } 3070 + ac_exeext=$ac_cv_exeext 3071 + 3072 + rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out 3073 + ac_clean_files=$ac_clean_files_save 3074 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 3075 + printf %s "checking for suffix of executables... " >&6; } 3076 + if { { ac_try="$ac_link" 3077 + case "(($ac_try" in 3078 + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; 3079 + *) ac_try_echo=$ac_try;; 3080 + esac 3081 + eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" 3082 + printf "%s\n" "$ac_try_echo"; } >&5 3083 + (eval "$ac_link") 2>&5 3084 + ac_status=$? 3085 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 3086 + test $ac_status = 0; } 3087 + then : 3088 + # If both `conftest.exe' and `conftest' are `present' (well, observable) 3089 + # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will 3090 + # work properly (i.e., refer to `conftest.exe'), while it won't with 3091 + # `rm'. 3092 + for ac_file in conftest.exe conftest conftest.*; do 3093 + test -f "$ac_file" || continue 3094 + case $ac_file in 3095 + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; 3096 + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` 3097 + break;; 3098 + * ) break;; 3099 + esac 3100 + done 3101 + else $as_nop 3102 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 3103 + printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} 3104 + as_fn_error $? "cannot compute suffix of executables: cannot compile and link 3105 + See \`config.log' for more details" "$LINENO" 5; } 3106 + fi 3107 + rm -f conftest conftest$ac_cv_exeext 3108 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 3109 + printf "%s\n" "$ac_cv_exeext" >&6; } 3110 + 3111 + rm -f conftest.$ac_ext 3112 + EXEEXT=$ac_cv_exeext 3113 + ac_exeext=$EXEEXT 3114 + cat confdefs.h - <<_ACEOF >conftest.$ac_ext 3115 + /* end confdefs.h. */ 3116 + #include <stdio.h> 3117 + int 3118 + main (void) 3119 + { 3120 + FILE *f = fopen ("conftest.out", "w"); 3121 + return ferror (f) || fclose (f) != 0; 3122 + 3123 + ; 3124 + return 0; 3125 + } 3126 + _ACEOF 3127 + ac_clean_files="$ac_clean_files conftest.out" 3128 + # Check that the compiler produces executables we can run. If not, either 3129 + # the compiler is broken, or we cross compile. 3130 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 3131 + printf %s "checking whether we are cross compiling... " >&6; } 3132 + if test "$cross_compiling" != yes; then 3133 + { { ac_try="$ac_link" 3134 + case "(($ac_try" in 3135 + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; 3136 + *) ac_try_echo=$ac_try;; 3137 + esac 3138 + eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" 3139 + printf "%s\n" "$ac_try_echo"; } >&5 3140 + (eval "$ac_link") 2>&5 3141 + ac_status=$? 3142 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 3143 + test $ac_status = 0; } 3144 + if { ac_try='./conftest$ac_cv_exeext' 3145 + { { case "(($ac_try" in 3146 + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; 3147 + *) ac_try_echo=$ac_try;; 3148 + esac 3149 + eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" 3150 + printf "%s\n" "$ac_try_echo"; } >&5 3151 + (eval "$ac_try") 2>&5 3152 + ac_status=$? 3153 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 3154 + test $ac_status = 0; }; }; then 3155 + cross_compiling=no 3156 + else 3157 + if test "$cross_compiling" = maybe; then 3158 + cross_compiling=yes 3159 + else 3160 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 3161 + printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} 3162 + as_fn_error 77 "cannot run C compiled programs. 3163 + If you meant to cross compile, use \`--host'. 3164 + See \`config.log' for more details" "$LINENO" 5; } 3165 + fi 3166 + fi 3167 + fi 3168 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 3169 + printf "%s\n" "$cross_compiling" >&6; } 3170 + 3171 + rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out 3172 + ac_clean_files=$ac_clean_files_save 3173 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 3174 + printf %s "checking for suffix of object files... " >&6; } 3175 + if test ${ac_cv_objext+y} 3176 + then : 3177 + printf %s "(cached) " >&6 3178 + else $as_nop 3179 + cat confdefs.h - <<_ACEOF >conftest.$ac_ext 3180 + /* end confdefs.h. */ 3181 + 3182 + int 3183 + main (void) 3184 + { 3185 + 3186 + ; 3187 + return 0; 3188 + } 3189 + _ACEOF 3190 + rm -f conftest.o conftest.obj 3191 + if { { ac_try="$ac_compile" 3192 + case "(($ac_try" in 3193 + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; 3194 + *) ac_try_echo=$ac_try;; 3195 + esac 3196 + eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" 3197 + printf "%s\n" "$ac_try_echo"; } >&5 3198 + (eval "$ac_compile") 2>&5 3199 + ac_status=$? 3200 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 3201 + test $ac_status = 0; } 3202 + then : 3203 + for ac_file in conftest.o conftest.obj conftest.*; do 3204 + test -f "$ac_file" || continue; 3205 + case $ac_file in 3206 + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; 3207 + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` 3208 + break;; 3209 + esac 3210 + done 3211 + else $as_nop 3212 + printf "%s\n" "$as_me: failed program was:" >&5 3213 + sed 's/^/| /' conftest.$ac_ext >&5 3214 + 3215 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 3216 + printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} 3217 + as_fn_error $? "cannot compute suffix of object files: cannot compile 3218 + See \`config.log' for more details" "$LINENO" 5; } 3219 + fi 3220 + rm -f conftest.$ac_cv_objext conftest.$ac_ext 3221 + fi 3222 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 3223 + printf "%s\n" "$ac_cv_objext" >&6; } 3224 + OBJEXT=$ac_cv_objext 3225 + ac_objext=$OBJEXT 3226 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5 3227 + printf %s "checking whether the compiler supports GNU C... " >&6; } 3228 + if test ${ac_cv_c_compiler_gnu+y} 3229 + then : 3230 + printf %s "(cached) " >&6 3231 + else $as_nop 3232 + cat confdefs.h - <<_ACEOF >conftest.$ac_ext 3233 + /* end confdefs.h. */ 3234 + 3235 + int 3236 + main (void) 3237 + { 3238 + #ifndef __GNUC__ 3239 + choke me 3240 + #endif 3241 + 3242 + ; 3243 + return 0; 3244 + } 3245 + _ACEOF 3246 + if ac_fn_c_try_compile "$LINENO" 3247 + then : 3248 + ac_compiler_gnu=yes 3249 + else $as_nop 3250 + ac_compiler_gnu=no 3251 + fi 3252 + rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext 3253 + ac_cv_c_compiler_gnu=$ac_compiler_gnu 3254 + 3255 + fi 3256 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 3257 + printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; } 3258 + ac_compiler_gnu=$ac_cv_c_compiler_gnu 3259 + 3260 + if test $ac_compiler_gnu = yes; then 3261 + GCC=yes 3262 + else 3263 + GCC= 3264 + fi 3265 + ac_test_CFLAGS=${CFLAGS+y} 3266 + ac_save_CFLAGS=$CFLAGS 3267 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 3268 + printf %s "checking whether $CC accepts -g... " >&6; } 3269 + if test ${ac_cv_prog_cc_g+y} 3270 + then : 3271 + printf %s "(cached) " >&6 3272 + else $as_nop 3273 + ac_save_c_werror_flag=$ac_c_werror_flag 3274 + ac_c_werror_flag=yes 3275 + ac_cv_prog_cc_g=no 3276 + CFLAGS="-g" 3277 + cat confdefs.h - <<_ACEOF >conftest.$ac_ext 3278 + /* end confdefs.h. */ 3279 + 3280 + int 3281 + main (void) 3282 + { 3283 + 3284 + ; 3285 + return 0; 3286 + } 3287 + _ACEOF 3288 + if ac_fn_c_try_compile "$LINENO" 3289 + then : 3290 + ac_cv_prog_cc_g=yes 3291 + else $as_nop 3292 + CFLAGS="" 3293 + cat confdefs.h - <<_ACEOF >conftest.$ac_ext 3294 + /* end confdefs.h. */ 3295 + 3296 + int 3297 + main (void) 3298 + { 3299 + 3300 + ; 3301 + return 0; 3302 + } 3303 + _ACEOF 3304 + if ac_fn_c_try_compile "$LINENO" 3305 + then : 3306 + 3307 + else $as_nop 3308 + ac_c_werror_flag=$ac_save_c_werror_flag 3309 + CFLAGS="-g" 3310 + cat confdefs.h - <<_ACEOF >conftest.$ac_ext 3311 + /* end confdefs.h. */ 3312 + 3313 + int 3314 + main (void) 3315 + { 3316 + 3317 + ; 3318 + return 0; 3319 + } 3320 + _ACEOF 3321 + if ac_fn_c_try_compile "$LINENO" 3322 + then : 3323 + ac_cv_prog_cc_g=yes 3324 + fi 3325 + rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext 3326 + fi 3327 + rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext 3328 + fi 3329 + rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext 3330 + ac_c_werror_flag=$ac_save_c_werror_flag 3331 + fi 3332 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 3333 + printf "%s\n" "$ac_cv_prog_cc_g" >&6; } 3334 + if test $ac_test_CFLAGS; then 3335 + CFLAGS=$ac_save_CFLAGS 3336 + elif test $ac_cv_prog_cc_g = yes; then 3337 + if test "$GCC" = yes; then 3338 + CFLAGS="-g -O2" 3339 + else 3340 + CFLAGS="-g" 3341 + fi 3342 + else 3343 + if test "$GCC" = yes; then 3344 + CFLAGS="-O2" 3345 + else 3346 + CFLAGS= 3347 + fi 3348 + fi 3349 + ac_prog_cc_stdc=no 3350 + if test x$ac_prog_cc_stdc = xno 3351 + then : 3352 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5 3353 + printf %s "checking for $CC option to enable C11 features... " >&6; } 3354 + if test ${ac_cv_prog_cc_c11+y} 3355 + then : 3356 + printf %s "(cached) " >&6 3357 + else $as_nop 3358 + ac_cv_prog_cc_c11=no 3359 + ac_save_CC=$CC 3360 + cat confdefs.h - <<_ACEOF >conftest.$ac_ext 3361 + /* end confdefs.h. */ 3362 + $ac_c_conftest_c11_program 3363 + _ACEOF 3364 + for ac_arg in '' -std=gnu11 3365 + do 3366 + CC="$ac_save_CC $ac_arg" 3367 + if ac_fn_c_try_compile "$LINENO" 3368 + then : 3369 + ac_cv_prog_cc_c11=$ac_arg 3370 + fi 3371 + rm -f core conftest.err conftest.$ac_objext conftest.beam 3372 + test "x$ac_cv_prog_cc_c11" != "xno" && break 3373 + done 3374 + rm -f conftest.$ac_ext 3375 + CC=$ac_save_CC 3376 + fi 3377 + 3378 + if test "x$ac_cv_prog_cc_c11" = xno 3379 + then : 3380 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 3381 + printf "%s\n" "unsupported" >&6; } 3382 + else $as_nop 3383 + if test "x$ac_cv_prog_cc_c11" = x 3384 + then : 3385 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 3386 + printf "%s\n" "none needed" >&6; } 3387 + else $as_nop 3388 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5 3389 + printf "%s\n" "$ac_cv_prog_cc_c11" >&6; } 3390 + CC="$CC $ac_cv_prog_cc_c11" 3391 + fi 3392 + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11 3393 + ac_prog_cc_stdc=c11 3394 + fi 3395 + fi 3396 + if test x$ac_prog_cc_stdc = xno 3397 + then : 3398 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5 3399 + printf %s "checking for $CC option to enable C99 features... " >&6; } 3400 + if test ${ac_cv_prog_cc_c99+y} 3401 + then : 3402 + printf %s "(cached) " >&6 3403 + else $as_nop 3404 + ac_cv_prog_cc_c99=no 3405 + ac_save_CC=$CC 3406 + cat confdefs.h - <<_ACEOF >conftest.$ac_ext 3407 + /* end confdefs.h. */ 3408 + $ac_c_conftest_c99_program 3409 + _ACEOF 3410 + for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99= 3411 + do 3412 + CC="$ac_save_CC $ac_arg" 3413 + if ac_fn_c_try_compile "$LINENO" 3414 + then : 3415 + ac_cv_prog_cc_c99=$ac_arg 3416 + fi 3417 + rm -f core conftest.err conftest.$ac_objext conftest.beam 3418 + test "x$ac_cv_prog_cc_c99" != "xno" && break 3419 + done 3420 + rm -f conftest.$ac_ext 3421 + CC=$ac_save_CC 3422 + fi 3423 + 3424 + if test "x$ac_cv_prog_cc_c99" = xno 3425 + then : 3426 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 3427 + printf "%s\n" "unsupported" >&6; } 3428 + else $as_nop 3429 + if test "x$ac_cv_prog_cc_c99" = x 3430 + then : 3431 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 3432 + printf "%s\n" "none needed" >&6; } 3433 + else $as_nop 3434 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 3435 + printf "%s\n" "$ac_cv_prog_cc_c99" >&6; } 3436 + CC="$CC $ac_cv_prog_cc_c99" 3437 + fi 3438 + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 3439 + ac_prog_cc_stdc=c99 3440 + fi 3441 + fi 3442 + if test x$ac_prog_cc_stdc = xno 3443 + then : 3444 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5 3445 + printf %s "checking for $CC option to enable C89 features... " >&6; } 3446 + if test ${ac_cv_prog_cc_c89+y} 3447 + then : 3448 + printf %s "(cached) " >&6 3449 + else $as_nop 3450 + ac_cv_prog_cc_c89=no 3451 + ac_save_CC=$CC 3452 + cat confdefs.h - <<_ACEOF >conftest.$ac_ext 3453 + /* end confdefs.h. */ 3454 + $ac_c_conftest_c89_program 3455 + _ACEOF 3456 + for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" 3457 + do 3458 + CC="$ac_save_CC $ac_arg" 3459 + if ac_fn_c_try_compile "$LINENO" 3460 + then : 3461 + ac_cv_prog_cc_c89=$ac_arg 3462 + fi 3463 + rm -f core conftest.err conftest.$ac_objext conftest.beam 3464 + test "x$ac_cv_prog_cc_c89" != "xno" && break 3465 + done 3466 + rm -f conftest.$ac_ext 3467 + CC=$ac_save_CC 3468 + fi 3469 + 3470 + if test "x$ac_cv_prog_cc_c89" = xno 3471 + then : 3472 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 3473 + printf "%s\n" "unsupported" >&6; } 3474 + else $as_nop 3475 + if test "x$ac_cv_prog_cc_c89" = x 3476 + then : 3477 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 3478 + printf "%s\n" "none needed" >&6; } 3479 + else $as_nop 3480 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 3481 + printf "%s\n" "$ac_cv_prog_cc_c89" >&6; } 3482 + CC="$CC $ac_cv_prog_cc_c89" 3483 + fi 3484 + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 3485 + ac_prog_cc_stdc=c89 3486 + fi 3487 + fi 3488 + 3489 + ac_ext=c 3490 + ac_cpp='$CPP $CPPFLAGS' 3491 + ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' 3492 + ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' 3493 + ac_compiler_gnu=$ac_cv_c_compiler_gnu 3494 + 3495 + 3496 + 3497 + ac_header= ac_cache= 3498 + for ac_item in $ac_header_c_list 3499 + do 3500 + if test $ac_cache; then 3501 + ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default" 3502 + if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then 3503 + printf "%s\n" "#define $ac_item 1" >> confdefs.h 3504 + fi 3505 + ac_header= ac_cache= 3506 + elif test $ac_header; then 3507 + ac_cache=$ac_item 3508 + else 3509 + ac_header=$ac_item 3510 + fi 3511 + done 3512 + 3513 + 3514 + 3515 + 3516 + 3517 + 3518 + 3519 + 3520 + if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes 3521 + then : 3522 + 3523 + printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h 3524 + 3525 + fi 3526 + ac_fn_c_check_header_compile "$LINENO" "endian.h" "ac_cv_header_endian_h" "$ac_includes_default 3527 + " 3528 + if test "x$ac_cv_header_endian_h" = xyes 3529 + then : 3530 + printf "%s\n" "#define HAVE_ENDIAN_H 1" >>confdefs.h 3531 + 3532 + fi 3533 + ac_fn_c_check_header_compile "$LINENO" "sys/endian.h" "ac_cv_header_sys_endian_h" "$ac_includes_default 3534 + " 3535 + if test "x$ac_cv_header_sys_endian_h" = xyes 3536 + then : 3537 + printf "%s\n" "#define HAVE_SYS_ENDIAN_H 1" >>confdefs.h 3538 + 3539 + fi 3540 + 3541 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC options needed to detect all undeclared functions" >&5 3542 + printf %s "checking for $CC options needed to detect all undeclared functions... " >&6; } 3543 + if test ${ac_cv_c_undeclared_builtin_options+y} 3544 + then : 3545 + printf %s "(cached) " >&6 3546 + else $as_nop 3547 + ac_save_CFLAGS=$CFLAGS 3548 + ac_cv_c_undeclared_builtin_options='cannot detect' 3549 + for ac_arg in '' -fno-builtin; do 3550 + CFLAGS="$ac_save_CFLAGS $ac_arg" 3551 + # This test program should *not* compile successfully. 3552 + cat confdefs.h - <<_ACEOF >conftest.$ac_ext 3553 + /* end confdefs.h. */ 3554 + 3555 + int 3556 + main (void) 3557 + { 3558 + (void) strchr; 3559 + ; 3560 + return 0; 3561 + } 3562 + _ACEOF 3563 + if ac_fn_c_try_compile "$LINENO" 3564 + then : 3565 + 3566 + else $as_nop 3567 + # This test program should compile successfully. 3568 + # No library function is consistently available on 3569 + # freestanding implementations, so test against a dummy 3570 + # declaration. Include always-available headers on the 3571 + # off chance that they somehow elicit warnings. 3572 + cat confdefs.h - <<_ACEOF >conftest.$ac_ext 3573 + /* end confdefs.h. */ 3574 + #include <float.h> 3575 + #include <limits.h> 3576 + #include <stdarg.h> 3577 + #include <stddef.h> 3578 + extern void ac_decl (int, char *); 3579 + 3580 + int 3581 + main (void) 3582 + { 3583 + (void) ac_decl (0, (char *) 0); 3584 + (void) ac_decl; 3585 + 3586 + ; 3587 + return 0; 3588 + } 3589 + _ACEOF 3590 + if ac_fn_c_try_compile "$LINENO" 3591 + then : 3592 + if test x"$ac_arg" = x 3593 + then : 3594 + ac_cv_c_undeclared_builtin_options='none needed' 3595 + else $as_nop 3596 + ac_cv_c_undeclared_builtin_options=$ac_arg 3597 + fi 3598 + break 3599 + fi 3600 + rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext 3601 + fi 3602 + rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext 3603 + done 3604 + CFLAGS=$ac_save_CFLAGS 3605 + 3606 + fi 3607 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_undeclared_builtin_options" >&5 3608 + printf "%s\n" "$ac_cv_c_undeclared_builtin_options" >&6; } 3609 + case $ac_cv_c_undeclared_builtin_options in #( 3610 + 'cannot detect') : 3611 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 3612 + printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} 3613 + as_fn_error $? "cannot make $CC report undeclared builtins 3614 + See \`config.log' for more details" "$LINENO" 5; } ;; #( 3615 + 'none needed') : 3616 + ac_c_undeclared_builtin_options='' ;; #( 3617 + *) : 3618 + ac_c_undeclared_builtin_options=$ac_cv_c_undeclared_builtin_options ;; 3619 + esac 3620 + 3621 + ac_fn_check_decl "$LINENO" "bswap16" "ac_cv_have_decl_bswap16" " 3622 + $ac_includes_default 3623 + #ifdef HAVE_ENDIAN_H 3624 + #include <endian.h> 3625 + #endif 3626 + #ifdef HAVE_SYS_ENDIAN_H 3627 + #include <sys/endian.h> 3628 + #endif 3629 + 3630 + " "$ac_c_undeclared_builtin_options" "CFLAGS" 3631 + if test "x$ac_cv_have_decl_bswap16" = xyes 3632 + then : 3633 + ac_have_decl=1 3634 + else $as_nop 3635 + ac_have_decl=0 3636 + fi 3637 + printf "%s\n" "#define HAVE_DECL_BSWAP16 $ac_have_decl" >>confdefs.h 3638 + ac_fn_check_decl "$LINENO" "bswap32" "ac_cv_have_decl_bswap32" " 3639 + $ac_includes_default 3640 + #ifdef HAVE_ENDIAN_H 3641 + #include <endian.h> 3642 + #endif 3643 + #ifdef HAVE_SYS_ENDIAN_H 3644 + #include <sys/endian.h> 3645 + #endif 3646 + 3647 + " "$ac_c_undeclared_builtin_options" "CFLAGS" 3648 + if test "x$ac_cv_have_decl_bswap32" = xyes 3649 + then : 3650 + ac_have_decl=1 3651 + else $as_nop 3652 + ac_have_decl=0 3653 + fi 3654 + printf "%s\n" "#define HAVE_DECL_BSWAP32 $ac_have_decl" >>confdefs.h 3655 + ac_fn_check_decl "$LINENO" "bswap64" "ac_cv_have_decl_bswap64" " 3656 + $ac_includes_default 3657 + #ifdef HAVE_ENDIAN_H 3658 + #include <endian.h> 3659 + #endif 3660 + #ifdef HAVE_SYS_ENDIAN_H 3661 + #include <sys/endian.h> 3662 + #endif 3663 + 3664 + " "$ac_c_undeclared_builtin_options" "CFLAGS" 3665 + if test "x$ac_cv_have_decl_bswap64" = xyes 3666 + then : 3667 + ac_have_decl=1 3668 + else $as_nop 3669 + ac_have_decl=0 3670 + fi 3671 + printf "%s\n" "#define HAVE_DECL_BSWAP64 $ac_have_decl" >>confdefs.h 3672 + 3673 + 3674 + # Check whether --enable-westmere was given. 3675 + if test ${enable_westmere+y} 3676 + then : 3677 + enableval=$enable_westmere; 3678 + fi 3679 + 3680 + case "$enable_westmere" in 3681 + no) enable_westmere=no ;; 3682 + yes|*) enable_westmere=yes ;; 3683 + esac 3684 + 3685 + # Check whether --enable-haswell was given. 3686 + if test ${enable_haswell+y} 3687 + then : 3688 + enableval=$enable_haswell; 3689 + fi 3690 + 3691 + case "$enable_haswell" in 3692 + no) enable_haswell=no ;; 3693 + yes|*) enable_haswell=yes ;; 3694 + esac 3695 + 3696 + # GCC and Clang 3697 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -MMD" >&5 3698 + printf %s "checking whether C compiler accepts -MMD... " >&6; } 3699 + if test ${ax_cv_check_cflags___MMD+y} 3700 + then : 3701 + printf %s "(cached) " >&6 3702 + else $as_nop 3703 + 3704 + ax_check_save_flags=$CFLAGS 3705 + CFLAGS="$CFLAGS -MMD" 3706 + cat confdefs.h - <<_ACEOF >conftest.$ac_ext 3707 + /* end confdefs.h. */ 3708 + 3709 + int 3710 + main (void) 3711 + { 3712 + 3713 + ; 3714 + return 0; 3715 + } 3716 + _ACEOF 3717 + if ac_fn_c_try_compile "$LINENO" 3718 + then : 3719 + ax_cv_check_cflags___MMD=yes 3720 + else $as_nop 3721 + ax_cv_check_cflags___MMD=no 3722 + fi 3723 + rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext 3724 + CFLAGS=$ax_check_save_flags 3725 + fi 3726 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___MMD" >&5 3727 + printf "%s\n" "$ax_cv_check_cflags___MMD" >&6; } 3728 + if test "x$ax_cv_check_cflags___MMD" = xyes 3729 + then : 3730 + DEPFLAGS="-MMD -MP" 3731 + else $as_nop 3732 + : 3733 + fi 3734 + 3735 + # Oracle Developer Studio (no -MP) 3736 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -xMMD" >&5 3737 + printf %s "checking whether C compiler accepts -xMMD... " >&6; } 3738 + if test ${ax_cv_check_cflags___xMMD+y} 3739 + then : 3740 + printf %s "(cached) " >&6 3741 + else $as_nop 3742 + 3743 + ax_check_save_flags=$CFLAGS 3744 + CFLAGS="$CFLAGS -xMMD" 3745 + cat confdefs.h - <<_ACEOF >conftest.$ac_ext 3746 + /* end confdefs.h. */ 3747 + 3748 + int 3749 + main (void) 3750 + { 3751 + 3752 + ; 3753 + return 0; 3754 + } 3755 + _ACEOF 3756 + if ac_fn_c_try_compile "$LINENO" 3757 + then : 3758 + ax_cv_check_cflags___xMMD=yes 3759 + else $as_nop 3760 + ax_cv_check_cflags___xMMD=no 3761 + fi 3762 + rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext 3763 + CFLAGS=$ax_check_save_flags 3764 + fi 3765 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___xMMD" >&5 3766 + printf "%s\n" "$ax_cv_check_cflags___xMMD" >&6; } 3767 + if test "x$ax_cv_check_cflags___xMMD" = xyes 3768 + then : 3769 + DEPFLAGS="-xMMD" 3770 + else $as_nop 3771 + : 3772 + fi 3773 + 3774 + 3775 + 3776 + 3777 + # Figure out the canonical target architecture. 3778 + 3779 + 3780 + 3781 + # Make sure we can run config.sub. 3782 + $SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 || 3783 + as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5 3784 + 3785 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 3786 + printf %s "checking build system type... " >&6; } 3787 + if test ${ac_cv_build+y} 3788 + then : 3789 + printf %s "(cached) " >&6 3790 + else $as_nop 3791 + ac_build_alias=$build_alias 3792 + test "x$ac_build_alias" = x && 3793 + ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"` 3794 + test "x$ac_build_alias" = x && 3795 + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 3796 + ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` || 3797 + as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5 3798 + 3799 + fi 3800 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 3801 + printf "%s\n" "$ac_cv_build" >&6; } 3802 + case $ac_cv_build in 3803 + *-*-*) ;; 3804 + *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; 3805 + esac 3806 + build=$ac_cv_build 3807 + ac_save_IFS=$IFS; IFS='-' 3808 + set x $ac_cv_build 3809 + shift 3810 + build_cpu=$1 3811 + build_vendor=$2 3812 + shift; shift 3813 + # Remember, the first character of IFS is used to create $*, 3814 + # except with old shells: 3815 + build_os=$* 3816 + IFS=$ac_save_IFS 3817 + case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac 3818 + 3819 + 3820 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 3821 + printf %s "checking host system type... " >&6; } 3822 + if test ${ac_cv_host+y} 3823 + then : 3824 + printf %s "(cached) " >&6 3825 + else $as_nop 3826 + if test "x$host_alias" = x; then 3827 + ac_cv_host=$ac_cv_build 3828 + else 3829 + ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` || 3830 + as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5 3831 + fi 3832 + 3833 + fi 3834 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 3835 + printf "%s\n" "$ac_cv_host" >&6; } 3836 + case $ac_cv_host in 3837 + *-*-*) ;; 3838 + *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; 3839 + esac 3840 + host=$ac_cv_host 3841 + ac_save_IFS=$IFS; IFS='-' 3842 + set x $ac_cv_host 3843 + shift 3844 + host_cpu=$1 3845 + host_vendor=$2 3846 + shift; shift 3847 + # Remember, the first character of IFS is used to create $*, 3848 + # except with old shells: 3849 + host_os=$* 3850 + IFS=$ac_save_IFS 3851 + case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac 3852 + 3853 + 3854 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 3855 + printf %s "checking target system type... " >&6; } 3856 + if test ${ac_cv_target+y} 3857 + then : 3858 + printf %s "(cached) " >&6 3859 + else $as_nop 3860 + if test "x$target_alias" = x; then 3861 + ac_cv_target=$ac_cv_host 3862 + else 3863 + ac_cv_target=`$SHELL "${ac_aux_dir}config.sub" $target_alias` || 3864 + as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $target_alias failed" "$LINENO" 5 3865 + fi 3866 + 3867 + fi 3868 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 3869 + printf "%s\n" "$ac_cv_target" >&6; } 3870 + case $ac_cv_target in 3871 + *-*-*) ;; 3872 + *) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;; 3873 + esac 3874 + target=$ac_cv_target 3875 + ac_save_IFS=$IFS; IFS='-' 3876 + set x $ac_cv_target 3877 + shift 3878 + target_cpu=$1 3879 + target_vendor=$2 3880 + shift; shift 3881 + # Remember, the first character of IFS is used to create $*, 3882 + # except with old shells: 3883 + target_os=$* 3884 + IFS=$ac_save_IFS 3885 + case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac 3886 + 3887 + 3888 + # The aliases save the names the user supplied, while $host etc. 3889 + # will get canonicalized. 3890 + test -n "$target_alias" && 3891 + test "$program_prefix$program_suffix$program_transform_name" = \ 3892 + NONENONEs,x,x, && 3893 + program_prefix=${target_alias}- 3894 + 3895 + # Multiple instruction sets may be supported by a specific architecture. 3896 + # e.g. x86_64 may (or may not) support any of SSE42, AVX2 and AVX-512. The 3897 + # best instruction set is automatically selected at runtime, but the compiler 3898 + # may or may not support generating code for an instruction set. 3899 + case "$target" in 3900 + *amd64*) x86_64=yes ;; 3901 + *x86_64*) x86_64=yes ;; 3902 + *) x86_64=no ;; 3903 + esac 3904 + 3905 + HAVE_WESTMERE=NO 3906 + HAVE_HASWELL=NO 3907 + 3908 + if test $x86_64 = "yes"; then 3909 + ac_fn_c_check_header_compile "$LINENO" "immintrin.h" "ac_cv_header_immintrin_h" "$ac_includes_default" 3910 + if test "x$ac_cv_header_immintrin_h" = xyes 3911 + then : 3912 + 3913 + fi 3914 + 3915 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -march=westmere" >&5 3916 + printf %s "checking whether C compiler accepts -march=westmere... " >&6; } 3917 + if test ${ax_cv_check_cflags__Werror__march_westmere+y} 3918 + then : 3919 + printf %s "(cached) " >&6 3920 + else $as_nop 3921 + 3922 + ax_check_save_flags=$CFLAGS 3923 + CFLAGS="$CFLAGS -Werror -march=westmere" 3924 + cat confdefs.h - <<_ACEOF >conftest.$ac_ext 3925 + /* end confdefs.h. */ 3926 + 3927 + int 3928 + main (void) 3929 + { 3930 + 3931 + ; 3932 + return 0; 3933 + } 3934 + _ACEOF 3935 + if ac_fn_c_try_compile "$LINENO" 3936 + then : 3937 + ax_cv_check_cflags__Werror__march_westmere=yes 3938 + else $as_nop 3939 + ax_cv_check_cflags__Werror__march_westmere=no 3940 + fi 3941 + rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext 3942 + CFLAGS=$ax_check_save_flags 3943 + fi 3944 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags__Werror__march_westmere" >&5 3945 + printf "%s\n" "$ax_cv_check_cflags__Werror__march_westmere" >&6; } 3946 + if test "x$ax_cv_check_cflags__Werror__march_westmere" = xyes 3947 + then : 3948 + : 3949 + else $as_nop 3950 + : 3951 + fi 3952 + 3953 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -march=haswell" >&5 3954 + printf %s "checking whether C compiler accepts -march=haswell... " >&6; } 3955 + if test ${ax_cv_check_cflags__Werror__march_haswell+y} 3956 + then : 3957 + printf %s "(cached) " >&6 3958 + else $as_nop 3959 + 3960 + ax_check_save_flags=$CFLAGS 3961 + CFLAGS="$CFLAGS -Werror -march=haswell" 3962 + cat confdefs.h - <<_ACEOF >conftest.$ac_ext 3963 + /* end confdefs.h. */ 3964 + 3965 + int 3966 + main (void) 3967 + { 3968 + 3969 + ; 3970 + return 0; 3971 + } 3972 + _ACEOF 3973 + if ac_fn_c_try_compile "$LINENO" 3974 + then : 3975 + ax_cv_check_cflags__Werror__march_haswell=yes 3976 + else $as_nop 3977 + ax_cv_check_cflags__Werror__march_haswell=no 3978 + fi 3979 + rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext 3980 + CFLAGS=$ax_check_save_flags 3981 + fi 3982 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags__Werror__march_haswell" >&5 3983 + printf "%s\n" "$ax_cv_check_cflags__Werror__march_haswell" >&6; } 3984 + if test "x$ax_cv_check_cflags__Werror__march_haswell" = xyes 3985 + then : 3986 + : 3987 + else $as_nop 3988 + : 3989 + fi 3990 + 3991 + 3992 + # Check if the arch instruction set support includes the simd instructions. 3993 + if test $enable_westmere != "no" -a \ 3994 + $ax_cv_check_cflags__Werror__march_westmere = "yes" -a \ 3995 + $ac_cv_header_immintrin_h = "yes" ; then 3996 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -march=westmere works" >&5 3997 + printf %s "checking whether -march=westmere works... " >&6; } 3998 + BAKCFLAGS="$CFLAGS" 3999 + CFLAGS="-march=westmere $CFLAGS" 4000 + cat confdefs.h - <<_ACEOF >conftest.$ac_ext 4001 + /* end confdefs.h. */ 4002 + 4003 + $ac_includes_default 4004 + 4005 + #include <stdint.h> 4006 + #include <immintrin.h> 4007 + 4008 + int main(int argc, char *argv[]) 4009 + { 4010 + (void)argv; 4011 + uint64_t popcnt = _mm_popcnt_u64((uint64_t)argc); 4012 + return popcnt == 11; 4013 + } 4014 + 4015 + 4016 + _ACEOF 4017 + if ac_fn_c_try_compile "$LINENO" 4018 + then : 4019 + 4020 + 4021 + printf "%s\n" "#define HAVE_WESTMERE 1" >>confdefs.h 4022 + 4023 + HAVE_WESTMERE=WESTMERE 4024 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 4025 + printf "%s\n" "yes" >&6; } 4026 + 4027 + else $as_nop 4028 + 4029 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 4030 + printf "%s\n" "no" >&6; } 4031 + 4032 + fi 4033 + rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext 4034 + CFLAGS="$BAKCFLAGS" 4035 + fi 4036 + 4037 + if test $enable_haswell != "no" -a \ 4038 + $ax_cv_check_cflags__Werror__march_haswell = "yes" -a \ 4039 + $ac_cv_header_immintrin_h = "yes" ; then 4040 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -march=haswell works" >&5 4041 + printf %s "checking whether -march=haswell works... " >&6; } 4042 + BAKCFLAGS="$CFLAGS" 4043 + CFLAGS="-march=haswell $CFLAGS" 4044 + cat confdefs.h - <<_ACEOF >conftest.$ac_ext 4045 + /* end confdefs.h. */ 4046 + 4047 + $ac_includes_default 4048 + 4049 + #include <stdint.h> 4050 + #include <immintrin.h> 4051 + 4052 + int main(int argc, char *argv[]) 4053 + { 4054 + (void)argv; 4055 + int argc32x8[8] = { argc, 0, 0, 0, 0, 0, 0, 0 }; 4056 + __m256i argc256 = _mm256_loadu_si256((__m256i *)argc32x8); 4057 + return _mm256_testz_si256(argc256, _mm256_set1_epi8(11)); 4058 + } 4059 + 4060 + 4061 + _ACEOF 4062 + if ac_fn_c_try_compile "$LINENO" 4063 + then : 4064 + 4065 + 4066 + printf "%s\n" "#define HAVE_HASWELL 1" >>confdefs.h 4067 + 4068 + HAVE_HASWELL=HASWELL 4069 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 4070 + printf "%s\n" "yes" >&6; } 4071 + 4072 + else $as_nop 4073 + 4074 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 4075 + printf "%s\n" "no" >&6; } 4076 + 4077 + fi 4078 + rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext 4079 + CFLAGS="$BAKCFLAGS" 4080 + fi 4081 + fi 4082 + 4083 + 4084 + for ac_func in realpath 4085 + do : 4086 + ac_fn_c_check_func "$LINENO" "realpath" "ac_cv_func_realpath" 4087 + if test "x$ac_cv_func_realpath" = xyes 4088 + then : 4089 + printf "%s\n" "#define HAVE_REALPATH 1" >>confdefs.h 4090 + 4091 + else $as_nop 4092 + as_fn_error $? "realpath is not available" "$LINENO" 5 4093 + fi 4094 + 4095 + done 4096 + 4097 + 4098 + 4099 + 4100 + 4101 + 4102 + 4103 + cat >confcache <<\_ACEOF 4104 + # This file is a shell script that caches the results of configure 4105 + # tests run on this system so they can be shared between configure 4106 + # scripts and configure runs, see configure's option --config-cache. 4107 + # It is not useful on other systems. If it contains results you don't 4108 + # want to keep, you may remove or edit it. 4109 + # 4110 + # config.status only pays attention to the cache file if you give it 4111 + # the --recheck option to rerun configure. 4112 + # 4113 + # `ac_cv_env_foo' variables (set or unset) will be overridden when 4114 + # loading this file, other *unset* `ac_cv_foo' will be assigned the 4115 + # following values. 4116 + 4117 + _ACEOF 4118 + 4119 + # The following way of writing the cache mishandles newlines in values, 4120 + # but we know of no workaround that is simple, portable, and efficient. 4121 + # So, we kill variables containing newlines. 4122 + # Ultrix sh set writes to stderr and can't be redirected directly, 4123 + # and sets the high bit in the cache file unless we assign to the vars. 4124 + ( 4125 + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do 4126 + eval ac_val=\$$ac_var 4127 + case $ac_val in #( 4128 + *${as_nl}*) 4129 + case $ac_var in #( 4130 + *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 4131 + printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; 4132 + esac 4133 + case $ac_var in #( 4134 + _ | IFS | as_nl) ;; #( 4135 + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( 4136 + *) { eval $ac_var=; unset $ac_var;} ;; 4137 + esac ;; 4138 + esac 4139 + done 4140 + 4141 + (set) 2>&1 | 4142 + case $as_nl`(ac_space=' '; set) 2>&1` in #( 4143 + *${as_nl}ac_space=\ *) 4144 + # `set' does not quote correctly, so add quotes: double-quote 4145 + # substitution turns \\\\ into \\, and sed turns \\ into \. 4146 + sed -n \ 4147 + "s/'/'\\\\''/g; 4148 + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" 4149 + ;; #( 4150 + *) 4151 + # `set' quotes correctly as required by POSIX, so do not add quotes. 4152 + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" 4153 + ;; 4154 + esac | 4155 + sort 4156 + ) | 4157 + sed ' 4158 + /^ac_cv_env_/b end 4159 + t clear 4160 + :clear 4161 + s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/ 4162 + t end 4163 + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ 4164 + :end' >>confcache 4165 + if diff "$cache_file" confcache >/dev/null 2>&1; then :; else 4166 + if test -w "$cache_file"; then 4167 + if test "x$cache_file" != "x/dev/null"; then 4168 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 4169 + printf "%s\n" "$as_me: updating cache $cache_file" >&6;} 4170 + if test ! -f "$cache_file" || test -h "$cache_file"; then 4171 + cat confcache >"$cache_file" 4172 + else 4173 + case $cache_file in #( 4174 + */* | ?:*) 4175 + mv -f confcache "$cache_file"$$ && 4176 + mv -f "$cache_file"$$ "$cache_file" ;; #( 4177 + *) 4178 + mv -f confcache "$cache_file" ;; 4179 + esac 4180 + fi 4181 + fi 4182 + else 4183 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 4184 + printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;} 4185 + fi 4186 + fi 4187 + rm -f confcache 4188 + 4189 + test "x$prefix" = xNONE && prefix=$ac_default_prefix 4190 + # Let make expand exec_prefix. 4191 + test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' 4192 + 4193 + DEFS=-DHAVE_CONFIG_H 4194 + 4195 + ac_libobjs= 4196 + ac_ltlibobjs= 4197 + U= 4198 + for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue 4199 + # 1. Remove the extension, and $U if already installed. 4200 + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' 4201 + ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"` 4202 + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR 4203 + # will be set to the directory where LIBOBJS objects are built. 4204 + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" 4205 + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' 4206 + done 4207 + LIBOBJS=$ac_libobjs 4208 + 4209 + LTLIBOBJS=$ac_ltlibobjs 4210 + 4211 + 4212 + 4213 + : "${CONFIG_STATUS=./config.status}" 4214 + ac_write_fail=0 4215 + ac_clean_files_save=$ac_clean_files 4216 + ac_clean_files="$ac_clean_files $CONFIG_STATUS" 4217 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 4218 + printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;} 4219 + as_write_fail=0 4220 + cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 4221 + #! $SHELL 4222 + # Generated by $as_me. 4223 + # Run this file to recreate the current configuration. 4224 + # Compiler output produced by configure, useful for debugging 4225 + # configure, is in config.log if it exists. 4226 + 4227 + debug=false 4228 + ac_cs_recheck=false 4229 + ac_cs_silent=false 4230 + 4231 + SHELL=\${CONFIG_SHELL-$SHELL} 4232 + export SHELL 4233 + _ASEOF 4234 + cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 4235 + ## -------------------- ## 4236 + ## M4sh Initialization. ## 4237 + ## -------------------- ## 4238 + 4239 + # Be more Bourne compatible 4240 + DUALCASE=1; export DUALCASE # for MKS sh 4241 + as_nop=: 4242 + if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 4243 + then : 4244 + emulate sh 4245 + NULLCMD=: 4246 + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which 4247 + # is contrary to our usage. Disable this feature. 4248 + alias -g '${1+"$@"}'='"$@"' 4249 + setopt NO_GLOB_SUBST 4250 + else $as_nop 4251 + case `(set -o) 2>/dev/null` in #( 4252 + *posix*) : 4253 + set -o posix ;; #( 4254 + *) : 4255 + ;; 4256 + esac 4257 + fi 4258 + 4259 + 4260 + 4261 + # Reset variables that may have inherited troublesome values from 4262 + # the environment. 4263 + 4264 + # IFS needs to be set, to space, tab, and newline, in precisely that order. 4265 + # (If _AS_PATH_WALK were called with IFS unset, it would have the 4266 + # side effect of setting IFS to empty, thus disabling word splitting.) 4267 + # Quoting is to prevent editors from complaining about space-tab. 4268 + as_nl=' 4269 + ' 4270 + export as_nl 4271 + IFS=" "" $as_nl" 4272 + 4273 + PS1='$ ' 4274 + PS2='> ' 4275 + PS4='+ ' 4276 + 4277 + # Ensure predictable behavior from utilities with locale-dependent output. 4278 + LC_ALL=C 4279 + export LC_ALL 4280 + LANGUAGE=C 4281 + export LANGUAGE 4282 + 4283 + # We cannot yet rely on "unset" to work, but we need these variables 4284 + # to be unset--not just set to an empty or harmless value--now, to 4285 + # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct 4286 + # also avoids known problems related to "unset" and subshell syntax 4287 + # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). 4288 + for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH 4289 + do eval test \${$as_var+y} \ 4290 + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : 4291 + done 4292 + 4293 + # Ensure that fds 0, 1, and 2 are open. 4294 + if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi 4295 + if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi 4296 + if (exec 3>&2) ; then :; else exec 2>/dev/null; fi 4297 + 4298 + # The user is always right. 4299 + if ${PATH_SEPARATOR+false} :; then 4300 + PATH_SEPARATOR=: 4301 + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { 4302 + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || 4303 + PATH_SEPARATOR=';' 4304 + } 4305 + fi 4306 + 4307 + 4308 + # Find who we are. Look in the path if we contain no directory separator. 4309 + as_myself= 4310 + case $0 in #(( 4311 + *[\\/]* ) as_myself=$0 ;; 4312 + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR 4313 + for as_dir in $PATH 4314 + do 4315 + IFS=$as_save_IFS 4316 + case $as_dir in #((( 4317 + '') as_dir=./ ;; 4318 + */) ;; 4319 + *) as_dir=$as_dir/ ;; 4320 + esac 4321 + test -r "$as_dir$0" && as_myself=$as_dir$0 && break 4322 + done 4323 + IFS=$as_save_IFS 4324 + 4325 + ;; 4326 + esac 4327 + # We did not find ourselves, most probably we were run as `sh COMMAND' 4328 + # in which case we are not to be found in the path. 4329 + if test "x$as_myself" = x; then 4330 + as_myself=$0 4331 + fi 4332 + if test ! -f "$as_myself"; then 4333 + printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 4334 + exit 1 4335 + fi 4336 + 4337 + 4338 + 4339 + # as_fn_error STATUS ERROR [LINENO LOG_FD] 4340 + # ---------------------------------------- 4341 + # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are 4342 + # provided, also output the error to LOG_FD, referencing LINENO. Then exit the 4343 + # script with STATUS, using 1 if that was 0. 4344 + as_fn_error () 4345 + { 4346 + as_status=$1; test $as_status -eq 0 && as_status=1 4347 + if test "$4"; then 4348 + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack 4349 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 4350 + fi 4351 + printf "%s\n" "$as_me: error: $2" >&2 4352 + as_fn_exit $as_status 4353 + } # as_fn_error 4354 + 4355 + 4356 + 4357 + # as_fn_set_status STATUS 4358 + # ----------------------- 4359 + # Set $? to STATUS, without forking. 4360 + as_fn_set_status () 4361 + { 4362 + return $1 4363 + } # as_fn_set_status 4364 + 4365 + # as_fn_exit STATUS 4366 + # ----------------- 4367 + # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. 4368 + as_fn_exit () 4369 + { 4370 + set +e 4371 + as_fn_set_status $1 4372 + exit $1 4373 + } # as_fn_exit 4374 + 4375 + # as_fn_unset VAR 4376 + # --------------- 4377 + # Portably unset VAR. 4378 + as_fn_unset () 4379 + { 4380 + { eval $1=; unset $1;} 4381 + } 4382 + as_unset=as_fn_unset 4383 + 4384 + # as_fn_append VAR VALUE 4385 + # ---------------------- 4386 + # Append the text in VALUE to the end of the definition contained in VAR. Take 4387 + # advantage of any shell optimizations that allow amortized linear growth over 4388 + # repeated appends, instead of the typical quadratic growth present in naive 4389 + # implementations. 4390 + if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null 4391 + then : 4392 + eval 'as_fn_append () 4393 + { 4394 + eval $1+=\$2 4395 + }' 4396 + else $as_nop 4397 + as_fn_append () 4398 + { 4399 + eval $1=\$$1\$2 4400 + } 4401 + fi # as_fn_append 4402 + 4403 + # as_fn_arith ARG... 4404 + # ------------------ 4405 + # Perform arithmetic evaluation on the ARGs, and store the result in the 4406 + # global $as_val. Take advantage of shells that can avoid forks. The arguments 4407 + # must be portable across $(()) and expr. 4408 + if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null 4409 + then : 4410 + eval 'as_fn_arith () 4411 + { 4412 + as_val=$(( $* )) 4413 + }' 4414 + else $as_nop 4415 + as_fn_arith () 4416 + { 4417 + as_val=`expr "$@" || test $? -eq 1` 4418 + } 4419 + fi # as_fn_arith 4420 + 4421 + 4422 + if expr a : '\(a\)' >/dev/null 2>&1 && 4423 + test "X`expr 00001 : '.*\(...\)'`" = X001; then 4424 + as_expr=expr 4425 + else 4426 + as_expr=false 4427 + fi 4428 + 4429 + if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then 4430 + as_basename=basename 4431 + else 4432 + as_basename=false 4433 + fi 4434 + 4435 + if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then 4436 + as_dirname=dirname 4437 + else 4438 + as_dirname=false 4439 + fi 4440 + 4441 + as_me=`$as_basename -- "$0" || 4442 + $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ 4443 + X"$0" : 'X\(//\)$' \| \ 4444 + X"$0" : 'X\(/\)' \| . 2>/dev/null || 4445 + printf "%s\n" X/"$0" | 4446 + sed '/^.*\/\([^/][^/]*\)\/*$/{ 4447 + s//\1/ 4448 + q 4449 + } 4450 + /^X\/\(\/\/\)$/{ 4451 + s//\1/ 4452 + q 4453 + } 4454 + /^X\/\(\/\).*/{ 4455 + s//\1/ 4456 + q 4457 + } 4458 + s/.*/./; q'` 4459 + 4460 + # Avoid depending upon Character Ranges. 4461 + as_cr_letters='abcdefghijklmnopqrstuvwxyz' 4462 + as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' 4463 + as_cr_Letters=$as_cr_letters$as_cr_LETTERS 4464 + as_cr_digits='0123456789' 4465 + as_cr_alnum=$as_cr_Letters$as_cr_digits 4466 + 4467 + 4468 + # Determine whether it's possible to make 'echo' print without a newline. 4469 + # These variables are no longer used directly by Autoconf, but are AC_SUBSTed 4470 + # for compatibility with existing Makefiles. 4471 + ECHO_C= ECHO_N= ECHO_T= 4472 + case `echo -n x` in #((((( 4473 + -n*) 4474 + case `echo 'xy\c'` in 4475 + *c*) ECHO_T=' ';; # ECHO_T is single tab character. 4476 + xy) ECHO_C='\c';; 4477 + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null 4478 + ECHO_T=' ';; 4479 + esac;; 4480 + *) 4481 + ECHO_N='-n';; 4482 + esac 4483 + 4484 + # For backward compatibility with old third-party macros, we provide 4485 + # the shell variables $as_echo and $as_echo_n. New code should use 4486 + # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. 4487 + as_echo='printf %s\n' 4488 + as_echo_n='printf %s' 4489 + 4490 + rm -f conf$$ conf$$.exe conf$$.file 4491 + if test -d conf$$.dir; then 4492 + rm -f conf$$.dir/conf$$.file 4493 + else 4494 + rm -f conf$$.dir 4495 + mkdir conf$$.dir 2>/dev/null 4496 + fi 4497 + if (echo >conf$$.file) 2>/dev/null; then 4498 + if ln -s conf$$.file conf$$ 2>/dev/null; then 4499 + as_ln_s='ln -s' 4500 + # ... but there are two gotchas: 4501 + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. 4502 + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. 4503 + # In both cases, we have to default to `cp -pR'. 4504 + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || 4505 + as_ln_s='cp -pR' 4506 + elif ln conf$$.file conf$$ 2>/dev/null; then 4507 + as_ln_s=ln 4508 + else 4509 + as_ln_s='cp -pR' 4510 + fi 4511 + else 4512 + as_ln_s='cp -pR' 4513 + fi 4514 + rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file 4515 + rmdir conf$$.dir 2>/dev/null 4516 + 4517 + 4518 + # as_fn_mkdir_p 4519 + # ------------- 4520 + # Create "$as_dir" as a directory, including parents if necessary. 4521 + as_fn_mkdir_p () 4522 + { 4523 + 4524 + case $as_dir in #( 4525 + -*) as_dir=./$as_dir;; 4526 + esac 4527 + test -d "$as_dir" || eval $as_mkdir_p || { 4528 + as_dirs= 4529 + while :; do 4530 + case $as_dir in #( 4531 + *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( 4532 + *) as_qdir=$as_dir;; 4533 + esac 4534 + as_dirs="'$as_qdir' $as_dirs" 4535 + as_dir=`$as_dirname -- "$as_dir" || 4536 + $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ 4537 + X"$as_dir" : 'X\(//\)[^/]' \| \ 4538 + X"$as_dir" : 'X\(//\)$' \| \ 4539 + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || 4540 + printf "%s\n" X"$as_dir" | 4541 + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ 4542 + s//\1/ 4543 + q 4544 + } 4545 + /^X\(\/\/\)[^/].*/{ 4546 + s//\1/ 4547 + q 4548 + } 4549 + /^X\(\/\/\)$/{ 4550 + s//\1/ 4551 + q 4552 + } 4553 + /^X\(\/\).*/{ 4554 + s//\1/ 4555 + q 4556 + } 4557 + s/.*/./; q'` 4558 + test -d "$as_dir" && break 4559 + done 4560 + test -z "$as_dirs" || eval "mkdir $as_dirs" 4561 + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" 4562 + 4563 + 4564 + } # as_fn_mkdir_p 4565 + if mkdir -p . 2>/dev/null; then 4566 + as_mkdir_p='mkdir -p "$as_dir"' 4567 + else 4568 + test -d ./-p && rmdir ./-p 4569 + as_mkdir_p=false 4570 + fi 4571 + 4572 + 4573 + # as_fn_executable_p FILE 4574 + # ----------------------- 4575 + # Test if FILE is an executable regular file. 4576 + as_fn_executable_p () 4577 + { 4578 + test -f "$1" && test -x "$1" 4579 + } # as_fn_executable_p 4580 + as_test_x='test -x' 4581 + as_executable_p=as_fn_executable_p 4582 + 4583 + # Sed expression to map a string onto a valid CPP name. 4584 + as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" 4585 + 4586 + # Sed expression to map a string onto a valid variable name. 4587 + as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" 4588 + 4589 + 4590 + exec 6>&1 4591 + ## ----------------------------------- ## 4592 + ## Main body of $CONFIG_STATUS script. ## 4593 + ## ----------------------------------- ## 4594 + _ASEOF 4595 + test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 4596 + 4597 + cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 4598 + # Save the log message, to keep $0 and so on meaningful, and to 4599 + # report actual input values of CONFIG_FILES etc. instead of their 4600 + # values after options handling. 4601 + ac_log=" 4602 + This file was extended by simdzone $as_me 0.2.0, which was 4603 + generated by GNU Autoconf 2.71. Invocation command line was 4604 + 4605 + CONFIG_FILES = $CONFIG_FILES 4606 + CONFIG_HEADERS = $CONFIG_HEADERS 4607 + CONFIG_LINKS = $CONFIG_LINKS 4608 + CONFIG_COMMANDS = $CONFIG_COMMANDS 4609 + $ $0 $@ 4610 + 4611 + on `(hostname || uname -n) 2>/dev/null | sed 1q` 4612 + " 4613 + 4614 + _ACEOF 4615 + 4616 + case $ac_config_files in *" 4617 + "*) set x $ac_config_files; shift; ac_config_files=$*;; 4618 + esac 4619 + 4620 + case $ac_config_headers in *" 4621 + "*) set x $ac_config_headers; shift; ac_config_headers=$*;; 4622 + esac 4623 + 4624 + 4625 + cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 4626 + # Files that config.status was made for. 4627 + config_files="$ac_config_files" 4628 + config_headers="$ac_config_headers" 4629 + 4630 + _ACEOF 4631 + 4632 + cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 4633 + ac_cs_usage="\ 4634 + \`$as_me' instantiates files and other configuration actions 4635 + from templates according to the current configuration. Unless the files 4636 + and actions are specified as TAGs, all are instantiated by default. 4637 + 4638 + Usage: $0 [OPTION]... [TAG]... 4639 + 4640 + -h, --help print this help, then exit 4641 + -V, --version print version number and configuration settings, then exit 4642 + --config print configuration, then exit 4643 + -q, --quiet, --silent 4644 + do not print progress messages 4645 + -d, --debug don't remove temporary files 4646 + --recheck update $as_me by reconfiguring in the same conditions 4647 + --file=FILE[:TEMPLATE] 4648 + instantiate the configuration file FILE 4649 + --header=FILE[:TEMPLATE] 4650 + instantiate the configuration header FILE 4651 + 4652 + Configuration files: 4653 + $config_files 4654 + 4655 + Configuration headers: 4656 + $config_headers 4657 + 4658 + Report bugs to <https://github.com/NLnetLabs/simdzone/issues>." 4659 + 4660 + _ACEOF 4661 + ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"` 4662 + ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"` 4663 + cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 4664 + ac_cs_config='$ac_cs_config_escaped' 4665 + ac_cs_version="\\ 4666 + simdzone config.status 0.2.0 4667 + configured by $0, generated by GNU Autoconf 2.71, 4668 + with options \\"\$ac_cs_config\\" 4669 + 4670 + Copyright (C) 2021 Free Software Foundation, Inc. 4671 + This config.status script is free software; the Free Software Foundation 4672 + gives unlimited permission to copy, distribute and modify it." 4673 + 4674 + ac_pwd='$ac_pwd' 4675 + srcdir='$srcdir' 4676 + test -n "\$AWK" || AWK=awk 4677 + _ACEOF 4678 + 4679 + cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 4680 + # The default lists apply if the user does not specify any file. 4681 + ac_need_defaults=: 4682 + while test $# != 0 4683 + do 4684 + case $1 in 4685 + --*=?*) 4686 + ac_option=`expr "X$1" : 'X\([^=]*\)='` 4687 + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` 4688 + ac_shift=: 4689 + ;; 4690 + --*=) 4691 + ac_option=`expr "X$1" : 'X\([^=]*\)='` 4692 + ac_optarg= 4693 + ac_shift=: 4694 + ;; 4695 + *) 4696 + ac_option=$1 4697 + ac_optarg=$2 4698 + ac_shift=shift 4699 + ;; 4700 + esac 4701 + 4702 + case $ac_option in 4703 + # Handling of the options. 4704 + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) 4705 + ac_cs_recheck=: ;; 4706 + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) 4707 + printf "%s\n" "$ac_cs_version"; exit ;; 4708 + --config | --confi | --conf | --con | --co | --c ) 4709 + printf "%s\n" "$ac_cs_config"; exit ;; 4710 + --debug | --debu | --deb | --de | --d | -d ) 4711 + debug=: ;; 4712 + --file | --fil | --fi | --f ) 4713 + $ac_shift 4714 + case $ac_optarg in 4715 + *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; 4716 + '') as_fn_error $? "missing file argument" ;; 4717 + esac 4718 + as_fn_append CONFIG_FILES " '$ac_optarg'" 4719 + ac_need_defaults=false;; 4720 + --header | --heade | --head | --hea ) 4721 + $ac_shift 4722 + case $ac_optarg in 4723 + *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; 4724 + esac 4725 + as_fn_append CONFIG_HEADERS " '$ac_optarg'" 4726 + ac_need_defaults=false;; 4727 + --he | --h) 4728 + # Conflict between --help and --header 4729 + as_fn_error $? "ambiguous option: \`$1' 4730 + Try \`$0 --help' for more information.";; 4731 + --help | --hel | -h ) 4732 + printf "%s\n" "$ac_cs_usage"; exit ;; 4733 + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ 4734 + | -silent | --silent | --silen | --sile | --sil | --si | --s) 4735 + ac_cs_silent=: ;; 4736 + 4737 + # This is an error. 4738 + -*) as_fn_error $? "unrecognized option: \`$1' 4739 + Try \`$0 --help' for more information." ;; 4740 + 4741 + *) as_fn_append ac_config_targets " $1" 4742 + ac_need_defaults=false ;; 4743 + 4744 + esac 4745 + shift 4746 + done 4747 + 4748 + ac_configure_extra_args= 4749 + 4750 + if $ac_cs_silent; then 4751 + exec 6>/dev/null 4752 + ac_configure_extra_args="$ac_configure_extra_args --silent" 4753 + fi 4754 + 4755 + _ACEOF 4756 + cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 4757 + if \$ac_cs_recheck; then 4758 + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion 4759 + shift 4760 + \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6 4761 + CONFIG_SHELL='$SHELL' 4762 + export CONFIG_SHELL 4763 + exec "\$@" 4764 + fi 4765 + 4766 + _ACEOF 4767 + cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 4768 + exec 5>>config.log 4769 + { 4770 + echo 4771 + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX 4772 + ## Running $as_me. ## 4773 + _ASBOX 4774 + printf "%s\n" "$ac_log" 4775 + } >&5 4776 + 4777 + _ACEOF 4778 + cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 4779 + _ACEOF 4780 + 4781 + cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 4782 + 4783 + # Handling of arguments. 4784 + for ac_config_target in $ac_config_targets 4785 + do 4786 + case $ac_config_target in 4787 + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; 4788 + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; 4789 + 4790 + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; 4791 + esac 4792 + done 4793 + 4794 + 4795 + # If the user did not use the arguments to specify the items to instantiate, 4796 + # then the envvar interface is used. Set only those that are not. 4797 + # We use the long form for the default assignment because of an extremely 4798 + # bizarre bug on SunOS 4.1.3. 4799 + if $ac_need_defaults; then 4800 + test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files 4801 + test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers 4802 + fi 4803 + 4804 + # Have a temporary directory for convenience. Make it in the build tree 4805 + # simply because there is no reason against having it here, and in addition, 4806 + # creating and moving files from /tmp can sometimes cause problems. 4807 + # Hook for its removal unless debugging. 4808 + # Note that there is a small window in which the directory will not be cleaned: 4809 + # after its creation but before its name has been assigned to `$tmp'. 4810 + $debug || 4811 + { 4812 + tmp= ac_tmp= 4813 + trap 'exit_status=$? 4814 + : "${ac_tmp:=$tmp}" 4815 + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status 4816 + ' 0 4817 + trap 'as_fn_exit 1' 1 2 13 15 4818 + } 4819 + # Create a (secure) tmp directory for tmp files. 4820 + 4821 + { 4822 + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && 4823 + test -d "$tmp" 4824 + } || 4825 + { 4826 + tmp=./conf$$-$RANDOM 4827 + (umask 077 && mkdir "$tmp") 4828 + } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 4829 + ac_tmp=$tmp 4830 + 4831 + # Set up the scripts for CONFIG_FILES section. 4832 + # No need to generate them if there are no CONFIG_FILES. 4833 + # This happens for instance with `./config.status config.h'. 4834 + if test -n "$CONFIG_FILES"; then 4835 + 4836 + 4837 + ac_cr=`echo X | tr X '\015'` 4838 + # On cygwin, bash can eat \r inside `` if the user requested igncr. 4839 + # But we know of no other shell where ac_cr would be empty at this 4840 + # point, so we can use a bashism as a fallback. 4841 + if test "x$ac_cr" = x; then 4842 + eval ac_cr=\$\'\\r\' 4843 + fi 4844 + ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null` 4845 + if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then 4846 + ac_cs_awk_cr='\\r' 4847 + else 4848 + ac_cs_awk_cr=$ac_cr 4849 + fi 4850 + 4851 + echo 'BEGIN {' >"$ac_tmp/subs1.awk" && 4852 + _ACEOF 4853 + 4854 + 4855 + { 4856 + echo "cat >conf$$subs.awk <<_ACEOF" && 4857 + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && 4858 + echo "_ACEOF" 4859 + } >conf$$subs.sh || 4860 + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 4861 + ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` 4862 + ac_delim='%!_!# ' 4863 + for ac_last_try in false false false false false :; do 4864 + . ./conf$$subs.sh || 4865 + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 4866 + 4867 + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` 4868 + if test $ac_delim_n = $ac_delim_num; then 4869 + break 4870 + elif $ac_last_try; then 4871 + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 4872 + else 4873 + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " 4874 + fi 4875 + done 4876 + rm -f conf$$subs.sh 4877 + 4878 + cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 4879 + cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && 4880 + _ACEOF 4881 + sed -n ' 4882 + h 4883 + s/^/S["/; s/!.*/"]=/ 4884 + p 4885 + g 4886 + s/^[^!]*!// 4887 + :repl 4888 + t repl 4889 + s/'"$ac_delim"'$// 4890 + t delim 4891 + :nl 4892 + h 4893 + s/\(.\{148\}\)..*/\1/ 4894 + t more1 4895 + s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ 4896 + p 4897 + n 4898 + b repl 4899 + :more1 4900 + s/["\\]/\\&/g; s/^/"/; s/$/"\\/ 4901 + p 4902 + g 4903 + s/.\{148\}// 4904 + t nl 4905 + :delim 4906 + h 4907 + s/\(.\{148\}\)..*/\1/ 4908 + t more2 4909 + s/["\\]/\\&/g; s/^/"/; s/$/"/ 4910 + p 4911 + b 4912 + :more2 4913 + s/["\\]/\\&/g; s/^/"/; s/$/"\\/ 4914 + p 4915 + g 4916 + s/.\{148\}// 4917 + t delim 4918 + ' <conf$$subs.awk | sed ' 4919 + /^[^""]/{ 4920 + N 4921 + s/\n// 4922 + } 4923 + ' >>$CONFIG_STATUS || ac_write_fail=1 4924 + rm -f conf$$subs.awk 4925 + cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 4926 + _ACAWK 4927 + cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && 4928 + for (key in S) S_is_set[key] = 1 4929 + FS = "" 4930 + 4931 + } 4932 + { 4933 + line = $ 0 4934 + nfields = split(line, field, "@") 4935 + substed = 0 4936 + len = length(field[1]) 4937 + for (i = 2; i < nfields; i++) { 4938 + key = field[i] 4939 + keylen = length(key) 4940 + if (S_is_set[key]) { 4941 + value = S[key] 4942 + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) 4943 + len += length(value) + length(field[++i]) 4944 + substed = 1 4945 + } else 4946 + len += 1 + keylen 4947 + } 4948 + 4949 + print line 4950 + } 4951 + 4952 + _ACAWK 4953 + _ACEOF 4954 + cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 4955 + if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then 4956 + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" 4957 + else 4958 + cat 4959 + fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ 4960 + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 4961 + _ACEOF 4962 + 4963 + # VPATH may cause trouble with some makes, so we remove sole $(srcdir), 4964 + # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and 4965 + # trailing colons and then remove the whole line if VPATH becomes empty 4966 + # (actually we leave an empty line to preserve line numbers). 4967 + if test "x$srcdir" = x.; then 4968 + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ 4969 + h 4970 + s/// 4971 + s/^/:/ 4972 + s/[ ]*$/:/ 4973 + s/:\$(srcdir):/:/g 4974 + s/:\${srcdir}:/:/g 4975 + s/:@srcdir@:/:/g 4976 + s/^:*// 4977 + s/:*$// 4978 + x 4979 + s/\(=[ ]*\).*/\1/ 4980 + G 4981 + s/\n// 4982 + s/^[^=]*=[ ]*$// 4983 + }' 4984 + fi 4985 + 4986 + cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 4987 + fi # test -n "$CONFIG_FILES" 4988 + 4989 + # Set up the scripts for CONFIG_HEADERS section. 4990 + # No need to generate them if there are no CONFIG_HEADERS. 4991 + # This happens for instance with `./config.status Makefile'. 4992 + if test -n "$CONFIG_HEADERS"; then 4993 + cat >"$ac_tmp/defines.awk" <<\_ACAWK || 4994 + BEGIN { 4995 + _ACEOF 4996 + 4997 + # Transform confdefs.h into an awk script `defines.awk', embedded as 4998 + # here-document in config.status, that substitutes the proper values into 4999 + # config.h.in to produce config.h. 5000 + 5001 + # Create a delimiter string that does not exist in confdefs.h, to ease 5002 + # handling of long lines. 5003 + ac_delim='%!_!# ' 5004 + for ac_last_try in false false :; do 5005 + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` 5006 + if test -z "$ac_tt"; then 5007 + break 5008 + elif $ac_last_try; then 5009 + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 5010 + else 5011 + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " 5012 + fi 5013 + done 5014 + 5015 + # For the awk script, D is an array of macro values keyed by name, 5016 + # likewise P contains macro parameters if any. Preserve backslash 5017 + # newline sequences. 5018 + 5019 + ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* 5020 + sed -n ' 5021 + s/.\{148\}/&'"$ac_delim"'/g 5022 + t rset 5023 + :rset 5024 + s/^[ ]*#[ ]*define[ ][ ]*/ / 5025 + t def 5026 + d 5027 + :def 5028 + s/\\$// 5029 + t bsnl 5030 + s/["\\]/\\&/g 5031 + s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ 5032 + D["\1"]=" \3"/p 5033 + s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p 5034 + d 5035 + :bsnl 5036 + s/["\\]/\\&/g 5037 + s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ 5038 + D["\1"]=" \3\\\\\\n"\\/p 5039 + t cont 5040 + s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p 5041 + t cont 5042 + d 5043 + :cont 5044 + n 5045 + s/.\{148\}/&'"$ac_delim"'/g 5046 + t clear 5047 + :clear 5048 + s/\\$// 5049 + t bsnlc 5050 + s/["\\]/\\&/g; s/^/"/; s/$/"/p 5051 + d 5052 + :bsnlc 5053 + s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p 5054 + b cont 5055 + ' <confdefs.h | sed ' 5056 + s/'"$ac_delim"'/"\\\ 5057 + "/g' >>$CONFIG_STATUS || ac_write_fail=1 5058 + 5059 + cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 5060 + for (key in D) D_is_set[key] = 1 5061 + FS = "" 5062 + } 5063 + /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { 5064 + line = \$ 0 5065 + split(line, arg, " ") 5066 + if (arg[1] == "#") { 5067 + defundef = arg[2] 5068 + mac1 = arg[3] 5069 + } else { 5070 + defundef = substr(arg[1], 2) 5071 + mac1 = arg[2] 5072 + } 5073 + split(mac1, mac2, "(") #) 5074 + macro = mac2[1] 5075 + prefix = substr(line, 1, index(line, defundef) - 1) 5076 + if (D_is_set[macro]) { 5077 + # Preserve the white space surrounding the "#". 5078 + print prefix "define", macro P[macro] D[macro] 5079 + next 5080 + } else { 5081 + # Replace #undef with comments. This is necessary, for example, 5082 + # in the case of _POSIX_SOURCE, which is predefined and required 5083 + # on some systems where configure will not decide to define it. 5084 + if (defundef == "undef") { 5085 + print "/*", prefix defundef, macro, "*/" 5086 + next 5087 + } 5088 + } 5089 + } 5090 + { print } 5091 + _ACAWK 5092 + _ACEOF 5093 + cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 5094 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 5095 + fi # test -n "$CONFIG_HEADERS" 5096 + 5097 + 5098 + eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " 5099 + shift 5100 + for ac_tag 5101 + do 5102 + case $ac_tag in 5103 + :[FHLC]) ac_mode=$ac_tag; continue;; 5104 + esac 5105 + case $ac_mode$ac_tag in 5106 + :[FHL]*:*);; 5107 + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; 5108 + :[FH]-) ac_tag=-:-;; 5109 + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; 5110 + esac 5111 + ac_save_IFS=$IFS 5112 + IFS=: 5113 + set x $ac_tag 5114 + IFS=$ac_save_IFS 5115 + shift 5116 + ac_file=$1 5117 + shift 5118 + 5119 + case $ac_mode in 5120 + :L) ac_source=$1;; 5121 + :[FH]) 5122 + ac_file_inputs= 5123 + for ac_f 5124 + do 5125 + case $ac_f in 5126 + -) ac_f="$ac_tmp/stdin";; 5127 + *) # Look for the file first in the build tree, then in the source tree 5128 + # (if the path is not absolute). The absolute path cannot be DOS-style, 5129 + # because $ac_f cannot contain `:'. 5130 + test -f "$ac_f" || 5131 + case $ac_f in 5132 + [\\/$]*) false;; 5133 + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; 5134 + esac || 5135 + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; 5136 + esac 5137 + case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac 5138 + as_fn_append ac_file_inputs " '$ac_f'" 5139 + done 5140 + 5141 + # Let's still pretend it is `configure' which instantiates (i.e., don't 5142 + # use $as_me), people would be surprised to read: 5143 + # /* config.h. Generated by config.status. */ 5144 + configure_input='Generated from '` 5145 + printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' 5146 + `' by configure.' 5147 + if test x"$ac_file" != x-; then 5148 + configure_input="$ac_file. $configure_input" 5149 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 5150 + printf "%s\n" "$as_me: creating $ac_file" >&6;} 5151 + fi 5152 + # Neutralize special characters interpreted by sed in replacement strings. 5153 + case $configure_input in #( 5154 + *\&* | *\|* | *\\* ) 5155 + ac_sed_conf_input=`printf "%s\n" "$configure_input" | 5156 + sed 's/[\\\\&|]/\\\\&/g'`;; #( 5157 + *) ac_sed_conf_input=$configure_input;; 5158 + esac 5159 + 5160 + case $ac_tag in 5161 + *:-:* | *:-) cat >"$ac_tmp/stdin" \ 5162 + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; 5163 + esac 5164 + ;; 5165 + esac 5166 + 5167 + ac_dir=`$as_dirname -- "$ac_file" || 5168 + $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ 5169 + X"$ac_file" : 'X\(//\)[^/]' \| \ 5170 + X"$ac_file" : 'X\(//\)$' \| \ 5171 + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || 5172 + printf "%s\n" X"$ac_file" | 5173 + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ 5174 + s//\1/ 5175 + q 5176 + } 5177 + /^X\(\/\/\)[^/].*/{ 5178 + s//\1/ 5179 + q 5180 + } 5181 + /^X\(\/\/\)$/{ 5182 + s//\1/ 5183 + q 5184 + } 5185 + /^X\(\/\).*/{ 5186 + s//\1/ 5187 + q 5188 + } 5189 + s/.*/./; q'` 5190 + as_dir="$ac_dir"; as_fn_mkdir_p 5191 + ac_builddir=. 5192 + 5193 + case "$ac_dir" in 5194 + .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; 5195 + *) 5196 + ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` 5197 + # A ".." for each directory in $ac_dir_suffix. 5198 + ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` 5199 + case $ac_top_builddir_sub in 5200 + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; 5201 + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; 5202 + esac ;; 5203 + esac 5204 + ac_abs_top_builddir=$ac_pwd 5205 + ac_abs_builddir=$ac_pwd$ac_dir_suffix 5206 + # for backward compatibility: 5207 + ac_top_builddir=$ac_top_build_prefix 5208 + 5209 + case $srcdir in 5210 + .) # We are building in place. 5211 + ac_srcdir=. 5212 + ac_top_srcdir=$ac_top_builddir_sub 5213 + ac_abs_top_srcdir=$ac_pwd ;; 5214 + [\\/]* | ?:[\\/]* ) # Absolute name. 5215 + ac_srcdir=$srcdir$ac_dir_suffix; 5216 + ac_top_srcdir=$srcdir 5217 + ac_abs_top_srcdir=$srcdir ;; 5218 + *) # Relative name. 5219 + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix 5220 + ac_top_srcdir=$ac_top_build_prefix$srcdir 5221 + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; 5222 + esac 5223 + ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix 5224 + 5225 + 5226 + case $ac_mode in 5227 + :F) 5228 + # 5229 + # CONFIG_FILE 5230 + # 5231 + 5232 + _ACEOF 5233 + 5234 + cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 5235 + # If the template does not know about datarootdir, expand it. 5236 + # FIXME: This hack should be removed a few years after 2.60. 5237 + ac_datarootdir_hack=; ac_datarootdir_seen= 5238 + ac_sed_dataroot=' 5239 + /datarootdir/ { 5240 + p 5241 + q 5242 + } 5243 + /@datadir@/p 5244 + /@docdir@/p 5245 + /@infodir@/p 5246 + /@localedir@/p 5247 + /@mandir@/p' 5248 + case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in 5249 + *datarootdir*) ac_datarootdir_seen=yes;; 5250 + *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) 5251 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 5252 + printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} 5253 + _ACEOF 5254 + cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 5255 + ac_datarootdir_hack=' 5256 + s&@datadir@&$datadir&g 5257 + s&@docdir@&$docdir&g 5258 + s&@infodir@&$infodir&g 5259 + s&@localedir@&$localedir&g 5260 + s&@mandir@&$mandir&g 5261 + s&\\\${datarootdir}&$datarootdir&g' ;; 5262 + esac 5263 + _ACEOF 5264 + 5265 + # Neutralize VPATH when `$srcdir' = `.'. 5266 + # Shell code in configure.ac might set extrasub. 5267 + # FIXME: do we really want to maintain this feature? 5268 + cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 5269 + ac_sed_extra="$ac_vpsub 5270 + $extrasub 5271 + _ACEOF 5272 + cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 5273 + :t 5274 + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b 5275 + s|@configure_input@|$ac_sed_conf_input|;t t 5276 + s&@top_builddir@&$ac_top_builddir_sub&;t t 5277 + s&@top_build_prefix@&$ac_top_build_prefix&;t t 5278 + s&@srcdir@&$ac_srcdir&;t t 5279 + s&@abs_srcdir@&$ac_abs_srcdir&;t t 5280 + s&@top_srcdir@&$ac_top_srcdir&;t t 5281 + s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t 5282 + s&@builddir@&$ac_builddir&;t t 5283 + s&@abs_builddir@&$ac_abs_builddir&;t t 5284 + s&@abs_top_builddir@&$ac_abs_top_builddir&;t t 5285 + $ac_datarootdir_hack 5286 + " 5287 + eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ 5288 + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 5289 + 5290 + test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && 5291 + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && 5292 + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ 5293 + "$ac_tmp/out"`; test -z "$ac_out"; } && 5294 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' 5295 + which seems to be undefined. Please make sure it is defined" >&5 5296 + printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' 5297 + which seems to be undefined. Please make sure it is defined" >&2;} 5298 + 5299 + rm -f "$ac_tmp/stdin" 5300 + case $ac_file in 5301 + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; 5302 + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; 5303 + esac \ 5304 + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 5305 + ;; 5306 + :H) 5307 + # 5308 + # CONFIG_HEADER 5309 + # 5310 + if test x"$ac_file" != x-; then 5311 + { 5312 + printf "%s\n" "/* $configure_input */" >&1 \ 5313 + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" 5314 + } >"$ac_tmp/config.h" \ 5315 + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 5316 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then 5317 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 5318 + printf "%s\n" "$as_me: $ac_file is unchanged" >&6;} 5319 + else 5320 + rm -f "$ac_file" 5321 + mv "$ac_tmp/config.h" "$ac_file" \ 5322 + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 5323 + fi 5324 + else 5325 + printf "%s\n" "/* $configure_input */" >&1 \ 5326 + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ 5327 + || as_fn_error $? "could not create -" "$LINENO" 5 5328 + fi 5329 + ;; 5330 + 5331 + 5332 + esac 5333 + 5334 + done # for ac_tag 5335 + 5336 + 5337 + as_fn_exit 0 5338 + _ACEOF 5339 + ac_clean_files=$ac_clean_files_save 5340 + 5341 + test $ac_write_fail = 0 || 5342 + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 5343 + 5344 + 5345 + # configure is writing to config.log, and then calls config.status. 5346 + # config.status does its own redirection, appending to config.log. 5347 + # Unfortunately, on DOS this fails, as config.log is still kept open 5348 + # by configure, so config.status won't be able to write to it; its 5349 + # output is simply discarded. So we exec the FD to /dev/null, 5350 + # effectively closing config.log, so it can be properly (re)opened and 5351 + # appended to by config.status. When coming back to configure, we 5352 + # need to make the FD available again. 5353 + if test "$no_create" != yes; then 5354 + ac_cs_success=: 5355 + ac_config_status_args= 5356 + test "$silent" = yes && 5357 + ac_config_status_args="$ac_config_status_args --quiet" 5358 + exec 5>/dev/null 5359 + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false 5360 + exec 5>>config.log 5361 + # Use ||, not &&, to avoid exiting from the if with $? = 1, which 5362 + # would make configure fail if this is the last instruction. 5363 + $ac_cs_success || as_fn_exit 1 5364 + fi 5365 + if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then 5366 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 5367 + printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} 5368 + fi 5369 + 5370 +
+146
usr.sbin/nsd/simdzone/configure.ac
··· 1 + # 2 + # configure.ac -- Autoconf script for simdzone 3 + # 4 + # Copyright (c) 2022-2023, NLnet Labs. All rights reserved. 5 + # 6 + # SPDX-License-Identifier: BSD-3-Clause 7 + # 8 + 9 + # This file is intended for inclusion by configure.ac in NSD. Support for any 10 + # platform not supported by NSD here is undesirable. Builds for standalone use 11 + # or development/testing are required to use CMake. 12 + 13 + AC_INIT([simdzone],[0.2.0],[https://github.com/NLnetLabs/simdzone/issues]) 14 + 15 + AC_CONFIG_HEADERS([config.h]) 16 + AC_CONFIG_FILES([Makefile]) 17 + 18 + m4_include(m4/ax_check_compile_flag.m4) 19 + m4_version_prereq([2.70], [AC_PROG_CC], [AC_PROG_CC_STDC]) 20 + 21 + AC_CHECK_HEADERS([endian.h sys/endian.h],,, [AC_INCLUDES_DEFAULT]) 22 + AC_CHECK_DECLS([bswap16,bswap32,bswap64], [], [], [ 23 + AC_INCLUDES_DEFAULT 24 + #ifdef HAVE_ENDIAN_H 25 + #include <endian.h> 26 + #endif 27 + #ifdef HAVE_SYS_ENDIAN_H 28 + #include <sys/endian.h> 29 + #endif 30 + ]) 31 + 32 + AC_ARG_ENABLE(westmere, AS_HELP_STRING([--disable-westmere],[Disable Westmere (SSE4.2) kernel])) 33 + case "$enable_westmere" in 34 + no) enable_westmere=no ;; 35 + yes|*) enable_westmere=yes ;; 36 + esac 37 + 38 + AC_ARG_ENABLE(haswell, AS_HELP_STRING([--disable-haswell],[Disable Haswell (AVX2) kernel])) 39 + case "$enable_haswell" in 40 + no) enable_haswell=no ;; 41 + yes|*) enable_haswell=yes ;; 42 + esac 43 + 44 + # GCC and Clang 45 + AX_CHECK_COMPILE_FLAG([-MMD],DEPFLAGS="-MMD -MP") 46 + # Oracle Developer Studio (no -MP) 47 + AX_CHECK_COMPILE_FLAG([-xMMD],DEPFLAGS="-xMMD") 48 + 49 + AC_SUBST([DEPFLAGS]) 50 + 51 + # Figure out the canonical target architecture. 52 + AC_CANONICAL_TARGET 53 + 54 + # Multiple instruction sets may be supported by a specific architecture. 55 + # e.g. x86_64 may (or may not) support any of SSE42, AVX2 and AVX-512. The 56 + # best instruction set is automatically selected at runtime, but the compiler 57 + # may or may not support generating code for an instruction set. 58 + case "$target" in 59 + *amd64*) x86_64=yes ;; 60 + *x86_64*) x86_64=yes ;; 61 + *) x86_64=no ;; 62 + esac 63 + 64 + HAVE_WESTMERE=NO 65 + HAVE_HASWELL=NO 66 + 67 + if test $x86_64 = "yes"; then 68 + AC_CHECK_HEADER(immintrin.h,,,) 69 + AX_CHECK_COMPILE_FLAG([-march=westmere],,,[-Werror]) 70 + AX_CHECK_COMPILE_FLAG([-march=haswell],,,[-Werror]) 71 + 72 + # Check if the arch instruction set support includes the simd instructions. 73 + if test $enable_westmere != "no" -a \ 74 + $ax_cv_check_cflags__Werror__march_westmere = "yes" -a \ 75 + $ac_cv_header_immintrin_h = "yes" ; then 76 + AC_MSG_CHECKING(whether -march=westmere works) 77 + BAKCFLAGS="$CFLAGS" 78 + CFLAGS="-march=westmere $CFLAGS" 79 + AC_COMPILE_IFELSE([AC_LANG_SOURCE([ 80 + AC_INCLUDES_DEFAULT 81 + [ 82 + #include <stdint.h> 83 + #include <immintrin.h> 84 + 85 + int main(int argc, char *argv[]) 86 + { 87 + (void)argv; 88 + uint64_t popcnt = _mm_popcnt_u64((uint64_t)argc); 89 + return popcnt == 11; 90 + } 91 + ]]) 92 + ],[ 93 + AC_DEFINE(HAVE_WESTMERE, 1, [Wether or not to compile support for SSE4.2]) 94 + HAVE_WESTMERE=WESTMERE 95 + AC_MSG_RESULT(yes) 96 + ],[ 97 + AC_MSG_RESULT(no) 98 + ]) 99 + CFLAGS="$BAKCFLAGS" 100 + fi 101 + 102 + if test $enable_haswell != "no" -a \ 103 + $ax_cv_check_cflags__Werror__march_haswell = "yes" -a \ 104 + $ac_cv_header_immintrin_h = "yes" ; then 105 + AC_MSG_CHECKING(whether -march=haswell works) 106 + BAKCFLAGS="$CFLAGS" 107 + CFLAGS="-march=haswell $CFLAGS" 108 + AC_COMPILE_IFELSE([AC_LANG_SOURCE([ 109 + AC_INCLUDES_DEFAULT 110 + [ 111 + #include <stdint.h> 112 + #include <immintrin.h> 113 + 114 + int main(int argc, char *argv[]) 115 + { 116 + (void)argv; 117 + int argc32x8[8] = { argc, 0, 0, 0, 0, 0, 0, 0 }; 118 + __m256i argc256 = _mm256_loadu_si256((__m256i *)argc32x8); 119 + return _mm256_testz_si256(argc256, _mm256_set1_epi8(11)); 120 + } 121 + ]]) 122 + ],[ 123 + AC_DEFINE(HAVE_HASWELL, 1, [Wether or not to compile support for AVX2]) 124 + HAVE_HASWELL=HASWELL 125 + AC_MSG_RESULT(yes) 126 + ],[ 127 + AC_MSG_RESULT(no) 128 + ]) 129 + CFLAGS="$BAKCFLAGS" 130 + fi 131 + fi 132 + 133 + AC_CHECK_FUNCS([realpath],,[AC_MSG_ERROR([realpath is not available])]) 134 + 135 + AC_SUBST([HAVE_ENDIAN_H]) 136 + AC_SUBST([HAVE_WESTMERE]) 137 + AC_SUBST([HAVE_HASWELL]) 138 + 139 + AH_BOTTOM([ 140 + /* Defines _XOPEN_SOURCE and _POSIX_C_SOURCE implicitly in features.h */ 141 + #ifndef _DEFAULT_SOURCE 142 + # define _DEFAULT_SOURCE 1 143 + #endif 144 + ]) 145 + 146 + AC_OUTPUT
+658
usr.sbin/nsd/simdzone/include/zone.h
··· 1 + /* 2 + * zone.h -- (DNS) presentation format parser 3 + * 4 + * Copyright (c) 2022-2024, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef ZONE_H 10 + #define ZONE_H 11 + 12 + /** 13 + * @file 14 + * @brief simdzone main header 15 + */ 16 + 17 + #include <stdarg.h> 18 + #include <stdint.h> 19 + #include <stdbool.h> 20 + #include <stdio.h> 21 + #include <stddef.h> 22 + 23 + #include "zone/attributes.h" 24 + #include "zone/export.h" 25 + 26 + #if defined (__cplusplus) 27 + extern "C" { 28 + #endif 29 + 30 + /** 31 + * @defgroup class_codes Class codes 32 + * 33 + * Supported CLASSes. 34 + * 35 + * See @iana{DNS CLASSes,dns-parameters,dns-parameters-2} for a list of 36 + * classes registered by IANA. 37 + * 38 + * @{ 39 + */ 40 + /** Internet @rfc{1035} */ 41 + #define ZONE_CLASS_IN (1u) 42 + /** CSNET @rfc{1035} @obsolete */ 43 + #define ZONE_CLASS_CS (2u) 44 + /** CHAOS @rfc{1035} */ 45 + #define ZONE_CLASS_CH (3u) 46 + /** Hesiod @rfc{1035} */ 47 + #define ZONE_CLASS_HS (4u) 48 + /** Any (QCLASS) @rfc{1035} */ 49 + #define ZONE_CLASS_ANY (255u) 50 + /** @} */ 51 + 52 + /** 53 + * @defgroup type_codes Type codes 54 + * 55 + * Supported resource record (RR) TYPEs. 56 + * 57 + * See @iana{RR TYPEs,dns-parameters,dns-parameters-4} for a list of 58 + * types registered by IANA. 59 + * 60 + * @{ 61 + */ 62 + /** Host address @rfc{1035} */ 63 + #define ZONE_TYPE_A (1u) 64 + /** Authoritative name server @rfc{1035} */ 65 + #define ZONE_TYPE_NS (2u) 66 + /** Mail destination @rfc{1035} @obsolete */ 67 + #define ZONE_TYPE_MD (3u) 68 + /** Mail forwarder @rfc{1035} @obsolete */ 69 + #define ZONE_TYPE_MF (4u) 70 + /** Canonical name for an alias @rfc{1035} */ 71 + #define ZONE_TYPE_CNAME (5u) 72 + /** Marks the start of authority @rfc{1035} */ 73 + #define ZONE_TYPE_SOA (6u) 74 + /** Mailbox domain name @rfc{1035} @experimental */ 75 + #define ZONE_TYPE_MB (7u) 76 + /** Mail group member @rfc{1035} @experimental */ 77 + #define ZONE_TYPE_MG (8u) 78 + /** Mail rename domain name @rfc{1035} @experimental */ 79 + #define ZONE_TYPE_MR (9u) 80 + /** Anything @rfc{883} @obsolete */ 81 + #define ZONE_TYPE_NULL (10u) 82 + /** Well known service description @rfc{1035} */ 83 + #define ZONE_TYPE_WKS (11u) 84 + /** Domain name pointer @rfc{1035} */ 85 + #define ZONE_TYPE_PTR (12u) 86 + /** Host information @rfc{1035} */ 87 + #define ZONE_TYPE_HINFO (13u) 88 + /** Mailbox or mail list information @rfc{1035} */ 89 + #define ZONE_TYPE_MINFO (14u) 90 + /** Mail exchange @rfc{1035} */ 91 + #define ZONE_TYPE_MX (15u) 92 + /** Text strings @rfc{1035} */ 93 + #define ZONE_TYPE_TXT (16u) 94 + /** Responsible person @rfc{1035} */ 95 + #define ZONE_TYPE_RP (17u) 96 + /** AFS Data Base location @rfc{1183} @rfc{5864} */ 97 + #define ZONE_TYPE_AFSDB (18u) 98 + /** X.25 PSDN address @rfc{1183} */ 99 + #define ZONE_TYPE_X25 (19u) 100 + /** ISDN address @rfc{1183} */ 101 + #define ZONE_TYPE_ISDN (20u) 102 + /** Route Through @rfc{1183} */ 103 + #define ZONE_TYPE_RT (21u) 104 + /** NSAP address, NSAP style A record @rfc{1706} */ 105 + #define ZONE_TYPE_NSAP (22u) 106 + /** Domain name pointer, NSAP style @rfc{1348} @rfc{1637} */ 107 + #define ZONE_TYPE_NSAP_PTR (23u) 108 + /** Signature @rfc{2535} */ 109 + #define ZONE_TYPE_SIG (24u) 110 + /** Public key @rfc{2535} @rfc{2930} */ 111 + #define ZONE_TYPE_KEY (25u) 112 + /** X.400 mail mapping information @rfc{2163} */ 113 + #define ZONE_TYPE_PX (26u) 114 + /** Geographical Position @rfc{1712} */ 115 + #define ZONE_TYPE_GPOS (27u) 116 + /** IPv6 Address @rfc{3596} */ 117 + #define ZONE_TYPE_AAAA (28u) 118 + /** Location Information @rfc{1876} */ 119 + #define ZONE_TYPE_LOC (29u) 120 + /** Next domain @rfc{3755} @rfc{2535} @obsolete */ 121 + #define ZONE_TYPE_NXT (30u) 122 + /** Server Selection @rfc{2782} */ 123 + #define ZONE_TYPE_SRV (33u) 124 + /** Naming Authority Pointer @rfc{2915} @rfc{2168} @rfc{3403} */ 125 + #define ZONE_TYPE_NAPTR (35u) 126 + /** Key Exchanger @rfc{2230} */ 127 + #define ZONE_TYPE_KX (36u) 128 + /** CERT @rfc{4398}*/ 129 + #define ZONE_TYPE_CERT (37u) 130 + /** IPv6 Address @rfc{3226} @rfc{2874} @rfc{6563} @obsolete */ 131 + #define ZONE_TYPE_A6 (38u) 132 + /** DNAME @rfc{6672} */ 133 + #define ZONE_TYPE_DNAME (39u) 134 + /** Address Prefix List @rfc{3123} */ 135 + #define ZONE_TYPE_APL (42u) 136 + /** Delegation Signer @rfc{4034} @rfc{3658} */ 137 + #define ZONE_TYPE_DS (43u) 138 + /** SSH Key Fingerprint @rfc{4255} */ 139 + #define ZONE_TYPE_SSHFP (44u) 140 + /** IPsec public key @rfc{4025} */ 141 + #define ZONE_TYPE_IPSECKEY (45u) 142 + /** Resource Record Signature @rfc{4034} @rfc{3755} */ 143 + #define ZONE_TYPE_RRSIG (46u) 144 + /** Next Secure @rfc{4034} @rfc{3755} */ 145 + #define ZONE_TYPE_NSEC (47u) 146 + /** DNS Public Key @rfc{4034} @rfc{3755} */ 147 + #define ZONE_TYPE_DNSKEY (48u) 148 + /** DHCID @rfc{4701} */ 149 + #define ZONE_TYPE_DHCID (49u) 150 + /** NSEC3 @rfc{5155} */ 151 + #define ZONE_TYPE_NSEC3 (50u) 152 + /** NSEC3PARAM @rfc{5155} */ 153 + #define ZONE_TYPE_NSEC3PARAM (51u) 154 + /** TLSA @rfc{6698} */ 155 + #define ZONE_TYPE_TLSA (52u) 156 + /** S/MIME cert association @rfc{8162} */ 157 + #define ZONE_TYPE_SMIMEA (53u) 158 + /** Host Identity Protocol @rfc{8005} */ 159 + #define ZONE_TYPE_HIP (55u) 160 + /** NINFO */ 161 + #define ZONE_TYPE_NINFO (56u) 162 + /** RKEY */ 163 + #define ZONE_TYPE_RKEY (57u) 164 + /** Child DS @rfc{7344} */ 165 + #define ZONE_TYPE_CDS (59u) 166 + /** DNSKEY(s) the Child wants reflected in DS @rfc{7344} */ 167 + #define ZONE_TYPE_CDNSKEY (60u) 168 + /** OpenPGP Key @rfc{7929} */ 169 + #define ZONE_TYPE_OPENPGPKEY (61u) 170 + /** Child-To-Parent Synchronization @rfc{7477} */ 171 + #define ZONE_TYPE_CSYNC (62u) 172 + /** Zone message digest @rfc{8976} */ 173 + #define ZONE_TYPE_ZONEMD (63u) 174 + /** Service binding @rfc{9460} */ 175 + #define ZONE_TYPE_SVCB (64u) 176 + /** Service binding @rfc{9460} */ 177 + #define ZONE_TYPE_HTTPS (65u) 178 + /** Sender Policy Framework @rfc{7208} */ 179 + #define ZONE_TYPE_SPF (99u) 180 + /** Node Identifier @rfc{6742} */ 181 + #define ZONE_TYPE_NID (104u) 182 + /** 32-bit Locator for ILNPv4-capable nodes @rfc{6742} */ 183 + #define ZONE_TYPE_L32 (105u) 184 + /** 64-bit Locator for ILNPv6-capable nodes @rfc{6742} */ 185 + #define ZONE_TYPE_L64 (106u) 186 + /** Name of an ILNP subnetwork @rfc{6742} */ 187 + #define ZONE_TYPE_LP (107u) 188 + /** EUI-48 address @rfc{7043} */ 189 + #define ZONE_TYPE_EUI48 (108u) 190 + /** EUI-64 address @rfc{7043} */ 191 + #define ZONE_TYPE_EUI64 (109u) 192 + /** Uniform Resource Identifier @rfc{7553} */ 193 + #define ZONE_TYPE_URI (256u) 194 + /** Certification Authority Restriction @rfc{6844} */ 195 + #define ZONE_TYPE_CAA (257u) 196 + /** DNS Authoritative Source (DNS-AS) */ 197 + #define ZONE_TYPE_AVC (258u) 198 + /** Resolver Information as Key/Value Pairs @rfc{9606} */ 199 + #define ZONE_TYPE_RESINFO (261u) 200 + /** Public wallet address */ 201 + #define ZONE_TYPE_WALLET (262u) 202 + /** BP Convergence Layer Adapter */ 203 + #define ZONE_TYPE_CLA (263u) 204 + /** DNSSEC Trust Authorities */ 205 + #define ZONE_TYPE_TA (32768u) 206 + /** DNSSEC Lookaside Validation @rfc{4431} @obsolete */ 207 + #define ZONE_TYPE_DLV (32769u) 208 + /** @} */ 209 + 210 + /** 211 + * @defgroup svc_params Service Parameter Keys 212 + * 213 + * Supported service parameters. 214 + * 215 + * See @iana{Service Parameter Keys (SvcParamKeys),dns-svcb,dns-svcparamkeys} 216 + * for a list of service parameter keys registered by IANA. 217 + * 218 + * @{ 219 + */ 220 + /** Parameters clients must not ignore @rfc{9460} */ 221 + #define ZONE_SVC_PARAM_KEY_MANDATORY (0u) 222 + /** Application Layer Protocol Negotiation (ALPN) protocol identifiers @rfc{9460} */ 223 + #define ZONE_SVC_PARAM_KEY_ALPN (1u) 224 + /** No support for default protocol (alpn must be specified) @rfc{9460} */ 225 + #define ZONE_SVC_PARAM_KEY_NO_DEFAULT_ALPN (2u) 226 + /** TCP or UDP port for alternative endpoint @rfc{9460} */ 227 + #define ZONE_SVC_PARAM_KEY_PORT (3u) 228 + /** IPv4 address hints @rfc{9460} */ 229 + #define ZONE_SVC_PARAM_KEY_IPV4HINT (4u) 230 + /** Encrypted ClientHello (ECH) configuration @draft{ietf, tls-svcb-ech} */ 231 + #define ZONE_SVC_PARAM_KEY_ECH (5u) 232 + /** IPv6 address hints @rfc{9460} */ 233 + #define ZONE_SVC_PARAM_KEY_IPV6HINT (6u) 234 + /** URI template in relative form @rfc{9461} */ 235 + #define ZONE_SVC_PARAM_KEY_DOHPATH (7u) 236 + /** Target is an Oblivious HTTP service @rfc{9540} */ 237 + #define ZONE_SVC_PARAM_KEY_OHTTP (8u) 238 + /** Supported groups in TLS @draft{ietf, tls-key-share-prediction} */ 239 + #define ZONE_SVC_PARAM_KEY_TLS_SUPPORTED_GROUPS (9u) 240 + /** Reserved ("invalid key") @rfc{9460} */ 241 + #define ZONE_SVC_PARAM_KEY_INVALID_KEY (65535u) 242 + /** @} */ 243 + 244 + /** 245 + * Number of bytes per block. 246 + * 247 + * Higher throughput is achieved by block-based operation. The size of a 248 + * block is determined by the word size of the CPU. To avoid pipeline flushes 249 + * as much as possible buffers are required to be padded by the number of 250 + * bytes in a single block. 251 + * 252 + * @warning The input buffer to @zone_parse_string is required to be 253 + * null-terminated and padded, which is somewhat counter intuitive. A 254 + * future release may lift this requirement (@issue{174}). 255 + */ 256 + #define ZONE_BLOCK_SIZE (64) 257 + 258 + /** 259 + * Number of blocks per window. 260 + * 261 + * Master files can become quite large and are read in multiples of blocks. 262 + * The input buffer is expanded as needed. 263 + */ 264 + #define ZONE_WINDOW_SIZE (256 * ZONE_BLOCK_SIZE) // 16KB 265 + 266 + /** Maximum size of domain name. */ 267 + #define ZONE_NAME_SIZE (255) 268 + 269 + typedef struct zone_name_buffer zone_name_buffer_t; 270 + struct zone_name_buffer { 271 + /** Length of domain name stored in buffer. */ 272 + size_t length; 273 + /** Maximum number of octets in a domain name plus padding. */ 274 + uint8_t octets[ ZONE_NAME_SIZE + ZONE_BLOCK_SIZE ]; 275 + }; 276 + 277 + /** Maximum size of RDATA section. */ 278 + #define ZONE_RDATA_SIZE (65535) 279 + 280 + typedef struct zone_rdata_buffer zone_rdata_buffer_t; 281 + struct zone_rdata_buffer { 282 + /** Maximum number of octets in RDATA section plus padding. */ 283 + uint8_t octets[ ZONE_RDATA_SIZE + ZONE_BLOCK_SIZE ]; 284 + }; 285 + 286 + /** 287 + * @brief Tape capacity per-file. 288 + * 289 + * Tape capacity must be sufficiently large to hold every token from a single 290 + * worst-case read (e.g. 64 consecutive line feeds). Not likely to occur in 291 + * practice, therefore, to optimize throughput, allocate at least twice the 292 + * size so consecutive index operations can be performed. 293 + */ 294 + #define ZONE_TAPE_SIZE ((100 * ZONE_BLOCK_SIZE) + ZONE_BLOCK_SIZE) 295 + 296 + typedef struct zone_file zone_file_t; 297 + struct zone_file { 298 + /** @private */ 299 + zone_file_t *includer; 300 + /** @private */ 301 + zone_name_buffer_t origin, owner; 302 + /** @private */ 303 + uint16_t last_type; 304 + /** Last stated TTL. */ 305 + uint32_t last_ttl; 306 + /** Last parsed TTL in $TTL entry. */ 307 + uint32_t dollar_ttl; 308 + /** TTL passed to accept callback. */ 309 + uint32_t *ttl; 310 + /** Default TTL passed to accept. */ 311 + /** Last stated TTL is used as default unless $TTL entry was found. */ 312 + uint32_t *default_ttl; 313 + /** @private */ 314 + uint16_t last_class; 315 + /** Number of lines spanned by RR. */ 316 + /** Non-terminating line feeds, i.e. escaped line feeds, line feeds in 317 + quoted sections or within parentheses, are counted, but deferred for 318 + consistency in error reports */ 319 + size_t span; 320 + /** Starting line of RR. */ 321 + size_t line; 322 + /** Filename in control directive. */ 323 + char *name; 324 + /** Absolute path. */ 325 + char *path; 326 + /** @private */ 327 + FILE *handle; 328 + /** @private */ 329 + bool grouped; 330 + /** @private */ 331 + bool start_of_line; 332 + /** @private */ 333 + uint8_t end_of_file; 334 + /** @private */ 335 + struct { 336 + size_t index, length, size; 337 + char *data; 338 + } buffer; 339 + /** @private */ 340 + /** scanner state is kept per-file */ 341 + struct { 342 + uint64_t in_comment; 343 + uint64_t in_quoted; 344 + uint64_t is_escaped; 345 + uint64_t follows_contiguous; 346 + } state; 347 + /** @private */ 348 + /** vector of tokens generated by the scanner guaranteed to be large 349 + enough to hold every token for a single read + terminators */ 350 + struct { const char **head, **tail, *tape[ZONE_TAPE_SIZE + 2]; } fields; 351 + struct { const char **head, **tail, *tape[ZONE_TAPE_SIZE + 1]; } delimiters; 352 + struct { uint16_t *head, *tail, tape[ZONE_TAPE_SIZE + 1]; } newlines; 353 + }; 354 + 355 + typedef struct zone_parser zone_parser_t; 356 + struct zone_parser; 357 + 358 + /** 359 + * @brief Signature of callback function that is invoked for log messages. 360 + * 361 + * By default messages are printed to stdout (info) and stderr (warnings, 362 + * errors). A custom log handler (callback) may be provided for better 363 + * integration of reporting. 364 + * 365 + * @note file maybe NULL if initial file does not exist. 366 + */ 367 + typedef void(*zone_log_t)( 368 + zone_parser_t *, 369 + uint32_t, // priority 370 + const char *, // file 371 + size_t, // line 372 + const char *, // message 373 + void *); // user data 374 + 375 + /** 376 + * @brief Domain name and corresponding length in wire format. 377 + */ 378 + typedef struct zone_name zone_name_t; 379 + struct zone_name { 380 + /** Length of domain name. */ 381 + uint8_t length; 382 + /** Absolute, uncompressed, domain name in wire format. */ 383 + const uint8_t *octets; 384 + }; 385 + 386 + /** 387 + * @brief Signature of callback function invoked for each RR. 388 + * 389 + * Header is in host order, RDATA section is in network order. 390 + */ 391 + typedef int32_t(*zone_accept_t)( 392 + zone_parser_t *, 393 + const zone_name_t *, // owner (length + octets) 394 + uint16_t, // type 395 + uint16_t, // class 396 + uint32_t, // ttl 397 + uint16_t, // rdlength 398 + const uint8_t *, // rdata 399 + void *); // user data 400 + 401 + /** 402 + * @brief Signature of callback function invoked on $INCLUDE. 403 + * 404 + * Signal file name in $INCLUDE directive to application. Useful for 405 + * dependency tracking, etc. 406 + */ 407 + typedef int32_t(*zone_include_t)( 408 + zone_parser_t *, 409 + const char *, // name in $INCLUDE entry 410 + const char *, // fully qualified path 411 + void *); // user data 412 + 413 + /** 414 + * @brief Available configuration options. 415 + */ 416 + typedef struct { 417 + /** Non-strict mode of operation. */ 418 + /** Authoritative servers may choose to be more lenient when operating as 419 + a secondary as data may have been transferred over AXFR/IXFR that 420 + would have triggered an error otherwise. */ 421 + bool secondary; 422 + /** Disable $INCLUDE directive. */ 423 + /** Useful in setups where untrusted input may be offered. */ 424 + bool no_includes; 425 + /** Maximum $INCLUDE depth. 0 for default. */ 426 + uint32_t include_limit; 427 + /** Enable 1h2m3s notations for TTLS. */ 428 + bool pretty_ttls; 429 + /** Origin in wire format. */ 430 + zone_name_t origin; 431 + /** Default TTL to use. */ 432 + uint32_t default_ttl; 433 + /** Default CLASS to use. */ 434 + uint16_t default_class; 435 + struct { 436 + /** Priorities NOT to write out. */ 437 + uint32_t mask; 438 + /** Callback invoked to write out log messages. */ 439 + zone_log_t callback; 440 + } log; 441 + struct { 442 + /** Callback invoked for each RR. */ 443 + zone_accept_t callback; 444 + } accept; 445 + struct { 446 + /** Callback invoked for each $INCLUDE entry. */ 447 + zone_include_t callback; 448 + } include; 449 + } zone_options_t; 450 + 451 + /** 452 + * @brief Scratch buffer space reserved for parser. 453 + * 454 + * @note Future versions may leverage multiple buffers to improve throughput 455 + * as parsing and committing resource records are disjunct operations. 456 + */ 457 + typedef struct zone_buffers zone_buffers_t; 458 + struct zone_buffers { 459 + /** Number of name and rdata buffers available. */ 460 + size_t size; 461 + /** Vector of name buffers to use as scratch buffer. */ 462 + zone_name_buffer_t *owner; 463 + /** Vector of rdata buffers to use as scratch buffer. */ 464 + zone_rdata_buffer_t *rdata; 465 + }; 466 + 467 + /** 468 + * @brief Parser state. 469 + * @warning Do not modify directly. 470 + */ 471 + struct zone_parser { 472 + /** @private */ 473 + zone_options_t options; 474 + /** @private */ 475 + void *user_data; 476 + struct { 477 + size_t size; 478 + struct { 479 + size_t active; 480 + zone_name_buffer_t *blocks; 481 + } owner; 482 + struct { 483 + size_t active; 484 + zone_rdata_buffer_t *blocks; 485 + } rdata; 486 + } buffers; 487 + /** @private */ 488 + zone_name_buffer_t *owner; 489 + /** @private */ 490 + zone_rdata_buffer_t *rdata; 491 + /** @private */ 492 + zone_file_t *file, first; 493 + }; 494 + 495 + /** 496 + * @defgroup return_codes Return codes 497 + * 498 + * @{ 499 + */ 500 + /** Success. */ 501 + #define ZONE_SUCCESS (0) 502 + /** A syntax error occurred. */ 503 + #define ZONE_SYNTAX_ERROR (-256) // (-1 << 8) 504 + /** A semantic error occurred. */ 505 + #define ZONE_SEMANTIC_ERROR (-512) // (-2 << 8) 506 + /** Operation failed due to lack of memory. */ 507 + #define ZONE_OUT_OF_MEMORY (-768) // (-3 << 8) 508 + /** Bad parameter value. */ 509 + #define ZONE_BAD_PARAMETER (-1024) // (-4 << 8) 510 + /** Error reading zone file. */ 511 + #define ZONE_READ_ERROR (-1280) // (-5 << 8) 512 + /** Control directive or support for record type is not implemented. */ 513 + #define ZONE_NOT_IMPLEMENTED (-1536) // (-6 << 8) 514 + /** Specified file does not exist. */ 515 + #define ZONE_NOT_A_FILE (-1792) // (-7 << 8) 516 + /** Access to specified file is not allowed. */ 517 + #define ZONE_NOT_PERMITTED (-2048) // (-8 << 8) 518 + /** @} */ 519 + 520 + /** 521 + * @brief Parse zone file 522 + * 523 + * Parse file containing resource records. 524 + * 525 + * @param[in] parser Zone parser 526 + * @param[in] options Settings used for parsing. 527 + * @param[in] buffers Scratch buffers used for parsing. 528 + * @param[in] path Path of master file to parse. 529 + * @param[in] user_data Pointer passed verbatim to callbacks. 530 + * 531 + * @returns @ref ZONE_SUCCESS on success or a negative number on error. 532 + */ 533 + ZONE_EXPORT int32_t 534 + zone_parse( 535 + zone_parser_t *parser, 536 + const zone_options_t *options, 537 + zone_buffers_t *buffers, 538 + const char *path, 539 + void *user_data) 540 + zone_nonnull((1,2,3,4)); 541 + 542 + /** 543 + * @brief Parse zone from string 544 + * 545 + * Parse string containing resource records in presentation format. 546 + * 547 + * @warning The input string must be null terminated and padded with at least 548 + * @ref ZONE_BLOCK_SIZE bytes. 549 + * 550 + * @param[in] parser Zone parser 551 + * @param[in] options Settings used for parsing. 552 + * @param[in] buffers Scratch buffers used by parsing. 553 + * @param[in] string Input string. 554 + * @param[in] length Length of string (excluding null byte and padding). 555 + * @param[in] user_data Pointer passed verbatim to callbacks. 556 + * 557 + * @returns @ref ZONE_SUCCESS on success or a negative number on error. 558 + */ 559 + ZONE_EXPORT int32_t 560 + zone_parse_string( 561 + zone_parser_t *parser, 562 + const zone_options_t *options, 563 + zone_buffers_t *buffers, 564 + const char *string, 565 + size_t length, 566 + void *user_data) 567 + zone_nonnull((1,2,3,4)); 568 + 569 + /** 570 + * @defgroup log_priorities Log categories. 571 + * 572 + * @note No direct relation between log categories and error codes exists. 573 + * Log categories communicate the importance of the log message, error 574 + * codes communicate what went wrong to the caller. 575 + * @{ 576 + */ 577 + /** Error condition. */ 578 + /** @hideinitializer */ 579 + #define ZONE_ERROR (1u<<1) 580 + /** Warning condition. */ 581 + /** @hideinitializer */ 582 + #define ZONE_WARNING (1u<<2) 583 + /** Informational message. */ 584 + /** @hideinitializer */ 585 + #define ZONE_INFO (1u<<3) 586 + /** @} */ 587 + 588 + /** 589 + * @brief Write message to active log handler. 590 + * 591 + * The zone parser operates on a per-record base and therefore cannot detect 592 + * errors that span records. e.g. SOA records being specified more than once. 593 + * The user may print a message using the active log handler, keeping the 594 + * error message format consistent. 595 + * 596 + * @param[in] parser Zone parser 597 + * @param[in] priority Log priority 598 + * @param[in] format Format string compatible with printf 599 + * @param[in] ... Variadic arguments corresponding to #format 600 + */ 601 + ZONE_EXPORT void zone_log( 602 + zone_parser_t *parser, 603 + uint32_t priority, 604 + const char *format, 605 + ...) 606 + zone_nonnull((1,3)) 607 + zone_format_printf(3,4); 608 + 609 + /** 610 + * @brief Write error message to active log handler. 611 + * @hideinitializer 612 + * 613 + * Shorthand to write out error message via @ref zone_log if error messages are 614 + * not to be discarded. 615 + * 616 + * @param[in] parser Zone parser 617 + * @param[in] format Format string 618 + * @param[in] ... Variadic arguments corresponding to #format 619 + */ 620 + #define zone_error(parser, ...) \ 621 + (((parser)->options.log.mask & ZONE_ERROR) ? \ 622 + (void)0 : zone_log((parser), ZONE_ERROR, __VA_ARGS__)) 623 + 624 + /** 625 + * @brief Write warning message to active log handler. 626 + * @hideinitializer 627 + * 628 + * Shorthand to write out warning message via @ref zone_log if warning messages 629 + * are not to be discarded. 630 + * 631 + * @param[in] parser Zone parser 632 + * @param[in] format Format string compatible with printf. 633 + * @param[in] ... Variadic arguments corresponding to @format. 634 + */ 635 + #define zone_warning(parser, ...) \ 636 + (((parser)->options.mask & ZONE_WARNING) ? \ 637 + (void)0 : zone_log((parser), ZONE_WARNING, __VA_ARGS__)) 638 + 639 + /** 640 + * @brief Write informational message to active log handler. 641 + * @hideinitializer 642 + * 643 + * Shorthand to write out informational message via @ref zone_log if 644 + * informational messages are not be discarded. 645 + * 646 + * @param[in] parser Zone parser. 647 + * @param[in] format Format string compatible with printf. 648 + * @param[in] ... Variadic arguments corresponding to @format. 649 + */ 650 + #define zone_info(parser, ...) \ 651 + (((parser)->options.mask & ZONE_INFO) ? \ 652 + (void)0 : zone_log((parser), ZONE_INFO, __VA_ARGS__)) 653 + 654 + #if defined(__cplusplus) 655 + } 656 + #endif 657 + 658 + #endif // ZONE_H
+52
usr.sbin/nsd/simdzone/include/zone/attributes.h
··· 1 + /* 2 + * attributes.h -- compiler attribute abstractions 3 + * 4 + * Copyright (c) 2022, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef ZONE_ATTRIBUTES_H 10 + #define ZONE_ATTRIBUTES_H 11 + 12 + #if defined __GNUC__ 13 + # define zone_has_gnuc(major, minor) \ 14 + ((__GNUC__ > major) || (__GNUC__ == major && __GNUC_MINOR__ >= minor)) 15 + #else 16 + # define zone_has_gnuc(major, minor) (0) 17 + #endif 18 + 19 + #if defined __has_attribute 20 + # define zone_has_attribute(params) __has_attribute(params) 21 + #else 22 + # define zone_has_attribute(params) (0) 23 + #endif 24 + 25 + #if zone_has_attribute(nonnull) 26 + # define zone_nonnull(params) __attribute__((__nonnull__ params)) 27 + # define zone_nonnull_all __attribute__((__nonnull__)) 28 + #else 29 + # define zone_nonnull(params) 30 + # define zone_nonnull_all 31 + #endif 32 + 33 + #if zone_has_attribute(format) || zone_has_gnuc(2, 4) 34 + # define zone_format(params) __attribute__((__format__ params)) 35 + # if __MINGW32__ 36 + # if __MINGW_PRINTF_FORMAT 37 + # define zone_format_printf(string_index, first_to_check) \ 38 + zone_format((__MINGW_PRINTF_FORMAT, string_index, first_to_check)) 39 + # else 40 + # define zone_format_printf(string_index, first_to_check) \ 41 + zone_format((gnu_printf, string_index, first_to_check)) 42 + # endif 43 + # else 44 + # define zone_format_printf(string_index, first_to_check) \ 45 + zone_format((printf, string_index, first_to_check)) 46 + # endif 47 + #else 48 + # define zone_format(params) 49 + # define zone_format_printf(string_index, first_to_check) 50 + #endif 51 + 52 + #endif // ZONE_ATTRIBUTES_H
+53
usr.sbin/nsd/simdzone/m4/ax_check_compile_flag.m4
··· 1 + # =========================================================================== 2 + # https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html 3 + # =========================================================================== 4 + # 5 + # SYNOPSIS 6 + # 7 + # AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) 8 + # 9 + # DESCRIPTION 10 + # 11 + # Check whether the given FLAG works with the current language's compiler 12 + # or gives an error. (Warnings, however, are ignored) 13 + # 14 + # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on 15 + # success/failure. 16 + # 17 + # If EXTRA-FLAGS is defined, it is added to the current language's default 18 + # flags (e.g. CFLAGS) when the check is done. The check is thus made with 19 + # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to 20 + # force the compiler to issue an error when a bad flag is given. 21 + # 22 + # INPUT gives an alternative input source to AC_COMPILE_IFELSE. 23 + # 24 + # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this 25 + # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. 26 + # 27 + # LICENSE 28 + # 29 + # Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de> 30 + # Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com> 31 + # 32 + # Copying and distribution of this file, with or without modification, are 33 + # permitted in any medium without royalty provided the copyright notice 34 + # and this notice are preserved. This file is offered as-is, without any 35 + # warranty. 36 + 37 + #serial 6 38 + 39 + AC_DEFUN([AX_CHECK_COMPILE_FLAG], 40 + [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF 41 + AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl 42 + AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ 43 + ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS 44 + _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" 45 + AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], 46 + [AS_VAR_SET(CACHEVAR,[yes])], 47 + [AS_VAR_SET(CACHEVAR,[no])]) 48 + _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) 49 + AS_VAR_IF(CACHEVAR,yes, 50 + [m4_default([$2], :)], 51 + [m4_default([$3], :)]) 52 + AS_VAR_POPDEF([CACHEVAR])dnl 53 + ])dnl AX_CHECK_COMPILE_FLAGS
+76
usr.sbin/nsd/simdzone/src/attributes.h
··· 1 + /* 2 + * attributes.h -- internal compiler attribute abstractions 3 + * 4 + * Copyright (c) 2023-2024, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #include "zone/attributes.h" 10 + 11 + #ifndef ATTRIBUTES_H 12 + #define ATTRIBUTES_H 13 + 14 + #define nonnull(params) zone_nonnull(params) 15 + #define nonnull_all zone_nonnull_all 16 + 17 + #if _MSC_VER 18 + # define really_inline __forceinline 19 + # define never_inline __declspec(noinline) 20 + # define warn_unused_result 21 + # define no_sanitize_undefined 22 + 23 + # define likely(params) (params) 24 + # define unlikely(params) (params) 25 + 26 + #else // _MSC_VER 27 + #if defined __has_builtin 28 + # define has_builtin(params) __has_builtin(params) 29 + #else 30 + # define has_builtin(params) (0) 31 + #endif 32 + 33 + # if (zone_has_attribute(always_inline) || zone_has_gnuc(3, 1)) && ! defined __NO_INLINE__ 34 + // Compilation using GCC 4.2.1 without optimizations fails. 35 + // sorry, unimplemented: inlining failed in call to ... 36 + // GCC 4.1.2 and GCC 4.30 compile forward declared functions annotated 37 + // with __attribute__((always_inline)) without problems. Test if 38 + // __NO_INLINE__ is defined and define macro accordingly. 39 + # define really_inline inline __attribute__((always_inline)) 40 + # else 41 + # define really_inline inline 42 + # endif 43 + 44 + # if zone_has_attribute(noinline) || zone_has_gnuc(2, 96) 45 + # define never_inline __attribute__((noinline)) 46 + # else 47 + # define never_inline 48 + # endif 49 + 50 + # if zone_has_attribute(warn_unused_result) 51 + # define warn_unused_result __attribute__((warn_unused_result)) 52 + # else 53 + # define warn_unused_result 54 + # endif 55 + 56 + # if zone_has_attribute(no_sanitize) 57 + // GCC 8.1 added the no_sanitize function attribute. 58 + # define no_sanitize_undefined __attribute__((no_sanitize("undefined"))) 59 + # elif zone_has_attribute(no_sanitize_undefined) 60 + // GCC 4.9.0 added the UndefinedBehaviorSanitizer (ubsan) and the 61 + // no_sanitize_undefined function attribute. 62 + # define no_sanitize_undefined 63 + # else 64 + # define no_sanitize_undefined 65 + # endif 66 + 67 + # if has_builtin(__builtin_expect) 68 + # define likely(params) __builtin_expect(!!(params), 1) 69 + # define unlikely(params) __builtin_expect(!!(params), 0) 70 + # else 71 + # define likely(params) (params) 72 + # define unlikely(params) (params) 73 + # endif 74 + #endif 75 + 76 + #endif // ATTRIBUTES_H
+236
usr.sbin/nsd/simdzone/src/bench.c
··· 1 + /* 2 + * bench.c -- simple scanner/parser benchmarking tool 3 + * 4 + * Copyright (c) 2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #include <assert.h> 10 + #include <stdio.h> 11 + #include <stdlib.h> 12 + #include <string.h> 13 + #if !defined(HAVE_GETOPT) 14 + # include "getopt.h" 15 + #else 16 + # include <unistd.h> 17 + #endif 18 + 19 + #include "zone.h" 20 + #include "config.h" 21 + #include "isadetection.h" 22 + #include "attributes.h" 23 + #include "diagnostic.h" 24 + 25 + #if _MSC_VER 26 + #define strcasecmp(s1, s2) _stricmp(s1, s2) 27 + #define strncasecmp(s1, s2, n) _strnicmp(s1, s2, n) 28 + #else 29 + #include <strings.h> 30 + #endif 31 + 32 + typedef zone_parser_t parser_t; 33 + 34 + #if HAVE_HASWELL 35 + extern int32_t zone_bench_haswell_lex(zone_parser_t *, size_t *); 36 + extern int32_t zone_haswell_parse(zone_parser_t *); 37 + #endif 38 + 39 + #if HAVE_WESTMERE 40 + extern int32_t zone_bench_westmere_lex(zone_parser_t *, size_t *); 41 + extern int32_t zone_westmere_parse(zone_parser_t *); 42 + #endif 43 + 44 + extern int32_t zone_bench_fallback_lex(zone_parser_t *, size_t *); 45 + extern int32_t zone_fallback_parse(zone_parser_t *); 46 + 47 + typedef struct kernel kernel_t; 48 + struct kernel { 49 + const char *name; 50 + uint32_t instruction_set; 51 + int32_t (*bench_lex)(zone_parser_t *, size_t *); 52 + int32_t (*parse)(zone_parser_t *); 53 + }; 54 + 55 + static const kernel_t kernels[] = { 56 + #if HAVE_HASWELL 57 + { "haswell", AVX2, &zone_bench_haswell_lex, &zone_haswell_parse }, 58 + #endif 59 + #if HAVE_WESTMERE 60 + { "westmere", SSE42|PCLMULQDQ, &zone_bench_westmere_lex, &zone_westmere_parse }, 61 + #endif 62 + { "fallback", DEFAULT, &zone_bench_fallback_lex, &zone_fallback_parse } 63 + }; 64 + 65 + extern int32_t zone_open( 66 + zone_parser_t *, 67 + const zone_options_t *, 68 + zone_buffers_t *, 69 + const char *, 70 + void *user_data); 71 + 72 + extern void zone_close( 73 + zone_parser_t *); 74 + 75 + static int32_t bench_lex(zone_parser_t *parser, const kernel_t *kernel) 76 + { 77 + size_t tokens = 0; 78 + int32_t result; 79 + 80 + if ((result = kernel->bench_lex(parser, &tokens)) < 0) 81 + return result; 82 + 83 + printf("Lexed %zu tokens\n", tokens); 84 + return 0; 85 + } 86 + 87 + static int32_t bench_accept( 88 + parser_t *parser, 89 + const zone_name_t *owner, 90 + uint16_t type, 91 + uint16_t class, 92 + uint32_t ttl, 93 + uint16_t rdlength, 94 + const uint8_t *rdata, 95 + void *user_data) 96 + { 97 + (void)parser; 98 + (void)owner; 99 + (void)type; 100 + (void)class; 101 + (void)ttl; 102 + (void)rdlength; 103 + (void)rdata; 104 + (*(size_t *)user_data)++; 105 + return ZONE_SUCCESS; 106 + } 107 + 108 + static int32_t bench_parse(zone_parser_t *parser, const kernel_t *kernel) 109 + { 110 + size_t records = 0; 111 + int32_t result; 112 + 113 + parser->user_data = &records; 114 + result = kernel->parse(parser); 115 + 116 + printf("Parsed %zu records\n", records); 117 + return result; 118 + } 119 + 120 + diagnostic_push() 121 + msvc_diagnostic_ignored(4996) 122 + 123 + static const kernel_t *select_kernel(const char *name) 124 + { 125 + const size_t n = sizeof(kernels)/sizeof(kernels[0]); 126 + const uint32_t supported = detect_supported_architectures(); 127 + const kernel_t *kernel = NULL; 128 + 129 + if ((!name || !*name) && !(name = getenv("ZONE_KERNEL"))) { 130 + for (size_t i=0; !kernel && i < n; i++) { 131 + if ((kernels[i].instruction_set & supported) == kernels[i].instruction_set) 132 + kernel = &kernels[i]; 133 + } 134 + assert(kernel != NULL); 135 + } else { 136 + for (size_t i=0; !kernel && i < n; i++) { 137 + if (strcasecmp(name, kernels[i].name) == 0) 138 + kernel = &kernels[i]; 139 + } 140 + 141 + if (!kernel || (kernel->instruction_set && !(kernel->instruction_set & supported))) { 142 + fprintf(stderr, "Target %s is unavailable\n", name); 143 + return NULL; 144 + } 145 + } 146 + 147 + printf("Selected target %s\n", kernel->name); 148 + return kernel; 149 + } 150 + 151 + diagnostic_pop() 152 + 153 + static void help(const char *program) 154 + { 155 + const char *format = 156 + "Usage: %s [OPTION] <lex or parse> <zone file>\n" 157 + "\n" 158 + "Options:\n" 159 + " -h Display available options.\n" 160 + " -t target Select target (default:%s)\n" 161 + "\n" 162 + "Kernels:\n"; 163 + 164 + printf(format, program, kernels[0].name); 165 + 166 + for (size_t i=0, n=sizeof(kernels)/sizeof(kernels[0]); i < n; i++) 167 + printf(" %s\n", kernels[i].name); 168 + } 169 + 170 + static void usage(const char *program) 171 + { 172 + fprintf(stderr, "Usage: %s [OPTION] <lex or parse> <zone file>\n", program); 173 + exit(EXIT_FAILURE); 174 + } 175 + 176 + static uint8_t root[] = { 0 }; 177 + 178 + int main(int argc, char *argv[]) 179 + { 180 + const char *name = NULL, *program = argv[0]; 181 + 182 + for (const char *slash = argv[0]; *slash; slash++) 183 + if (*slash == '/' || *slash == '\\') 184 + program = slash + 1; 185 + 186 + for (int option; (option = getopt(argc, argv, "ht:")) != -1;) { 187 + switch (option) { 188 + case 'h': 189 + help(program); 190 + exit(EXIT_SUCCESS); 191 + case 't': 192 + name = optarg; 193 + break; 194 + default: 195 + usage(program); 196 + } 197 + } 198 + 199 + if (optind > argc || argc - optind < 2) 200 + usage(program); 201 + 202 + int32_t (*bench)(zone_parser_t *, const kernel_t *) = 0; 203 + if (strcasecmp(argv[optind], "lex") == 0) 204 + bench = &bench_lex; 205 + else if (strcasecmp(argv[optind], "parse") == 0) 206 + bench = &bench_parse; 207 + else 208 + usage(program); 209 + 210 + const kernel_t *kernel; 211 + if (!(kernel = select_kernel(name))) 212 + exit(EXIT_FAILURE); 213 + 214 + zone_parser_t parser; 215 + memset(&parser, 0, sizeof(parser)); 216 + zone_options_t options; 217 + memset(&options, 0, sizeof(options)); 218 + options.pretty_ttls = true; 219 + options.origin.octets = root; 220 + options.origin.length = 1; 221 + options.accept.callback = &bench_accept; 222 + options.default_ttl = 3600; 223 + options.default_class = 1; 224 + 225 + zone_name_buffer_t owner; 226 + zone_rdata_buffer_t rdata; 227 + zone_buffers_t buffers = { 1, &owner, &rdata }; 228 + 229 + if (zone_open(&parser, &options, &buffers, argv[argc-1], NULL) < 0) 230 + exit(EXIT_FAILURE); 231 + if (bench(&parser, kernel) < 0) 232 + exit(EXIT_FAILURE); 233 + 234 + zone_close(&parser); 235 + return EXIT_SUCCESS; 236 + }
+41
usr.sbin/nsd/simdzone/src/config.h.in
··· 1 + /* 2 + * config.h.in -- configuration header template 3 + * 4 + * Copyright (c) 2024, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef CONFIG_H 10 + #define CONFIG_H 11 + 12 + /* Define to 1 if you have the declaration of `bswap16', and to 0 if you 13 + don't. */ 14 + #cmakedefine01 HAVE_DECL_BSWAP16 15 + 16 + /* Define to 1 if you have the declaration of `bswap32', and to 0 if you 17 + don't. */ 18 + #cmakedefine01 HAVE_DECL_BSWAP32 19 + 20 + /* Define to 1 if you have the declaration of `bswap64', and to 0 if you 21 + don't. */ 22 + #cmakedefine01 HAVE_DECL_BSWAP64 23 + 24 + /* Define to 1 if you have the <endian.h> header file. */ 25 + #cmakedefine HAVE_ENDIAN_H 1 26 + 27 + /* Define to 1 if you have the `getopt' function. */ 28 + #cmakedefine HAVE_GETOPT 1 29 + 30 + /* Wether or not to compile support for AVX2 */ 31 + #cmakedefine HAVE_HASWELL 1 32 + 33 + /* Wether or not to compile support for SSE4.2 */ 34 + #cmakedefine HAVE_WESTMERE 1 35 + 36 + /* Defines _XOPEN_SOURCE and _POSIX_C_SOURCE implicitly in features.h */ 37 + #ifndef _DEFAULT_SOURCE 38 + # define _DEFAULT_SOURCE 1 39 + #endif 40 + 41 + #endif // CONFIG_H
+57
usr.sbin/nsd/simdzone/src/diagnostic.h
··· 1 + /* 2 + * diagnostic.h -- compiler diagnostic abstractions 3 + * 4 + * Copyright (c) 2022-2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef DIAGNOSTIC_H 10 + #define DIAGNOSTIC_H 11 + 12 + #if _MSC_VER 13 + # define diagnostic_push() \ 14 + __pragma(warning(push)) 15 + # define msvc_diagnostic_ignored(warning_specifier) \ 16 + __pragma(warning(disable:warning_specifier)) 17 + # define diagnostic_pop() \ 18 + __pragma(warning(pop)) 19 + // Support for selectively enabling and disabling warnings via 20 + // #pragma GCC diagnostic was added in GCC 4.6 21 + // (https://gcc.gnu.org/gcc-4.6/changes.html). 22 + #elif (defined __clang__) \ 23 + || (defined __GNUC__ && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 406)) 24 + # define stringify(x) #x 25 + # define paste(flag, warning) stringify(flag ## warning) 26 + # define pragma(x) _Pragma(#x) 27 + # define diagnostic_ignored(warning) pragma(warning) 28 + 29 + # define diagnostic_push() _Pragma("GCC diagnostic push") 30 + # define diagnostic_pop() _Pragma("GCC diagnostic pop") 31 + # if __clang__ 32 + # define clang_diagnostic_ignored(warning) \ 33 + diagnostic_ignored(GCC diagnostic ignored paste(-W,warning)) 34 + # else 35 + # define gcc_diagnostic_ignored(warning) \ 36 + diagnostic_ignored(GCC diagnostic ignored paste(-W,warning)) 37 + # endif 38 + #endif 39 + 40 + #if !defined diagnostic_push 41 + # define diagnostic_push() 42 + # define diagnostic_pop() 43 + #endif 44 + 45 + #if !defined gcc_diagnostic_ignored 46 + # define gcc_diagnostic_ignored(warning) 47 + #endif 48 + 49 + #if !defined clang_diagnostic_ignored 50 + # define clang_diagnostic_ignored(warning) 51 + #endif 52 + 53 + #if !defined msvc_diagnostic_ignored 54 + # define msvc_diagnostic_ignored(warning) 55 + #endif 56 + 57 + #endif // DIAGNOSTIC_H
+32
usr.sbin/nsd/simdzone/src/fallback/bench.c
··· 1 + /* 2 + * bench.c -- benchmark function(s) for fallback (non-simd) implementation 3 + * 4 + * Copyright (c) 2022, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #include "zone.h" 10 + #include "attributes.h" 11 + #include "diagnostic.h" 12 + #include "generic/parser.h" 13 + #include "fallback/scanner.h" 14 + 15 + diagnostic_push() 16 + clang_diagnostic_ignored(missing-prototypes) 17 + 18 + int32_t zone_bench_fallback_lex(parser_t *parser, size_t *tokens) 19 + { 20 + token_t token; 21 + 22 + (*tokens) = 0; 23 + take(parser, &token); 24 + while (token.code > 0) { 25 + (*tokens)++; 26 + take(parser, &token); 27 + } 28 + 29 + return token.code ? -1 : 0; 30 + } 31 + 32 + diagnostic_pop()
+88
usr.sbin/nsd/simdzone/src/fallback/bits.h
··· 1 + /* 2 + * bits.h -- bit manipulation instructions 3 + * 4 + * Copyright (c) 2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef BITS_H 10 + #define BITS_H 11 + 12 + #if _MSC_VER 13 + #include <intrin.h> 14 + 15 + static really_inline uint64_t trailing_zeroes(uint64_t mask) 16 + { 17 + unsigned long index; 18 + if (_BitScanForward64(&index, mask)) 19 + return index; 20 + else 21 + return 64; 22 + } 23 + 24 + static really_inline uint64_t leading_zeroes(uint64_t mask) 25 + { 26 + unsigned long index; 27 + if (_BitScanReverse64(&index, mask)) 28 + return 63 - index; 29 + else 30 + return 64; 31 + } 32 + 33 + #else 34 + 35 + static really_inline uint64_t trailing_zeroes(uint64_t mask) 36 + { 37 + #if has_builtin(__builtin_ctzll) 38 + return (uint64_t)__builtin_ctzll(mask); 39 + #else 40 + // Code by Kim Walish from https://www.chessprogramming.org/BitScan. 41 + // Distributed under CC BY-SA 3.0. 42 + static const uint64_t magic = 0x03f79d71b4cb0a89ull; 43 + const int magictable[64] = { 44 + 0, 47, 1, 56, 48, 27, 2, 60, 45 + 57, 49, 41, 37, 28, 16, 3, 61, 46 + 54, 58, 35, 52, 50, 42, 21, 44, 47 + 38, 32, 29, 23, 17, 11, 4, 62, 48 + 46, 55, 26, 59, 40, 36, 15, 53, 49 + 34, 51, 20, 43, 31, 22, 10, 45, 50 + 25, 39, 14, 33, 19, 30, 9, 24, 51 + 13, 18, 8, 12, 7, 6, 5, 63 52 + }; 53 + 54 + return magictable[((mask ^ (mask - 1)) * magic) >> 58]; 55 + #endif 56 + } 57 + 58 + static really_inline uint64_t leading_zeroes(uint64_t mask) 59 + { 60 + #if has_builtin(__builtin_clzll) 61 + return (uint64_t)__builtin_clzll(mask); 62 + #else 63 + // Code by Kim Walish from https://www.chessprogramming.org/BitScan. 64 + // Distributed under CC BY-SA 3.0. 65 + static const uint64_t magic = 0x03f79d71b4cb0a89ull; 66 + const int magictable[64] = { 67 + 63, 16, 62, 7, 15, 36, 61, 3, 68 + 6, 14, 22, 26, 35, 47, 60, 2, 69 + 9, 5, 28, 11, 13, 21, 42, 19, 70 + 25, 31, 34, 40, 46, 52, 59, 1, 71 + 17, 8, 37, 4, 23, 27, 48, 10, 72 + 29, 12, 43, 20, 32, 41, 53, 18, 73 + 38, 24, 49, 30, 44, 33, 54, 39, 74 + 50, 45, 55, 51, 56, 57, 58, 0 75 + }; 76 + 77 + mask |= mask >> 1; 78 + mask |= mask >> 2; 79 + mask |= mask >> 4; 80 + mask |= mask >> 8; 81 + mask |= mask >> 16; 82 + mask |= mask >> 32; 83 + 84 + return magictable[(mask * magic) >> 58]; 85 + #endif 86 + } 87 + #endif // _MSC_VER 88 + #endif // BITS_H
+58
usr.sbin/nsd/simdzone/src/fallback/name.h
··· 1 + /* 2 + * name.h -- domain name parser 3 + * 4 + * Copyright (c) 2022-2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef NAME_H 10 + #define NAME_H 11 + 12 + nonnull_all 13 + static really_inline int32_t scan_name( 14 + const char *data, 15 + size_t length, 16 + uint8_t octets[255 + ZONE_BLOCK_SIZE], 17 + size_t *lengthp) 18 + { 19 + uint8_t *l = octets, *w = octets + 1; 20 + const uint8_t *we = octets + 255; 21 + const char *t = data, *te = t + length; 22 + 23 + l[0] = 0; 24 + 25 + if (*t == '.') 26 + return (*lengthp = length) == 1 ? 0 : -1; 27 + 28 + while ((t < te) & (w < we)) { 29 + *w = (uint8_t)*t; 30 + if (*t == '\\') { 31 + uint32_t n; 32 + if (!(n = unescape(t, w))) 33 + return -1; 34 + w += 1; t += n; 35 + } else if (*t == '.') { 36 + if ((w - 1) - l > 63 || (w - 1) - l == 0) 37 + return -1; 38 + l[0] = (uint8_t)((w - 1) - l); 39 + l = w; 40 + l[0] = 0; 41 + w += 1; t += 1; 42 + } else { 43 + w += 1; t += 1; 44 + } 45 + } 46 + 47 + if ((w - 1) - l > 63) 48 + return -1; 49 + *l = (uint8_t)((w - 1) - l); 50 + 51 + if (t != te || w > we) 52 + return -1; 53 + 54 + *lengthp = (size_t)(w - octets); 55 + return *l != 0; 56 + } 57 + 58 + #endif // NAME_H
+51
usr.sbin/nsd/simdzone/src/fallback/parser.c
··· 1 + /* 2 + * parser.c -- compilation target for fallback (DNS) zone parser 3 + * 4 + * Copyright (c) 2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #include "zone.h" 10 + #include "attributes.h" 11 + #include "diagnostic.h" 12 + #include "generic/endian.h" 13 + #include "fallback/bits.h" 14 + #include "generic/parser.h" 15 + #include "fallback/scanner.h" 16 + #include "generic/number.h" 17 + #include "generic/ttl.h" 18 + #include "generic/time.h" 19 + #include "fallback/text.h" 20 + #include "fallback/name.h" 21 + #include "generic/ip4.h" 22 + #include "generic/ip6.h" 23 + #include "generic/base16.h" 24 + #include "generic/base32.h" 25 + #include "generic/base64.h" 26 + #include "generic/nsec.h" 27 + #include "generic/nxt.h" 28 + #include "generic/caa.h" 29 + #include "generic/ilnp64.h" 30 + #include "generic/eui.h" 31 + #include "generic/nsap.h" 32 + #include "generic/wks.h" 33 + #include "generic/loc.h" 34 + #include "generic/gpos.h" 35 + #include "generic/apl.h" 36 + #include "generic/svcb.h" 37 + #include "generic/cert.h" 38 + #include "generic/algorithm.h" 39 + #include "generic/types.h" 40 + #include "generic/type.h" 41 + #include "generic/format.h" 42 + 43 + diagnostic_push() 44 + clang_diagnostic_ignored(missing-prototypes) 45 + 46 + int32_t zone_fallback_parse(parser_t *parser) 47 + { 48 + return parse(parser); 49 + } 50 + 51 + diagnostic_pop()
+174
usr.sbin/nsd/simdzone/src/fallback/scanner.h
··· 1 + /* 2 + * scanner.h -- fallback (non-simd) lexical analyzer for (DNS) zone data 3 + * 4 + * Copyright (c) 2022-2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef SCANNER_H 10 + #define SCANNER_H 11 + 12 + #include <assert.h> 13 + #include <stdint.h> 14 + #include <string.h> 15 + 16 + nonnull_all 17 + static really_inline const char *scan_comment( 18 + parser_t *parser, const char *start, const char *end) 19 + { 20 + assert(!parser->file->state.is_escaped); 21 + 22 + while (start < end) { 23 + if (unlikely(*start == '\n')) { 24 + parser->file->state.in_comment = 0; 25 + return start; 26 + } 27 + start++; 28 + } 29 + 30 + parser->file->state.in_comment = 1; 31 + return start; 32 + } 33 + 34 + nonnull_all 35 + static really_inline const char *scan_quoted( 36 + parser_t *parser, const char *start, const char *end) 37 + { 38 + if (unlikely(parser->file->state.is_escaped && start < end)) 39 + goto escaped; 40 + 41 + while (start < end) { 42 + if (*start == '\\') { 43 + start++; 44 + escaped: 45 + if ((parser->file->state.is_escaped = (start == end))) 46 + break; 47 + assert(start < end); 48 + *parser->file->newlines.tail += (*start == '\n'); 49 + start++; 50 + } else if (*start == '\"') { 51 + parser->file->state.in_quoted = 0; 52 + *parser->file->delimiters.tail++ = start; 53 + return ++start; 54 + } else { 55 + *parser->file->newlines.tail += (*start == '\n'); 56 + start++; 57 + } 58 + } 59 + 60 + parser->file->state.in_quoted = 1; 61 + return start; 62 + } 63 + 64 + nonnull_all 65 + static really_inline const char *scan_contiguous( 66 + parser_t *parser, const char *start, const char *end) 67 + { 68 + if (parser->file->state.is_escaped && start < end) 69 + goto escaped; 70 + 71 + while (start < end) { 72 + // null-byte is considered contiguous by the indexer (for now) 73 + if (likely((classify[ (uint8_t)*start ] & ~CONTIGUOUS) == 0)) { 74 + if (unlikely(*start == '\\')) { 75 + start++; 76 + escaped: 77 + if ((parser->file->state.is_escaped = (start == end))) 78 + break; 79 + assert(start < end); 80 + parser->file->newlines.tail[0] += (*start == '\n'); 81 + } 82 + start++; 83 + } else { 84 + parser->file->state.follows_contiguous = 0; 85 + *parser->file->delimiters.tail++ = start; 86 + return start; 87 + } 88 + } 89 + 90 + parser->file->state.follows_contiguous = 1; 91 + return start; 92 + } 93 + 94 + nonnull_all 95 + static really_inline void scan( 96 + parser_t *parser, const char *start, const char *end) 97 + { 98 + if (parser->file->state.follows_contiguous) 99 + start = scan_contiguous(parser, start, end); 100 + else if (parser->file->state.in_comment) 101 + start = scan_comment(parser, start, end); 102 + else if (parser->file->state.in_quoted) 103 + start = scan_quoted(parser, start, end); 104 + 105 + while (start < end) { 106 + const int32_t code = classify[(uint8_t)*start]; 107 + if (code == BLANK) { 108 + start++; 109 + } else if ((code & ~CONTIGUOUS) == 0) { 110 + // null-byte is considered contiguous by the indexer (for now) 111 + *parser->file->fields.tail++ = start; 112 + start = scan_contiguous(parser, start, end); 113 + } else if (code == LINE_FEED) { 114 + if (*parser->file->newlines.tail) { 115 + *parser->file->fields.tail++ = line_feed; 116 + parser->file->newlines.tail++; 117 + } else { 118 + *parser->file->fields.tail++ = start; 119 + } 120 + start++; 121 + } else if (code == QUOTED) { 122 + *parser->file->fields.tail++ = start; 123 + start = scan_quoted(parser, start + 1, end); 124 + } else if (code == LEFT_PAREN || code == RIGHT_PAREN) { 125 + *parser->file->fields.tail++ = start; 126 + start++; 127 + } else { 128 + assert(code == COMMENT); 129 + start = scan_comment(parser, start, end); 130 + } 131 + } 132 + } 133 + 134 + nonnull_all 135 + warn_unused_result 136 + static really_inline int32_t reindex(parser_t *parser) 137 + { 138 + assert(parser->file->buffer.index <= parser->file->buffer.length); 139 + size_t left = parser->file->buffer.length - parser->file->buffer.index; 140 + const char *data = parser->file->buffer.data + parser->file->buffer.index; 141 + const char **tape = parser->file->fields.tail; 142 + const char **tape_limit = parser->file->fields.tape + ZONE_TAPE_SIZE; 143 + 144 + if (left >= ZONE_BLOCK_SIZE) { 145 + const char *data_limit = parser->file->buffer.data + 146 + (parser->file->buffer.length - ZONE_BLOCK_SIZE); 147 + while (data <= data_limit && ((uintptr_t)tape_limit - (uintptr_t)tape) >= ZONE_BLOCK_SIZE) { 148 + scan(parser, data, data + ZONE_BLOCK_SIZE); 149 + parser->file->buffer.index += ZONE_BLOCK_SIZE; 150 + data += ZONE_BLOCK_SIZE; 151 + tape = parser->file->fields.tail; 152 + } 153 + 154 + assert(parser->file->buffer.index <= parser->file->buffer.length); 155 + left = parser->file->buffer.length - parser->file->buffer.index; 156 + } 157 + 158 + // only scan partial blocks after reading all data 159 + if (parser->file->end_of_file) { 160 + assert(left < ZONE_BLOCK_SIZE); 161 + if (!left) { 162 + parser->file->end_of_file = NO_MORE_DATA; 163 + } else if (((uintptr_t)tape_limit - (uintptr_t)tape) >= left) { 164 + scan(parser, data, data + left); 165 + parser->file->end_of_file = NO_MORE_DATA; 166 + parser->file->buffer.index += left; 167 + parser->file->state.follows_contiguous = 0; 168 + } 169 + } 170 + 171 + return (parser->file->state.follows_contiguous | parser->file->state.in_quoted) != 0; 172 + } 173 + 174 + #endif // SCANNER_H
+78
usr.sbin/nsd/simdzone/src/fallback/text.h
··· 1 + /* 2 + * text.h -- fallback string parser 3 + * 4 + * Copyright (c) 2022-2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef TEXT_H 10 + #define TEXT_H 11 + 12 + nonnull_all 13 + static really_inline uint32_t unescape(const char *text, uint8_t *wire) 14 + { 15 + uint8_t d[3]; 16 + 17 + if ((d[0] = (uint8_t)text[1] - '0') > 9) { 18 + *wire = (uint8_t)text[1]; 19 + return 2u; 20 + } else { 21 + d[1] = (uint8_t)text[2] - '0'; 22 + d[2] = (uint8_t)text[3] - '0'; 23 + uint32_t o = d[0] * 100 + d[1] * 10 + d[2]; 24 + *wire = (uint8_t)o; 25 + return (o > 255 || d[1] > 9 || d[2] > 9) ? 0 : 4u; 26 + } 27 + } 28 + 29 + nonnull_all 30 + static really_inline int32_t scan_string( 31 + const char *data, 32 + size_t length, 33 + uint8_t *octets, 34 + const uint8_t *limit) 35 + { 36 + const char *text = data, *text_limit = data + length; 37 + uint8_t *wire = octets; 38 + 39 + if (likely((uintptr_t)limit - (uintptr_t)wire >= length)) { 40 + while (text < text_limit) { 41 + *wire = (uint8_t)*text; 42 + if (likely(*text != '\\')) { 43 + text += 1; 44 + wire += 1; 45 + } else { 46 + const uint32_t octet = unescape(text, wire); 47 + if (!octet) 48 + return -1; 49 + text += octet; 50 + wire += 1; 51 + } 52 + } 53 + 54 + if (text != text_limit) 55 + return -1; 56 + return (int32_t)(wire - octets); 57 + } else { 58 + while (text < text_limit && wire < limit) { 59 + *wire = (uint8_t)*text; 60 + if (likely(*text != '\\')) { 61 + text += 1; 62 + wire += 1; 63 + } else { 64 + const uint32_t octet = unescape(text, wire); 65 + if (!octet) 66 + return -1; 67 + text += octet; 68 + wire += 1; 69 + } 70 + } 71 + 72 + if (text != text_limit || wire > limit) 73 + return -1; 74 + return (int32_t)(wire - octets); 75 + } 76 + } 77 + 78 + #endif // TEXT_H
+173
usr.sbin/nsd/simdzone/src/generic/algorithm.h
··· 1 + /** 2 + * algorithm.h -- Algorithm RDATA parser 3 + * 4 + * Copyright (c) 2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef ALGORITHM_H 10 + #define ALGORITHM_H 11 + 12 + // https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml 13 + 14 + typedef struct algorithm algorithm_t; 15 + struct algorithm { 16 + struct { 17 + char name[24]; 18 + size_t length; 19 + } key; 20 + uint8_t value; 21 + }; 22 + 23 + #define BAD_ALGORITHM(value) \ 24 + { { "", 0 }, 0 } 25 + #define ALGORITHM(name, value) \ 26 + { { name, sizeof(name) - 1 }, value } 27 + 28 + static const algorithm_t algorithms[32] = { 29 + BAD_ALGORITHM(0), 30 + ALGORITHM("RSAMD5", 1), 31 + ALGORITHM("DH", 2), 32 + ALGORITHM("DSA", 3), 33 + ALGORITHM("ECC", 4), 34 + ALGORITHM("RSASHA1", 5), 35 + ALGORITHM("DSA-NSEC-SHA1", 6), 36 + ALGORITHM("RSASHA1-NSEC3-SHA1", 7), 37 + ALGORITHM("RSASHA256", 8), 38 + BAD_ALGORITHM(9), 39 + ALGORITHM("RSASHA512", 10), 40 + BAD_ALGORITHM(11), 41 + ALGORITHM("ECC-GOST", 12), 42 + ALGORITHM("ECDSAP256SHA256", 13), 43 + ALGORITHM("ECDSAP384SHA384", 14), 44 + BAD_ALGORITHM(15), 45 + ALGORITHM("INDIRECT", 252), 46 + ALGORITHM("PRIVATEDNS", 253), 47 + ALGORITHM("PRIVATEOID", 254), 48 + }; 49 + 50 + static const struct { 51 + const algorithm_t *algorithm; 52 + uint8_t mask[24]; 53 + } algorithm_hash_map[16] = { 54 + { &algorithms[2], // DH (0) 55 + { 0xdf, 0xdf, 0 } }, 56 + { &algorithms[10], // RSASHA512 (1) 57 + { 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xff, 0xff, 58 + 0xff, 0 } }, 59 + { &algorithms[7], // RSASHA1-NSEC3-SHA1 (2) 60 + { 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xff, 0xff, 61 + 0xdf, 0xdf, 0xdf, 0xdf, 0xff, 0xff, 0xdf, 0xdf, 62 + 0xdf, 0xff, 0 } }, 63 + { &algorithms[8], // RSASHA256 (3) 64 + { 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xff, 0xff, 65 + 0xff, 0 } }, 66 + { &algorithms[13], // ECDSAP256SHA256 (4) 67 + { 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xff, 0xff, 68 + 0xff, 0xdf, 0xdf, 0xdf, 0xff, 0xff, 0xff, 0 } }, 69 + { &algorithms[0], // unknown 70 + { 0 } }, 71 + { &algorithms[6], // DSA-NSEC-SHA1 (6) 72 + { 0xdf, 0xdf, 0xdf, 0xff, 0xdf, 0xdf, 0xdf, 0xdf, 73 + 0xff, 0xdf, 0xdf, 0xdf, 0xff, 0 } }, 74 + { &algorithms[1], // RSAMD5 (7) 75 + { 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xff, 0 } }, 76 + { &algorithms[5], // RSASHA1 (8) 77 + { 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xff, 0 } }, 78 + { &algorithms[17], // PRIVATEDNS (9) 79 + { 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 80 + 0xdf, 0xdf, 0 } }, 81 + { &algorithms[18], // PRIVATEOID (10) 82 + { 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 83 + 0xdf, 0xdf, 0 } }, 84 + { &algorithms[16], // INDIRECT (11) 85 + { 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 86 + 0 } }, 87 + { &algorithms[14], // ECDSAP384SHA384 (12) 88 + { 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xff, 0xff, 89 + 0xff, 0xdf, 0xdf, 0xdf, 0xff, 0xff, 0xff, 0 } }, 90 + { &algorithms[3], // DSA (13) 91 + { 0xdf, 0xdf, 0xdf, 0 } }, 92 + { &algorithms[4], // ECC (14) 93 + { 0xdf, 0xdf, 0xdf, 0 } }, 94 + { &algorithms[12], // ECC-GHOST (15) 95 + { 0xdf, 0xdf, 0xdf, 0xff, 0xdf, 0xdf, 0xdf, 0xdf, 96 + 0 } } 97 + }; 98 + 99 + #undef UNKNOWN_ALGORITHM 100 + #undef ALGORITHM 101 + 102 + // magic value generated using algorithm-hash.c 103 + static uint8_t algorithm_hash(uint64_t value) 104 + { 105 + value = le64toh(value); 106 + uint32_t value32 = (uint32_t)((value >> 32) ^ value); 107 + return (uint8_t)((value32 * 29874llu) >> 32) & 0xf; 108 + } 109 + 110 + nonnull_all 111 + warn_unused_result 112 + static really_inline int32_t scan_algorithm( 113 + const char *data, size_t length, uint8_t *number) 114 + { 115 + static const int8_t zero_masks[48] = { 116 + -1, -1, -1, -1, -1, -1, -1, -1, 117 + -1, -1, -1, -1, -1, -1, -1, -1, 118 + -1, -1, -1, -1, -1, -1, -1, -1, 119 + -1, -1, -1, -1, -1, -1, -1, -1, 120 + 0, 0, 0, 0, 0, 0, 0, 0, 121 + 0, 0, 0, 0, 0, 0, 0, 0 122 + }; 123 + 124 + if ((uint8_t)*data - '0' > 9) { 125 + uint64_t input; 126 + memcpy(&input, data, 8); 127 + const uint64_t letter_mask = 0x4040404040404040llu; 128 + // convert to upper case 129 + input &= ~((input & letter_mask) >> 1); 130 + // zero out non-relevant bytes 131 + uint64_t zero_mask; 132 + memcpy(&zero_mask, &zero_masks[32 - (length & 0x1f)], 8); 133 + input &= zero_mask; 134 + const uint8_t index = algorithm_hash(input); 135 + assert(index < 16); 136 + const algorithm_t *algorithm = algorithm_hash_map[index].algorithm; 137 + uint64_t matches, mask, name; 138 + // compare bytes 0-7 139 + memcpy(&name, algorithm->key.name, 8); 140 + matches = input == name; 141 + // compare bytes 8-15 142 + memcpy(&input, data + 8, 8); 143 + memcpy(&mask, algorithm_hash_map[index].mask + 8, 8); 144 + memcpy(&name, algorithm->key.name + 8, 8); 145 + matches &= (input & mask) == name; 146 + // compare bytes 16-23 147 + memcpy(&input, data + 16, 8); 148 + memcpy(&mask, algorithm_hash_map[index].mask + 16, 8); 149 + memcpy(&name, algorithm->key.name + 16, 8); 150 + matches &= (input & mask) == name; 151 + *number = algorithm->value; 152 + return matches & (length == algorithm->key.length) & (*number > 0); 153 + } 154 + 155 + return scan_int8(data, length, number); 156 + } 157 + 158 + nonnull_all 159 + warn_unused_result 160 + static really_inline int32_t parse_algorithm( 161 + parser_t *parser, 162 + const type_info_t *type, 163 + const rdata_info_t *field, 164 + rdata_t *rdata, 165 + const token_t *token) 166 + { 167 + if (!scan_algorithm(token->data, token->length, rdata->octets)) 168 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 169 + rdata->octets++; 170 + return 0; 171 + } 172 + 173 + #endif // ALGORITHM_H
+74
usr.sbin/nsd/simdzone/src/generic/apl.h
··· 1 + /* 2 + * apl.h -- Address Prefix Lists (RFC3123) parser 3 + * 4 + * Copyright (c) 2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef APL_H 10 + #define APL_H 11 + 12 + static really_inline int32_t scan_apl( 13 + const char *text, size_t length, uint8_t *octets, size_t size) 14 + { 15 + uint8_t negate = text[0] == '!'; 16 + uint8_t digits[3]; 17 + int32_t count; 18 + uint32_t prefix; 19 + const uint8_t af_inet[2] = { 0x00, 0x01 }, af_inet6[2] = { 0x00, 0x02 }; 20 + 21 + // address family is immediately followed by a colon ":" 22 + if (text[negate + 1] != ':') 23 + return -1; 24 + 25 + switch (text[negate]) { 26 + case '1': 27 + if (size < 8) 28 + return -1; 29 + memcpy(octets, af_inet, sizeof(af_inet)); 30 + if (!(count = scan_ip4(&text[negate+2], &octets[4]))) 31 + return -1; 32 + count += negate + 2; 33 + digits[0] = (uint8_t)text[count+1] - '0'; 34 + digits[1] = (uint8_t)text[count+2] - '0'; 35 + if (text[count] != '/' || digits[0] > 9) 36 + return -1; 37 + if (digits[1] > 9) 38 + (void)(count += 2), prefix = digits[0]; 39 + else 40 + (void)(count += 3), prefix = digits[0] * 10 + digits[1]; 41 + if (prefix > 32 || (size_t)count != length) 42 + return -1; 43 + octets[2] = (uint8_t)prefix; 44 + octets[3] = (uint8_t)((negate << 7) | 4); 45 + return 8; 46 + case '2': 47 + if (size < 20) 48 + return -1; 49 + memcpy(octets, af_inet6, sizeof(af_inet6)); 50 + if (!(count = scan_ip6(&text[negate+2], &octets[4]))) 51 + return -1; 52 + count += negate + 2; 53 + digits[0] = (uint8_t)text[count+1] - '0'; 54 + digits[1] = (uint8_t)text[count+2] - '0'; 55 + digits[2] = (uint8_t)text[count+3] - '0'; 56 + if (text[count] != '/' || digits[0] > 9) 57 + return -1; 58 + if (digits[1] > 9) 59 + (void)(count += 2), prefix = digits[0]; 60 + else if (digits[2] > 9) 61 + (void)(count += 3), prefix = digits[0] * 10 + digits[1]; 62 + else 63 + (void)(count += 4), prefix = digits[0] * 100 + digits[1] * 10 + digits[0]; 64 + if (prefix > 128 || (size_t)count != length) 65 + return -1; 66 + octets[2] = (uint8_t)prefix; 67 + octets[3] = (uint8_t)((negate << 7) | 16); 68 + return 20; 69 + default: 70 + return -1; 71 + } 72 + } 73 + 74 + #endif // APL_H
+304
usr.sbin/nsd/simdzone/src/generic/base16.h
··· 1 + /* 2 + * base16.h -- Fast Base16 stream decoder 3 + * 4 + * Copyright (c) 2005-2016, Nick Galbreath. 5 + * Copyright (c) 2022, NLnet Labs. All rights reserved. 6 + * 7 + * SPDX-License-Identifier: BSD-2-Clause 8 + * 9 + */ 10 + #ifndef BASE16_H 11 + #define BASE16_H 12 + 13 + // adaptation of base16 decoder by Nick Galbreath to operate similar to the 14 + // base64 stream decoder by Alfred Klomp. 15 + // https://github.com/client9/stringencoders 16 + // https://github.com/aklomp/base64 17 + 18 + struct base16_state { 19 + int eof; 20 + int bytes; 21 + unsigned char carry; 22 + }; 23 + 24 + #define BASE16_EOF 1 25 + 26 + static const uint32_t base16_table_dec_32bit_d0[256] = { 27 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 28 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 29 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 30 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 31 + 0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 256, 256, 32 + 256, 256, 256, 256, 256, 160, 176, 192, 208, 224, 240, 256, 33 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 34 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 35 + 256, 160, 176, 192, 208, 224, 240, 256, 256, 256, 256, 256, 36 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 37 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 38 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 39 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 40 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 41 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 42 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 43 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 44 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 45 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 46 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 47 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 48 + 256, 256, 256, 256 49 + }; 50 + 51 + static const uint32_t base16_table_dec_32bit_d1[256] = { 52 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 53 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 54 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 55 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 56 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 256, 256, 57 + 256, 256, 256, 256, 256, 10, 11, 12, 13, 14, 15, 256, 58 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 59 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 60 + 256, 10, 11, 12, 13, 14, 15, 256, 256, 256, 256, 256, 61 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 62 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 63 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 64 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 65 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 66 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 67 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 68 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 69 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 70 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 71 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 72 + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 73 + 256, 256, 256, 256 74 + }; 75 + 76 + static really_inline int 77 + base16_dec_loop_generic_32_inner( 78 + const uint8_t **s, uint8_t **o, size_t *rounds) 79 + { 80 + const uint32_t val1 = base16_table_dec_32bit_d0[(*s)[0]] 81 + | base16_table_dec_32bit_d1[(*s)[1]]; 82 + const uint32_t val2 = base16_table_dec_32bit_d0[(*s)[2]] 83 + | base16_table_dec_32bit_d1[(*s)[3]]; 84 + 85 + if (val1 > 0xff || val2 > 0xff) 86 + return 0; 87 + 88 + (*o)[0] = (uint8_t)val1; 89 + (*o)[1] = (uint8_t)val2; 90 + 91 + *s += 4; 92 + *o += 2; 93 + *rounds -= 1; 94 + 95 + return 1; 96 + } 97 + 98 + static really_inline void 99 + base16_dec_loop_generic_32( 100 + const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen) 101 + { 102 + if (*slen < 4) 103 + return; 104 + 105 + // some comment on the how and what... 106 + size_t rounds = (*slen - 4) / 4; 107 + 108 + *slen -= rounds * 4; // 4 bytes consumed per round 109 + *olen += rounds * 2; // 2 bytes produced per round 110 + 111 + do { 112 + if (rounds >= 8) { 113 + if (base16_dec_loop_generic_32_inner(s, o, &rounds) && 114 + base16_dec_loop_generic_32_inner(s, o, &rounds) && 115 + base16_dec_loop_generic_32_inner(s, o, &rounds) && 116 + base16_dec_loop_generic_32_inner(s, o, &rounds) && 117 + base16_dec_loop_generic_32_inner(s, o, &rounds) && 118 + base16_dec_loop_generic_32_inner(s, o, &rounds) && 119 + base16_dec_loop_generic_32_inner(s, o, &rounds) && 120 + base16_dec_loop_generic_32_inner(s, o, &rounds)) 121 + continue; 122 + break; 123 + } 124 + if (rounds >= 4) { 125 + if (base16_dec_loop_generic_32_inner(s, o, &rounds) && 126 + base16_dec_loop_generic_32_inner(s, o, &rounds) && 127 + base16_dec_loop_generic_32_inner(s, o, &rounds) && 128 + base16_dec_loop_generic_32_inner(s, o, &rounds)) 129 + continue; 130 + break; 131 + } 132 + if (rounds >= 2) { 133 + if (base16_dec_loop_generic_32_inner(s, o, &rounds) && 134 + base16_dec_loop_generic_32_inner(s, o, &rounds)) 135 + continue; 136 + break; 137 + } 138 + base16_dec_loop_generic_32_inner(s, o, &rounds); 139 + break; 140 + } while (rounds > 0); 141 + 142 + // Adjust for any rounds that were skipped: 143 + *slen += rounds * 4; 144 + *olen -= rounds * 2; 145 + } 146 + 147 + nonnull((1,2,4,5)) 148 + static really_inline int base16_stream_decode( 149 + struct base16_state *state, 150 + const char *src, 151 + size_t srclen, 152 + uint8_t *out, 153 + size_t *outlen) 154 + { 155 + int ret = 0; 156 + const uint8_t *s = (const uint8_t *) src; 157 + uint8_t *o = (uint8_t *) out; 158 + uint32_t q; 159 + 160 + // Use local temporaries to avoid cache thrashing: 161 + size_t olen = 0; 162 + size_t slen = srclen; 163 + struct base16_state st; 164 + st.eof = state->eof; 165 + st.bytes = state->bytes; 166 + st.carry = state->carry; 167 + 168 + if (st.eof) { 169 + *outlen = 0; 170 + return ret; 171 + } 172 + 173 + // Duff's device again: 174 + switch (st.bytes) 175 + { 176 + #if defined(__SUNPRO_C) 177 + #pragma error_messages(off, E_STATEMENT_NOT_REACHED) 178 + #endif 179 + for (;;) 180 + #if defined(__SUNPRO_C) 181 + #pragma error_messages(default, E_STATEMENT_NOT_REACHED) 182 + #endif 183 + { 184 + case 0: 185 + base16_dec_loop_generic_32(&s, &slen, &o, &olen); 186 + if (slen-- == 0) { 187 + ret = 1; 188 + break; 189 + } 190 + if ((q = base16_table_dec_32bit_d0[*s++]) >= 255) { 191 + st.eof = BASE16_EOF; 192 + break; 193 + } 194 + st.carry = (uint8_t)q; 195 + st.bytes = 1; 196 + 197 + // fallthrough 198 + 199 + case 1: 200 + if (slen-- == 0) { 201 + ret = 1; 202 + break; 203 + } 204 + if ((q = base16_table_dec_32bit_d1[*s++]) >= 255) { 205 + st.eof = BASE16_EOF; 206 + break; 207 + } 208 + *o++ = st.carry | (uint8_t)q; 209 + st.carry = 0; 210 + st.bytes = 0; 211 + olen++; 212 + } 213 + } 214 + 215 + state->eof = st.eof; 216 + state->bytes = st.bytes; 217 + state->carry = st.carry; 218 + *outlen = olen; 219 + return ret; 220 + } 221 + 222 + nonnull((1,3,4)) 223 + static really_inline int base16_decode( 224 + const char *src, size_t srclen, uint8_t *out, size_t *outlen) 225 + { 226 + struct base16_state state = { .eof = 0, .bytes = 0, .carry = 0 }; 227 + return base16_stream_decode(&state, src, srclen, out, outlen) & !state.bytes; 228 + } 229 + 230 + // FIXME: RFC3597 section 5 states each word of data must contain an even 231 + // number of hexadecimal digits. The same is not true for DS records. 232 + // RFC4043 section 5.3 merely states whitespace is allowed within the 233 + // hexadecimal text. Words containing an uneven number of hexadecimal 234 + // digits are impractical, but supported (BIND supports uneven 235 + // sequences) 236 + nonnull_all 237 + static really_inline int32_t parse_base16_sequence( 238 + parser_t *parser, 239 + const type_info_t *type, 240 + const rdata_info_t *field, 241 + rdata_t *rdata, 242 + token_t *token) 243 + { 244 + if (is_contiguous(token)) { 245 + struct base16_state state = { .eof = 0, .bytes = 0, .carry = 0 }; 246 + 247 + do { 248 + size_t length = (token->length + 1) / 2; 249 + if ((uintptr_t)rdata->limit - (uintptr_t)rdata->octets < length) 250 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 251 + if (!base16_stream_decode(&state, token->data, token->length, rdata->octets, &length)) 252 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 253 + rdata->octets += length; 254 + take(parser, token); 255 + } while (is_contiguous(token)); 256 + 257 + if (state.bytes) 258 + *rdata->octets++ = state.carry; 259 + } 260 + 261 + return have_delimiter(parser, type, token); 262 + } 263 + 264 + nonnull_all 265 + static really_inline int32_t parse_base16( 266 + parser_t *parser, 267 + const type_info_t *type, 268 + const rdata_info_t *field, 269 + rdata_t *rdata, 270 + const token_t *token) 271 + { 272 + size_t length = token->length / 2; 273 + if ((uintptr_t)rdata->limit - (uintptr_t)rdata->octets < length) 274 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 275 + if (!base16_decode(token->data, token->length, rdata->octets, &length)) 276 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 277 + rdata->octets += length; 278 + return 0; 279 + } 280 + 281 + nonnull_all 282 + static really_inline int32_t parse_salt( 283 + parser_t *parser, 284 + const type_info_t *type, 285 + const rdata_info_t *field, 286 + rdata_t *rdata, 287 + const token_t *token) 288 + { 289 + if (token->length == 1 && token->data[0] == '-') 290 + return (void)(*rdata->octets++ = 0), 0; 291 + 292 + size_t length = token->length / 2; 293 + uint8_t *octets = rdata->octets++; 294 + // FIXME: not quite right yet! we must not exceed 255 octets! 295 + if ((uintptr_t)rdata->limit - (uintptr_t)rdata->octets < (length + 1)) 296 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 297 + if (!base16_decode(token->data, token->length, rdata->octets, &length)) 298 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 299 + *octets = (uint8_t)length; 300 + rdata->octets += length; 301 + return 0; 302 + } 303 + 304 + #endif // BASE16_H
+117
usr.sbin/nsd/simdzone/src/generic/base32.h
··· 1 + /* 2 + * base32.h -- Base32 decoder 3 + * 4 + * Copyright (c) 2022, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef BASE32_H 10 + #define BASE32_H 11 + 12 + static const uint8_t b32rmap[256] = { 13 + 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0 - 7 */ 14 + 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, /* 8 - 15 */ 15 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 16 - 23 */ 16 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 24 - 31 */ 17 + 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 32 - 39 */ 18 + 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, /* 40 - 47 */ 19 + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 48 - 55 */ 20 + 0x08, 0x09, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, /* 56 - 63 */ 21 + 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, /* 64 - 71 */ 22 + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, /* 72 - 79 */ 23 + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0xff, /* 80 - 87 */ 24 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 88 - 95 */ 25 + 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, /* 96 - 103 */ 26 + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, /* 104 - 111 */ 27 + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0xff, /* 112 - 119 */ 28 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 120 - 127 */ 29 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 128 - 135 */ 30 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 136 - 143 */ 31 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 144 - 151 */ 32 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 152 - 159 */ 33 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 160 - 167 */ 34 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 168 - 175 */ 35 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 176 - 183 */ 36 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 184 - 191 */ 37 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 192 - 199 */ 38 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 200 - 207 */ 39 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 208 - 215 */ 40 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 216 - 223 */ 41 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 224 - 231 */ 42 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 232 - 239 */ 43 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 240 - 247 */ 44 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 248 - 255 */ 45 + }; 46 + 47 + static const uint8_t b32rmap_special = 0xf0; 48 + 49 + nonnull_all 50 + static really_inline int32_t parse_base32( 51 + parser_t *parser, 52 + const type_info_t *type, 53 + const rdata_info_t *field, 54 + rdata_t *rdata, 55 + const token_t *token) 56 + { 57 + uint32_t state = 0; 58 + 59 + size_t length = (token->length * 5) / 8; 60 + if (length > 255 || (uintptr_t)rdata->limit - (uintptr_t)rdata->octets < (length + 1)) 61 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 62 + 63 + *rdata->octets++ = (uint8_t)length; 64 + 65 + const char *p = token->data; 66 + for (;; p++) { 67 + const uint8_t ofs = b32rmap[(uint8_t)*p]; 68 + 69 + if (ofs >= b32rmap_special) 70 + break; 71 + 72 + switch (state) { 73 + case 0: 74 + *rdata->octets = (uint8_t)(ofs << 3); 75 + state = 1; 76 + break; 77 + case 1: 78 + *rdata->octets++ |= (uint8_t)(ofs >> 2); 79 + *rdata->octets = (uint8_t)(ofs << 6); 80 + state = 2; 81 + break; 82 + case 2: 83 + *rdata->octets |= (uint8_t)(ofs << 1); 84 + state = 3; 85 + break; 86 + case 3: 87 + *rdata->octets++ |= (uint8_t)(ofs >> 4); 88 + *rdata->octets = (uint8_t)(ofs << 4); 89 + state = 4; 90 + break; 91 + case 4: 92 + *rdata->octets++ |= (uint8_t)(ofs >> 1); 93 + *rdata->octets = (uint8_t)(ofs << 7); 94 + state = 5; 95 + break; 96 + case 5: 97 + *rdata->octets |= (uint8_t)(ofs << 2); 98 + state = 6; 99 + break; 100 + case 6: 101 + *rdata->octets++ |= (uint8_t)(ofs >> 3); 102 + *rdata->octets = (uint8_t)(ofs << 5); 103 + state = 7; 104 + break; 105 + case 7: 106 + *rdata->octets++ |= ofs; 107 + state = 0; 108 + break; 109 + } 110 + } 111 + 112 + if (p != token->data + token->length) 113 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 114 + return 0; 115 + } 116 + 117 + #endif // BASE32_H
+738
usr.sbin/nsd/simdzone/src/generic/base64.h
··· 1 + /* 2 + * base64.h -- Fast Base64 stream decoder 3 + * 4 + * Copyright (c) 2005-2007, Nick Galbreath. 5 + * Copyright (c) 2015-2018, Wojciech Muła. 6 + * Copyright (c) 2016-2017, Matthieu Darbois. 7 + * Copyright (c) 2013-2022, Alfred Klomp. 8 + * Copyright (c) 2022, NLnet Labs. All rights reserved. 9 + * 10 + * SPDX-License-Identifier: BSD-2-Clause 11 + * 12 + */ 13 + #ifndef BASE64_H 14 + #define BASE64_H 15 + 16 + // Modified version of https://github.com/aklomp/base64 17 + 18 + struct base64_state { 19 + int eof; 20 + int bytes; 21 + unsigned char carry; 22 + }; 23 + 24 + #include <stdint.h> 25 + #define CHAR62 '+' 26 + #define CHAR63 '/' 27 + #define CHARPAD '=' 28 + 29 + // End-of-file definitions. 30 + // Almost end-of-file when waiting for the last '=' character: 31 + #define BASE64_AEOF 1 32 + // End-of-file when stream end has been reached or invalid input provided: 33 + #define BASE64_EOF 2 34 + 35 + // In the lookup table below, note that the value for '=' (character 61) is 36 + // 254, not 255. This character is used for in-band signaling of the end of 37 + // the datastream, and we will use that later. The characters A-Z, a-z, 0-9 38 + // and + / are mapped to their "decoded" values. The other bytes all map to 39 + // the value 255, which flags them as "invalid input". 40 + 41 + static const uint8_t 42 + base64_table_dec_8bit[] = 43 + { 44 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 0..15 45 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 16..31 46 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, // 32..47 47 + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 254, 255, 255, // 48..63 48 + 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64..79 49 + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, // 80..95 50 + 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96..111 51 + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255, // 112..127 52 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 128..143 53 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 54 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 55 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 56 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 57 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 58 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 59 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 60 + }; 61 + 62 + 63 + #if BYTE_ORDER == LITTLE_ENDIAN 64 + 65 + /* SPECIAL DECODE TABLES FOR LITTLE ENDIAN (INTEL) CPUS */ 66 + 67 + static const uint32_t base64_table_dec_32bit_d0[256] = { 68 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 69 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 70 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 71 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 72 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 73 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 74 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 75 + 0xffffffff, 0x000000f8, 0xffffffff, 0xffffffff, 0xffffffff, 0x000000fc, 76 + 0x000000d0, 0x000000d4, 0x000000d8, 0x000000dc, 0x000000e0, 0x000000e4, 77 + 0x000000e8, 0x000000ec, 0x000000f0, 0x000000f4, 0xffffffff, 0xffffffff, 78 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 79 + 0x00000004, 0x00000008, 0x0000000c, 0x00000010, 0x00000014, 0x00000018, 80 + 0x0000001c, 0x00000020, 0x00000024, 0x00000028, 0x0000002c, 0x00000030, 81 + 0x00000034, 0x00000038, 0x0000003c, 0x00000040, 0x00000044, 0x00000048, 82 + 0x0000004c, 0x00000050, 0x00000054, 0x00000058, 0x0000005c, 0x00000060, 83 + 0x00000064, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 84 + 0xffffffff, 0x00000068, 0x0000006c, 0x00000070, 0x00000074, 0x00000078, 85 + 0x0000007c, 0x00000080, 0x00000084, 0x00000088, 0x0000008c, 0x00000090, 86 + 0x00000094, 0x00000098, 0x0000009c, 0x000000a0, 0x000000a4, 0x000000a8, 87 + 0x000000ac, 0x000000b0, 0x000000b4, 0x000000b8, 0x000000bc, 0x000000c0, 88 + 0x000000c4, 0x000000c8, 0x000000cc, 0xffffffff, 0xffffffff, 0xffffffff, 89 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 90 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 91 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 92 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 93 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 94 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 95 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 96 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 97 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 98 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 99 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 100 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 101 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 102 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 103 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 104 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 105 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 106 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 107 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 108 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 109 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 110 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff 111 + }; 112 + 113 + 114 + static const uint32_t base64_table_dec_32bit_d1[256] = { 115 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 116 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 117 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 118 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 119 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 120 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 121 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 122 + 0xffffffff, 0x0000e003, 0xffffffff, 0xffffffff, 0xffffffff, 0x0000f003, 123 + 0x00004003, 0x00005003, 0x00006003, 0x00007003, 0x00008003, 0x00009003, 124 + 0x0000a003, 0x0000b003, 0x0000c003, 0x0000d003, 0xffffffff, 0xffffffff, 125 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 126 + 0x00001000, 0x00002000, 0x00003000, 0x00004000, 0x00005000, 0x00006000, 127 + 0x00007000, 0x00008000, 0x00009000, 0x0000a000, 0x0000b000, 0x0000c000, 128 + 0x0000d000, 0x0000e000, 0x0000f000, 0x00000001, 0x00001001, 0x00002001, 129 + 0x00003001, 0x00004001, 0x00005001, 0x00006001, 0x00007001, 0x00008001, 130 + 0x00009001, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 131 + 0xffffffff, 0x0000a001, 0x0000b001, 0x0000c001, 0x0000d001, 0x0000e001, 132 + 0x0000f001, 0x00000002, 0x00001002, 0x00002002, 0x00003002, 0x00004002, 133 + 0x00005002, 0x00006002, 0x00007002, 0x00008002, 0x00009002, 0x0000a002, 134 + 0x0000b002, 0x0000c002, 0x0000d002, 0x0000e002, 0x0000f002, 0x00000003, 135 + 0x00001003, 0x00002003, 0x00003003, 0xffffffff, 0xffffffff, 0xffffffff, 136 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 137 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 138 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 139 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 140 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 141 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 142 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 143 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 144 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 145 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 146 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 147 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 148 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 149 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 150 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 151 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 152 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 153 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 154 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 155 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 156 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 157 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff 158 + }; 159 + 160 + 161 + static const uint32_t base64_table_dec_32bit_d2[256] = { 162 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 163 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 164 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 165 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 166 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 167 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 168 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 169 + 0xffffffff, 0x00800f00, 0xffffffff, 0xffffffff, 0xffffffff, 0x00c00f00, 170 + 0x00000d00, 0x00400d00, 0x00800d00, 0x00c00d00, 0x00000e00, 0x00400e00, 171 + 0x00800e00, 0x00c00e00, 0x00000f00, 0x00400f00, 0xffffffff, 0xffffffff, 172 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 173 + 0x00400000, 0x00800000, 0x00c00000, 0x00000100, 0x00400100, 0x00800100, 174 + 0x00c00100, 0x00000200, 0x00400200, 0x00800200, 0x00c00200, 0x00000300, 175 + 0x00400300, 0x00800300, 0x00c00300, 0x00000400, 0x00400400, 0x00800400, 176 + 0x00c00400, 0x00000500, 0x00400500, 0x00800500, 0x00c00500, 0x00000600, 177 + 0x00400600, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 178 + 0xffffffff, 0x00800600, 0x00c00600, 0x00000700, 0x00400700, 0x00800700, 179 + 0x00c00700, 0x00000800, 0x00400800, 0x00800800, 0x00c00800, 0x00000900, 180 + 0x00400900, 0x00800900, 0x00c00900, 0x00000a00, 0x00400a00, 0x00800a00, 181 + 0x00c00a00, 0x00000b00, 0x00400b00, 0x00800b00, 0x00c00b00, 0x00000c00, 182 + 0x00400c00, 0x00800c00, 0x00c00c00, 0xffffffff, 0xffffffff, 0xffffffff, 183 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 184 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 185 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 186 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 187 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 188 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 189 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 190 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 191 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 192 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 193 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 194 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 195 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 196 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 197 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 198 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 199 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 200 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 201 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 202 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 203 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 204 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff 205 + }; 206 + 207 + 208 + static const uint32_t base64_table_dec_32bit_d3[256] = { 209 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 210 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 211 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 212 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 213 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 214 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 215 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 216 + 0xffffffff, 0x003e0000, 0xffffffff, 0xffffffff, 0xffffffff, 0x003f0000, 217 + 0x00340000, 0x00350000, 0x00360000, 0x00370000, 0x00380000, 0x00390000, 218 + 0x003a0000, 0x003b0000, 0x003c0000, 0x003d0000, 0xffffffff, 0xffffffff, 219 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 220 + 0x00010000, 0x00020000, 0x00030000, 0x00040000, 0x00050000, 0x00060000, 221 + 0x00070000, 0x00080000, 0x00090000, 0x000a0000, 0x000b0000, 0x000c0000, 222 + 0x000d0000, 0x000e0000, 0x000f0000, 0x00100000, 0x00110000, 0x00120000, 223 + 0x00130000, 0x00140000, 0x00150000, 0x00160000, 0x00170000, 0x00180000, 224 + 0x00190000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 225 + 0xffffffff, 0x001a0000, 0x001b0000, 0x001c0000, 0x001d0000, 0x001e0000, 226 + 0x001f0000, 0x00200000, 0x00210000, 0x00220000, 0x00230000, 0x00240000, 227 + 0x00250000, 0x00260000, 0x00270000, 0x00280000, 0x00290000, 0x002a0000, 228 + 0x002b0000, 0x002c0000, 0x002d0000, 0x002e0000, 0x002f0000, 0x00300000, 229 + 0x00310000, 0x00320000, 0x00330000, 0xffffffff, 0xffffffff, 0xffffffff, 230 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 231 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 232 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 233 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 234 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 235 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 236 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 237 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 238 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 239 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 240 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 241 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 242 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 243 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 244 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 245 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 246 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 247 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 248 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 249 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 250 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 251 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff 252 + }; 253 + 254 + #elif BYTE_ORDER == BIG_ENDIAN 255 + 256 + /* SPECIAL DECODE TABLES FOR BIG ENDIAN (IBM/MOTOROLA/SUN) CPUS */ 257 + 258 + const uint32_t base64_table_dec_32bit_d0[256] = { 259 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 260 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 261 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 262 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 263 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 264 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 265 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 266 + 0xffffffff, 0xf8000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xfc000000, 267 + 0xd0000000, 0xd4000000, 0xd8000000, 0xdc000000, 0xe0000000, 0xe4000000, 268 + 0xe8000000, 0xec000000, 0xf0000000, 0xf4000000, 0xffffffff, 0xffffffff, 269 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 270 + 0x04000000, 0x08000000, 0x0c000000, 0x10000000, 0x14000000, 0x18000000, 271 + 0x1c000000, 0x20000000, 0x24000000, 0x28000000, 0x2c000000, 0x30000000, 272 + 0x34000000, 0x38000000, 0x3c000000, 0x40000000, 0x44000000, 0x48000000, 273 + 0x4c000000, 0x50000000, 0x54000000, 0x58000000, 0x5c000000, 0x60000000, 274 + 0x64000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 275 + 0xffffffff, 0x68000000, 0x6c000000, 0x70000000, 0x74000000, 0x78000000, 276 + 0x7c000000, 0x80000000, 0x84000000, 0x88000000, 0x8c000000, 0x90000000, 277 + 0x94000000, 0x98000000, 0x9c000000, 0xa0000000, 0xa4000000, 0xa8000000, 278 + 0xac000000, 0xb0000000, 0xb4000000, 0xb8000000, 0xbc000000, 0xc0000000, 279 + 0xc4000000, 0xc8000000, 0xcc000000, 0xffffffff, 0xffffffff, 0xffffffff, 280 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 281 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 282 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 283 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 284 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 285 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 286 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 287 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 288 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 289 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 290 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 291 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 292 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 293 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 294 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 295 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 296 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 297 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 298 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 299 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 300 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 301 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff 302 + }; 303 + 304 + const uint32_t base64_table_dec_32bit_d1[256] = { 305 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 306 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 307 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 308 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 309 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 310 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 311 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 312 + 0xffffffff, 0x03e00000, 0xffffffff, 0xffffffff, 0xffffffff, 0x03f00000, 313 + 0x03400000, 0x03500000, 0x03600000, 0x03700000, 0x03800000, 0x03900000, 314 + 0x03a00000, 0x03b00000, 0x03c00000, 0x03d00000, 0xffffffff, 0xffffffff, 315 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 316 + 0x00100000, 0x00200000, 0x00300000, 0x00400000, 0x00500000, 0x00600000, 317 + 0x00700000, 0x00800000, 0x00900000, 0x00a00000, 0x00b00000, 0x00c00000, 318 + 0x00d00000, 0x00e00000, 0x00f00000, 0x01000000, 0x01100000, 0x01200000, 319 + 0x01300000, 0x01400000, 0x01500000, 0x01600000, 0x01700000, 0x01800000, 320 + 0x01900000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 321 + 0xffffffff, 0x01a00000, 0x01b00000, 0x01c00000, 0x01d00000, 0x01e00000, 322 + 0x01f00000, 0x02000000, 0x02100000, 0x02200000, 0x02300000, 0x02400000, 323 + 0x02500000, 0x02600000, 0x02700000, 0x02800000, 0x02900000, 0x02a00000, 324 + 0x02b00000, 0x02c00000, 0x02d00000, 0x02e00000, 0x02f00000, 0x03000000, 325 + 0x03100000, 0x03200000, 0x03300000, 0xffffffff, 0xffffffff, 0xffffffff, 326 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 327 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 328 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 329 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 330 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 331 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 332 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 333 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 334 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 335 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 336 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 337 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 338 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 339 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 340 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 341 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 342 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 343 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 344 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 345 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 346 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 347 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff 348 + }; 349 + 350 + const uint32_t base64_table_dec_32bit_d2[256] = { 351 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 352 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 353 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 354 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 355 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 356 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 357 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 358 + 0xffffffff, 0x000f8000, 0xffffffff, 0xffffffff, 0xffffffff, 0x000fc000, 359 + 0x000d0000, 0x000d4000, 0x000d8000, 0x000dc000, 0x000e0000, 0x000e4000, 360 + 0x000e8000, 0x000ec000, 0x000f0000, 0x000f4000, 0xffffffff, 0xffffffff, 361 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 362 + 0x00004000, 0x00008000, 0x0000c000, 0x00010000, 0x00014000, 0x00018000, 363 + 0x0001c000, 0x00020000, 0x00024000, 0x00028000, 0x0002c000, 0x00030000, 364 + 0x00034000, 0x00038000, 0x0003c000, 0x00040000, 0x00044000, 0x00048000, 365 + 0x0004c000, 0x00050000, 0x00054000, 0x00058000, 0x0005c000, 0x00060000, 366 + 0x00064000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 367 + 0xffffffff, 0x00068000, 0x0006c000, 0x00070000, 0x00074000, 0x00078000, 368 + 0x0007c000, 0x00080000, 0x00084000, 0x00088000, 0x0008c000, 0x00090000, 369 + 0x00094000, 0x00098000, 0x0009c000, 0x000a0000, 0x000a4000, 0x000a8000, 370 + 0x000ac000, 0x000b0000, 0x000b4000, 0x000b8000, 0x000bc000, 0x000c0000, 371 + 0x000c4000, 0x000c8000, 0x000cc000, 0xffffffff, 0xffffffff, 0xffffffff, 372 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 373 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 374 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 375 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 376 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 377 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 378 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 379 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 380 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 381 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 382 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 383 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 384 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 385 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 386 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 387 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 388 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 389 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 390 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 391 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 392 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 393 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff 394 + }; 395 + 396 + 397 + const uint32_t base64_table_dec_32bit_d3[256] = { 398 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 399 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 400 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 401 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 402 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 403 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 404 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 405 + 0xffffffff, 0x00003e00, 0xffffffff, 0xffffffff, 0xffffffff, 0x00003f00, 406 + 0x00003400, 0x00003500, 0x00003600, 0x00003700, 0x00003800, 0x00003900, 407 + 0x00003a00, 0x00003b00, 0x00003c00, 0x00003d00, 0xffffffff, 0xffffffff, 408 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 409 + 0x00000100, 0x00000200, 0x00000300, 0x00000400, 0x00000500, 0x00000600, 410 + 0x00000700, 0x00000800, 0x00000900, 0x00000a00, 0x00000b00, 0x00000c00, 411 + 0x00000d00, 0x00000e00, 0x00000f00, 0x00001000, 0x00001100, 0x00001200, 412 + 0x00001300, 0x00001400, 0x00001500, 0x00001600, 0x00001700, 0x00001800, 413 + 0x00001900, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 414 + 0xffffffff, 0x00001a00, 0x00001b00, 0x00001c00, 0x00001d00, 0x00001e00, 415 + 0x00001f00, 0x00002000, 0x00002100, 0x00002200, 0x00002300, 0x00002400, 416 + 0x00002500, 0x00002600, 0x00002700, 0x00002800, 0x00002900, 0x00002a00, 417 + 0x00002b00, 0x00002c00, 0x00002d00, 0x00002e00, 0x00002f00, 0x00003000, 418 + 0x00003100, 0x00003200, 0x00003300, 0xffffffff, 0xffffffff, 0xffffffff, 419 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 420 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 421 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 422 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 423 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 424 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 425 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 426 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 427 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 428 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 429 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 430 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 431 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 432 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 433 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 434 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 435 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 436 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 437 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 438 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 439 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 440 + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff 441 + }; 442 + 443 + #else 444 + 445 + # error "byte order unknown" 446 + 447 + #endif // LITTLE_ENDIAN 448 + 449 + static really_inline int 450 + dec_loop_generic_32_inner (const uint8_t **s, uint8_t **o, size_t *rounds) 451 + { 452 + const uint32_t str 453 + = base64_table_dec_32bit_d0[(*s)[0]] 454 + | base64_table_dec_32bit_d1[(*s)[1]] 455 + | base64_table_dec_32bit_d2[(*s)[2]] 456 + | base64_table_dec_32bit_d3[(*s)[3]]; 457 + 458 + #if BYTE_ORDER == LITTLE_ENDIAN 459 + 460 + // LUTs for little-endian set MSB in case of invalid character: 461 + if (str & UINT32_C(0x80000000)) { 462 + return 0; 463 + } 464 + #else 465 + // LUTs for big-endian set LSB in case of invalid character: 466 + if (str & UINT32_C(1)) { 467 + return 0; 468 + } 469 + #endif 470 + // Store the output: 471 + memcpy(*o, &str, sizeof (str)); 472 + 473 + *s += 4; 474 + *o += 3; 475 + *rounds -= 1; 476 + 477 + return 1; 478 + } 479 + 480 + static really_inline void 481 + dec_loop_generic_32 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen) 482 + { 483 + if (*slen < 8) { 484 + return; 485 + } 486 + 487 + // Process blocks of 4 bytes per round. Because one extra zero byte is 488 + // written after the output, ensure that there will be at least 4 bytes 489 + // of input data left to cover the gap. (Two data bytes and up to two 490 + // end-of-string markers.) 491 + size_t rounds = (*slen - 4) / 4; 492 + 493 + *slen -= rounds * 4; // 4 bytes consumed per round 494 + *olen += rounds * 3; // 3 bytes produced per round 495 + 496 + do { 497 + if (rounds >= 8) { 498 + if (dec_loop_generic_32_inner(s, o, &rounds) && 499 + dec_loop_generic_32_inner(s, o, &rounds) && 500 + dec_loop_generic_32_inner(s, o, &rounds) && 501 + dec_loop_generic_32_inner(s, o, &rounds) && 502 + dec_loop_generic_32_inner(s, o, &rounds) && 503 + dec_loop_generic_32_inner(s, o, &rounds) && 504 + dec_loop_generic_32_inner(s, o, &rounds) && 505 + dec_loop_generic_32_inner(s, o, &rounds)) { 506 + continue; 507 + } 508 + break; 509 + } 510 + if (rounds >= 4) { 511 + if (dec_loop_generic_32_inner(s, o, &rounds) && 512 + dec_loop_generic_32_inner(s, o, &rounds) && 513 + dec_loop_generic_32_inner(s, o, &rounds) && 514 + dec_loop_generic_32_inner(s, o, &rounds)) { 515 + continue; 516 + } 517 + break; 518 + } 519 + if (rounds >= 2) { 520 + if (dec_loop_generic_32_inner(s, o, &rounds) && 521 + dec_loop_generic_32_inner(s, o, &rounds)) { 522 + continue; 523 + } 524 + break; 525 + } 526 + dec_loop_generic_32_inner(s, o, &rounds); 527 + break; 528 + 529 + } while (rounds > 0); 530 + 531 + // Adjust for any rounds that were skipped: 532 + *slen += rounds * 4; 533 + *olen -= rounds * 3; 534 + } 535 + 536 + nonnull((1,2,4,5)) 537 + static really_inline int base64_stream_decode( 538 + struct base64_state *state, 539 + const char *src, 540 + size_t srclen, 541 + uint8_t *out, 542 + size_t *outlen) 543 + { 544 + int ret = 0; 545 + const uint8_t *s = (const uint8_t *) src; 546 + uint8_t *o = (uint8_t *) out; 547 + uint8_t q; 548 + 549 + // Use local temporaries to avoid cache thrashing: 550 + size_t olen = 0; 551 + size_t slen = srclen; 552 + struct base64_state st; 553 + st.eof = state->eof; 554 + st.bytes = state->bytes; 555 + st.carry = state->carry; 556 + 557 + // If we previously saw an EOF or an invalid character, bail out: 558 + if (st.eof) { 559 + *outlen = 0; 560 + ret = 0; 561 + // If there was a trailing '=' to check, check it: 562 + if (slen && (st.eof == BASE64_AEOF)) { 563 + state->bytes = 0; 564 + state->eof = BASE64_EOF; 565 + ret = ((base64_table_dec_8bit[*s++] == 254) && (slen == 1)) ? 1 : 0; 566 + } 567 + return ret; 568 + } 569 + 570 + // Turn four 6-bit numbers into three bytes: 571 + // out[0] = 11111122 572 + // out[1] = 22223333 573 + // out[2] = 33444444 574 + 575 + // Duff's device again: 576 + switch (st.bytes) 577 + { 578 + #if defined(__SUNPRO_C) 579 + #pragma error_messages(off, E_STATEMENT_NOT_REACHED) 580 + #endif 581 + for (;;) 582 + #if defined(__SUNPRO_C) 583 + #pragma error_messages(default, E_STATEMENT_NOT_REACHED) 584 + #endif 585 + { 586 + case 0: 587 + dec_loop_generic_32(&s, &slen, &o, &olen); 588 + if (slen-- == 0) { 589 + ret = 1; 590 + break; 591 + } 592 + if ((q = base64_table_dec_8bit[*s++]) >= 254) { 593 + st.eof = BASE64_EOF; 594 + // Treat character '=' as invalid for byte 0: 595 + break; 596 + } 597 + st.carry = (uint8_t)(q << 2); 598 + st.bytes++; 599 + 600 + // fallthrough 601 + 602 + case 1: 603 + if (slen-- == 0) { 604 + ret = 1; 605 + break; 606 + } 607 + if ((q = base64_table_dec_8bit[*s++]) >= 254) { 608 + st.eof = BASE64_EOF; 609 + // Treat character '=' as invalid for byte 1: 610 + break; 611 + } 612 + *o++ = st.carry | (q >> 4); 613 + st.carry = (uint8_t)(q << 4); 614 + st.bytes++; 615 + olen++; 616 + 617 + // fallthrough 618 + 619 + case 2: 620 + if (slen-- == 0) { 621 + ret = 1; 622 + break; 623 + } 624 + if ((q = base64_table_dec_8bit[*s++]) >= 254) { 625 + st.bytes++; 626 + // When q == 254, the input char is '='. 627 + // Check if next byte is also '=': 628 + if (q == 254) { 629 + if (slen-- != 0) { 630 + st.bytes = 0; 631 + // EOF: 632 + st.eof = BASE64_EOF; 633 + q = base64_table_dec_8bit[*s++]; 634 + ret = ((q == 254) && (slen == 0)) ? 1 : 0; 635 + break; 636 + } 637 + else { 638 + // Almost EOF 639 + st.eof = BASE64_AEOF; 640 + ret = 1; 641 + break; 642 + } 643 + } 644 + // If we get here, there was an error: 645 + break; 646 + } 647 + *o++ = st.carry | (q >> 2); 648 + st.carry = (uint8_t)(q << 6); 649 + st.bytes++; 650 + olen++; 651 + 652 + // fallthrough 653 + 654 + case 3: 655 + if (slen-- == 0) { 656 + ret = 1; 657 + break; 658 + } 659 + if ((q = base64_table_dec_8bit[*s++]) >= 254) { 660 + st.bytes = 0; 661 + st.eof = BASE64_EOF; 662 + // When q == 254, the input char is '='. Return 1 and EOF. 663 + // When q == 255, the input char is invalid. Return 0 and EOF. 664 + ret = ((q == 254) && (slen == 0)) ? 1 : 0; 665 + break; 666 + } 667 + *o++ = st.carry | q; 668 + st.carry = 0; 669 + st.bytes = 0; 670 + olen++; 671 + } 672 + } 673 + 674 + state->eof = st.eof; 675 + state->bytes = st.bytes; 676 + state->carry = st.carry; 677 + *outlen = olen; 678 + return ret; 679 + } 680 + 681 + nonnull((1,3,4)) 682 + static really_inline int base64_decode( 683 + const char *src, 684 + size_t srclen, 685 + uint8_t *out, 686 + size_t *outlen) 687 + { 688 + struct base64_state state = { .eof = 0, .bytes = 0, .carry = 0 }; 689 + return base64_stream_decode(&state, src, srclen, out, outlen) & !state.bytes; 690 + } 691 + 692 + nonnull_all 693 + static really_inline int32_t parse_base64_sequence( 694 + parser_t *parser, 695 + const type_info_t *type, 696 + const rdata_info_t *item, 697 + rdata_t *rdata, 698 + token_t *token) 699 + { 700 + if (is_contiguous(token)) { 701 + struct base64_state state = { .eof = 0, .bytes = 0, .carry = 0 }; 702 + 703 + do { 704 + size_t length = token->length / 4; 705 + if (((uintptr_t)rdata->limit - (uintptr_t)rdata->octets) / 3 < length) 706 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(item), NAME(type)); 707 + if (!base64_stream_decode(&state, token->data, token->length, rdata->octets, &length)) 708 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(item), NAME(type)); 709 + rdata->octets += length; 710 + take(parser, token); 711 + } while (is_contiguous(token)); 712 + 713 + // incomplete base64 sequence 714 + if (state.bytes) 715 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(item), NAME(type)); 716 + } 717 + 718 + return have_delimiter(parser, type, token); 719 + } 720 + 721 + nonnull_all 722 + static really_inline int32_t parse_base64( 723 + parser_t *parser, 724 + const type_info_t *type, 725 + const rdata_info_t *item, 726 + rdata_t *rdata, 727 + const token_t *token) 728 + { 729 + size_t length = token->length / 4; 730 + if (((uintptr_t)rdata->limit - (uintptr_t)rdata->octets) / 3 < length) 731 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(item), NAME(type)); 732 + if (!base64_decode(token->data, token->length, rdata->octets, &length)) 733 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(item), NAME(type)); 734 + rdata->octets += length; 735 + return 0; 736 + } 737 + 738 + #endif // BASE64_H
+81
usr.sbin/nsd/simdzone/src/generic/caa.h
··· 1 + /* 2 + * caa.h -- CAA (RFC8659) parser 3 + * 4 + * Copyright (c) 2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef CAA_H 10 + #define CAA_H 11 + 12 + static const uint8_t bad_caa_chars[256] = { 13 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x00 - 0x07 14 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x08 - 0x0f 15 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x10 - 0x17 16 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x18 - 0x10f 17 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x20 - 0x27 18 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x28 - 0x2f 19 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x30 - 0x37 20 + 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x38 - 0x3f 21 + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x40 - 0x47 22 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x48 - 0x4f 23 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50 - 0x57 24 + 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x58 - 0x5f 25 + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x60 - 0x67 26 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x68 - 0x6f 27 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x70 - 0x77 28 + 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x78 - 0x7f 29 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x80 - 0x87 30 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x88 - 0x8f 31 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x90 - 0x97 32 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x98 - 0x9f 33 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xa0 - 0xa7 34 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xa8 - 0xaf 35 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xb0 - 0xb7 36 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xb8 - 0xbf 37 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xc0 - 0xc7 38 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xc8 - 0xcf 39 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xd0 - 0xd7 40 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xd8 - 0xdf 41 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xe0 - 0xe7 42 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xe0 - 0xe7 43 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xf8 - 0xff 44 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xf8 - 0xff 45 + }; 46 + 47 + nonnull_all 48 + static really_inline int32_t parse_caa_tag( 49 + parser_t *parser, 50 + const type_info_t *type, 51 + const rdata_info_t *field, 52 + rdata_t *rdata, 53 + const token_t *token) 54 + { 55 + // RFC8659 section 4.1 56 + // https://datatracker.ietf.org/doc/html/rfc8659 57 + // 58 + // Certification Authority Restriction Properties registered by IANA 59 + // https://www.iana.org/assignments/pkix-parameters/pkix-parameters.xhtml 60 + 61 + if (token->length > 255) 62 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 63 + *rdata->octets++ = (uint8_t)token->length; 64 + 65 + uint32_t bad_chars = 0; 66 + for (size_t count=0; count < token->length; count++) { 67 + const uint8_t octet = (uint8_t)token->data[count]; 68 + *rdata->octets++ = octet; 69 + bad_chars |= bad_caa_chars[octet]; 70 + } 71 + 72 + // Tags MAY contain ASCII characters "a" through "z", "A" through "Z", 73 + // and the numbers 0 through 9. Tags MUST NOT contain any other 74 + // characters. Matching of tags is case insensitive. 75 + if (bad_chars) 76 + SEMANTIC_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 77 + 78 + return 0; 79 + } 80 + 81 + #endif // CAA_H
+123
usr.sbin/nsd/simdzone/src/generic/cert.h
··· 1 + /* 2 + * cert.h 3 + * 4 + * Copyright (c) 2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef CERT_H 10 + #define CERT_H 11 + 12 + // https://www.iana.org/assignments/cert-rr-types/cert-rr-types.xhtml 13 + 14 + typedef struct certificate_type certificate_type_t; 15 + struct certificate_type { 16 + struct { 17 + char name[8]; 18 + size_t length; 19 + } key; 20 + uint16_t value; 21 + }; 22 + 23 + #define BAD_CERTIFICATE_TYPE(value) \ 24 + { { "", 0 }, 0 } 25 + #define CERTIFICATE_TYPE(name, value) \ 26 + { { name, sizeof(name) - 1 }, value } 27 + 28 + static const certificate_type_t certificate_types[] = { 29 + BAD_CERTIFICATE_TYPE(0), 30 + CERTIFICATE_TYPE("PKIX", 1), 31 + CERTIFICATE_TYPE("SPKI", 2), 32 + CERTIFICATE_TYPE("PGP", 3), 33 + CERTIFICATE_TYPE("IPKIX", 4), 34 + CERTIFICATE_TYPE("ISPKI", 5), 35 + CERTIFICATE_TYPE("IPGP", 6), 36 + CERTIFICATE_TYPE("ACPKIX", 7), 37 + CERTIFICATE_TYPE("IACPKIX", 8), 38 + CERTIFICATE_TYPE("URI", 253), 39 + CERTIFICATE_TYPE("OID", 254), 40 + }; 41 + 42 + static const certificate_type_t *certificate_type_map[16] = { 43 + &certificate_types[5], // ISPKI (0) 44 + &certificate_types[0], 45 + &certificate_types[0], 46 + &certificate_types[0], 47 + &certificate_types[0], 48 + &certificate_types[0], 49 + &certificate_types[10], // OID (6) 50 + &certificate_types[0], 51 + &certificate_types[3], // PGP (8) 52 + &certificate_types[4], // IPKIX (9) 53 + &certificate_types[2], // SPKI (10) 54 + &certificate_types[1], // PKIX (11) 55 + &certificate_types[8], // IACPKIX (12) 56 + &certificate_types[9], // URI (13) 57 + &certificate_types[6], // IPGP (14) 58 + &certificate_types[7] // ACPKIX (15) 59 + }; 60 + 61 + // magic value generated using certificate-hash.c 62 + static uint8_t certificate_hash(uint64_t value) 63 + { 64 + value = le64toh(value); 65 + uint32_t value32 = (uint32_t)((value >> 32) ^ value); 66 + return (uint8_t)((value32 * 98112ull) >> 32) & 0xf; 67 + } 68 + 69 + nonnull_all 70 + static really_inline int32_t scan_certificate_type( 71 + const char *data, size_t length, uint16_t *type) 72 + { 73 + static const int8_t zero_masks[48] = { 74 + -1, -1, -1, -1, -1, -1, -1, -1, 75 + -1, -1, -1, -1, -1, -1, -1, -1, 76 + -1, -1, -1, -1, -1, -1, -1, -1, 77 + -1, -1, -1, -1, -1, -1, -1, -1, 78 + 0, 0, 0, 0, 0, 0, 0, 0, 79 + 0, 0, 0, 0, 0, 0, 0, 0 80 + }; 81 + 82 + if ((uint8_t)*data - '0' > 9) { 83 + uint64_t input; 84 + memcpy(&input, data, 8); 85 + static const uint64_t letter_mask = 0x4040404040404040llu; 86 + // convert to upper case 87 + input &= ~((input & letter_mask) >> 1); 88 + // zero out non-relevant bytes 89 + uint64_t zero_mask; 90 + memcpy(&zero_mask, &zero_masks[32 - (length & 0xf)], 8); 91 + input &= zero_mask; 92 + const uint8_t index = certificate_hash(input); 93 + assert(index < 16); 94 + const certificate_type_t *certificate_type = certificate_type_map[index]; 95 + uint64_t name; 96 + memcpy(&name, certificate_type->key.name, 8); 97 + *type = certificate_type->value; 98 + return (input == name) & 99 + (length == certificate_type->key.length) & 100 + (*type != 0); 101 + } 102 + 103 + return scan_int16(data, length, type); 104 + } 105 + 106 + nonnull_all 107 + static really_inline int32_t parse_certificate_type( 108 + parser_t *parser, 109 + const type_info_t *type, 110 + const rdata_info_t *field, 111 + rdata_t *rdata, 112 + const token_t *token) 113 + { 114 + uint16_t cert; 115 + if (!scan_certificate_type(token->data, token->length, &cert)) 116 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 117 + cert = htobe16(cert); 118 + memcpy(rdata->octets, &cert, 2); 119 + rdata->octets += 2; 120 + return 0; 121 + } 122 + 123 + #endif // CERT_H
+226
usr.sbin/nsd/simdzone/src/generic/endian.h
··· 1 + /* 2 + * endian.h -- byte order abstractions 3 + * 4 + * Copyright (c) 2023, NLnet Labs. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef ENDIAN_H 10 + #define ENDIAN_H 11 + 12 + #include "config.h" 13 + 14 + // https://www.austingroupbugs.net/view.php?id=162#c665 15 + 16 + #if _WIN32 17 + #include <stdlib.h> 18 + 19 + #define LITTLE_ENDIAN 1234 20 + #define BIG_ENDIAN 4321 21 + #define BYTE_ORDER LITTLE_ENDIAN 22 + 23 + #if BYTE_ORDER == LITTLE_ENDIAN 24 + #define htobe16(x) _byteswap_ushort(x) 25 + #define htobe32(x) _byteswap_ulong(x) 26 + #define htobe64(x) _byteswap_uint64(x) 27 + #define htole16(x) (x) 28 + #define htole32(x) (x) 29 + #define htole64(x) (x) 30 + 31 + #define be16toh(x) _byteswap_ushort(x) 32 + #define be32toh(x) _byteswap_ulong(x) 33 + #define be64toh(x) _byteswap_uint64(x) 34 + #define le16toh(x) (x) 35 + #define le32toh(x) (x) 36 + #define le64toh(x) (x) 37 + #else 38 + #define htobe16(x) (x) 39 + #define htobe32(x) (x) 40 + #define htobe64(x) (x) 41 + #define htole16(x) _byteswap_ushort(x) 42 + #define htole32(x) _byteswap_ulong(x) 43 + #define htole64(x) _byteswap_uint64(x) 44 + 45 + #define be16toh(x) (x) 46 + #define be32toh(x) (x) 47 + #define be64toh(x) (x) 48 + #define le16toh(x) _byteswap_ushort(x) 49 + #define le32toh(x) _byteswap_ulong(x) 50 + #define le64toh(x) _byteswap_uint64(x) 51 + #endif 52 + 53 + #elif __APPLE__ 54 + #include <libkern/OSByteOrder.h> 55 + 56 + #if !defined BYTE_ORDER 57 + # define BYTE_ORDER __BYTE_ORDER__ 58 + #endif 59 + #if !defined LITTLE_ENDIAN 60 + # define LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__ 61 + #endif 62 + #if !defined BIG_ENDIAN 63 + # define BIG_ENDIAN __ORDER_BIG_ENDIAN__ 64 + #endif 65 + 66 + #define htobe16(x) OSSwapHostToBigInt16(x) 67 + #define htobe32(x) OSSwapHostToBigInt32(x) 68 + #define htobe64(x) OSSwapHostToBigInt64(x) 69 + #define htole16(x) OSSwapHostToLittleInt16(x) 70 + #define htole32(x) OSSwapHostToLittleInt32(x) 71 + #define htole64(x) OSSwapHostToLittleInt64(x) 72 + 73 + #define be16toh(x) OSSwapBigToHostInt16(x) 74 + #define be32toh(x) OSSwapBigToHostInt32(x) 75 + #define be64toh(x) OSSwapBigToHostInt64(x) 76 + #define le16toh(x) OSSwapLittleToHostInt16(x) 77 + #define le32toh(x) OSSwapLittleToHostInt32(x) 78 + #define le64toh(x) OSSwapLittleToHostInt64(x) 79 + 80 + #else 81 + #if HAVE_ENDIAN_H 82 + #include <endian.h> 83 + #elif defined(__OpenBSD__) 84 + // endian.h was added in OpenBSD 5.6. machine/endian.h exports optimized 85 + // bswap routines for use in sys/endian.h, which it includes. 86 + #include <machine/endian.h> 87 + #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) 88 + #include <sys/endian.h> 89 + #endif 90 + 91 + #if defined(__NetBSD__) 92 + /* Bring bswap{16,32,64} into scope: */ 93 + #include <sys/types.h> 94 + #include <machine/bswap.h> 95 + #endif 96 + 97 + #if !defined(LITTLE_ENDIAN) 98 + # if defined(__ORDER_LITTLE_ENDIAN__) 99 + # define LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__ 100 + # else 101 + # define LITTLE_ENDIAN 1234 102 + # endif 103 + #endif 104 + 105 + #if !defined(BIG_ENDIAN) 106 + # if defined(__ORDER_BIG_ENDIAN__) 107 + # define BIG_ENDIAN __ORDER_BIG_ENDIAN__ 108 + # else 109 + # define BIG_ENDIAN 4321 110 + # endif 111 + #endif 112 + 113 + #if !defined(BYTE_ORDER) 114 + # if defined(__BYTE_ORDER__) 115 + # define BYTE_ORDER __BYTE_ORDER__ 116 + # elif defined(__BYTE_ORDER) 117 + # define BYTE_ORDER __BYTE_ORDER 118 + # elif defined(i386) || defined(__i386__) || defined(__i486__) || \ 119 + defined(__i586__) || defined(__i686__) || \ 120 + defined(__x86) || defined(__x86_64) || defined(__x86_64__) || \ 121 + defined(__amd64) || defined(__amd64__) 122 + # define BYTE_ORDER LITTLE_ENDIAN 123 + # elif defined(sparc) || defined(__sparc) || defined(__sparc__) || \ 124 + defined(POWERPC) || defined(mc68000) || defined(sel) 125 + # define BYTE_ORDER BIG_ENDIAN 126 + # else 127 + # error "missing definition of BYTE_ORDER" 128 + # endif 129 + #endif 130 + 131 + #if !defined(__NetBSD__) 132 + 133 + #if !HAVE_DECL_BSWAP16 134 + static really_inline uint16_t bswap16(uint16_t x) 135 + { 136 + // Copied from src/common/lib/libc/gen/bswap16.c in NetBSD 137 + // Written by Manuel Bouyer <bouyer@NetBSD.org>. 138 + // Public domain. 139 + return ((x << 8) & 0xff00) | ((x >> 8) & 0x00ff); 140 + } 141 + #endif 142 + 143 + #if !HAVE_DECL_BSWAP32 144 + static really_inline uint32_t bswap32(uint32_t x) 145 + { 146 + // Copied from src/common/lib/libc/gen/bswap32.c in NetBSD 147 + // Written by Manuel Bouyer <bouyer@NetBSD.org>. 148 + // Public domain. 149 + return ( (x << 24) & 0xff000000 ) | 150 + ( (x << 8) & 0x00ff0000 ) | 151 + ( (x >> 8) & 0x0000ff00 ) | 152 + ( (x >> 24) & 0x000000ff ); 153 + } 154 + #endif 155 + 156 + #if !HAVE_DECL_BSWAP64 157 + static really_inline uint64_t bswap64(uint64_t x) 158 + { 159 + // Copied from src/common/lib/libc/gen/bswap64.c in NetBSD 160 + // Written by Manuel Bouyer <bouyer@NetBSD.org>. 161 + // Public domain. 162 + return ( (x << 56) & 0xff00000000000000ull ) | 163 + ( (x << 40) & 0x00ff000000000000ull ) | 164 + ( (x << 24) & 0x0000ff0000000000ull ) | 165 + ( (x << 8) & 0x000000ff00000000ull ) | 166 + ( (x >> 8) & 0x00000000ff000000ull ) | 167 + ( (x >> 24) & 0x0000000000ff0000ull ) | 168 + ( (x >> 40) & 0x000000000000ff00ull ) | 169 + ( (x >> 56) & 0x00000000000000ffull ); 170 + } 171 + #endif 172 + 173 + #endif /* !defined(__NetBSD__) */ 174 + 175 + # if BYTE_ORDER == LITTLE_ENDIAN 176 + # define htobe(bits, x) bswap ## bits((x)) 177 + # define htole(bits, x) (x) 178 + # define betoh(bits, x) bswap ## bits((x)) 179 + # define letoh(bits, x) (x) 180 + # else 181 + # define htobe(bits, x) (x) 182 + # define htole(bits, x) bswap ## bits((x)) 183 + # define betoh(bits, x) (x) 184 + # define letoh(bits, x) bswap ## bits((x)) 185 + # endif 186 + 187 + # if !defined htobe16 188 + # define htobe16(x) htobe(16,(x)) 189 + # endif 190 + # if !defined htobe32 191 + # define htobe32(x) htobe(32,(x)) 192 + # endif 193 + # if !defined htobe64 194 + # define htobe64(x) htobe(64,(x)) 195 + # endif 196 + # if !defined htole16 197 + # define htole16(x) htole(16,(x)) 198 + # endif 199 + # if !defined htole32 200 + # define htole32(x) htole(32,(x)) 201 + # endif 202 + # if !defined htole64 203 + # define htole64(x) htole(64,(x)) 204 + # endif 205 + 206 + # if !defined be16toh 207 + # define be16toh(x) betoh(16,(x)) 208 + # endif 209 + # if !defined be32toh 210 + # define be32toh(x) betoh(32,(x)) 211 + # endif 212 + # if !defined be64toh 213 + # define be64toh(x) betoh(64,(x)) 214 + # endif 215 + # if !defined le16toh 216 + # define le16toh(x) letoh(16,(x)) 217 + # endif 218 + # if !defined le32toh 219 + # define le32toh(x) letoh(32,(x)) 220 + # endif 221 + # if !defined le64toh 222 + # define le64toh(x) letoh(64,(x)) 223 + # endif 224 + #endif 225 + 226 + #endif // ENDIAN_H
+67
usr.sbin/nsd/simdzone/src/generic/eui.h
··· 1 + /* 2 + * eui.h -- EUI-48 and EUI-64 (RFC7043) parser 3 + * 4 + * Copyright (c) 2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef EUI_H 10 + #define EUI_H 11 + 12 + nonnull((1,2)) 13 + static really_inline bool 14 + eui_base16_dec_loop_generic_32_inner(const uint8_t *s, uint8_t *o, bool last) 15 + { 16 + const uint32_t val1 = base16_table_dec_32bit_d0[s[0]] 17 + | base16_table_dec_32bit_d1[s[1]]; 18 + const uint32_t val2 = base16_table_dec_32bit_d0[s[3]] 19 + | base16_table_dec_32bit_d1[s[4]]; 20 + 21 + if (val1 > 0xff || val2 > 0xff || s[2] != '-' || (!last && s[5] != '-')) 22 + return false; 23 + 24 + o[0] = (uint8_t)val1; 25 + o[1] = (uint8_t)val2; 26 + 27 + return true; 28 + } 29 + 30 + // RFC7043 section 3.2, require xx-xx-xx-xx-xx-xx 31 + nonnull_all 32 + static really_inline int32_t parse_eui48( 33 + parser_t *parser, 34 + const type_info_t *type, 35 + const rdata_info_t *field, 36 + rdata_t *rdata, 37 + const token_t *token) 38 + { 39 + const uint8_t *input = (const uint8_t *)token->data; 40 + if (token->length == 17 && 41 + eui_base16_dec_loop_generic_32_inner(input, rdata->octets, false) && 42 + eui_base16_dec_loop_generic_32_inner(input+6, rdata->octets+2, false) && 43 + eui_base16_dec_loop_generic_32_inner(input+12, rdata->octets+4, true)) 44 + return (void)(rdata->octets += 6), 0; 45 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 46 + } 47 + 48 + // RFC7043 section 4.2, require xx-xx-xx-xx-xx-xx-xx-xx 49 + nonnull_all 50 + static really_inline int32_t parse_eui64( 51 + parser_t *parser, 52 + const type_info_t *type, 53 + const rdata_info_t *field, 54 + rdata_t *rdata, 55 + const token_t *token) 56 + { 57 + const uint8_t *input = (const uint8_t *)token->data; 58 + if (token->length == 23 && 59 + eui_base16_dec_loop_generic_32_inner(input, rdata->octets, false) && 60 + eui_base16_dec_loop_generic_32_inner(input+6, rdata->octets+2, false) && 61 + eui_base16_dec_loop_generic_32_inner(input+12, rdata->octets+4, false) && 62 + eui_base16_dec_loop_generic_32_inner(input+18, rdata->octets+6, true)) 63 + return (void)(rdata->octets += 8), 0; 64 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 65 + } 66 + 67 + #endif // EUI_H
+419
usr.sbin/nsd/simdzone/src/generic/format.h
··· 1 + /* 2 + * format.h 3 + * 4 + * Copyright (c) 2022, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef FORMAT_H 10 + #define FORMAT_H 11 + 12 + #define FIELDS(fields) \ 13 + { (sizeof(fields)/sizeof(fields[0])), fields } 14 + 15 + #define FIELD(name) \ 16 + { { { name, sizeof(name) - 1 } } } 17 + 18 + #define ENTRY(name, fields) \ 19 + { { { name, sizeof(name) - 1 }, 0 }, 0, false, false, fields, 0, 0 } 20 + 21 + nonnull_all 22 + static really_inline int32_t parse_type( 23 + parser_t *parser, 24 + const type_info_t *type, 25 + const rdata_info_t *field, 26 + rdata_t *rdata, 27 + const token_t *token) 28 + { 29 + uint16_t code; 30 + const mnemonic_t *mnemonic; 31 + 32 + if (scan_type(token->data, token->length, &code, &mnemonic) != 1) 33 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 34 + code = htobe16(code); 35 + memcpy(rdata->octets, &code, 2); 36 + rdata->octets += 2; 37 + return 0; 38 + } 39 + 40 + nonnull_all 41 + static really_inline int32_t parse_name( 42 + parser_t *parser, 43 + const type_info_t *type, 44 + const rdata_info_t *field, 45 + rdata_t *rdata, 46 + const token_t *token) 47 + { 48 + size_t length = 0; 49 + 50 + assert(is_contiguous(token)); 51 + 52 + // a freestanding "@" denotes the current origin 53 + if (unlikely(token->length == 1 && token->data[0] == '@')) 54 + goto relative; 55 + switch (scan_name(token->data, token->length, rdata->octets, &length)) { 56 + case 0: 57 + rdata->octets += length; 58 + return 0; 59 + case 1: 60 + goto relative; 61 + } 62 + 63 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 64 + 65 + relative: 66 + if (length > 255 - parser->file->origin.length) 67 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 68 + memcpy(rdata->octets + length, parser->file->origin.octets, parser->file->origin.length); 69 + rdata->octets += length + parser->file->origin.length; 70 + return 0; 71 + } 72 + 73 + nonnull_all 74 + static really_inline int32_t parse_owner( 75 + parser_t *parser, 76 + const type_info_t *type, 77 + const rdata_info_t *field, 78 + const token_t *token) 79 + { 80 + size_t length = 0; 81 + uint8_t *octets = parser->file->owner.octets; 82 + 83 + assert(is_contiguous(token)); 84 + 85 + // a freestanding "@" denotes the origin 86 + if (unlikely(token->length == 1 && token->data[0] == '@')) 87 + goto relative; 88 + switch (scan_name(token->data, token->length, octets, &length)) { 89 + case 0: 90 + parser->file->owner.length = length; 91 + parser->owner = &parser->file->owner; 92 + return 0; 93 + case 1: 94 + goto relative; 95 + } 96 + 97 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 98 + 99 + relative: 100 + if (length > 255 - parser->file->origin.length) 101 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 102 + memcpy(octets+length, parser->file->origin.octets, parser->file->origin.length); 103 + parser->file->owner.length = length + parser->file->origin.length; 104 + parser->owner = &parser->file->owner; 105 + return 0; 106 + } 107 + 108 + nonnull_all 109 + static really_inline int32_t parse_string( 110 + parser_t *parser, 111 + const type_info_t *type, 112 + const rdata_info_t *field, 113 + rdata_t *rdata, 114 + const token_t *token) 115 + { 116 + if (rdata->limit == rdata->octets) 117 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(type), NAME(field)); 118 + assert(rdata->limit > rdata->octets); 119 + 120 + int32_t length; 121 + uint8_t *octets = rdata->octets + 1; 122 + const uint8_t *limit = rdata->limit; 123 + 124 + if (rdata->limit - rdata->octets > (1 + 255)) 125 + limit = rdata->octets + 1 + 255; 126 + if ((length = scan_string(token->data, token->length, octets, limit)) == -1) 127 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(type), NAME(field)); 128 + *rdata->octets = (uint8_t)length; 129 + rdata->octets += 1u + (uint32_t)length; 130 + return 0; 131 + } 132 + 133 + nonnull_all 134 + static really_inline int32_t parse_text( 135 + parser_t *parser, 136 + const type_info_t *type, 137 + const rdata_info_t *field, 138 + rdata_t *rdata, 139 + const token_t *token) 140 + { 141 + int32_t length; 142 + 143 + if ((length = scan_string(token->data, token->length, rdata->octets, rdata->limit)) == -1) 144 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(type), NAME(field)); 145 + rdata->octets += (uint32_t)length; 146 + return 0; 147 + } 148 + 149 + nonnull_all 150 + static really_inline int32_t parse_rr( 151 + parser_t *parser, token_t *token) 152 + { 153 + static const rdata_info_t fields[] = { 154 + FIELD("OWNER"), 155 + FIELD("TYPE"), 156 + FIELD("CLASS"), 157 + FIELD("TTL") 158 + }; 159 + 160 + static const type_info_t rr = ENTRY("RR", FIELDS(fields)); 161 + 162 + int32_t code; 163 + const type_info_t *descriptor; 164 + const mnemonic_t *mnemonic; 165 + rdata_t rdata = { parser->rdata->octets, parser->rdata->octets + 65535 }; 166 + 167 + parser->file->ttl = parser->file->default_ttl; 168 + 169 + if ((uint8_t)token->data[0] - '0' < 10) { 170 + parser->file->ttl = &parser->file->last_ttl; 171 + if (!scan_ttl(token->data, token->length, parser->options.pretty_ttls, &parser->file->last_ttl)) 172 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[3]), NAME(&rr)); 173 + if (parser->file->last_ttl & (1u << 31)) 174 + SEMANTIC_ERROR(parser, "Invalid %s in %s", NAME(&fields[3]), NAME(&rr)); 175 + goto class_or_type; 176 + } else { 177 + switch (scan_type_or_class(token->data, token->length, &parser->file->last_type, &mnemonic)) { 178 + case 1: 179 + goto rdata; 180 + case 2: 181 + parser->file->last_class = parser->file->last_type; 182 + goto ttl_or_type; 183 + default: 184 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[1]), NAME(&rr)); 185 + } 186 + } 187 + 188 + ttl_or_type: 189 + if ((code = take_contiguous(parser, &rr, &fields[1], token)) < 0) 190 + return code; 191 + if ((uint8_t)token->data[0] - '0' < 10) { 192 + parser->file->ttl = &parser->file->last_ttl; 193 + if (!scan_ttl(token->data, token->length, parser->options.pretty_ttls, &parser->file->last_ttl)) 194 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[3]), NAME(&rr)); 195 + if (parser->file->last_ttl & (1u << 31)) 196 + SEMANTIC_ERROR(parser, "Invalid %s in %s", NAME(&fields[3]), NAME(&rr)); 197 + goto type; 198 + } else { 199 + if (unlikely(scan_type(token->data, token->length, &parser->file->last_type, &mnemonic) != 1)) 200 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[1]), NAME(&rr)); 201 + goto rdata; 202 + } 203 + 204 + class_or_type: 205 + if ((code = take_contiguous(parser, &rr, &fields[1], token)) < 0) 206 + return code; 207 + switch (scan_type_or_class(token->data, token->length, &parser->file->last_type, &mnemonic)) { 208 + case 1: 209 + goto rdata; 210 + case 2: 211 + parser->file->last_class = parser->file->last_type; 212 + goto type; 213 + default: 214 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[0]), NAME(&rr)); 215 + } 216 + 217 + type: 218 + if ((code = take_contiguous(parser, &rr, &fields[1], token)) < 0) 219 + return code; 220 + if (unlikely(scan_type(token->data, token->length, &parser->file->last_type, &mnemonic) != 1)) 221 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[1]), NAME(&rr)); 222 + 223 + rdata: 224 + descriptor = (const type_info_t *)mnemonic; 225 + 226 + // RFC3597 227 + // parse generic rdata if rdata starts with "\\#" 228 + take(parser, token); 229 + if (likely(token->data[0] != '\\')) 230 + return descriptor->parse(parser, descriptor, &rdata, token); 231 + else if (is_contiguous(token) && strncmp(token->data, "\\#", token->length) == 0) 232 + return parse_generic_rdata(parser, descriptor, &rdata, token); 233 + else 234 + return descriptor->parse(parser, descriptor, &rdata, token); 235 + } 236 + 237 + // RFC1035 section 5.1 238 + // $INCLUDE <file-name> [<domain-name>] [<comment>] 239 + nonnull_all 240 + static really_inline int32_t parse_dollar_include( 241 + parser_t *parser, token_t *token) 242 + { 243 + static const rdata_info_t fields[] = { 244 + FIELD("file-name"), 245 + FIELD("domain-name") 246 + }; 247 + 248 + static const type_info_t include = ENTRY("$INCLUDE", FIELDS(fields)); 249 + 250 + if (parser->options.no_includes) 251 + NOT_PERMITTED(parser, "%s is disabled", NAME(&include)); 252 + 253 + int32_t code; 254 + file_t *file; 255 + if ((code = take_quoted_or_contiguous(parser, &include, &fields[0], token)) < 0) 256 + return code; 257 + if ((code = zone_open_file(parser, token->data, token->length, &file)) < 0) 258 + return code; 259 + 260 + name_buffer_t name; 261 + const name_buffer_t *origin = &parser->file->origin; 262 + 263 + // $INCLUDE directive MAY specify an origin 264 + take(parser, token); 265 + if (is_contiguous(token)) { 266 + if (scan_name(token->data, token->length, name.octets, &name.length) != 0) { 267 + zone_close_file(parser, file); 268 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[1]), NAME(&include)); 269 + } 270 + origin = &name; 271 + take(parser, token); 272 + } 273 + 274 + // store the current owner to restore later if necessary 275 + file_t *includer; 276 + includer = parser->file; 277 + includer->owner = *parser->owner; 278 + file->includer = includer; 279 + file->owner = *origin; 280 + file->origin = *origin; 281 + file->last_type = 0; 282 + file->last_class = includer->last_class; 283 + file->last_ttl = includer->last_ttl; 284 + file->line = 1; 285 + 286 + if (!is_delimiter(token)) { 287 + zone_close_file(parser, file); 288 + return have_delimiter(parser, &include, token); 289 + } 290 + 291 + // check for recursive includes 292 + for (uint32_t depth = 1; includer; depth++, includer = includer->includer) { 293 + if (strcmp(includer->path, file->path) == 0) { 294 + zone_error(parser, "Circular include in %s", file->name); 295 + zone_close_file(parser, file); 296 + return ZONE_SEMANTIC_ERROR; 297 + } 298 + if (depth > parser->options.include_limit) { 299 + zone_error(parser, "Include %s nested too deeply", file->name); 300 + zone_close_file(parser, file); 301 + return ZONE_SEMANTIC_ERROR; 302 + } 303 + } 304 + 305 + // signal $INCLUDE to application 306 + if (parser->options.include.callback) { 307 + code = parser->options.include.callback( 308 + parser, file->name, file->path, parser->user_data); 309 + if (code) { 310 + zone_close_file(parser, file); 311 + return code; 312 + } 313 + } 314 + 315 + adjust_line_count(parser->file); 316 + parser->file = file; 317 + return 0; 318 + } 319 + 320 + // RFC1035 section 5.1 321 + // $ORIGIN <domain-name> [<comment>] 322 + nonnull_all 323 + static inline int32_t parse_dollar_origin( 324 + parser_t *parser, token_t *token) 325 + { 326 + static const rdata_info_t fields[] = { FIELD("name") }; 327 + static const type_info_t origin = ENTRY("$ORIGIN", FIELDS(fields)); 328 + int32_t code; 329 + 330 + if ((code = take_contiguous_or_quoted(parser, &origin, &fields[0], token)) < 0) 331 + return code; 332 + if (scan_name(token->data, token->length, parser->file->origin.octets, &parser->file->origin.length) != 0) 333 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[0]), NAME(&origin)); 334 + if ((code = take_delimiter(parser, &origin, token)) < 0) 335 + return code; 336 + 337 + adjust_line_count(parser->file); 338 + return code; 339 + } 340 + 341 + // RFC2308 section 4 342 + // $TTL <TTL> [<comment>] 343 + nonnull_all 344 + static really_inline int32_t parse_dollar_ttl( 345 + parser_t *parser, token_t *token) 346 + { 347 + static const rdata_info_t fields[] = { FIELD("ttl") }; 348 + static const type_info_t ttl = ENTRY("$TTL", FIELDS(fields)); 349 + int32_t code; 350 + 351 + if ((code = take_contiguous(parser, &ttl, &fields[0], token)) < 0) 352 + return code; 353 + if (!scan_ttl(token->data, token->length, parser->options.pretty_ttls, &parser->file->dollar_ttl)) 354 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[0]), NAME(&ttl)); 355 + if (parser->file->dollar_ttl & (1u << 31)) 356 + SEMANTIC_ERROR(parser, "Invalid %s in %s", NAME(&fields[0]), NAME(&ttl)); 357 + if ((code = take_delimiter(parser, &ttl, token)) < 0) 358 + return code; 359 + 360 + parser->file->ttl = parser->file->default_ttl = &parser->file->dollar_ttl; 361 + adjust_line_count(parser->file); 362 + return 0; 363 + } 364 + 365 + static inline int32_t parse(parser_t *parser) 366 + { 367 + static const rdata_info_t fields[] = { FIELD("OWNER") }; 368 + static const type_info_t rr = ENTRY("RR", FIELDS(fields)); 369 + 370 + int32_t code = 0; 371 + token_t token; 372 + 373 + while (code >= 0) { 374 + take(parser, &token); 375 + if (likely(is_contiguous(&token))) { 376 + if (likely(parser->file->start_of_line)) { 377 + // control entry 378 + if (unlikely(token.data[0] == '$')) { 379 + if (token.length == 4 && memcmp(token.data, "$TTL", 4) == 0) 380 + code = parse_dollar_ttl(parser, &token); 381 + else if (token.length == 7 && memcmp(token.data, "$ORIGIN", 7) == 0) 382 + code = parse_dollar_origin(parser, &token); 383 + else if (token.length == 8 && memcmp(token.data, "$INCLUDE", 8) == 0) 384 + code = parse_dollar_include(parser, &token); 385 + else 386 + SYNTAX_ERROR(parser, "Unknown control entry"); 387 + continue; 388 + } 389 + 390 + if ((code = parse_owner(parser, &rr, &fields[0], &token)) < 0) 391 + return code; 392 + if ((code = take_contiguous(parser, &rr, &fields[0], &token)) < 0) 393 + return code; 394 + } else if (unlikely(!parser->owner->length)) { 395 + SYNTAX_ERROR(parser, "No last stated owner"); 396 + } 397 + 398 + code = parse_rr(parser, &token); 399 + } else if (is_end_of_file(&token)) { 400 + if (parser->file->end_of_file == NO_MORE_DATA) { 401 + if (!parser->file->includer) 402 + break; 403 + file_t *file = parser->file; 404 + parser->file = parser->file->includer; 405 + parser->owner = &parser->file->owner; 406 + zone_close_file(parser, file); 407 + } 408 + } else if (is_line_feed(&token)) { 409 + assert(token.code == LINE_FEED); 410 + adjust_line_count(parser->file); 411 + } else { 412 + code = have_contiguous(parser, &rr, &fields[0], &token); 413 + } 414 + } 415 + 416 + return code; 417 + } 418 + 419 + #endif // FORMAT_H
+194
usr.sbin/nsd/simdzone/src/generic/gpos.h
··· 1 + /* 2 + * gpos.h -- Geographical Location (RFC1712) parser 3 + * 4 + * Copyright (c) 2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef GPOS_H 10 + #define GPOS_H 11 + 12 + nonnull_all 13 + static really_inline int32_t parse_latitude( 14 + parser_t *parser, 15 + const type_info_t *type, 16 + const rdata_info_t *field, 17 + rdata_t *rdata, 18 + const token_t *token) 19 + { 20 + const char *text = token->data + (token->data[0] == '-'); 21 + uint32_t degrees; 22 + uint8_t digits[4]; 23 + digits[0] = (uint8_t)text[0] - '0'; 24 + digits[1] = (uint8_t)text[1] - '0'; 25 + digits[2] = (uint8_t)text[2] - '0'; 26 + digits[3] = (uint8_t)text[3] - '0'; 27 + 28 + int32_t mask = ((digits[0] <= 9) << 0) | // 0b0001 29 + ((digits[1] <= 9) << 1) | // 0b0010 30 + ((digits[2] <= 9) << 2) | // 0b0100 31 + ((digits[3] <= 9) << 3); // 0b1000 32 + 33 + if (token->length > 255) 34 + goto bad_latitude; 35 + 36 + switch (mask) { 37 + case 0x01: // 0b0001 ("d...") 38 + case 0x09: // 0b1001 ("d..d") 39 + text += 1; 40 + break; 41 + case 0x03: // 0b0011 ("dd..") 42 + // ensure no leading zero and range is between -90 and 90 43 + degrees = digits[0] * 10 + digits[1]; 44 + if (degrees < 10 || degrees > 90) 45 + goto bad_latitude; 46 + text += 2; 47 + break; 48 + case 0x05: // 0b1010 ("d.d.") 49 + case 0x0d: // 0b1011 ("d.dd") 50 + if (text[1] != '.') 51 + text += 1; 52 + else 53 + for (text += 2; 10u > (uint8_t)((uint8_t)text[0] - '0'); text++) ; 54 + break; 55 + case 0x0b: // 0b1011 ("dd.d") 56 + if (text[2] != '.') 57 + text += 2; 58 + else 59 + for (text += 3; 10u > (uint8_t)((uint8_t)text[0] - '0'); text++) ; 60 + break; 61 + default: 62 + goto bad_latitude; 63 + } 64 + 65 + if (text != token->data + token->length) 66 + goto bad_latitude; 67 + 68 + *rdata->octets = (uint8_t)token->length; 69 + memcpy(rdata->octets + 1, token->data, token->length); 70 + rdata->octets += 1 + token->length; 71 + return 0; 72 + bad_latitude: 73 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 74 + } 75 + 76 + nonnull_all 77 + static really_inline int32_t parse_longitude( 78 + parser_t *parser, 79 + const type_info_t *type, 80 + const rdata_info_t *field, 81 + rdata_t *rdata, 82 + const token_t *token) 83 + { 84 + const char *text = token->data + (token->data[0] == '-'); 85 + uint32_t degrees; 86 + uint8_t digits[5]; 87 + digits[0] = (uint8_t)text[0] - '0'; 88 + digits[1] = (uint8_t)text[1] - '0'; 89 + digits[2] = (uint8_t)text[2] - '0'; 90 + digits[3] = (uint8_t)text[3] - '0'; 91 + digits[4] = (uint8_t)text[4] - '0'; 92 + 93 + int32_t mask = ((digits[0] <= 9) << 0) | // 0b00001 94 + ((digits[1] <= 9) << 1) | // 0b00010 95 + ((digits[2] <= 9) << 2) | // 0b00100 96 + ((digits[3] <= 9) << 3) | // 0b01000 97 + ((digits[4] <= 9) << 4); // 0b10000 98 + 99 + if (token->length > 255) 100 + goto bad_longitude; 101 + 102 + switch (mask) { 103 + case 0x01: // 0b00001 ("d....") 104 + case 0x09: // 0b01001 ("d..d.") 105 + case 0x19: // 0b11001 ("d..dd") 106 + text += 1; 107 + break; 108 + case 0x03: // 0b00011 ("dd...") 109 + case 0x13: // 0b10011 ("dd..d") 110 + degrees = digits[0] * 10 + digits[1]; 111 + // ensure no leading zero 112 + if (degrees < 10) 113 + goto bad_longitude; 114 + text += 2; 115 + break; 116 + case 0x07: // 0b00111 ("ddd..") 117 + // ensure no leading zero and range is between -180 and 180 118 + degrees = digits[0] * 100 + digits[1] * 10 + digits[2]; 119 + if (degrees < 100 || degrees > 180) 120 + goto bad_longitude; 121 + text += 3; 122 + break; 123 + case 0x05: // 0b00101 ("d.d..") 124 + case 0x0d: // 0b01101 ("d.dd.") 125 + case 0x1d: // 0b11101 ("d.ddd") 126 + if (text[1] != '.') 127 + text += 1; 128 + else 129 + for (text += 2; (uint8_t)((uint8_t)text[0] - '0') <= 9u; text++) ; 130 + break; 131 + case 0x0b: // 0b01011 ("dd.d.") 132 + case 0x1b: // 0b11011 ("dd.dd") 133 + // ensure no leading zero 134 + degrees = digits[0] * 10 + digits[1]; 135 + if (degrees < 10) 136 + goto bad_longitude; 137 + if (text[2] != '.') 138 + text += 2; 139 + else 140 + for (text += 3; (uint8_t)((uint8_t)text[0] - '0') <= 9u; text++) ; 141 + break; 142 + case 0x17: // 0b10111 ("ddd.d") 143 + // ensure no leading zero and range is between -180 and 180 144 + degrees = digits[0] * 100 + digits[1] * 10 + digits[2]; 145 + if (degrees < 100 || degrees > 180) 146 + goto bad_longitude; 147 + if (text[3] != '.') 148 + text += 3; 149 + else 150 + for (text += 4; (uint8_t)((uint8_t)text[0] - '0') <= 9u; text++) ; 151 + break; 152 + default: 153 + goto bad_longitude; 154 + } 155 + 156 + if (text != token->data + token->length) 157 + goto bad_longitude; 158 + 159 + *rdata->octets = (uint8_t)token->length; 160 + memcpy(rdata->octets + 1, token->data, token->length); 161 + rdata->octets += 1 + token->length; 162 + return 0; 163 + bad_longitude: 164 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 165 + } 166 + 167 + nonnull_all 168 + static really_inline int32_t parse_altitude( 169 + parser_t *parser, 170 + const type_info_t *type, 171 + const rdata_info_t *field, 172 + rdata_t *rdata, 173 + const token_t *token) 174 + { 175 + const char *text = token->data; 176 + 177 + if (token->length > 255) 178 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 179 + 180 + for (; (uint8_t)((uint8_t)*text - '0') <= 9u; text++) ; 181 + 182 + if (*text == '.') 183 + for (text++; (uint8_t)((uint8_t)*text - '0') <= 9u; text++) ; 184 + 185 + if (text != token->data + token->length) 186 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 187 + 188 + *rdata->octets = (uint8_t)token->length; 189 + memcpy(rdata->octets + 1, token->data, token->length); 190 + rdata->octets += 1 + token->length; 191 + return 0; 192 + } 193 + 194 + #endif // GPOS_H
+58
usr.sbin/nsd/simdzone/src/generic/ilnp64.h
··· 1 + /* 2 + * ilnp64.h -- 64-bit Locator (RFC6742 section 2.3) parser 3 + * 4 + * Copyright (c) 2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef ILNP64_H 10 + #define ILNP64_H 11 + 12 + // FIXME: very likely eligable for vectorization (or optimization even), but 13 + // gains are small as the type is not frequently used 14 + nonnull_all 15 + static really_inline int32_t parse_ilnp64( 16 + parser_t *parser, 17 + const type_info_t *type, 18 + const rdata_info_t *field, 19 + rdata_t *rdata, 20 + const token_t *token) 21 + { 22 + uint16_t a[4] = { 0, 0, 0, 0 }; 23 + size_t n = 0; 24 + const char *p = token->data, *g = p; 25 + for (;;) { 26 + const uint8_t c = (uint8_t)*p; 27 + if (c == ':') { 28 + if (n == 3 || p == g || p - g > 4) 29 + break; 30 + g = p += 1; 31 + n += 1; 32 + } else { 33 + uint16_t x; 34 + if (c >= '0' && c <= '9') 35 + x = c - '0'; 36 + else if (c >= 'A' && c <= 'F') 37 + x = c - ('A' - 10); 38 + else if (c >= 'a' && c <= 'f') 39 + x = c - ('a' - 10); 40 + else 41 + break; 42 + a[n] = (uint16_t)(a[n] << 4u) + x; 43 + p += 1; 44 + } 45 + } 46 + 47 + if (n != 3 || p == g || p - g > 4 || classify[(uint8_t)*p] == CONTIGUOUS) 48 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 49 + a[0] = htobe16(a[0]); 50 + a[1] = htobe16(a[1]); 51 + a[2] = htobe16(a[2]); 52 + a[3] = htobe16(a[3]); 53 + memcpy(rdata->octets, a, 8); 54 + rdata->octets += 8; 55 + return 0; 56 + } 57 + 58 + #endif // ILNP64_H
+60
usr.sbin/nsd/simdzone/src/generic/ip4.h
··· 1 + /* 2 + * ip4.h -- fallback parser for IPv4 addresses 3 + * 4 + * Copyright (c) 2022-2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef IP4_H 10 + #define IP4_H 11 + 12 + nonnull_all 13 + static really_inline int32_t scan_ip4(const char *text, uint8_t *wire) 14 + { 15 + const char *start = text; 16 + uint32_t round = 0; 17 + for (;;) { 18 + uint8_t digits[3], count; 19 + uint32_t octet; 20 + digits[0] = (uint8_t)text[0] - '0'; 21 + digits[1] = (uint8_t)text[1] - '0'; 22 + digits[2] = (uint8_t)text[2] - '0'; 23 + if (digits[0] > 9) 24 + return 0; 25 + else if (digits[1] > 9) 26 + (void)(count = 1), octet = digits[0]; 27 + else if (digits[2] > 9) 28 + (void)(count = 2), octet = digits[0] * 10 + digits[1]; 29 + else 30 + (void)(count = 3), octet = digits[0] * 100 + digits[1] * 10 + digits[2]; 31 + 32 + if (octet > 255 || (count > 1 && !digits[0])) 33 + return 0; 34 + text += count; 35 + wire[round++] = (uint8_t)octet; 36 + if (text[0] != '.' || round == 4) 37 + break; 38 + text += 1; 39 + } 40 + 41 + if (round != 4) 42 + return 0; 43 + return (int32_t)(text - start); 44 + } 45 + 46 + nonnull_all 47 + static really_inline int32_t parse_ip4( 48 + parser_t *parser, 49 + const type_info_t *type, 50 + const rdata_info_t *item, 51 + rdata_t *rdata, 52 + const token_t *token) 53 + { 54 + if ((size_t)scan_ip4(token->data, rdata->octets) != token->length) 55 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(item), NAME(type)); 56 + rdata->octets += 4; 57 + return 0; 58 + } 59 + 60 + #endif // IP4_H
+203
usr.sbin/nsd/simdzone/src/generic/ip6.h
··· 1 + /*- 2 + * SPDX-License-Identifier: ISC 3 + * 4 + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 5 + * Copyright (c) 1996,1999 by Internet Software Consortium. 6 + * 7 + * Permission to use, copy, modify, and distribute this software for any 8 + * purpose with or without fee is hereby granted, provided that the above 9 + * copyright notice and this permission notice appear in all copies. 10 + * 11 + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 12 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 14 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 17 + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 + */ 19 + #ifndef IP6_H 20 + #define IP6_H 21 + 22 + #ifndef NS_INT16SZ 23 + #define NS_INT16SZ 2 24 + #endif 25 + 26 + #ifndef NS_IN6ADDRSZ 27 + #define NS_IN6ADDRSZ 16 28 + #endif 29 + 30 + #ifndef NS_INADDRSZ 31 + #define NS_INADDRSZ 4 32 + #endif 33 + 34 + /* int 35 + * inet_pton4(src, dst) 36 + * like inet_aton() but without all the hexadecimal and shorthand. 37 + * return: 38 + * length if `src' is a valid dotted quad, else 0. 39 + * notice: 40 + * does not touch `dst' unless it's returning !0. 41 + * author: 42 + * Paul Vixie, 1996. 43 + */ 44 + static int 45 + inet_pton4(const char *src, uint8_t *dst) 46 + { 47 + static const char digits[] = "0123456789"; 48 + int saw_digit, octets, ch; 49 + uint8_t tmp[NS_INADDRSZ], *tp; 50 + const char *start = src; 51 + 52 + saw_digit = 0; 53 + octets = 0; 54 + *(tp = tmp) = 0; 55 + for (; (ch = *src); src++) { 56 + const char *pch; 57 + 58 + if ((pch = strchr(digits, ch)) != NULL) { 59 + uint32_t new = *tp * 10 + (uint32_t)(pch - digits); 60 + 61 + if (new > 255) 62 + return (0); 63 + *tp = (uint8_t)new; 64 + if (! saw_digit) { 65 + if (++octets > 4) 66 + return (0); 67 + saw_digit = 1; 68 + } 69 + } else if (ch == '.' && saw_digit) { 70 + if (octets == 4) 71 + return (0); 72 + *++tp = 0; 73 + saw_digit = 0; 74 + } else 75 + break; 76 + } 77 + if (octets < 4) 78 + return (0); 79 + 80 + memcpy(dst, tmp, NS_INADDRSZ); 81 + return (int)(src - start); 82 + } 83 + 84 + /* int 85 + * inet_pton6(src, dst) 86 + * convert presentation level address to network order binary form. 87 + * return: 88 + * length if `src' is a valid [RFC1884 2.2] address, else 0. 89 + * notice: 90 + * (1) does not touch `dst' unless it's returning !0. 91 + * (2) :: in a full address is silently ignored. 92 + * credit: 93 + * inspired by Mark Andrews. 94 + * author: 95 + * Paul Vixie, 1996. 96 + */ 97 + static int 98 + inet_pton6(const char *src, uint8_t *dst) 99 + { 100 + static const char xdigits_l[] = "0123456789abcdef", 101 + xdigits_u[] = "0123456789ABCDEF"; 102 + uint8_t tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; 103 + const char *xdigits, *curtok; 104 + int ch, saw_xdigit; 105 + uint32_t val; 106 + int len; 107 + const char *start = src; 108 + 109 + memset((tp = tmp), '\0', NS_IN6ADDRSZ); 110 + endp = tp + NS_IN6ADDRSZ; 111 + colonp = NULL; 112 + /* Leading :: requires some special handling. */ 113 + if (*src == ':') 114 + if (*++src != ':') 115 + return (0); 116 + curtok = src; 117 + saw_xdigit = 0; 118 + val = 0; 119 + for (; (ch = *src); src++) { 120 + const char *pch; 121 + 122 + if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) 123 + pch = strchr((xdigits = xdigits_u), ch); 124 + if (pch != NULL) { 125 + val <<= 4; 126 + val |= (pch - xdigits); 127 + if (val > 0xffff) 128 + return (0); 129 + saw_xdigit = 1; 130 + continue; 131 + } 132 + if (ch == ':') { 133 + curtok = src+1; 134 + if (!saw_xdigit) { 135 + if (colonp) 136 + return (0); 137 + colonp = tp; 138 + continue; 139 + } 140 + if (tp + NS_INT16SZ > endp) 141 + return (0); 142 + *tp++ = (uint8_t) (val >> 8) & 0xff; 143 + *tp++ = (uint8_t) val & 0xff; 144 + saw_xdigit = 0; 145 + val = 0; 146 + continue; 147 + } 148 + if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && 149 + (len = inet_pton4(curtok, tp)) > 0) { 150 + src = curtok + len; 151 + tp += NS_INADDRSZ; 152 + saw_xdigit = 0; 153 + break; /* '\0' was seen by inet_pton4(). */ 154 + } 155 + break; 156 + } 157 + if (saw_xdigit) { 158 + if (tp + NS_INT16SZ > endp) 159 + return (0); 160 + *tp++ = (uint8_t) (val >> 8) & 0xff; 161 + *tp++ = (uint8_t) val & 0xff; 162 + } 163 + if (colonp != NULL) { 164 + /* 165 + * Since some memmove()'s erroneously fail to handle 166 + * overlapping regions, we'll do the shift by hand. 167 + */ 168 + const int n = (int)(tp - colonp); 169 + int i; 170 + 171 + for (i = 1; i <= n; i++) { 172 + endp[- i] = colonp[n - i]; 173 + colonp[n - i] = 0; 174 + } 175 + tp = endp; 176 + } 177 + if (tp != endp) 178 + return (0); 179 + memcpy(dst, tmp, NS_IN6ADDRSZ); 180 + return (int)(src - start); 181 + } 182 + 183 + nonnull_all 184 + static really_inline int32_t scan_ip6(const char *text, uint8_t *wire) 185 + { 186 + return inet_pton6(text, wire); 187 + } 188 + 189 + nonnull_all 190 + static really_inline int32_t parse_ip6( 191 + parser_t *parser, 192 + const type_info_t *type, 193 + const rdata_info_t *item, 194 + rdata_t *rdata, 195 + const token_t *token) 196 + { 197 + if ((size_t)inet_pton6(token->data, rdata->octets) != token->length) 198 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(item), NAME(type)); 199 + rdata->octets += 16; 200 + return 0; 201 + } 202 + 203 + #endif // IP6_H
+249
usr.sbin/nsd/simdzone/src/generic/loc.h
··· 1 + /* 2 + * loc.h -- Location Information (RFC1876) parser 3 + * 4 + * Copyright (c) 2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef LOC_H 10 + #define LOC_H 11 + 12 + nonnull_all 13 + static really_inline int32_t scan_degrees( 14 + const char *text, size_t length, uint32_t *degrees) 15 + { 16 + uint8_t digits[3]; 17 + 18 + digits[0] = (uint8_t)text[0] - '0'; 19 + digits[1] = (uint8_t)text[1] - '0'; 20 + digits[2] = (uint8_t)text[2] - '0'; 21 + 22 + switch (length) { 23 + case 1: 24 + *degrees = digits[0] * 3600000; 25 + if (digits[0] > 9) 26 + return -1; 27 + return 0; 28 + case 2: 29 + *degrees = digits[0] * 36000000 + digits[1] * 3600000; 30 + if (digits[0] > 9 || digits[1] > 9) 31 + return -1; 32 + return 0; 33 + case 3: 34 + *degrees = digits[0] * 360000000 + 35 + digits[1] * 36000000 + 36 + digits[2] * 3600000; 37 + if (*degrees > 648000000u) 38 + return -1; 39 + if (digits[0] > 9 || digits[1] > 9 || digits[2] > 9) 40 + return -1; 41 + return 0; 42 + default: 43 + return -1; 44 + } 45 + } 46 + 47 + nonnull_all 48 + static really_inline int64_t scan_minutes( 49 + const char *text, size_t length, uint32_t *minutes) 50 + { 51 + uint8_t digits[2]; 52 + 53 + digits[0] = (uint8_t)text[0] - '0'; 54 + digits[1] = (uint8_t)text[1] - '0'; 55 + 56 + switch (length) { 57 + case 1: 58 + *minutes = digits[0] * 60000; 59 + if (digits[0] > 9) 60 + return -1; 61 + return 0; 62 + case 2: 63 + *minutes = digits[0] * 600000 + digits[1] * 60000; 64 + if (*minutes > 3600000 || digits[0] > 9 || digits[1] > 9) 65 + return -1; 66 + return 0; 67 + default: 68 + return -1; 69 + } 70 + } 71 + 72 + nonnull_all 73 + static really_inline int64_t scan_seconds( 74 + const char *text, size_t length, uint32_t *seconds) 75 + { 76 + uint8_t digits[3]; 77 + size_t count; 78 + 79 + digits[0] = (uint8_t)text[0] - '0'; 80 + digits[1] = (uint8_t)text[1] - '0'; 81 + 82 + if (length == 1 || text[1] == '.') { 83 + count = 1; 84 + *seconds = digits[0] * 1000; 85 + if (digits[0] > 9) 86 + return -1; 87 + digits[0] = (uint8_t)text[2] - '0'; 88 + digits[1] = (uint8_t)text[3] - '0'; 89 + digits[2] = (uint8_t)text[4] - '0'; 90 + } else if (length == 2 || text[2] == '.') { 91 + count = 2; 92 + *seconds = digits[0] * 10000 + digits[1] * 1000; 93 + if (*seconds > 60000 || digits[0] > 5 || digits[1] > 9) 94 + return -1; 95 + digits[0] = (uint8_t)text[3] - '0'; 96 + digits[1] = (uint8_t)text[4] - '0'; 97 + digits[2] = (uint8_t)text[5] - '0'; 98 + } else { 99 + return -1; 100 + } 101 + 102 + switch (length - count) { 103 + case 0: 104 + return 0; 105 + case 1: 106 + return -1; 107 + case 2: 108 + *seconds += digits[0] * 100u; 109 + if (digits[0] > 9) 110 + return -1; 111 + return 0; 112 + case 3: 113 + *seconds += digits[0] * 100u + digits[1] * 10u; 114 + if (digits[0] > 9 || digits[1] > 9) 115 + return -1; 116 + return 0; 117 + case 4: 118 + *seconds += digits[0] * 100u + digits[1] * 10u + digits[2]; 119 + if (digits[0] > 9 || digits[1] > 9 || digits[0] > 9) 120 + return -1; 121 + return 0; 122 + default: 123 + return -1; 124 + } 125 + } 126 + 127 + nonnull((1,3)) 128 + static really_inline int32_t scan_altitude( 129 + const char *text, size_t length, uint32_t *altitude) 130 + { 131 + uint64_t negative = 0, limit = 11, maximum = 4284967295llu; 132 + 133 + if (text[0] == '-') 134 + (void)(negative = 1), (void)(limit = 8), maximum = 10000000llu; 135 + 136 + length -= (text[length - 1] == 'm'); 137 + 138 + uint64_t meters = 0, index = negative; 139 + for (;; index++) { 140 + const uint8_t digit = (uint8_t)text[index] - '0'; 141 + if (digit > 9) 142 + break; 143 + meters = meters * 10 + digit; 144 + } 145 + 146 + uint64_t centimeters = meters * 100u; // convert to centimeters 147 + if (text[index] == '.') { 148 + uint8_t digits[2]; 149 + limit += 1; 150 + digits[0] = (uint8_t)text[index+1] - '0'; 151 + digits[1] = (uint8_t)text[index+2] - '0'; 152 + switch (length - index) { 153 + case 1: 154 + index += 1; 155 + break; 156 + case 2: 157 + if (digits[0] > 9) 158 + return -1; 159 + centimeters += (uint64_t)digits[0] * 10u; 160 + index += 2; 161 + break; 162 + case 3: 163 + if (digits[0] > 9 || digits[1] > 9) 164 + return -1; 165 + centimeters += (uint64_t)digits[0] * 10u + (uint64_t)digits[1]; 166 + index += 3; 167 + break; 168 + default: 169 + return -1; 170 + } 171 + } 172 + 173 + if (index == negative || index > limit || index != length || centimeters > maximum) 174 + return -1; 175 + 176 + if (negative) 177 + *altitude = (uint32_t)(10000000llu - centimeters); 178 + else 179 + *altitude = (uint32_t)(10000000llu + centimeters); 180 + 181 + return 0; 182 + } 183 + 184 + // converts ascii size/precision X * 10**Y(cm) to 0xXY 185 + nonnull((1,3)) 186 + static really_inline int32_t scan_precision( 187 + const char *text, size_t length, uint8_t *scientific) 188 + { 189 + uint64_t meters = 0, centimeters; 190 + 191 + // RFC1876 conversion routines 192 + static uint64_t poweroften[10] = { 193 + 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; 194 + 195 + length -= text[length - 1] == 'm'; 196 + 197 + size_t index = 0; 198 + for (;; index++) { 199 + const uint8_t digit = (uint8_t)text[index] - '0'; 200 + if (digit > 9) 201 + break; 202 + meters = meters * 10 + digit; 203 + } 204 + 205 + if (index == 0 || index > 8) // 0 .. 90000000.00 206 + return -1; // syntax error 207 + 208 + centimeters = meters * 100; // convert to centimeters 209 + if (text[index] == '.') { 210 + uint8_t digits[2]; 211 + digits[0] = (uint8_t)text[index+1] - '0'; 212 + digits[1] = (uint8_t)text[index+2] - '0'; 213 + switch (length - index) { 214 + case 1: 215 + index += 1; 216 + break; 217 + case 2: 218 + if (digits[0] > 9) 219 + return -1; 220 + index += 2; 221 + centimeters += digits[0] * 10; 222 + break; 223 + case 3: 224 + if (digits[0] > 9 || digits[1] > 9) 225 + return -1; 226 + index += 3; 227 + centimeters += digits[0] * 10 + digits[1]; 228 + break; 229 + default: 230 + return -1; 231 + } 232 + } 233 + 234 + if (index != length) 235 + return -1; // syntax error 236 + 237 + uint8_t exponent = 0; 238 + while (centimeters >= poweroften[exponent+1] && exponent < 9) 239 + exponent++; 240 + 241 + uint8_t mantissa = (uint8_t)(centimeters / poweroften[exponent]); 242 + if (mantissa > 9u) 243 + mantissa = 9u; 244 + 245 + *scientific = (uint8_t)(mantissa << 4) | exponent; 246 + return 0; 247 + } 248 + 249 + #endif // LOC_H
+158
usr.sbin/nsd/simdzone/src/generic/name.h
··· 1 + /* 2 + * name.h -- domain name parser 3 + * 4 + * Copyright (c) 2022-2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef NAME_H 10 + #define NAME_H 11 + 12 + typedef struct name_block name_block_t; 13 + struct name_block { 14 + uint64_t backslashes; 15 + uint64_t dots; 16 + }; 17 + 18 + nonnull_all 19 + static really_inline void copy_name_block( 20 + name_block_t *block, const char *text, uint8_t *wire) 21 + { 22 + simd_8x32_t input; 23 + simd_loadu_8x32(&input, text); 24 + simd_storeu_8x32(wire, &input); 25 + block->backslashes = simd_find_8x32(&input, '\\'); 26 + block->dots = simd_find_8x32(&input, '.'); 27 + } 28 + 29 + nonnull_all 30 + static really_inline int32_t scan_name( 31 + const char *data, 32 + size_t tlength, 33 + uint8_t octets[255 + ZONE_BLOCK_SIZE], 34 + size_t *lengthp) 35 + { 36 + uint64_t label = 0; 37 + const char *text = data; 38 + uint8_t *wire = octets + 1; 39 + name_block_t block; 40 + 41 + octets[0] = 0; 42 + 43 + // real world domain names quickly exceed 16 octets (www.example.com is 44 + // encoded as 3www7example3com0, or 18 octets), but rarely exceed 32 45 + // octets. encode in 32-byte blocks. 46 + copy_name_block(&block, text, wire); 47 + 48 + uint64_t count = 32, length = 0, base = 0, left = tlength; 49 + uint64_t carry = 0; 50 + if (tlength < 32) 51 + count = tlength; 52 + uint64_t mask = (1llu << count) - 1u; 53 + 54 + // check for escape sequences 55 + if (unlikely(block.backslashes & mask)) 56 + goto escaped; 57 + 58 + // check for root, i.e. "." 59 + if (unlikely(block.dots & 1llu)) 60 + return ((*lengthp = tlength) == 1 ? 0 : -1); 61 + 62 + length = count; 63 + block.dots &= mask; 64 + carry = (block.dots >> (length - 1)); 65 + 66 + // check for null labels, i.e. ".." 67 + if (unlikely(block.dots & (block.dots >> 1))) 68 + return -1; 69 + 70 + if (likely(block.dots)) { 71 + count = trailing_zeroes(block.dots); 72 + block.dots = clear_lowest_bit(block.dots); 73 + octets[label] = (uint8_t)count; 74 + label = count + 1; 75 + while (block.dots) { 76 + count = trailing_zeroes(block.dots); 77 + block.dots = clear_lowest_bit(block.dots); 78 + octets[label] = (uint8_t)(count - label); 79 + label = count + 1; 80 + } 81 + } 82 + 83 + octets[label] = (uint8_t)(length - label); 84 + 85 + if (tlength <= 32) 86 + return (void)(*lengthp = length + 1), carry == 0; 87 + 88 + text += length; 89 + wire += length; 90 + left -= length; 91 + 92 + do { 93 + copy_name_block(&block, text, wire); 94 + count = 32; 95 + if (left < 32) 96 + count = left; 97 + mask = (1llu << count) - 1u; 98 + base = length; 99 + 100 + // check for escape sequences 101 + if (unlikely(block.backslashes & mask)) { 102 + escaped: 103 + block.backslashes &= -block.backslashes; 104 + mask = block.backslashes - 1; 105 + block.dots &= mask; 106 + count = count_ones(mask); 107 + const uint32_t octet = unescape(text+count, wire+count); 108 + if (!octet) 109 + return -1; 110 + text += count + octet; 111 + wire += count + 1; 112 + length += count + 1; 113 + left -= count + octet; 114 + count += 1; // for correct carry 115 + } else { 116 + block.dots &= mask; 117 + text += count; 118 + wire += count; 119 + length += count; 120 + left -= count; 121 + } 122 + 123 + // check for null labels, i.e. ".." 124 + if (unlikely(block.dots & ((block.dots >> 1) | carry))) 125 + return -1; 126 + carry = block.dots >> (count - 1); 127 + 128 + if (likely(block.dots)) { 129 + count = trailing_zeroes(block.dots) + base; 130 + block.dots = clear_lowest_bit(block.dots); 131 + octets[label] = (uint8_t)(count - label); 132 + // check if label exceeds 63 octets 133 + if (unlikely(count - label > 63)) 134 + return -1; 135 + label = count + 1; 136 + while (block.dots) { 137 + count = trailing_zeroes(block.dots) + base; 138 + block.dots = clear_lowest_bit(block.dots); 139 + octets[label] = (uint8_t)(count - label); 140 + label = count + 1; 141 + } 142 + } else { 143 + // check if label exceeds 63 octets 144 + if (length - label > 63) 145 + return -1; 146 + } 147 + 148 + octets[label] = (uint8_t)(length - label); 149 + } while (left && length < 255); 150 + 151 + if (length >= 255) 152 + return -1; 153 + 154 + *lengthp = length + 1; 155 + return carry == 0; 156 + } 157 + 158 + #endif // NAME_H
+63
usr.sbin/nsd/simdzone/src/generic/nsap.h
··· 1 + /* 2 + * nsap.h -- NSAP (RFC1706) parser 3 + * 4 + * Copyright (c) 2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef NSAP_H 10 + #define NSAP_H 11 + 12 + // https://datatracker.ietf.org/doc/html/rfc1706 (historic) 13 + 14 + nonnull_all 15 + static really_inline int32_t parse_nsap( 16 + parser_t *parser, 17 + const type_info_t *type, 18 + const rdata_info_t *field, 19 + rdata_t *rdata, 20 + const token_t *token) 21 + { 22 + const uint8_t *data = (const uint8_t *)token->data; 23 + 24 + // RFC1706 section 7 25 + // NSAP format is "0x" (i.e., a zero followed by an 'x' character) followed 26 + // by a variable length string of hex characters (0 to 9, a to f). The hex 27 + // string is case-insensitive. "."s (i.e., periods) may be inserted in the 28 + // hex string anywhere after "0x" for readability. The "."s have no 29 + // significance other than for readability and are not propagated in the 30 + // protocol (e.g., queries or zone transfers). 31 + if (unlikely(data[0] != '0' || !(data[1] == 'X' || data[1] == 'x'))) 32 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 33 + 34 + data += 2; 35 + 36 + while (rdata->octets < rdata->limit) { 37 + uint32_t d0 = base16_table_dec_32bit_d0[data[0]]; 38 + uint32_t d1 = base16_table_dec_32bit_d1[data[1]]; 39 + if ((d0 | d1) > 0xff) { 40 + while (*data == '.') data++; 41 + d0 = base16_table_dec_32bit_d0[data[0]]; 42 + if (d0 > 0xff) 43 + break; 44 + data += 1; 45 + while (*data == '.') data++; 46 + d1 = base16_table_dec_32bit_d1[data[0]]; 47 + if (d1 > 0xff) 48 + goto bad_sequence; 49 + data += 1; 50 + } else { 51 + data += 2; 52 + } 53 + *rdata->octets++ = (uint8_t)(d0 | d1); 54 + } 55 + 56 + if (rdata->octets <= rdata->limit && data == (uint8_t *)token->data + token->length) 57 + return 0; 58 + 59 + bad_sequence: 60 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 61 + } 62 + 63 + #endif // NSAP_H
+68
usr.sbin/nsd/simdzone/src/generic/nsec.h
··· 1 + /* 2 + * nsec.h -- NSEC (RFC4043) parser 3 + * 4 + * Copyright (c) 2022-2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef NSEC_H 10 + #define NSEC_H 11 + 12 + nonnull_all 13 + static really_inline int32_t scan_type( 14 + const char *, size_t, uint16_t *, const mnemonic_t **); 15 + 16 + typedef uint8_t nsec_t[32 /* 256 / 8 */ + 2]; 17 + 18 + nonnull_all 19 + static really_inline int32_t parse_nsec( 20 + parser_t *parser, 21 + const type_info_t *type, 22 + const rdata_info_t *field, 23 + rdata_t *rdata, 24 + token_t *token) 25 + { 26 + if (likely(is_contiguous(token))) { 27 + nsec_t *bitmap = (void *)rdata->octets; 28 + assert(rdata->octets <= rdata->limit); 29 + assert((size_t)(rdata->limit - rdata->octets) >= 256 * sizeof(nsec_t)); 30 + 31 + uint32_t highest_window = 0; 32 + uint32_t windows[256] = { 0 }; 33 + 34 + do { 35 + uint16_t code; 36 + const mnemonic_t *mnemonic; 37 + 38 + if (scan_type(token->data, token->length, &code, &mnemonic) != 1) 39 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 40 + 41 + const uint8_t bit = (uint8_t)(code % 256); 42 + const uint8_t window = code / 256; 43 + const uint8_t block = bit / 8; 44 + 45 + if (!windows[window]) 46 + memset(bitmap[window], 0, sizeof(bitmap[window])); 47 + if (window > highest_window) 48 + highest_window = window; 49 + windows[window] |= 1 << block; 50 + bitmap[window][2 + block] |= (1 << (7 - bit % 8)); 51 + take(parser, token); 52 + } while (is_contiguous(token)); 53 + 54 + for (uint32_t window = 0; window <= highest_window; window++) { 55 + if (!windows[window]) 56 + continue; 57 + const uint8_t blocks = (uint8_t)(64 - leading_zeroes(windows[window])); 58 + memmove(rdata->octets, &bitmap[window], 2 + blocks); 59 + rdata->octets[0] = (uint8_t)window; 60 + rdata->octets[1] = blocks; 61 + rdata->octets += 2 + blocks; 62 + } 63 + } 64 + 65 + return have_delimiter(parser, type, token); 66 + } 67 + 68 + #endif // NSEC_H
+121
usr.sbin/nsd/simdzone/src/generic/number.h
··· 1 + /* 2 + * number.h -- integer parsing routines 3 + * 4 + * Copyright (c) 2022-2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef NUMBER_H 10 + #define NUMBER_H 11 + 12 + nonnull((1,3)) 13 + static really_inline int32_t scan_int8( 14 + const char *data, size_t length, uint8_t *number) 15 + { 16 + uint32_t sum = (uint8_t)data[0] - '0'; 17 + 18 + if (sum > 9 || !length || length > 3) 19 + return 0; 20 + 21 + for (size_t count=1; count < length; count++) { 22 + const uint8_t digit = (uint8_t)data[count] - '0'; 23 + sum = sum * 10 + digit; 24 + if (digit > 9) 25 + return 0; 26 + } 27 + 28 + *number = (uint8_t)sum; 29 + return sum <= 255u; 30 + } 31 + 32 + nonnull((1,3)) 33 + static really_inline int32_t scan_int16( 34 + const char *data, size_t length, uint16_t *number) 35 + { 36 + uint32_t sum = (uint8_t)data[0] - '0'; 37 + 38 + if (sum > 9 || !length || length > 5) 39 + return 0; 40 + 41 + for (size_t count=1; count < length; count++) { 42 + const uint8_t digit = (uint8_t)data[count] - '0'; 43 + sum = sum * 10 + digit; 44 + if (digit > 9) 45 + return 0; 46 + } 47 + 48 + *number = (uint16_t)sum; 49 + return sum <= 65535u; 50 + } 51 + 52 + nonnull((1,3)) 53 + static really_inline int32_t scan_int32( 54 + const char *data, size_t length, uint32_t *number) 55 + { 56 + uint64_t sum = (uint8_t)data[0] - '0'; 57 + 58 + if (sum > 9 || !length || length > 10) 59 + return 0; 60 + 61 + for (size_t count=1; count < length; count++) { 62 + const uint8_t digit = (uint8_t)data[count] - '0'; 63 + sum = sum * 10 + digit; 64 + if (digit > 9) 65 + return 0; 66 + } 67 + 68 + *number = (uint32_t)sum; 69 + return sum <= 4294967295u; 70 + } 71 + 72 + nonnull_all 73 + static really_inline int32_t parse_int8( 74 + parser_t *parser, 75 + const type_info_t *type, 76 + const rdata_info_t *field, 77 + rdata_t *rdata, 78 + const token_t *token) 79 + { 80 + uint8_t number; 81 + if (!scan_int8(token->data, token->length, &number)) 82 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 83 + *rdata->octets++ = number; 84 + return 0; 85 + } 86 + 87 + nonnull_all 88 + static really_inline int32_t parse_int16( 89 + parser_t *parser, 90 + const type_info_t *type, 91 + const rdata_info_t *field, 92 + rdata_t *rdata, 93 + const token_t *token) 94 + { 95 + uint16_t number; 96 + if (!scan_int16(token->data, token->length, &number)) 97 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 98 + number = htobe16(number); 99 + memcpy(rdata->octets, &number, 2); 100 + rdata->octets += 2; 101 + return 0; 102 + } 103 + 104 + nonnull_all 105 + static really_inline int32_t parse_int32( 106 + parser_t *parser, 107 + const type_info_t *type, 108 + const rdata_info_t *field, 109 + rdata_t *rdata, 110 + const token_t *token) 111 + { 112 + uint32_t number; 113 + if (!scan_int32(token->data, token->length, &number)) 114 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 115 + number = htobe32(number); 116 + memcpy(rdata->octets, &number, 4); 117 + rdata->octets += 4; 118 + return 0; 119 + } 120 + 121 + #endif // NUMBER_H
+59
usr.sbin/nsd/simdzone/src/generic/nxt.h
··· 1 + /* 2 + * nxt.h - NXT (RFC2535) parser 3 + * 4 + * Copyright (c) 2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef NXT_H 10 + #define NXT_H 11 + 12 + nonnull_all 13 + static really_inline int32_t scan_type( 14 + const char *data, 15 + size_t length, 16 + uint16_t *code, 17 + const mnemonic_t **mnemonic); 18 + 19 + nonnull_all 20 + static really_inline int32_t parse_nxt( 21 + parser_t *parser, 22 + const type_info_t *type, 23 + const rdata_info_t *field, 24 + rdata_t *rdata, 25 + token_t *token) 26 + { 27 + uint16_t code; 28 + const mnemonic_t *mnemonic; 29 + 30 + if (is_contiguous(token)) { 31 + if (scan_type(token->data, token->length, &code, &mnemonic) != 1) 32 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 33 + uint8_t bit = (uint8_t)(code % 8); 34 + uint8_t block = (uint8_t)(code / 8), highest_block = block; 35 + 36 + memset(rdata->octets, 0, block + 1); 37 + rdata->octets[block] = (uint8_t)(1 << (7 - bit)); 38 + 39 + take(parser, token); 40 + while (is_contiguous(token)) { 41 + if (scan_type(token->data, token->length, &code, &mnemonic) != 1) 42 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 43 + bit = (uint8_t)(code % 8); 44 + block = (uint8_t)(code / 8); 45 + if (block > highest_block) { 46 + memset(&rdata->octets[highest_block+1], 0, block - highest_block); 47 + highest_block = block; 48 + } 49 + rdata->octets[block] |= 1 << (7 - bit); 50 + take(parser, token); 51 + } 52 + 53 + rdata->octets += highest_block + 1; 54 + } 55 + 56 + return have_delimiter(parser, type, token); 57 + } 58 + 59 + #endif // NXT_H
+985
usr.sbin/nsd/simdzone/src/generic/parser.h
··· 1 + /* 2 + * parser.h -- base parser definitions 3 + * 4 + * Copyright (c) 2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef PARSER_H 10 + #define PARSER_H 11 + 12 + #include <assert.h> 13 + #include <stdbool.h> 14 + #include <stdint.h> 15 + #include <string.h> 16 + #include <stdlib.h> 17 + 18 + #if _MSC_VER 19 + # define strncasecmp(s1, s2, n) _strnicmp((s1), (s2), (n)) 20 + #else 21 + # include <strings.h> 22 + #endif 23 + 24 + typedef zone_parser_t parser_t; // convenience 25 + typedef zone_file_t file_t; 26 + typedef zone_name_buffer_t name_buffer_t; 27 + typedef zone_rdata_buffer_t rdata_buffer_t; 28 + 29 + typedef struct token token_t; 30 + struct token { 31 + int32_t code; 32 + const char *data; 33 + size_t length; 34 + }; 35 + 36 + // view of current RDATA buffer 37 + typedef struct rdata rdata_t; 38 + struct rdata { 39 + uint8_t *octets; 40 + uint8_t *limit; 41 + }; 42 + 43 + typedef struct string string_t; 44 + struct string { 45 + const char *data; 46 + size_t length; 47 + }; 48 + 49 + typedef struct mnemonic mnemonic_t; 50 + struct mnemonic { 51 + struct { 52 + char data[16]; /* MUST be 16 because of usage with SIMD cmpeq */ 53 + size_t length; 54 + } key; 55 + uint32_t value; 56 + }; 57 + 58 + #define NAME(info) ((info)->name.key.data) 59 + 60 + 61 + typedef struct svc_param_info svc_param_info_t; 62 + struct svc_param_info; 63 + 64 + typedef struct rdata_info rdata_info_t; 65 + struct rdata_info; 66 + 67 + typedef struct type_info type_info_t; 68 + struct type_info; 69 + 70 + 71 + typedef int32_t (*parse_svc_param_t)( 72 + parser_t *, 73 + const type_info_t *, 74 + const rdata_info_t *, 75 + uint16_t, 76 + const svc_param_info_t *, 77 + rdata_t *, 78 + const token_t *); 79 + 80 + struct svc_param_info { 81 + struct { 82 + struct { 83 + char data[24]; 84 + size_t length; 85 + } key; 86 + uint32_t value; 87 + } name; 88 + uint32_t has_value; 89 + parse_svc_param_t parse, parse_lax; 90 + }; 91 + 92 + struct rdata_info { 93 + struct { string_t key; } name; // convenience 94 + }; 95 + 96 + typedef struct class_info class_info_t; 97 + struct class_info { 98 + mnemonic_t name; 99 + }; 100 + 101 + typedef int32_t (*check_rr_t)( 102 + parser_t *, 103 + const type_info_t *, 104 + const rdata_t *); 105 + 106 + typedef int32_t (*parse_rdata_t)( 107 + parser_t *, 108 + const type_info_t *, 109 + rdata_t *, 110 + token_t *); 111 + 112 + struct type_info { 113 + mnemonic_t name; 114 + uint16_t defined_in; 115 + bool is_obsolete; 116 + bool is_experimental; 117 + struct { 118 + size_t length; 119 + const rdata_info_t *fields; 120 + } rdata; 121 + check_rr_t check; 122 + parse_rdata_t parse; 123 + }; 124 + 125 + 126 + #define END_OF_FILE (0) 127 + #define CONTIGUOUS (1<<0) 128 + #define QUOTED (1<<1) 129 + #define LINE_FEED (1<<2) 130 + #define LEFT_PAREN (1<<3) 131 + #define RIGHT_PAREN (1<<4) 132 + #define BLANK (1<<6) 133 + #define COMMENT (1<<7) 134 + 135 + static const uint8_t classify[256] = { 136 + // 0x00 = "\0" 137 + 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x00 - 0x07 138 + // 0x09 = "\t", 0x0a = "\n", 0x0d = "\r" 139 + 0x01, 0x40, 0x04, 0x01, 0x01, 0x40, 0x01, 0x01, // 0x08 - 0x0f 140 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x10 - 0x17 141 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x18 - 0x1f 142 + // 0x20 = " ", 0x22 = "\"" 143 + 0x40, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x20 - 0x27 144 + // 0x28 = "(", 0x29 = ")" 145 + 0x08, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x28 - 0x2f 146 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x30 - 0x37 147 + // 0x3b = ";" 148 + 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, // 0x38 - 0x3f 149 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x40 - 0x47 150 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x48 - 0x4f 151 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x50 - 0x57 152 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x58 - 0x5f 153 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x60 - 0x67 154 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x68 - 0x6f 155 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x70 - 0x77 156 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x78 - 0x7f 157 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x80 - 0x87 158 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x88 - 0x8f 159 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x90 - 0x97 160 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x98 - 0x9f 161 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xa0 - 0xa7 162 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xa8 - 0xaf 163 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xb0 - 0xb7 164 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xb8 - 0xbf 165 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xc0 - 0xc7 166 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xc8 - 0xcf 167 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xd0 - 0xd7 168 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xd8 - 0xdf 169 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xe0 - 0xe7 170 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xe8 - 0xef 171 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xf8 - 0xf7 172 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 // 0xf8 - 0xff 173 + }; 174 + 175 + 176 + 177 + // special constant to mark line feeds with additional line count. i.e. CRLF 178 + // within text. line feeds have no special meaning other than terminating the 179 + // record and require no further processing 180 + static const char line_feed[ZONE_BLOCK_SIZE] = { '\n', '\0' }; 181 + 182 + // special constant used as data on errors 183 + static const char end_of_file[ZONE_BLOCK_SIZE] = { '\0' }; 184 + 185 + #define READ_ALL_DATA (1) 186 + #define NO_MORE_DATA (2) 187 + #define MISSING_QUOTE (3) 188 + 189 + extern int32_t zone_open_file( 190 + parser_t *, const char *path, size_t length, zone_file_t **); 191 + 192 + extern void zone_close_file( 193 + parser_t *, zone_file_t *); 194 + 195 + extern void zone_vlog(parser_t *, uint32_t, const char *, va_list); 196 + 197 + nonnull((1)) 198 + static really_inline void defer_error(token_t *token, int32_t code) 199 + { 200 + token->code = code; 201 + token->data = end_of_file; 202 + token->length = 0; 203 + } 204 + 205 + nonnull((1,3)) 206 + warn_unused_result 207 + static never_inline int32_t raise_error( 208 + parser_t *parser, int32_t code, const char *format, ...) 209 + { 210 + va_list arguments; 211 + uint32_t category = ZONE_ERROR; 212 + if (code == ZONE_SEMANTIC_ERROR && parser->options.secondary) 213 + category = ZONE_WARNING; 214 + va_start(arguments, format); 215 + zone_vlog(parser, category, format, arguments); 216 + va_end(arguments); 217 + if (category == ZONE_WARNING) 218 + return 0; 219 + return code; 220 + } 221 + 222 + #define RAISE_ERROR(parser, code, ...) \ 223 + do { \ 224 + return raise_error((parser), (code), __VA_ARGS__); \ 225 + } while (0) 226 + 227 + #define SYNTAX_ERROR(parser, ...) \ 228 + RAISE_ERROR((parser), ZONE_SYNTAX_ERROR, __VA_ARGS__) 229 + #define OUT_OF_MEMORY(parser, ...) \ 230 + RAISE_ERROR((parser), ZONE_OUT_OF_MEMORY, __VA_ARGS__) 231 + #define READ_ERROR(parser, ...) \ 232 + RAISE_ERROR((parser), ZONE_READ_ERROR, __VA_ARGS__) 233 + #define NOT_IMPLEMENTED(parser, ...) \ 234 + RAISE_ERROR((parser), ZONE_NOT_IMPLEMENTED, __VA_ARGS__) 235 + #define NOT_PERMITTED(parser, ...) \ 236 + RAISE_ERROR((parser), ZONE_NOT_PERMITTED, __VA_ARGS__) 237 + #define NOT_A_FILE(parser, ...) \ 238 + RAISE_ERROR((parser), ZONE_NOT_A_FILE, __VA_ARGS__) 239 + 240 + // semantic errors in zone files are special as a secondary may choose 241 + // to report, but otherwise ignore them. e.g. a TTL with the MSB set. cases 242 + // where the data can be presented in wire format but is otherwise considered 243 + // invalid. e.g. a TTL is limited to 32-bits, values that require more bits 244 + // are invalid without exception, but secondaries may choose to accept values 245 + // with the MSB set in order to update the zone 246 + #define SEMANTIC_ERROR(parser, ...) \ 247 + do { \ 248 + if (raise_error((parser), ZONE_SEMANTIC_ERROR, __VA_ARGS__)) \ 249 + return ZONE_SEMANTIC_ERROR; \ 250 + } while (0) 251 + 252 + 253 + nonnull_all 254 + warn_unused_result 255 + static really_inline int32_t reindex(parser_t *parser); 256 + 257 + // limit maximum size of buffer to avoid malicious inputs claiming all memory. 258 + // the maximum size of the buffer is the worst-case size of rdata, or 65535 259 + // bytes, in presentation format. comma-separated value lists as introduced 260 + // by RFC 9460 allow for double escaping. a reasonable limit is therefore 261 + // 65535 (rdata) * 4 (\DDD) * 4 (\DDD) + 64 (sufficiently large enough to 262 + // cover longest key and ancillary characters) bytes. 263 + #define MAXIMUM_WINDOW_SIZE (65535u * 4u * 4u + 64u) 264 + 265 + nonnull_all 266 + warn_unused_result 267 + static int32_t refill(parser_t *parser) 268 + { 269 + // refill if possible (i.e. not if string or if file is empty) 270 + if (parser->file->end_of_file) 271 + return 0; 272 + 273 + assert(parser->file->handle); 274 + 275 + // move unread data to start of buffer 276 + char *data = parser->file->buffer.data + parser->file->buffer.index; 277 + // account for non-terminated character-strings 278 + if (*parser->file->fields.head[0] != '\0') 279 + data = (char *)parser->file->fields.head[0]; 280 + 281 + *parser->file->fields.head = parser->file->buffer.data; 282 + // account for unread data left in buffer 283 + size_t length = (size_t) 284 + ((parser->file->buffer.data + parser->file->buffer.length) - data); 285 + // account for non-terminated character-string left in buffer 286 + assert((parser->file->buffer.data + parser->file->buffer.index) >= data); 287 + size_t index = (size_t) 288 + ((parser->file->buffer.data + parser->file->buffer.index) - data); 289 + memmove(parser->file->buffer.data, data, length); 290 + parser->file->buffer.length = length; 291 + parser->file->buffer.index = index; 292 + parser->file->buffer.data[length] = '\0'; 293 + 294 + // allocate extra space if required 295 + if (parser->file->buffer.length == parser->file->buffer.size) { 296 + size_t size = parser->file->buffer.size; 297 + if (parser->file->buffer.size >= MAXIMUM_WINDOW_SIZE) 298 + SYNTAX_ERROR(parser, "Impossibly large input, exceeds %zu bytes", size); 299 + size += ZONE_WINDOW_SIZE; 300 + if (!(data = realloc(parser->file->buffer.data, size + 1 + ZONE_BLOCK_SIZE))) 301 + OUT_OF_MEMORY(parser, "Not enough memory to allocate buffer of %zu", size); 302 + parser->file->buffer.size = size; 303 + parser->file->buffer.data = data; 304 + // update reference to partial token 305 + parser->file->fields.head[0] = data; 306 + } 307 + 308 + size_t count = fread( 309 + parser->file->buffer.data + parser->file->buffer.length, 310 + sizeof(parser->file->buffer.data[0]), 311 + parser->file->buffer.size - parser->file->buffer.length, 312 + parser->file->handle); 313 + 314 + if (!count && ferror(parser->file->handle)) 315 + READ_ERROR(parser, "Cannot refill buffer"); 316 + 317 + // always null-terminate for terminating token 318 + parser->file->buffer.length += (size_t)count; 319 + parser->file->buffer.data[parser->file->buffer.length] = '\0'; 320 + parser->file->end_of_file = feof(parser->file->handle) != 0; 321 + return 0; 322 + } 323 + 324 + // do not invoke directly 325 + nonnull_all 326 + warn_unused_result 327 + static really_inline int32_t advance(parser_t *parser) 328 + { 329 + int32_t code; 330 + 331 + // save embedded line count (quoted or escaped newlines) 332 + parser->file->newlines.tape[0] = parser->file->newlines.tail[0]; 333 + parser->file->newlines.head = parser->file->newlines.tape; 334 + parser->file->newlines.tail = parser->file->newlines.tape; 335 + // restore non-terminated token (partial quoted or contiguous) 336 + parser->file->fields.tape[0] = parser->file->fields.tail[1]; 337 + parser->file->fields.head = parser->file->fields.tape; 338 + parser->file->fields.tail = 339 + parser->file->fields.tape + (*parser->file->fields.tape[0] != '\0'); 340 + // reset delimiters 341 + parser->file->delimiters.head = parser->file->delimiters.tape; 342 + parser->file->delimiters.tail = parser->file->delimiters.tape; 343 + 344 + // delayed syntax error 345 + if (parser->file->end_of_file == MISSING_QUOTE) 346 + SYNTAX_ERROR(parser, "Missing closing quote"); 347 + if ((code = refill(parser)) < 0) 348 + return code; 349 + 350 + if (reindex(parser)) { 351 + // save non-terminated token 352 + parser->file->fields.tail[0] = parser->file->fields.tail[-1]; 353 + parser->file->fields.tail--; 354 + // delay syntax error so correct line number is available 355 + if (parser->file->end_of_file == NO_MORE_DATA && 356 + *parser->file->fields.tail[1] == '"') 357 + parser->file->end_of_file = MISSING_QUOTE; 358 + } else { 359 + parser->file->fields.tail[1] = end_of_file; 360 + } 361 + 362 + // FIXME: if tail is still equal to tape, refill immediately?! 363 + 364 + // terminate (end of buffer is null-terminated) 365 + parser->file->fields.tail[0] = 366 + parser->file->buffer.data + parser->file->buffer.length; 367 + parser->file->delimiters.tail[0] = 368 + parser->file->buffer.data + parser->file->buffer.length; 369 + // start-of-line must be false if start of tape is not start of buffer 370 + if (*parser->file->fields.head != parser->file->buffer.data) 371 + parser->file->start_of_line = false; 372 + return 0; 373 + } 374 + 375 + nonnull_all 376 + warn_unused_result 377 + static really_inline bool is_contiguous(const token_t *token) 378 + { 379 + return token->code == CONTIGUOUS; 380 + } 381 + 382 + nonnull_all 383 + warn_unused_result 384 + static really_inline bool is_quoted(const token_t *token) 385 + { 386 + return token->code == QUOTED; 387 + } 388 + 389 + nonnull_all 390 + warn_unused_result 391 + static really_inline bool is_contiguous_or_quoted(const token_t *token) 392 + { 393 + return (token->code == CONTIGUOUS || token->code == QUOTED); 394 + } 395 + 396 + nonnull_all 397 + warn_unused_result 398 + static really_inline bool is_delimiter(const token_t *token) 399 + { 400 + return (token->code == LINE_FEED || token->code == END_OF_FILE); 401 + } 402 + 403 + nonnull_all 404 + warn_unused_result 405 + static really_inline bool is_line_feed(const token_t *token) 406 + { 407 + return token->code == LINE_FEED; 408 + } 409 + 410 + nonnull_all 411 + warn_unused_result 412 + static really_inline bool is_end_of_file(const token_t *token) 413 + { 414 + return token->code == 0; 415 + } 416 + 417 + 418 + #undef SYNTAX_ERROR 419 + #define SYNTAX_ERROR(parser, token, ...) \ 420 + do { \ 421 + zone_log((parser), ZONE_ERROR, __VA_ARGS__); \ 422 + defer_error((token), ZONE_SYNTAX_ERROR); \ 423 + return; \ 424 + } while (0) 425 + 426 + #define ERROR(parser, token, code) \ 427 + do { \ 428 + defer_error(token, code); \ 429 + return; \ 430 + } while (0) 431 + 432 + 433 + nonnull_all 434 + static never_inline void maybe_take(parser_t *parser, token_t *token) 435 + { 436 + for (;;) { 437 + token->data = *parser->file->fields.head; 438 + token->code = (int32_t)classify[ (uint8_t)**parser->file->fields.head ]; 439 + if (likely(token->code == CONTIGUOUS)) { 440 + assert(*parser->file->delimiters.head > *parser->file->fields.head); 441 + token->length = (uintptr_t)*parser->file->delimiters.head - 442 + (uintptr_t)*parser->file->fields.head; 443 + parser->file->fields.head++; 444 + parser->file->delimiters.head++; 445 + return; 446 + } else if (token->code == LINE_FEED) { 447 + if (unlikely(token->data == line_feed)) 448 + parser->file->span += *parser->file->newlines.head++; 449 + parser->file->span++; 450 + parser->file->fields.head++; 451 + if (unlikely(parser->file->grouped)) 452 + continue; 453 + parser->file->start_of_line = classify[ (uint8_t)*(token->data+1) ] != BLANK; 454 + token->length = 1; 455 + return; 456 + } else if (token->code == QUOTED) { 457 + assert(*parser->file->delimiters.head > *parser->file->fields.head); 458 + token->data++; 459 + token->length = ((uintptr_t)*parser->file->delimiters.head - 460 + (uintptr_t)*parser->file->fields.head) - 1; 461 + parser->file->fields.head++; 462 + parser->file->delimiters.head++; 463 + return; 464 + } else if (token->code == END_OF_FILE) { 465 + int32_t code; 466 + if (parser->file->end_of_file == NO_MORE_DATA) { 467 + if (parser->file->grouped) 468 + SYNTAX_ERROR(parser, token, "Missing closing brace"); 469 + token->data = end_of_file; 470 + token->length = 1; 471 + return; 472 + } else if (unlikely((code = advance(parser)) < 0)) { 473 + ERROR(parser, token, code); 474 + } 475 + } else if (token->code == LEFT_PAREN) { 476 + if (unlikely(parser->file->grouped)) 477 + SYNTAX_ERROR(parser, token, "Nested opening brace"); 478 + parser->file->grouped = true; 479 + parser->file->fields.head++; 480 + } else { 481 + assert(token->code == RIGHT_PAREN); 482 + if (unlikely(!parser->file->grouped)) 483 + SYNTAX_ERROR(parser, token, "Missing opening brace"); 484 + parser->file->grouped = false; 485 + parser->file->fields.head++; 486 + } 487 + } 488 + } 489 + 490 + nonnull_all 491 + static really_inline void take(parser_t *parser, token_t *token) 492 + { 493 + for (;;) { 494 + token->data = *parser->file->fields.head; 495 + token->code = (int32_t)classify[ (uint8_t)**parser->file->fields.head ]; 496 + if (likely(token->code == CONTIGUOUS)) { 497 + assert(*parser->file->delimiters.head > *parser->file->fields.head); 498 + token->length = (uintptr_t)*parser->file->delimiters.head - 499 + (uintptr_t)*parser->file->fields.head; 500 + parser->file->fields.head++; 501 + parser->file->delimiters.head++; 502 + return; 503 + } else if (token->code == LINE_FEED) { 504 + if (unlikely(token->data == line_feed)) 505 + parser->file->span += *parser->file->newlines.head++; 506 + parser->file->span++; 507 + parser->file->fields.head++; 508 + if (unlikely(parser->file->grouped)) 509 + continue; 510 + parser->file->start_of_line = classify[ (uint8_t)*(token->data+1) ] != BLANK; 511 + token->length = 1; 512 + return; 513 + } else if (token->code == QUOTED) { 514 + assert(*parser->file->delimiters.head > *parser->file->fields.head); 515 + token->data++; 516 + token->length = ((uintptr_t)*parser->file->delimiters.head - 517 + (uintptr_t)*parser->file->fields.head) - 1; 518 + parser->file->fields.head++; 519 + parser->file->delimiters.head++; 520 + return; 521 + } else { 522 + maybe_take(parser, token); 523 + return; 524 + } 525 + } 526 + } 527 + 528 + #undef SYNTAX_ERROR 529 + #undef ERROR 530 + 531 + // token sequence is predictable. fields typically require a specific type, 532 + // except names, strings and SvcParams. even then, names are typically not 533 + // quoted and strings (or text) are typically quoted. implement specialized 534 + // tape accessors for performance and reduction in binary size. 535 + 536 + #define SYNTAX_ERROR(parser, token, ...) \ 537 + do { \ 538 + zone_log((parser), ZONE_ERROR, __VA_ARGS__); \ 539 + defer_error((token), ZONE_SYNTAX_ERROR); \ 540 + return ZONE_SYNTAX_ERROR; \ 541 + } while (0) 542 + 543 + #define ERROR(parser, token, code) \ 544 + do { \ 545 + defer_error((token), (code)); \ 546 + return (code); \ 547 + } while (0) 548 + 549 + nonnull_all 550 + warn_unused_result 551 + static never_inline int32_t dont_have_contiguous( 552 + parser_t *parser, 553 + const type_info_t *type, 554 + const rdata_info_t *field, 555 + token_t *token) 556 + { 557 + if (token->code < 0) 558 + return token->code; 559 + assert(token->code != CONTIGUOUS); 560 + if (token->code == QUOTED) 561 + SYNTAX_ERROR(parser, token, "Invalid %s in %s", NAME(field), NAME(type)); 562 + assert(token->code == END_OF_FILE || token->code == LINE_FEED); 563 + SYNTAX_ERROR(parser, token, "Missing %s in %s", NAME(field), NAME(type)); 564 + } 565 + 566 + nonnull_all 567 + warn_unused_result 568 + static really_inline int32_t have_contiguous( 569 + parser_t *parser, 570 + const type_info_t *type, 571 + const rdata_info_t *field, 572 + token_t *token) 573 + { 574 + if (unlikely(token->code != CONTIGUOUS)) 575 + return dont_have_contiguous(parser, type, field, token); 576 + return 0; 577 + } 578 + 579 + nonnull_all 580 + warn_unused_result 581 + static never_inline int32_t maybe_take_contiguous( 582 + parser_t *parser, 583 + const type_info_t *type, 584 + const rdata_info_t *field, 585 + token_t *token) 586 + { 587 + int32_t code; 588 + 589 + assert(token->code != CONTIGUOUS); 590 + 591 + for (;;) { 592 + if (likely(token->code == CONTIGUOUS)) { 593 + assert(*parser->file->delimiters.head > *parser->file->fields.head); 594 + token->length = (uintptr_t)*parser->file->delimiters.head - 595 + (uintptr_t)*parser->file->fields.head; 596 + parser->file->fields.head++; 597 + parser->file->delimiters.head++; 598 + return 0; 599 + } else if (token->code == END_OF_FILE) { 600 + if (parser->file->end_of_file == NO_MORE_DATA) 601 + SYNTAX_ERROR(parser, token, "Missing %s in %s", NAME(field), NAME(type)); 602 + if ((code = advance(parser)) < 0) 603 + ERROR(parser, token, code); 604 + } else if (token->code == QUOTED) { 605 + SYNTAX_ERROR(parser, token, "Invalid %s in %s", NAME(field), NAME(type)); 606 + } else if (token->code == LEFT_PAREN) { 607 + if (parser->file->grouped) 608 + SYNTAX_ERROR(parser, token, "Nested opening brace"); 609 + parser->file->grouped = true; 610 + parser->file->fields.head++; 611 + } else if (token->code == RIGHT_PAREN) { 612 + if (!parser->file->grouped) 613 + SYNTAX_ERROR(parser, token, "Missing opening brace"); 614 + parser->file->grouped = false; 615 + parser->file->fields.head++; 616 + } else if (token->code == LINE_FEED) { 617 + if (token->data == line_feed) 618 + parser->file->span += *parser->file->newlines.head++; 619 + parser->file->span++; 620 + if (!parser->file->grouped) 621 + SYNTAX_ERROR(parser, token, "Missing %s in %s", NAME(field), NAME(type)); 622 + parser->file->fields.head++; 623 + } 624 + token->data = *parser->file->fields.head; 625 + token->code = (int32_t)classify[ (uint8_t)**parser->file->fields.head ]; 626 + } 627 + } 628 + 629 + nonnull_all 630 + warn_unused_result 631 + static really_inline int32_t take_contiguous( 632 + parser_t *parser, 633 + const type_info_t *type, 634 + const rdata_info_t *field, 635 + token_t *token) 636 + { 637 + token->data = *parser->file->fields.head; 638 + token->code = (int32_t)classify[ (uint8_t)**parser->file->fields.head ]; 639 + if (unlikely(token->code != CONTIGUOUS)) 640 + return maybe_take_contiguous(parser, type, field, token); 641 + assert(*parser->file->delimiters.head > *parser->file->fields.head); 642 + token->length = (uintptr_t)*parser->file->delimiters.head - 643 + (uintptr_t)*parser->file->fields.head; 644 + parser->file->fields.head++; 645 + parser->file->delimiters.head++; 646 + return 0; 647 + } 648 + 649 + nonnull_all 650 + warn_unused_result 651 + static never_inline int32_t dont_have_quoted( 652 + parser_t *parser, 653 + const type_info_t *type, 654 + const rdata_info_t *field, 655 + token_t *token) 656 + { 657 + if (token->code < 0) 658 + return token->code; 659 + assert(token->code != QUOTED); 660 + if (token->code == CONTIGUOUS) 661 + SYNTAX_ERROR(parser, token, "Invalid %s in %s", NAME(field), NAME(type)); 662 + assert(token->code == END_OF_FILE || token->code == LINE_FEED); 663 + SYNTAX_ERROR(parser, token, "Missing %s in %s", NAME(field), NAME(type)); 664 + } 665 + 666 + nonnull_all 667 + warn_unused_result 668 + static really_inline int32_t have_quoted( 669 + parser_t *parser, 670 + const type_info_t *type, 671 + const rdata_info_t *field, 672 + token_t *token) 673 + { 674 + if (unlikely(token->code != QUOTED)) 675 + return dont_have_quoted(parser, type, field, token); 676 + return 0; 677 + } 678 + 679 + nonnull_all 680 + warn_unused_result 681 + static never_inline int32_t maybe_take_quoted( 682 + parser_t *parser, 683 + const type_info_t *type, 684 + const rdata_info_t *field, 685 + token_t *token) 686 + { 687 + int32_t code; 688 + 689 + assert(token->code != QUOTED); 690 + 691 + for (;;) { 692 + if (likely(token->code == QUOTED)) { 693 + assert(*parser->file->delimiters.head > *parser->file->fields.head); 694 + token->data++; 695 + token->length = ((uintptr_t)*parser->file->delimiters.head - 696 + (uintptr_t)*parser->file->fields.head) - 1; 697 + parser->file->fields.head++; 698 + parser->file->delimiters.head++; 699 + return 0; 700 + } else if (token->code == END_OF_FILE) { 701 + if (parser->file->end_of_file == NO_MORE_DATA) 702 + SYNTAX_ERROR(parser, token, "Missing %s in %s", NAME(field), NAME(type)); 703 + if ((code = advance(parser)) < 0) 704 + ERROR(parser, token, code); 705 + } else if (token->code == CONTIGUOUS) { 706 + SYNTAX_ERROR(parser, token, "Invalid %s in %s", NAME(field), NAME(type)); 707 + } else if (token->code == LEFT_PAREN) { 708 + if (parser->file->grouped) 709 + SYNTAX_ERROR(parser, token, "Nested opening brace"); 710 + parser->file->grouped = true; 711 + parser->file->fields.head++; 712 + } else if (token->code == RIGHT_PAREN) { 713 + if (!parser->file->grouped) 714 + SYNTAX_ERROR(parser, token, "Missing opening brace"); 715 + parser->file->grouped = false; 716 + parser->file->fields.head++; 717 + } else if (token->code == LINE_FEED) { 718 + if (token->data == line_feed) 719 + parser->file->span += *parser->file->newlines.head++; 720 + parser->file->span++; 721 + if (!parser->file->grouped) 722 + SYNTAX_ERROR(parser, token, "Missing %s in %s", NAME(field), NAME(type)); 723 + parser->file->fields.head++; 724 + } else { 725 + assert(token->code < 0); 726 + return token->code; 727 + } 728 + token->data = *parser->file->fields.head; 729 + token->code = (int32_t)classify[ (uint8_t)**parser->file->fields.head ]; 730 + } 731 + } 732 + 733 + nonnull_all 734 + warn_unused_result 735 + static really_inline int32_t take_quoted( 736 + parser_t *parser, 737 + const type_info_t *type, 738 + const rdata_info_t *field, 739 + token_t *token) 740 + { 741 + token->data = *parser->file->fields.head; 742 + token->code = (int32_t)classify[ (uint8_t)**parser->file->fields.head ]; 743 + if (unlikely((token->code != QUOTED))) 744 + return maybe_take_quoted(parser, type, field, token); 745 + assert(*parser->file->delimiters.head > *parser->file->fields.head); 746 + token->data++; 747 + token->length = ((uintptr_t)*parser->file->delimiters.head - 748 + (uintptr_t)*parser->file->fields.head) - 1; 749 + parser->file->fields.head++; 750 + parser->file->delimiters.head++; 751 + return 0; 752 + } 753 + 754 + nonnull_all 755 + warn_unused_result 756 + static never_inline int32_t dont_have_contiguous_or_quoted( 757 + parser_t *parser, 758 + const type_info_t *type, 759 + const rdata_info_t *field, 760 + token_t *token) 761 + { 762 + if (token->code == QUOTED || token->code < 0) 763 + return token->code; 764 + assert(token->code == END_OF_FILE || token->code == LINE_FEED); 765 + SYNTAX_ERROR(parser, token, "Missing %s in %s", NAME(field), NAME(type)); 766 + } 767 + 768 + nonnull_all 769 + warn_unused_result 770 + static really_inline int32_t have_contiguous_or_quoted( 771 + parser_t *parser, 772 + const type_info_t *type, 773 + const rdata_info_t *field, 774 + token_t *token) 775 + { 776 + if (unlikely(token->code != CONTIGUOUS)) 777 + return dont_have_contiguous_or_quoted(parser, type, field, token); 778 + return 0; 779 + } 780 + 781 + nonnull_all 782 + warn_unused_result 783 + static never_inline int32_t maybe_take_contiguous_or_quoted( 784 + parser_t *parser, 785 + const type_info_t *type, 786 + const rdata_info_t *field, 787 + token_t *token) 788 + { 789 + int32_t code; 790 + 791 + for (;;) { 792 + if (likely(token->code == CONTIGUOUS)) { 793 + assert(*parser->file->delimiters.head > *parser->file->fields.head); 794 + token->length = (uintptr_t)*parser->file->delimiters.head - 795 + (uintptr_t)*parser->file->fields.head; 796 + parser->file->fields.head++; 797 + parser->file->delimiters.head++; 798 + return 0; 799 + } else if (token->code == QUOTED) { 800 + assert(*parser->file->delimiters.head > *parser->file->fields.head); 801 + token->data++; 802 + token->length = ((uintptr_t)*parser->file->delimiters.head - 803 + (uintptr_t)*parser->file->fields.head) - 1; 804 + parser->file->fields.head++; 805 + parser->file->delimiters.head++; 806 + return 0; 807 + } else if (token->code == END_OF_FILE) { 808 + if (parser->file->end_of_file == NO_MORE_DATA) 809 + SYNTAX_ERROR(parser, token, "Missing %s in %s", NAME(field), NAME(type)); 810 + if ((code = advance(parser)) < 0) 811 + ERROR(parser, token, code); 812 + } else if (token->code == LEFT_PAREN) { 813 + if (parser->file->grouped) 814 + SYNTAX_ERROR(parser, token, "Nested opening brace"); 815 + parser->file->grouped = true; 816 + parser->file->fields.head++; 817 + } else if (token->code == RIGHT_PAREN) { 818 + if (!parser->file->grouped) 819 + SYNTAX_ERROR(parser, token, "Missing opening brace"); 820 + parser->file->grouped = false; 821 + parser->file->fields.head++; 822 + } else if (token->code == LINE_FEED) { 823 + if (token->data == line_feed) 824 + parser->file->span += *parser->file->newlines.head++; 825 + parser->file->span++; 826 + if (!parser->file->grouped) 827 + SYNTAX_ERROR(parser, token, "Missing %s in %s", NAME(field), NAME(type)); 828 + parser->file->fields.head++; 829 + } 830 + token->data = *parser->file->fields.head; 831 + token->code = (int32_t)classify[ (uint8_t)**parser->file->fields.head ]; 832 + } 833 + } 834 + 835 + nonnull_all 836 + warn_unused_result 837 + static really_inline int32_t take_contiguous_or_quoted( 838 + parser_t *parser, 839 + const type_info_t *type, 840 + const rdata_info_t *field, 841 + token_t *token) 842 + { 843 + token->data = *parser->file->fields.head; 844 + token->code = (int32_t)classify[ (uint8_t)**parser->file->fields.head ]; 845 + if (likely(token->code == CONTIGUOUS)) { 846 + assert(*parser->file->delimiters.head > *parser->file->fields.head); 847 + token->length = (uintptr_t)*parser->file->delimiters.head - 848 + (uintptr_t)*parser->file->fields.head; 849 + parser->file->fields.head++; 850 + parser->file->delimiters.head++; 851 + return 0; 852 + } else { 853 + return maybe_take_contiguous_or_quoted(parser, type, field, token); 854 + } 855 + } 856 + 857 + nonnull_all 858 + warn_unused_result 859 + static really_inline int32_t take_quoted_or_contiguous( 860 + parser_t *parser, 861 + const type_info_t *type, 862 + const rdata_info_t *field, 863 + token_t *token) 864 + { 865 + token->data = *parser->file->fields.head; 866 + token->code = (int32_t)classify[ (uint8_t)**parser->file->fields.head ]; 867 + if (likely(token->code == QUOTED)) { 868 + assert(*parser->file->delimiters.head > *parser->file->fields.head); 869 + token->data++; 870 + token->length = ((uintptr_t)*parser->file->delimiters.head - 871 + (uintptr_t)*parser->file->fields.head) - 1; 872 + parser->file->fields.head++; 873 + parser->file->delimiters.head++; 874 + return 0; 875 + } else { 876 + return maybe_take_contiguous_or_quoted(parser, type, field, token); 877 + } 878 + } 879 + 880 + diagnostic_push() 881 + clang_diagnostic_ignored(unused-function) 882 + gcc_diagnostic_ignored(unused-function) 883 + 884 + nonnull_all 885 + warn_unused_result 886 + static never_inline int32_t dont_have_delimiter( 887 + parser_t *parser, const type_info_t *type, token_t *token) 888 + { 889 + if (token->code == END_OF_FILE || token->code < 0) 890 + return token->code; 891 + assert(token->code == CONTIGUOUS || token->code == QUOTED); 892 + SYNTAX_ERROR(parser, token, "Trailing data in %s", NAME(type)); 893 + } 894 + 895 + nonnull_all 896 + warn_unused_result 897 + static never_inline int32_t have_delimiter( 898 + parser_t *parser, const type_info_t *type, token_t *token) 899 + { 900 + if (unlikely(token->code != LINE_FEED)) 901 + return dont_have_delimiter(parser, type, token); 902 + return 0; 903 + } 904 + 905 + diagnostic_pop() 906 + 907 + nonnull_all 908 + warn_unused_result 909 + static never_inline int32_t maybe_take_delimiter( 910 + parser_t *parser, const type_info_t *type, token_t *token) 911 + { 912 + int32_t code; 913 + 914 + for (;;) { 915 + if (likely(token->code == LINE_FEED)) { 916 + if (unlikely(token->data == line_feed)) 917 + parser->file->span += *parser->file->newlines.head++; 918 + if (unlikely(parser->file->grouped)) { 919 + parser->file->span++; 920 + parser->file->fields.head++; 921 + } else { 922 + token->length = 1; 923 + parser->file->span++; 924 + parser->file->start_of_line = classify[ (uint8_t)*(token->data+1) ] != BLANK; 925 + parser->file->fields.head++; 926 + return 0; 927 + } 928 + } else if (token->code == END_OF_FILE) { 929 + if (parser->file->end_of_file == NO_MORE_DATA) { 930 + if (parser->file->grouped) 931 + SYNTAX_ERROR(parser, token, "Missing closing brace"); 932 + token->data = end_of_file; 933 + token->length = 1; 934 + return 0; 935 + } 936 + 937 + if ((code = advance(parser)) < 0) 938 + ERROR(parser, token, code); 939 + } else if (token->code == LEFT_PAREN) { 940 + if (parser->file->grouped) 941 + SYNTAX_ERROR(parser, token, "Nested opening brace"); 942 + parser->file->grouped = true; 943 + parser->file->fields.head++; 944 + } else if (token->code == RIGHT_PAREN) { 945 + if (!parser->file->grouped) 946 + SYNTAX_ERROR(parser, token, "Missing opening brace"); 947 + parser->file->grouped = false; 948 + parser->file->fields.head++; 949 + } else { 950 + assert(token->code == CONTIGUOUS || token->code == QUOTED); 951 + SYNTAX_ERROR(parser, token, "Trailing data in %s", NAME(type)); 952 + } 953 + token->data = *parser->file->fields.head; 954 + token->code = (int32_t)classify[ (uint8_t)**parser->file->fields.head ]; 955 + } 956 + } 957 + 958 + nonnull_all 959 + warn_unused_result 960 + static really_inline int32_t take_delimiter( 961 + parser_t *parser, const type_info_t *type, token_t *token) 962 + { 963 + token->data = *parser->file->fields.head; 964 + token->code = (int32_t)classify[ (uint8_t)**parser->file->fields.head ]; 965 + if (likely(token->code == LINE_FEED)) { 966 + if (unlikely(parser->file->grouped || token->data == line_feed)) 967 + return maybe_take_delimiter(parser, type, token); 968 + token->length = 1; 969 + parser->file->span++; 970 + parser->file->start_of_line = classify[ (uint8_t)*(*parser->file->fields.head+1) ] != BLANK; 971 + parser->file->fields.head++; 972 + return 0; 973 + } else { 974 + return maybe_take_delimiter(parser, type, token); 975 + } 976 + } 977 + 978 + #undef SYNTAX_ERROR 979 + #undef ERROR 980 + 981 + // define SYNTAX_ERROR for the rest of the code base 982 + #define SYNTAX_ERROR(parser, ...) \ 983 + RAISE_ERROR((parser), ZONE_SYNTAX_ERROR, __VA_ARGS__) 984 + 985 + #endif // PARSER_H
+338
usr.sbin/nsd/simdzone/src/generic/scanner.h
··· 1 + /* 2 + * scanner.h -- fast lexical analyzer for (DNS) zone files 3 + * 4 + * Copyright (c) 2022, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef SCANNER_H 10 + #define SCANNER_H 11 + 12 + #include <assert.h> 13 + #include <string.h> 14 + #include <stdio.h> 15 + 16 + // Copied from simdjson under the terms of The 3-Clause BSD License. 17 + // Copyright (c) 2018-2023 The simdjson authors 18 + static really_inline uint64_t find_escaped( 19 + uint64_t backslash, uint64_t *is_escaped) 20 + { 21 + backslash &= ~ *is_escaped; 22 + 23 + uint64_t follows_escape = backslash << 1 | *is_escaped; 24 + 25 + // Get sequences starting on even bits by clearing out the odd series using + 26 + const uint64_t even_bits = 0x5555555555555555ULL; 27 + uint64_t odd_sequence_starts = backslash & ~even_bits & ~follows_escape; 28 + uint64_t sequences_starting_on_even_bits; 29 + *is_escaped = add_overflow(odd_sequence_starts, backslash, &sequences_starting_on_even_bits); 30 + uint64_t invert_mask = sequences_starting_on_even_bits << 1; // The mask we want to return is the *escaped* bits, not escapes. 31 + 32 + // Mask every other backslashed character as an escaped character 33 + // Flip the mask for sequences that start on even bits, to correct them 34 + return (even_bits ^ invert_mask) & follows_escape; 35 + } 36 + 37 + // special characters in zone files cannot be identified without branching 38 + // (unlike json) due to comments (*). no algorithm was found (so far) that 39 + // can correctly identify quoted and comment regions where a quoted region 40 + // includes a semicolon (or newline for that matter) and/or a comment region 41 + // includes one (or more) quote characters. also, for comments, only newlines 42 + // directly following a non-escaped, non-quoted semicolon must be included 43 + static really_inline void find_delimiters( 44 + uint64_t quotes, 45 + uint64_t semicolons, 46 + uint64_t newlines, 47 + uint64_t in_quoted, 48 + uint64_t in_comment, 49 + uint64_t *quoted_, 50 + uint64_t *comment) 51 + { 52 + uint64_t delimiters, starts = quotes | semicolons; 53 + uint64_t end; 54 + 55 + assert(!(quotes & semicolons)); 56 + 57 + // carry over state from previous block 58 + end = (newlines & in_comment) | (quotes & in_quoted); 59 + end &= -end; 60 + 61 + delimiters = end; 62 + starts &= ~((in_comment | in_quoted) ^ (-end - end)); 63 + 64 + while (starts) { 65 + const uint64_t start = -starts & starts; 66 + assert(start); 67 + const uint64_t quote = quotes & start; 68 + const uint64_t semicolon = semicolons & start; 69 + 70 + // FIXME: technically, this introduces a data dependency 71 + end = (newlines & -semicolon) | (quotes & (-quote - quote)); 72 + end &= -end; 73 + 74 + delimiters |= end | start; 75 + starts &= -end - end; 76 + } 77 + 78 + *quoted_ = delimiters & quotes; 79 + *comment = delimiters & ~quotes; 80 + } 81 + 82 + static inline uint64_t follows(const uint64_t match, uint64_t *overflow) 83 + { 84 + const uint64_t result = match << 1 | (*overflow); 85 + *overflow = match >> 63; 86 + return result; 87 + } 88 + 89 + static const simd_table_t blank = SIMD_TABLE( 90 + 0x20, // 0x00 : " " : 0x20 -- space 91 + 0x00, // 0x01 92 + 0x00, // 0x02 93 + 0x00, // 0x03 94 + 0x00, // 0x04 95 + 0x00, // 0x05 96 + 0x00, // 0x06 97 + 0x00, // 0x07 98 + 0x00, // 0x08 99 + 0x09, // 0x09 : "\t" : 0x09 -- tab 100 + 0x00, // 0x0a 101 + 0x00, // 0x0b 102 + 0x00, // 0x0c 103 + 0x0d, // 0x0d : "\r" : 0x0d -- carriage return 104 + 0x00, // 0x0e 105 + 0x00 // 0x0f 106 + ); 107 + 108 + static const simd_table_t special = SIMD_TABLE( 109 + 0x00, // 0x00 : "\0" : 0x00 -- end-of-file 110 + 0x00, // 0x01 111 + 0x00, // 0x02 112 + 0x00, // 0x03 113 + 0x00, // 0x04 114 + 0x00, // 0x05 115 + 0x00, // 0x06 116 + 0x00, // 0x07 117 + 0x28, // 0x08 : "(" : 0x28 -- start grouped 118 + 0x29, // 0x09 : ")" : 0x29 -- end grouped 119 + 0x0a, // 0x0a : "\n" : 0x0a -- end-of-line 120 + 0x00, // 0x0b 121 + 0x00, // 0x0c 122 + 0x00, // 0x0d 123 + 0x00, // 0x0e 124 + 0x00 // 0x0f 125 + ); 126 + 127 + typedef struct block block_t; 128 + struct block { 129 + simd_8x64_t input; 130 + uint64_t newline; 131 + uint64_t backslash; 132 + uint64_t escaped; 133 + uint64_t comment; 134 + uint64_t quoted; 135 + uint64_t semicolon; 136 + uint64_t in_quoted; 137 + uint64_t in_comment; 138 + uint64_t contiguous; 139 + uint64_t follows_contiguous; 140 + uint64_t blank; 141 + uint64_t special; 142 + }; 143 + 144 + static really_inline void scan(parser_t *parser, block_t *block) 145 + { 146 + // escaped newlines are classified as contiguous. however, escape sequences 147 + // have no meaning in comments and newlines, escaped or not, have no 148 + // special meaning in quoted 149 + block->newline = simd_find_8x64(&block->input, '\n'); 150 + block->backslash = simd_find_8x64(&block->input, '\\'); 151 + block->escaped = find_escaped( 152 + block->backslash, &parser->file->state.is_escaped); 153 + 154 + block->comment = 0; 155 + block->quoted = simd_find_8x64(&block->input, '"') & ~block->escaped; 156 + block->semicolon = simd_find_8x64(&block->input, ';') & ~block->escaped; 157 + 158 + block->in_quoted = parser->file->state.in_quoted; 159 + block->in_comment = parser->file->state.in_comment; 160 + 161 + if (block->in_comment || block->semicolon) { 162 + find_delimiters( 163 + block->quoted, 164 + block->semicolon, 165 + block->newline, 166 + block->in_quoted, 167 + block->in_comment, 168 + &block->quoted, 169 + &block->comment); 170 + 171 + block->in_quoted ^= prefix_xor(block->quoted); 172 + parser->file->state.in_quoted = (uint64_t)((int64_t)block->in_quoted >> 63); 173 + block->in_comment ^= prefix_xor(block->comment); 174 + parser->file->state.in_comment = (uint64_t)((int64_t)block->in_comment >> 63); 175 + } else { 176 + block->in_quoted ^= prefix_xor(block->quoted); 177 + parser->file->state.in_quoted = (uint64_t)((int64_t)block->in_quoted >> 63); 178 + } 179 + 180 + block->blank = 181 + simd_find_any_8x64(&block->input, blank) & ~(block->escaped | block->in_quoted | block->in_comment); 182 + block->special = 183 + simd_find_any_8x64(&block->input, special) & ~(block->escaped | block->in_quoted | block->in_comment); 184 + 185 + block->contiguous = 186 + ~(block->blank | block->special | block->quoted) & ~(block->in_quoted | block->in_comment); 187 + block->follows_contiguous = 188 + follows(block->contiguous, &parser->file->state.follows_contiguous); 189 + } 190 + 191 + static really_inline void write_indexes(parser_t *parser, const block_t *block, uint64_t clear) 192 + { 193 + uint64_t fields = (block->contiguous & ~block->follows_contiguous) | 194 + (block->quoted & block->in_quoted) | 195 + (block->special); 196 + 197 + // delimiters are only important for contigouos and quoted character strings 198 + // (all other tokens automatically have a length 1). write out both in 199 + // separate vectors and base logic solely on field vector, order is 200 + // automatically correct 201 + uint64_t delimiters = (~block->contiguous & block->follows_contiguous) | 202 + (block->quoted & ~block->in_quoted); 203 + 204 + fields &= ~clear; 205 + delimiters &= ~clear; 206 + 207 + const char *base = parser->file->buffer.data + parser->file->buffer.index; 208 + uint64_t field_count = count_ones(fields); 209 + uint64_t delimiter_count = count_ones(delimiters); 210 + // bulk of the data are contiguous and quoted character strings. field and 211 + // delimiter counts are therefore (mostly) equal. select the greater number 212 + // and write out indexes in a single loop leveraging superscalar properties 213 + // of modern CPUs 214 + uint64_t count = field_count; 215 + if (delimiter_count > field_count) 216 + count = delimiter_count; 217 + 218 + // take slow path if (escaped) newlines appear in contiguous or quoted 219 + // character strings. edge case, but must be supported and handled in the 220 + // scanner for ease of use and to accommodate for parallel processing in the 221 + // parser. escaped newlines may have been present in the last block 222 + uint64_t newlines = block->newline & (block->contiguous | block->in_quoted); 223 + 224 + // non-delimiting tokens may contain (escaped) newlines. tracking newlines 225 + // within tokens by taping them makes the lex operation more complex, resulting 226 + // in a significantly larger binary and slower operation, and may introduce an 227 + // infinite loop if the tape may not be sufficiently large enough. tokens 228 + // containing newlines is very much an edge case, therefore the scanner 229 + // implements an unlikely slow path that tracks the number of escaped newlines 230 + // during tokenization and registers them with each consecutive newline token. 231 + // this mode of operation nicely isolates location tracking in the scanner and 232 + // accommodates parallel processing should that ever be desired 233 + if (unlikely(*parser->file->newlines.tail || newlines)) { 234 + for (uint64_t i=0; i < count; i++) { 235 + const uint64_t field = fields & -fields; 236 + const uint64_t delimiter = delimiters & -delimiters; 237 + if (field & block->newline) { 238 + *parser->file->newlines.tail += count_ones(newlines & (field - 1)); 239 + if (*parser->file->newlines.tail) { 240 + parser->file->fields.tail[i] = line_feed; 241 + parser->file->newlines.tail++; 242 + } else { 243 + parser->file->fields.tail[i] = base + trailing_zeroes(field); 244 + } 245 + newlines &= -field; 246 + } else { 247 + parser->file->fields.tail[i] = base + trailing_zeroes(field); 248 + } 249 + parser->file->delimiters.tail[i] = base + trailing_zeroes(delimiter); 250 + fields &= ~field; 251 + delimiters &= ~delimiter; 252 + } 253 + 254 + *parser->file->newlines.tail += count_ones(newlines); 255 + parser->file->fields.tail += field_count; 256 + parser->file->delimiters.tail += delimiter_count; 257 + } else { 258 + for (uint64_t i=0; i < 6; i++) { 259 + parser->file->fields.tail[i] = base + trailing_zeroes(fields); 260 + parser->file->delimiters.tail[i] = base + trailing_zeroes(delimiters); 261 + fields = clear_lowest_bit(fields); 262 + delimiters = clear_lowest_bit(delimiters); 263 + } 264 + 265 + if (unlikely(count > 6)) { 266 + for (uint64_t i=6; i < 12; i++) { 267 + parser->file->fields.tail[i] = base + trailing_zeroes(fields); 268 + parser->file->delimiters.tail[i] = base + trailing_zeroes(delimiters); 269 + fields = clear_lowest_bit(fields); 270 + delimiters = clear_lowest_bit(delimiters); 271 + } 272 + 273 + if (unlikely(count > 12)) { 274 + for (uint64_t i=12; i < count; i++) { 275 + parser->file->fields.tail[i] = base + trailing_zeroes(fields); 276 + parser->file->delimiters.tail[i] = base + trailing_zeroes(delimiters); 277 + fields = clear_lowest_bit(fields); 278 + delimiters = clear_lowest_bit(delimiters); 279 + } 280 + } 281 + } 282 + 283 + parser->file->fields.tail += field_count; 284 + parser->file->delimiters.tail += delimiter_count; 285 + } 286 + } 287 + 288 + nonnull_all 289 + warn_unused_result 290 + static really_inline int32_t reindex(parser_t *parser) 291 + { 292 + block_t block = { 0 }; 293 + 294 + assert(parser->file->buffer.index <= parser->file->buffer.length); 295 + size_t left = parser->file->buffer.length - parser->file->buffer.index; 296 + const char *data = parser->file->buffer.data + parser->file->buffer.index; 297 + const char **tape = parser->file->fields.tail; 298 + const char **tape_limit = parser->file->fields.tape + ZONE_TAPE_SIZE; 299 + 300 + if (left >= ZONE_BLOCK_SIZE) { 301 + const char *data_limit = parser->file->buffer.data + 302 + (parser->file->buffer.length - ZONE_BLOCK_SIZE); 303 + while (data <= data_limit && ((uintptr_t)tape_limit - (uintptr_t)tape) >= ZONE_BLOCK_SIZE) { 304 + simd_loadu_8x64(&block.input, (const uint8_t *)data); 305 + scan(parser, &block); 306 + write_indexes(parser, &block, 0); 307 + parser->file->buffer.index += ZONE_BLOCK_SIZE; 308 + data += ZONE_BLOCK_SIZE; 309 + tape = parser->file->fields.tail; 310 + } 311 + 312 + assert(parser->file->buffer.index <= parser->file->buffer.length); 313 + left = parser->file->buffer.length - parser->file->buffer.index; 314 + } 315 + 316 + // only scan partial blocks after reading all data 317 + if (parser->file->end_of_file) { 318 + assert(left < ZONE_BLOCK_SIZE); 319 + if (!left) { 320 + parser->file->end_of_file = NO_MORE_DATA; 321 + } else if (((uintptr_t)tape_limit - (uintptr_t)tape) >= left) { 322 + // input is required to be padded, but may contain garbage 323 + uint8_t buffer[ZONE_BLOCK_SIZE] = { 0 }; 324 + memcpy(buffer, data, left); 325 + const uint64_t clear = ~((1llu << left) - 1); 326 + simd_loadu_8x64(&block.input, buffer); 327 + scan(parser, &block); 328 + block.contiguous &= ~clear; 329 + write_indexes(parser, &block, clear); 330 + parser->file->end_of_file = NO_MORE_DATA; 331 + parser->file->buffer.index += left; 332 + } 333 + } 334 + 335 + return (uint64_t)((int64_t)(block.contiguous | block.in_quoted) >> 63) != 0; 336 + } 337 + 338 + #endif // SCANNER_H
+1050
usr.sbin/nsd/simdzone/src/generic/svcb.h
··· 1 + /* 2 + * svcb.h -- svcb (RFC9460) parser 3 + * 4 + * Copyright (c) 2022-2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef SVCB_H 10 + #define SVCB_H 11 + 12 + #include <inttypes.h> 13 + 14 + // RFC9460 section 7.1: 15 + // The "alpn" and "no-default-alpn" SvcParamKeys together indicate the set 16 + // of Application-Layer Protocol Negotiation (ALPN) protocol identifiers 17 + // [ALPN] and associated transport protocols supported by this service 18 + // endpoint (the "SVCB ALPN set"). 19 + // 20 + // RFC9460 section 7.1.1: 21 + // ALPNs are identified by their registered "Identification Sequence" 22 + // (alpn-id), which is a sequence of 1-255 octets. For "alpn", the 23 + // presentation value SHALL be a comma-separated list (Appendix A.1) of 24 + // one or more alpn-ids. Zone-file implementations MAY disallow the "," 25 + // and "\" characters in ALPN IDs instead of implementing the value-list 26 + // escaping procedure, relying on the opaque key format (e.g., key=\002h2) 27 + // in the event that these characters are needed. 28 + // 29 + // Application-Layer Protocol Negotiation (ALPN) protocol identifiers are 30 + // maintained by IANA: 31 + // 32 + // https://www.iana.org/assignments/tls-extensiontype-values#alpn-protocol-ids 33 + // 34 + // RFC9460 section 7.1.1: 35 + // For "alpn", the presentation value SHALL be a comma-separated list 36 + // (Appendix A.1) of one or more alpn-ids. Zone-file implementations MAY 37 + // disallow the "," and "\" characters in ALPN IDs instead of implementing 38 + // the value-list escaping procedure, relying on the opaque key format 39 + // (e.g., key1=\002h2) in the event that these characters are needed. 40 + // 41 + // RFC9460 appendix A.1: 42 + // A value-list parser that splits on "," and prohibits items containing 43 + // "\\" is sufficient to comply with all requirements in this document. 44 + // 45 + // RFC9460 appendix A.1: 46 + // Decoding of value-lists happens after character-string decoding. 47 + // 48 + // 49 + // 50 + // RFC9460 (somewhat incorrectly) states that an SvcParamValue is a 51 + // character-string. An SvcParamValue is just that, an SvcParamValue. The 52 + // presentation format is not a context-free format like JSON. Tokens can be 53 + // identified, not classified, by syntax. 54 + // 55 + // Context-free languages (e.g. C, JSON) classify a token as a string if it is 56 + // quoted, an identifier or keyword if it is a contiguous set of characters, 57 + // etc. Unescaping is done by the scanner because the token is classified 58 + // during that stage. The presentation format defines basic syntax to identify 59 + // tokens, but as the format is NOT context-free and intentionally extensible, 60 + // the token is classified by the parser. Conversion of domain names from text 61 + // format to wire format is a prime example. 62 + // 63 + // Example: 64 + // "foo. NS bar\." defines "bar\." as a relative domain. The "\" (backslash) 65 + // is important because it signals that the trailing dot does not serve as a 66 + // label separator. 67 + // 68 + // Note that RFC9460 is contradicts itself by stating that the value-list 69 + // escaping procedure may rely on the opaque key format (e.g., key1=\002h2) 70 + // in the event that these characters are needed. Escaping using \DDD, if 71 + // SvcParamValue is indeed to be interpreted as a string, would produce 72 + // 0x03 0x02 0x68 0x32 in wire format. 73 + // 74 + // IETF mailing list discussion on this topic: 75 + // https://mailarchive.ietf.org/arch/msg/dnsop/SXnlsE1B8gmlDjn4HtOo1lwtqAI/ 76 + // 77 + // 78 + // BIND disallows any escape sequences in port, ipv4hint, etc. Regular 79 + // (single stage) escaping rules are applied to dohpath. Special (two stage) 80 + // escaping rules apply for alpn. 81 + // 82 + // Knot disallows escape sequences in port, ipv4hint, etc. kzonecheck 3.3.4 83 + // does not to accept dohpath. Special (two stage) escaping rules apply for 84 + // alpn. 85 + nonnull_all 86 + static int32_t parse_alpn( 87 + parser_t *parser, 88 + const type_info_t *type, 89 + const rdata_info_t *field, 90 + uint16_t key, 91 + const svc_param_info_t *param, 92 + rdata_t *rdata, 93 + const token_t *token) 94 + { 95 + assert(rdata->octets < rdata->limit); 96 + 97 + (void)field; 98 + (void)key; 99 + (void)param; 100 + 101 + uint8_t *comma = rdata->octets++; 102 + const char *data = token->data, *limit = token->data + token->length; 103 + 104 + while (data < limit && rdata->octets < rdata->limit) { 105 + *rdata->octets = (uint8_t)*data; 106 + if (unlikely(*rdata->octets == '\\')) { 107 + uint32_t length; 108 + if (!(length = unescape(data, rdata->octets))) 109 + SYNTAX_ERROR(parser, "Invalid alpn in %s", NAME(type)); 110 + data += length; 111 + // second level escape processing 112 + if (*rdata->octets == '\\') { 113 + assert(length); 114 + if (*data == '\\') { 115 + if (!(length = unescape(data, rdata->octets))) 116 + SYNTAX_ERROR(parser, "Invalid alpn in %s", NAME(type)); 117 + data += length; 118 + } else { 119 + *rdata->octets = (uint8_t)*data; 120 + data++; 121 + } 122 + rdata->octets++; 123 + continue; 124 + } 125 + } else { 126 + data++; 127 + } 128 + 129 + if (*rdata->octets == ',') { 130 + assert(comma < rdata->octets); 131 + const size_t length = ((uintptr_t)rdata->octets - (uintptr_t)comma) - 1; 132 + if (!length || length > 255) 133 + SYNTAX_ERROR(parser, "Invalid alpn in %s", NAME(type)); 134 + *comma = (uint8_t)length; 135 + comma = rdata->octets; 136 + } 137 + 138 + rdata->octets++; 139 + } 140 + 141 + if (data != limit || rdata->octets > rdata->limit) 142 + SYNTAX_ERROR(parser, "Invalid alpn in %s", NAME(type)); 143 + const size_t length = ((uintptr_t)rdata->octets - (uintptr_t)comma) - 1; 144 + if (!length || length > 255) 145 + SYNTAX_ERROR(parser, "Invalid alpn in %s", NAME(type)); 146 + *comma = (uint8_t)length; 147 + return 0; 148 + } 149 + 150 + nonnull_all 151 + static int32_t parse_port( 152 + parser_t *parser, 153 + const type_info_t *type, 154 + const rdata_info_t *field, 155 + uint16_t key, 156 + const svc_param_info_t *param, 157 + rdata_t *rdata, 158 + const token_t *token) 159 + { 160 + const char *data = token->data; 161 + 162 + (void)field; 163 + (void)key; 164 + (void)param; 165 + 166 + if (!token->length || token->length > 5) 167 + SYNTAX_ERROR(parser, "Invalid port in %s", NAME(type)); 168 + 169 + uint64_t number = 0; 170 + for (;; data++) { 171 + const uint64_t digit = (uint8_t)*data - '0'; 172 + if (digit > 9) 173 + break; 174 + number = number * 10 + digit; 175 + } 176 + 177 + uint16_t port = (uint16_t)number; 178 + port = htobe16(port); 179 + memcpy(rdata->octets, &port, 2); 180 + rdata->octets += 2; 181 + 182 + if (rdata->octets > rdata->limit) 183 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 184 + if (data != token->data + token->length || number > 65535) 185 + SYNTAX_ERROR(parser, "Invalid port in %s", NAME(type)); 186 + return 0; 187 + } 188 + 189 + nonnull_all 190 + static int32_t parse_ipv4hint( 191 + parser_t *parser, 192 + const type_info_t *type, 193 + const rdata_info_t *field, 194 + uint16_t key, 195 + const svc_param_info_t *param, 196 + rdata_t *rdata, 197 + const token_t *token) 198 + { 199 + const char *t = token->data, *te = token->data + token->length; 200 + size_t n = 0; 201 + 202 + (void)field; 203 + (void)key; 204 + (void)param; 205 + 206 + if ((n = (size_t)scan_ip4(t, rdata->octets)) == 0) 207 + SYNTAX_ERROR(parser, "Invalid ipv4hint in %s", NAME(type)); 208 + rdata->octets += 4; 209 + t += n; 210 + 211 + while (*t == ',') { 212 + if (rdata->octets > rdata->limit) 213 + SYNTAX_ERROR(parser, "Invalid ipv4hint in %s", NAME(type)); 214 + if ((n = (size_t)scan_ip4(t + 1, rdata->octets)) == 0) 215 + SYNTAX_ERROR(parser, "Invalid ipv4hint in %s", NAME(type)); 216 + rdata->octets += 4; 217 + t += n + 1; 218 + } 219 + 220 + if (t != te || rdata->octets > rdata->limit) 221 + SYNTAX_ERROR(parser, "Invalid ipv4hint in %s", NAME(type)); 222 + return 0; 223 + } 224 + 225 + nonnull_all 226 + static int32_t parse_ech( 227 + parser_t *parser, 228 + const type_info_t *type, 229 + const rdata_info_t *field, 230 + uint16_t key, 231 + const svc_param_info_t *param, 232 + rdata_t *rdata, 233 + const token_t *token) 234 + { 235 + size_t size = (uintptr_t)rdata->limit - (uintptr_t)rdata->octets; 236 + size_t length; 237 + 238 + (void)field; 239 + (void)key; 240 + (void)param; 241 + 242 + if (token->length / 4 > size / 3) 243 + SYNTAX_ERROR(parser, "maximum size exceeded"); 244 + 245 + struct base64_state state = { .eof = 0, .bytes = 0, .carry = 0 }; 246 + if (!base64_stream_decode( 247 + &state, token->data, token->length, rdata->octets, &length)) 248 + SYNTAX_ERROR(parser, "Invalid ech in %s", NAME(type)); 249 + 250 + rdata->octets += length; 251 + if (state.bytes) 252 + SYNTAX_ERROR(parser, "Invalid ech in %s", NAME(type)); 253 + 254 + return 0; 255 + } 256 + 257 + nonnull_all 258 + static int32_t parse_ipv6hint( 259 + parser_t *parser, 260 + const type_info_t *type, 261 + const rdata_info_t *field, 262 + uint16_t key, 263 + const svc_param_info_t *param, 264 + rdata_t *rdata, 265 + const token_t *token) 266 + { 267 + const char *t = token->data, *te = token->data + token->length; 268 + size_t n = 0; 269 + 270 + (void)field; 271 + (void)key; 272 + (void)param; 273 + 274 + if ((n = (size_t)scan_ip6(t, rdata->octets)) == 0) 275 + SYNTAX_ERROR(parser, "Invalid ipv6hint in %s", NAME(type)); 276 + rdata->octets += 16; 277 + t += n; 278 + 279 + while (*t == ',') { 280 + if (rdata->octets >= rdata->limit) 281 + SYNTAX_ERROR(parser, "Invalid ipv6hint in %s", NAME(type)); 282 + if ((n = (size_t)scan_ip6(t + 1, rdata->octets)) == 0) 283 + SYNTAX_ERROR(parser, "Invalid ipv6hint in %s", NAME(type)); 284 + rdata->octets += 16; 285 + t += n + 1; 286 + } 287 + 288 + if (t != te || rdata->octets > rdata->limit) 289 + SYNTAX_ERROR(parser, "Invalid ipv6hint in %s", NAME(type)); 290 + return 0; 291 + } 292 + 293 + // RFC9461 section 5: 294 + // "dohpath" is a single-valued SvcParamKey whose value (in both 295 + // presentation format and wire format) MUST be a URI Template in 296 + // relative form ([RFC6570], Section 1.1) encoded in UTF-8 [RFC3629]. 297 + nonnull_all 298 + static int32_t parse_dohpath( 299 + parser_t *parser, 300 + const type_info_t *type, 301 + const rdata_info_t *field, 302 + uint16_t key, 303 + const svc_param_info_t *param, 304 + rdata_t *rdata, 305 + const token_t *token) 306 + { 307 + const char *t = token->data, *te = t + token->length; 308 + 309 + (void)field; 310 + (void)key; 311 + (void)param; 312 + 313 + // FIXME: easily optimized using SIMD (and possibly SWAR) 314 + while ((t < te) & (rdata->octets < rdata->limit)) { 315 + *rdata->octets = (uint8_t)*t; 316 + if (*t == '\\') { 317 + uint32_t o; 318 + if (!(o = unescape(t, rdata->octets))) 319 + SYNTAX_ERROR(parser, "Invalid dohpath in %s", NAME(type)); 320 + rdata->octets += 1; t += o; 321 + } else { 322 + rdata->octets += 1; t += 1; 323 + } 324 + } 325 + 326 + // RFC9461 section 5: 327 + // The URI Template MUST contain a "dns" variable, and MUST be chosen such 328 + // that the result after DoH URI Template expansion (RFC8484 section 6) 329 + // is always a valid and function ":path" value (RFC9113 section 8.3.1) 330 + // FIXME: implement 331 + 332 + if (t != te || rdata->octets >= rdata->limit) 333 + SYNTAX_ERROR(parser, "Invalid dohpath in %s", NAME(type)); 334 + return 0; 335 + } 336 + 337 + nonnull_all 338 + static int32_t parse_unknown( 339 + parser_t *parser, 340 + const type_info_t *type, 341 + const rdata_info_t *field, 342 + uint16_t key, 343 + const svc_param_info_t *param, 344 + rdata_t *rdata, 345 + const token_t *token) 346 + { 347 + const char *t = token->data, *te = t + token->length; 348 + 349 + (void)key; 350 + (void)param; 351 + 352 + while ((t < te) & (rdata->octets < rdata->limit)) { 353 + *rdata->octets = (uint8_t)*t; 354 + if (*t == '\\') { 355 + uint32_t o; 356 + if (!(o = unescape(t, rdata->octets))) 357 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 358 + rdata->octets += 1; t += o; 359 + } else { 360 + rdata->octets += 1; t += 1; 361 + } 362 + } 363 + 364 + if (t != te || rdata->octets >= rdata->limit) 365 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 366 + return 0; 367 + } 368 + 369 + nonnull_all 370 + static int32_t parse_tls_supported_groups( 371 + parser_t *parser, 372 + const type_info_t *type, 373 + const rdata_info_t *field, 374 + uint16_t key, 375 + const svc_param_info_t *param, 376 + rdata_t *rdata, 377 + const token_t *token) 378 + { 379 + const char *t = token->data, *te = token->data + token->length; 380 + const uint8_t *rdata_start = rdata->octets; 381 + 382 + (void)field; 383 + (void)key; 384 + (void)param; 385 + 386 + while (t < te && rdata->octets+2 <= rdata->limit) { 387 + uint64_t number = 0; 388 + for (;; t++) { 389 + const uint64_t digit = (uint8_t)*t - '0'; 390 + if (digit > 9) 391 + break; 392 + number = number * 10 + digit; 393 + } 394 + 395 + uint16_t group = (uint16_t)number; 396 + group = htobe16(group); 397 + memcpy(rdata->octets, &group, 2); 398 + rdata->octets += 2; 399 + if (number > 65535) 400 + SYNTAX_ERROR(parser, "Invalid tls-supported-group in %s", NAME(type)); 401 + 402 + const uint8_t *g; 403 + for (g = rdata_start; g < rdata->octets - 2; g += 2) { 404 + if (memcmp(g, &group, 2) == 0) 405 + SEMANTIC_ERROR(parser, "Duplicate group in tls-supported-groups in %s", NAME(type)); 406 + } 407 + if (*t != ',') 408 + break; 409 + else 410 + t++; 411 + } 412 + 413 + if (t != te || rdata->octets > rdata->limit) 414 + SYNTAX_ERROR(parser, "Invalid tls-supported-groups in %s", NAME(type)); 415 + return 0; 416 + } 417 + 418 + nonnull_all 419 + static int32_t parse_mandatory_lax( 420 + parser_t *parser, 421 + const type_info_t *type, 422 + const rdata_info_t *field, 423 + uint16_t key, 424 + const svc_param_info_t *svc_param, 425 + rdata_t *rdata, 426 + const token_t *token); 427 + 428 + nonnull_all 429 + static int32_t parse_mandatory( 430 + parser_t *parser, 431 + const type_info_t *type, 432 + const rdata_info_t *field, 433 + uint16_t key, 434 + const svc_param_info_t *svc_param, 435 + rdata_t *rdata, 436 + const token_t *token); 437 + 438 + #define SVC_PARAM(name, key, value, parse, parse_lax) \ 439 + { { { name, sizeof(name) - 1 }, key }, value, parse, parse_lax } 440 + 441 + #define NO_VALUE (0u) 442 + #define OPTIONAL_VALUE (1u << 1) 443 + #define MANDATORY_VALUE (1u << 2) 444 + 445 + static const svc_param_info_t svc_params[] = { 446 + // RFC9460 section 8: 447 + // The presentation value SHALL be a comma-separated list (Appendix A.1) 448 + // of one or more valid SvcParamKeys ... 449 + SVC_PARAM("mandatory", 0u, MANDATORY_VALUE, 450 + parse_mandatory, parse_mandatory_lax), 451 + SVC_PARAM("alpn", 1u, MANDATORY_VALUE, parse_alpn, parse_alpn), 452 + // RFC9460 section 7.1.1: 453 + // For "no-default-alpn", the presentation and wire format values MUST be 454 + // empty. When "no-default-alpn" is specified in an RR, "alpn" must also be 455 + // specified in order for the RR to be "self-consistent" (Section 2.4.3). 456 + SVC_PARAM("no-default-alpn", 2u, NO_VALUE, parse_unknown, parse_unknown), 457 + // RFC9460 section 7.2: 458 + // The presentation value of the SvcParamValue is a single decimal integer 459 + // between 0 and 65535 in ASCII. ... 460 + SVC_PARAM("port", 3u, MANDATORY_VALUE, parse_port, parse_port), 461 + // RFC9460 section 7.3: 462 + // The presentation value SHALL be a comma-separated list (Appendix A.1) 463 + // of one or more IP addresses ... 464 + SVC_PARAM("ipv4hint", 4u, MANDATORY_VALUE, parse_ipv4hint, parse_ipv4hint), 465 + SVC_PARAM("ech", 5u, OPTIONAL_VALUE, parse_ech, parse_ech), 466 + // RFC9460 section 7.3: 467 + // See "ipv4hint". 468 + SVC_PARAM("ipv6hint", 6u, MANDATORY_VALUE, parse_ipv6hint, parse_ipv6hint), 469 + // RFC9461 section 5: 470 + // If the "alpn" SvcParam indicates support for HTTP, "dohpath" MUST be 471 + // present. 472 + SVC_PARAM("dohpath", 7u, MANDATORY_VALUE, parse_dohpath, parse_dohpath), 473 + // RFC9540 section 4. 474 + // Both the presentation and wire-format values for the "ohttp" parameter 475 + // MUST be empty. 476 + SVC_PARAM("ohttp", 8u, NO_VALUE, parse_unknown, parse_unknown), 477 + // draft-ietf-tls-key-share-prediction-01 section 3.1 478 + SVC_PARAM("tls-supported-groups", 9u, MANDATORY_VALUE, 479 + parse_tls_supported_groups, parse_tls_supported_groups), 480 + }; 481 + 482 + static const svc_param_info_t unknown_svc_param = 483 + SVC_PARAM("unknown", 0u, OPTIONAL_VALUE, parse_unknown, parse_unknown); 484 + 485 + #undef SVC_PARAM 486 + 487 + nonnull_all 488 + static really_inline size_t scan_unknown_svc_param_key( 489 + const char *data, uint16_t *key, const svc_param_info_t **param) 490 + { 491 + size_t length = 4; 492 + uint32_t number = (uint8_t)data[3] - '0'; 493 + 494 + if (number > 9) 495 + return 0; 496 + 497 + uint32_t leading_zero = number == 0; 498 + 499 + for (;; length++) { 500 + const uint32_t digit = (uint8_t)data[length] - '0'; 501 + if (digit > 9) 502 + break; 503 + number = number * 10 + digit; 504 + } 505 + 506 + leading_zero &= length > 4; 507 + if (leading_zero || length > 3 + 5) 508 + return 0; 509 + if (number < (sizeof(svc_params) / sizeof(svc_params[0]))) 510 + return (void)(*param = &svc_params[(*key = (uint16_t)number)]), length; 511 + if (number < 65535) 512 + return (void)(*key = (uint16_t)number), (void)(*param = &unknown_svc_param), length; 513 + return 0; 514 + } 515 + 516 + nonnull_all 517 + static really_inline size_t scan_svc_param( 518 + const char *data, uint16_t *key, const svc_param_info_t **param) 519 + { 520 + // draft-ietf-dnsop-svcb-https-12 section 2.1: 521 + // alpha-lc = %x61-7A ; a-z 522 + // SvcParamKey = 1*63(alpha-lc / DIGIT / "-") 523 + // 524 + // FIXME: naive implementation 525 + if (memcmp(data, "mandatory", 9) == 0) 526 + return (void)(*param = &svc_params[(*key = ZONE_SVC_PARAM_KEY_MANDATORY)]), 9; 527 + else if (memcmp(data, "alpn", 4) == 0) 528 + return (void)(*param = &svc_params[(*key = ZONE_SVC_PARAM_KEY_ALPN)]), 4; 529 + else if (memcmp(data, "no-default-alpn", 15) == 0) 530 + return (void)(*param = &svc_params[(*key = ZONE_SVC_PARAM_KEY_NO_DEFAULT_ALPN)]), 15; 531 + else if (memcmp(data, "port", 4) == 0) 532 + return (void)(*param = &svc_params[(*key = ZONE_SVC_PARAM_KEY_PORT)]), 4; 533 + else if (memcmp(data, "ipv4hint", 8) == 0) 534 + return (void)(*param = &svc_params[(*key = ZONE_SVC_PARAM_KEY_IPV4HINT)]), 8; 535 + else if (memcmp(data, "ech", 3) == 0) 536 + return (void)(*param = &svc_params[(*key = ZONE_SVC_PARAM_KEY_ECH)]), 3; 537 + else if (memcmp(data, "ipv6hint", 8) == 0) 538 + return (void)(*param = &svc_params[(*key = ZONE_SVC_PARAM_KEY_IPV6HINT)]), 8; 539 + else if (memcmp(data, "dohpath", 7) == 0) 540 + return (void)(*param = &svc_params[(*key = ZONE_SVC_PARAM_KEY_DOHPATH)]), 7; 541 + else if (memcmp(data, "ohttp", 5) == 0) 542 + return (void)(*param = &svc_params[(*key = ZONE_SVC_PARAM_KEY_OHTTP)]), 5; 543 + else if (memcmp(data, "tls-supported-groups", 20) == 0) 544 + return (void)(*param = &svc_params[(*key = ZONE_SVC_PARAM_KEY_TLS_SUPPORTED_GROUPS)]), 20; 545 + else if (memcmp(data, "key", 3) == 0) 546 + return scan_unknown_svc_param_key(data, key, param); 547 + else 548 + return 0; 549 + } 550 + 551 + nonnull_all 552 + static really_inline size_t scan_svc_param_key( 553 + const char *data, uint16_t *key) 554 + { 555 + // FIXME: improve implementation 556 + const svc_param_info_t *param; 557 + return scan_svc_param(data, key, &param); 558 + } 559 + 560 + nonnull_all 561 + static int32_t parse_mandatory( 562 + parser_t *parser, 563 + const type_info_t *type, 564 + const rdata_info_t *field, 565 + uint16_t key, 566 + const svc_param_info_t *param, 567 + rdata_t *rdata, 568 + const token_t *token) 569 + { 570 + (void)field; 571 + (void)param; 572 + 573 + // RFC9460 section 8: 574 + // This SvcParamKey is always automatically mandatory and MUST NOT appear 575 + // in its own value-list. Other automatically mandatory keys SHOULD NOT 576 + // appear in the list either. 577 + uint64_t mandatory = (1u << ZONE_SVC_PARAM_KEY_MANDATORY); 578 + uint64_t keys = 0u; 579 + int32_t highest_key = -1; 580 + const char *data = token->data; 581 + uint8_t *whence = rdata->octets; 582 + size_t skip; 583 + 584 + // RFC9460 section 9: 585 + // The "automatically mandatory" keys (Section 8) are "port" and 586 + // "no-default-alpn". 587 + if (type->name.value == ZONE_TYPE_HTTPS) 588 + mandatory = (1u << ZONE_SVC_PARAM_KEY_MANDATORY) | 589 + (1u << ZONE_SVC_PARAM_KEY_NO_DEFAULT_ALPN) | 590 + (1u << ZONE_SVC_PARAM_KEY_PORT); 591 + 592 + // RFC9460 section 8: 593 + // The presentation value SHALL be a comma-seperatred list of one or more 594 + // valid SvcParamKeys, ... 595 + if (!(skip = scan_svc_param_key(data, &key))) 596 + SYNTAX_ERROR(parser, "Invalid mandatory in %s", NAME(type)); 597 + if (key < 64) 598 + keys = 1llu << key; 599 + 600 + highest_key = key; 601 + key = htobe16(key); 602 + memcpy(rdata->octets, &key, sizeof(key)); 603 + rdata->octets += sizeof(key); 604 + data += skip; 605 + 606 + while (*data == ',' && rdata->octets < rdata->limit) { 607 + if (!(skip = scan_svc_param_key(data + 1, &key))) 608 + SYNTAX_ERROR(parser, "Invalid mandatory of %s", NAME(type)); 609 + 610 + // check if key appears in automatically mandatory key list 611 + if (key < 64) 612 + keys |= 1llu << key; 613 + 614 + data += skip + 1; 615 + if (key > highest_key) { 616 + highest_key = key; 617 + key = htobe16(key); 618 + memcpy(rdata->octets, &key, 2); 619 + rdata->octets += 2; 620 + } else { 621 + // RFC9460 section 8: 622 + // In wire format, the keys are represented by their numeric values in 623 + // network byte order, concatenated in ascending order. 624 + uint8_t *octets = whence; 625 + uint16_t smaller_key = 0; 626 + while (octets < rdata->octets) { 627 + memcpy(&smaller_key, octets, sizeof(smaller_key)); 628 + smaller_key = be16toh(smaller_key); 629 + if (key <= smaller_key) 630 + break; 631 + octets += 2; 632 + } 633 + assert(octets <= rdata->octets); 634 + // RFC9460 section 8: 635 + // Keys MAY appear in any order, but MUST NOT appear more than once. 636 + if (key == smaller_key) 637 + SEMANTIC_ERROR(parser, "Duplicate key in mandatory of %s", NAME(type)); 638 + assert(key < smaller_key); 639 + uint16_t length = (uint16_t)(rdata->octets - octets); 640 + memmove(octets + 2, octets, length); 641 + key = htobe16(key); 642 + memcpy(octets, &key, 2); 643 + rdata->octets += 2; 644 + } 645 + } 646 + 647 + if (keys & mandatory) 648 + SEMANTIC_ERROR(parser, "Automatically mandatory key(s) in mandatory of %s", NAME(type)); 649 + if (rdata->octets >= rdata->limit) 650 + SYNTAX_ERROR(parser, "Invalid mandatory in %s", NAME(type)); 651 + if (data != token->data + token->length) 652 + SYNTAX_ERROR(parser, "Invalid mandatory in %s", NAME(type)); 653 + return 0; 654 + } 655 + 656 + nonnull_all 657 + static int32_t parse_mandatory_lax( 658 + parser_t *parser, 659 + const type_info_t *type, 660 + const rdata_info_t *field, 661 + uint16_t key, 662 + const svc_param_info_t *param, 663 + rdata_t *rdata, 664 + const token_t *token) 665 + { 666 + (void)field; 667 + 668 + // RFC9460 section 8: 669 + // This SvcParamKey is always automatically mandatory and MUST NOT appear 670 + // in its own value-list. Other automatically mandatory keys SHOULD NOT 671 + // appear in the list either. 672 + uint64_t mandatory = (1u << ZONE_SVC_PARAM_KEY_MANDATORY); 673 + uint64_t keys = 0; 674 + // RFC9460 section 8: 675 + // In wire format, the keys are represented by their numeric values in 676 + // network byte order, concatenated in strictly increasing numeric order. 677 + // 678 + // cannot reorder in secondary mode, print an error 679 + bool out_of_order = false; 680 + int32_t highest_key = -1; 681 + const uint8_t *whence = rdata->octets; 682 + const char *data = token->data; 683 + size_t skip; 684 + 685 + // RFC9460 section 8: 686 + // The presentation value SHALL be a comma-seperatred list of one or more 687 + // valid SvcParamKeys, ... 688 + if (!(skip = scan_svc_param_key(data, &key))) 689 + SYNTAX_ERROR(parser, "Invalid key in %s of %s", NAME(param), NAME(type)); 690 + if (key < 64) 691 + keys |= 1llu << key; 692 + 693 + // RFC9460 section 9: 694 + // The "automatically mandatory" keys (Section 8) are "port" and 695 + // "no-default-alpn". 696 + if (type->name.value == ZONE_TYPE_HTTPS) 697 + mandatory = (1u << ZONE_SVC_PARAM_KEY_MANDATORY) | 698 + (1u << ZONE_SVC_PARAM_KEY_NO_DEFAULT_ALPN) | 699 + (1u << ZONE_SVC_PARAM_KEY_PORT); 700 + 701 + key = htobe16(key); 702 + memcpy(rdata->octets, &key, 2); 703 + rdata->octets += 2; 704 + data += skip; 705 + 706 + while (*data == ',' && rdata->octets < rdata->limit) { 707 + if (!(skip = scan_svc_param_key(data + 1, &key))) 708 + SYNTAX_ERROR(parser, "Invalid key in %s of %s", NAME(param), NAME(type)); 709 + 710 + // check if key appears in automatically mandatory key list 711 + if (key < 64) 712 + keys |= (1llu << key); 713 + 714 + if ((int32_t)key <= highest_key) { 715 + // RFC9460 section 8: 716 + // In wire format, the keys are represented by their numeric values in 717 + // network byte order, concatenated in ascending order. 718 + const uint8_t *octets = whence; 719 + uint16_t smaller_key = 0; 720 + while (octets < rdata->octets) { 721 + memcpy(&smaller_key, octets, sizeof(smaller_key)); 722 + smaller_key = be16toh(smaller_key); 723 + if (key <= smaller_key) 724 + break; 725 + octets += 2; 726 + } 727 + assert(octets <= rdata->octets); 728 + // RFC9460 section 8: 729 + // Keys MAY appear in any order, but MUST NOT appear more than once. 730 + if (key == smaller_key) 731 + SEMANTIC_ERROR(parser, "Duplicate key in mandatory of %s", NAME(type)); 732 + assert(key < smaller_key); 733 + out_of_order = true; 734 + } 735 + 736 + data += skip + 1; 737 + key = htobe16(key); 738 + memcpy(rdata->octets, &key, 2); 739 + rdata->octets += 2; 740 + } 741 + 742 + if (keys & mandatory) 743 + SEMANTIC_ERROR(parser, "Automatically mandatory key(s) in mandatory of %s", NAME(type)); 744 + if (out_of_order) 745 + SEMANTIC_ERROR(parser, "Out of order keys in mandatory of %s", NAME(type)); 746 + if (rdata->octets >= rdata->limit - 2) 747 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 748 + if (data != token->data + token->length) 749 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 750 + return 0; 751 + } 752 + 753 + nonnull_all 754 + static really_inline int32_t check_mandatory( 755 + zone_parser_t *parser, 756 + const type_info_t *type, 757 + const rdata_info_t *field, 758 + const rdata_t *rdata, 759 + const uint8_t *parameters) 760 + { 761 + // parameters are guaranteed to be in order (automatic in strict mode) 762 + if (parameters[0] || parameters[1]) 763 + return 0; // no mandatory parameter 764 + 765 + uint16_t length; 766 + memcpy(&length, parameters + 2, sizeof(length)); 767 + length = be16toh(length); 768 + assert(rdata->octets - parameters >= 4 + length); 769 + 770 + bool missing_keys = false; 771 + const uint8_t *limit = parameters + 4 + length; 772 + const uint8_t *keys = parameters + 4; 773 + parameters += 4 + length; 774 + 775 + assert(parameters <= rdata->octets); 776 + 777 + for (; keys < limit; keys += 2) { 778 + uint16_t key; 779 + memcpy(&key, keys, sizeof(key)); 780 + // no byteswap, compare big endian 781 + 782 + // mandatory is guaranteed to exist 783 + if (key == 0) 784 + continue; 785 + if ((missing_keys = (parameters == rdata->octets))) 786 + break; 787 + assert(rdata->octets - parameters >= 4); 788 + memcpy(&length, parameters + 2, 2); 789 + length = be16toh(length); 790 + assert(rdata->octets - parameters >= 4 + length); 791 + // parameters are guaranteed to be sorted 792 + if (memcmp(parameters, &key, 2) == 0) { 793 + parameters += 4 + length; 794 + } else { 795 + const uint8_t *parameter = parameters + 4 + length; 796 + assert(rdata->octets - parameters >= 4); 797 + while (parameter < rdata->octets) { 798 + if (memcmp(parameter, &key, 2) == 0) 799 + break; 800 + memcpy(&length, parameter + 2, 2); 801 + length = be16toh(length); 802 + assert(rdata->octets - parameters >= 4 + length); 803 + parameter += 4 + length; 804 + } 805 + 806 + if ((missing_keys = (parameter == rdata->octets))) 807 + break; 808 + } 809 + } 810 + 811 + if (missing_keys) 812 + SEMANTIC_ERROR(parser, "Mandatory %s missing in %s", NAME(field), NAME(type)); 813 + return 0; 814 + } 815 + 816 + nonnull((1, 2, 3, 5, 7)) 817 + static really_inline int32_t parse_svc_param( 818 + parser_t *parser, 819 + const type_info_t *type, 820 + const rdata_info_t *field, 821 + uint16_t key, 822 + const svc_param_info_t *param, 823 + const parse_svc_param_t parse, 824 + rdata_t *rdata, 825 + const token_t *token) 826 + { 827 + switch ((token != NULL) | param->has_value) { 828 + case 0: // void parameter without value 829 + return 0; 830 + case 1: // void parameter with value 831 + assert(token); 832 + SEMANTIC_ERROR(parser, "%s with value in %s", NAME(field), NAME(type)); 833 + if (unlikely(!token->length)) 834 + return 0; 835 + break; 836 + case 2: // parameter without optional value 837 + return 0; 838 + case 3: // parameter with optional value 839 + assert(token); 840 + if (unlikely(!token->length)) 841 + return 0; 842 + break; 843 + case 4: // parameter without value 844 + SEMANTIC_ERROR(parser, "%s without value in %s", NAME(field), NAME(type)); 845 + return 0; 846 + case 5: // parameter with value 847 + assert(token); 848 + if (unlikely(!token->length)) 849 + SEMANTIC_ERROR(parser, "%s without value in %s", NAME(field), NAME(type)); 850 + break; 851 + } 852 + 853 + return parse(parser, type, field, key, param, rdata, token); 854 + } 855 + 856 + nonnull_all 857 + static int32_t parse_svc_params_lax( 858 + parser_t *parser, 859 + const type_info_t *type, 860 + const rdata_info_t *field, 861 + rdata_t *rdata, 862 + token_t *token) 863 + { 864 + bool out_of_order = false; 865 + int32_t code, highest_key = -1; 866 + uint32_t errors = 0; 867 + const uint8_t *whence = rdata->octets; 868 + uint64_t keys = 0; 869 + 870 + // FIXME: check if parameter even fits 871 + while (is_contiguous(token)) { 872 + size_t count; 873 + uint16_t key; 874 + const svc_param_info_t *param; 875 + const token_t *value = token; 876 + 877 + if (!(count = scan_svc_param(token->data, &key, &param))) 878 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 879 + assert(param); 880 + 881 + if (likely(key > highest_key)) 882 + highest_key = key; 883 + else 884 + out_of_order = true; 885 + 886 + if (key < 64) 887 + keys |= (1llu << key); 888 + 889 + if (token->data[count] != '=') 890 + value = NULL; 891 + else if (token->data[count+1] != '"') 892 + (void)(token->data += count + 1), token->length -= count + 1; 893 + else if ((code = take_quoted(parser, type, field, token)) < 0) 894 + return code; 895 + 896 + uint8_t *octets = rdata->octets; 897 + uint16_t length; 898 + rdata->octets += 4; 899 + if ((code = parse_svc_param( 900 + parser, type, field, key, param, param->parse_lax, rdata, value)) < 0) 901 + return code; 902 + 903 + errors += (code != 0); 904 + key = htobe16(key); 905 + memcpy(octets, &key, sizeof(key)); 906 + assert(rdata->octets >= octets && (rdata->octets - octets) <= 65535 + 4); 907 + length = (uint16_t)((rdata->octets - octets) - 4); 908 + length = htobe16(length); 909 + memcpy(octets + 2, &length, sizeof(length)); 910 + take(parser, token); 911 + } 912 + 913 + if (likely(errors == 0 && whence != rdata->octets)) { 914 + assert(whence <= rdata->octets + 4); 915 + 916 + if (unlikely(out_of_order)) { 917 + SEMANTIC_ERROR(parser, "Out of order %s in %s", NAME(field), NAME(type)); 918 + } else { // warn about missing or out-of-order parameters 919 + if (keys & 0x01) 920 + check_mandatory(parser, type, field, rdata, whence); 921 + // RFC9460 section 7.2: 922 + // For "no-default-alpn", the presentation and wire-format values MUST 923 + // be empty. When "no-default-alpn" is specified in an RR, "alpn" must 924 + // also be specified in order for the RR to be "self-consistent" 925 + // (Section 2.4.3). 926 + if ((keys & 0x04) && !(keys & 0x02)) 927 + SEMANTIC_ERROR(parser, "%s with no-default-alpn but without alpn in %s", 928 + NAME(field), NAME(type)); 929 + } 930 + } 931 + 932 + return have_delimiter(parser, type, token); 933 + } 934 + 935 + // https://www.iana.org/assignments/dns-svcb/dns-svcb.xhtml 936 + nonnull_all 937 + static really_inline int32_t parse_svc_params( 938 + parser_t *parser, 939 + const type_info_t *type, 940 + const rdata_info_t *field, 941 + rdata_t *rdata, 942 + token_t *token) 943 + { 944 + // propagate data as-is if secondary 945 + if (parser->options.secondary) 946 + return parse_svc_params_lax(parser, type, field, rdata, token); 947 + 948 + int32_t code; 949 + int32_t highest_key = -1; 950 + uint8_t *whence = rdata->octets; 951 + uint64_t keys = 0; 952 + 953 + while (is_contiguous(token)) { 954 + size_t count; 955 + uint16_t key; 956 + const token_t *value = token; 957 + const svc_param_info_t *param; 958 + 959 + if (!(count = scan_svc_param(token->data, &key, &param))) 960 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 961 + assert(param); 962 + 963 + if (key < 64) 964 + keys |= (1llu << key); 965 + 966 + if (token->data[count] != '=') 967 + value = NULL; 968 + else if (token->data[count+1] != '"') 969 + (void)(token->data += count + 1), token->length -= count + 1; 970 + else if ((code = take_quoted(parser, type, field, token)) < 0) 971 + return code; 972 + 973 + uint8_t *octets; 974 + uint16_t length; 975 + 976 + if (likely(key > highest_key)) { 977 + highest_key = key; 978 + octets = rdata->octets; 979 + rdata->octets += 4; 980 + if ((code = parse_svc_param( 981 + parser, type, field, key, param, param->parse, rdata, value))) 982 + return code; 983 + assert(rdata->octets >= octets && (rdata->octets - octets) <= 65535 + 4); 984 + length = (uint16_t)((rdata->octets - octets) - 4); 985 + } else { 986 + octets = whence; 987 + uint16_t smaller_key = 65535; 988 + 989 + // this can probably be done in a function or something 990 + while (octets < rdata->octets) { 991 + memcpy(&smaller_key, octets, sizeof(smaller_key)); 992 + smaller_key = be16toh(smaller_key); 993 + if (key <= smaller_key) 994 + break; 995 + memcpy(&length, octets + 2, sizeof(length)); 996 + length = be16toh(length); 997 + octets += length + 4; 998 + } 999 + 1000 + assert(octets < rdata->octets); 1001 + if (key == smaller_key) 1002 + SEMANTIC_ERROR(parser, "Duplicate key in %s", NAME(type)); 1003 + 1004 + rdata_t rdata_view; 1005 + // RFC9460 section 2.2: 1006 + // SvcParamKeys SHALL appear in increasing numeric order. 1007 + // 1008 + // move existing data to end of the buffer and reset limit to 1009 + // avoid allocating memory 1010 + assert(rdata->octets - octets < ZONE_RDATA_SIZE); 1011 + length = (uint16_t)(rdata->octets - octets); 1012 + rdata_view.octets = octets + 4u; 1013 + rdata_view.limit = parser->rdata->octets + (ZONE_RDATA_SIZE - length); 1014 + // move data PADDING_SIZE past limit to ensure SIMD operatations 1015 + // do not overwrite existing data 1016 + memmove(rdata_view.limit + ZONE_BLOCK_SIZE, octets, length); 1017 + if ((code = parse_svc_param( 1018 + parser, type, field, key, param, param->parse, &rdata_view, token))) 1019 + return code; 1020 + assert(rdata_view.octets < rdata_view.limit); 1021 + memmove(rdata_view.octets, rdata_view.limit + ZONE_BLOCK_SIZE, length); 1022 + rdata->octets = rdata_view.octets + length; 1023 + length = (uint16_t)(rdata_view.octets - octets) - 4u; 1024 + } 1025 + 1026 + key = htobe16(key); 1027 + memcpy(octets, &key, sizeof(key)); 1028 + length = htobe16(length); 1029 + memcpy(octets + 2, &length, sizeof(length)); 1030 + take(parser, token); 1031 + } 1032 + 1033 + if ((code = have_delimiter(parser, type, token))) 1034 + return code; 1035 + assert(whence); 1036 + if ((keys & (1u << ZONE_SVC_PARAM_KEY_MANDATORY)) && 1037 + (code = check_mandatory(parser, type, field, rdata, whence)) < 0) 1038 + return code; 1039 + // RFC9460 section 7.2: 1040 + // For "no-default-alpn", the presentation and wire-format values MUST be 1041 + // empty. When "no-default-alpn" is specified in an RR, "alpn" must also 1042 + // be specified in order for the RR to be "self-consistent" 1043 + // (Section 2.4.3). 1044 + if ((keys & 0x04) && !(keys & 0x02)) 1045 + SEMANTIC_ERROR(parser, "%s with no-default-alpn but without alpn in %s", 1046 + NAME(field), NAME(type)); 1047 + return 0; 1048 + } 1049 + 1050 + #endif // SVCB_H
+107
usr.sbin/nsd/simdzone/src/generic/text.h
··· 1 + /* 2 + * text.h -- string parser 3 + * 4 + * Copyright (c) 2022-2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef TEXT_H 10 + #define TEXT_H 11 + 12 + nonnull_all 13 + static really_inline uint32_t unescape(const char *text, uint8_t *wire) 14 + { 15 + uint8_t d[3]; 16 + uint32_t o; 17 + 18 + if ((d[0] = (uint8_t)text[1] - '0') > 9) { 19 + o = (uint8_t)text[1]; 20 + *wire = (uint8_t)o; 21 + return 2u; 22 + } else { 23 + d[1] = (uint8_t)text[2] - '0'; 24 + d[2] = (uint8_t)text[3] - '0'; 25 + o = d[0] * 100 + d[1] * 10 + d[2]; 26 + *wire = (uint8_t)o; 27 + return (o > 255 || d[1] > 9 || d[2] > 9) ? 0 : 4u; 28 + } 29 + } 30 + 31 + typedef struct string_block string_block_t; 32 + struct string_block { 33 + uint64_t backslashes; 34 + }; 35 + 36 + nonnull_all 37 + static really_inline void copy_string_block( 38 + string_block_t *block, const char *text, uint8_t *wire) 39 + { 40 + simd_8x32_t input; 41 + simd_loadu_8x32(&input, text); 42 + simd_storeu_8x32(wire, &input); 43 + block->backslashes = simd_find_8x32(&input, '\\'); 44 + } 45 + 46 + nonnull_all 47 + static really_inline int32_t scan_string( 48 + const char *data, 49 + size_t length, 50 + uint8_t *octets, 51 + const uint8_t *limit) 52 + { 53 + const char *text = data; 54 + uint8_t *wire = octets; 55 + string_block_t block; 56 + 57 + copy_string_block(&block, text, octets); 58 + 59 + uint64_t count = 32; 60 + if (length < 32) 61 + count = length; 62 + uint64_t mask = (1llu << count) - 1u; 63 + 64 + // check for escape sequences 65 + if (unlikely(block.backslashes & mask)) 66 + goto escaped; 67 + 68 + if (length < 32) 69 + return (int32_t)count; 70 + 71 + text += count; 72 + wire += count; 73 + length -= count; 74 + 75 + do { 76 + copy_string_block(&block, text, wire); 77 + count = 32; 78 + if (length < 32) 79 + count = length; 80 + mask = (1llu << count) - 1u; 81 + 82 + // check for escape sequences 83 + if (unlikely(block.backslashes & mask)) { 84 + escaped: 85 + block.backslashes &= -block.backslashes; 86 + mask = block.backslashes - 1; 87 + count = count_ones(mask); 88 + const uint32_t octet = unescape(text+count, wire+count); 89 + if (!octet) 90 + return -1; 91 + text += count + octet; 92 + wire += count + 1; 93 + length -= count + octet; 94 + } else { 95 + text += count; 96 + wire += count; 97 + length -= count; 98 + } 99 + } while (length && wire < limit); 100 + 101 + if (length || (wire > limit)) 102 + return -1; 103 + assert(!length); 104 + return (int32_t)(wire - octets); 105 + } 106 + 107 + #endif // TEXT_H
+85
usr.sbin/nsd/simdzone/src/generic/time.h
··· 1 + /* 2 + * time.h -- timestamp parser 3 + * 4 + * Copyright (c) 2022-2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef TIME_H 10 + #define TIME_H 11 + 12 + /* number of days per month (except for February in leap years) */ 13 + static const uint8_t days_in_month[13] = { 14 + 0 /* no --month */, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 15 + 16 + static const uint16_t days_to_month[13] = { 17 + 0 /* no --month */, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; 18 + 19 + static uint64_t is_leap_year(uint64_t year) 20 + { 21 + return (year % 4 == 0) & ((year % 100 != 0) | (year % 400 == 0)); 22 + } 23 + 24 + static uint64_t leap_days(uint64_t y1, uint64_t y2) 25 + { 26 + --y1; 27 + --y2; 28 + return (y2/4 - y1/4) - (y2/100 - y1/100) + (y2/400 - y1/400); 29 + } 30 + 31 + nonnull_all 32 + static really_inline int32_t parse_time( 33 + parser_t *parser, 34 + const type_info_t *type, 35 + const rdata_info_t *field, 36 + rdata_t *rdata, 37 + const token_t *token) 38 + { 39 + if (token->length != 14) 40 + return parse_int32(parser, type, field, rdata, token); 41 + 42 + uint64_t d[14]; // YYYYmmddHHMMSS 43 + const char *p = token->data; 44 + for (int i = 0; i < 14; i++) { 45 + d[i] = (uint8_t)p[i] - '0'; 46 + if (d[i] > 9) 47 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 48 + } 49 + 50 + // code adapted from Python 2.4.1 sources (Lib/calendar.py) 51 + const uint64_t year = (d[0] * 1000) + (d[1] * 100) + (d[2] * 10) + d[3]; 52 + const uint64_t mon = (d[4] * 10) + d[5]; 53 + const uint64_t mday = (d[6] * 10) + d[7]; 54 + const uint64_t hour = (d[8] * 10) + d[9]; 55 + const uint64_t min = (d[10] * 10) + d[11]; 56 + const uint64_t sec = (d[12] * 10) + d[13]; 57 + 58 + if (year < 1970) 59 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 60 + 61 + uint64_t leap_year = is_leap_year(year); 62 + uint64_t days = 365 * (year - 1970) + leap_days(1970, year); 63 + 64 + if (!mon || mon > 12) 65 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 66 + if (!mday || mday > days_in_month[mon] + (leap_year & (mon == 2))) 67 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 68 + if (hour > 23 || min > 59 || sec > 59) 69 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 70 + 71 + days += days_to_month[mon]; 72 + days += (mon > 2) & leap_year; 73 + days += mday - 1; 74 + 75 + const uint64_t hours = days * 24 + hour; 76 + const uint64_t minutes = hours * 60 + min; 77 + const uint64_t seconds = minutes * 60 + sec; 78 + 79 + uint32_t time = htobe32((uint32_t)seconds); 80 + memcpy(rdata->octets, &time, sizeof(time)); 81 + rdata->octets += 4; 82 + return 0; 83 + } 84 + 85 + #endif // TIME_H
+117
usr.sbin/nsd/simdzone/src/generic/ttl.h
··· 1 + /* 2 + * ttl.h -- Time to Live (TTL) parser 3 + * 4 + * Copyright (c) 2022-2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef TTL_H 10 + #define TTL_H 11 + 12 + // [sS] = 1, [mM] = 60, [hH] = 60*60, [dD] = 24*60*60, [wW] = 7*24*60*60 13 + static const uint32_t ttl_units[256] = { 14 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x00 - 0x0f 15 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x10 - 0x1f 16 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x20 - 0x2f 17 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x30 - 0x3f 18 + 0, 0, 0, 0, 86400, 0, 0, 0, 3600, 0, 0, 0, 0, 60, 0, 0, // 0x40 - 0x4f 19 + 0, 0, 0, 1, 0, 0, 0, 604800, 0, 0, 0, 0, 0, 0, 0, 0, // 0x50 - 0xf5 20 + 0, 0, 0, 0, 86400, 0, 0, 0, 3600, 0, 0, 0, 0, 60, 0, 0, // 0x60 - 0x6f 21 + 0, 0, 0, 1, 0, 0, 0, 604800, 0, 0, 0, 0, 0, 0, 0, 0, // 0x70 - 0x7f 22 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x80 - 0x8f 23 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x90 - 0x9f 24 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xa0 - 0xaf 25 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xb0 - 0xbf 26 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xc0 - 0xcf 27 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xd0 - 0xdf 28 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xe0 - 0xef 29 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 0xf0 - 0xff 30 + }; 31 + 32 + nonnull_all 33 + static really_inline int32_t scan_ttl( 34 + const char *data, size_t length, bool allow_units, uint32_t *ttl) 35 + { 36 + if (scan_int32(data, length, ttl)) 37 + return 1; 38 + if (!allow_units) 39 + return 0; 40 + 41 + uint64_t sum = 0, number = (uint8_t)data[0] - '0'; 42 + // ttls must start with a number. e.g. 1h not h1 43 + if (number > 9) 44 + return 0; 45 + 46 + uint64_t unit = 0, last_unit = 0; 47 + enum { NUMBER, UNIT } state = NUMBER; 48 + 49 + for (size_t count = 1; count < length; count++) { 50 + const uint64_t digit = (uint8_t)data[count] - '0'; 51 + 52 + if (state == NUMBER) { 53 + if (digit < 10) { 54 + number = number * 10 + digit; 55 + if (number > UINT32_MAX) 56 + return 0; 57 + } else if (!(unit = ttl_units[ (uint8_t)data[count] ])) { 58 + return 0; 59 + // units must not be repeated e.g. 1m1m 60 + } else if (unit == last_unit) { 61 + return 0; 62 + // greater units must precede smaller units. e.g. 1m1s, not 1s1m 63 + } else if (unit < last_unit) { 64 + return 0; 65 + } else { 66 + if (UINT32_MAX / unit < number) 67 + return 0; 68 + number *= unit; 69 + if (UINT32_MAX - sum < number) 70 + return 0; 71 + last_unit = unit; 72 + sum += number; 73 + number = 0; 74 + state = UNIT; 75 + } 76 + } else if (state == UNIT) { 77 + // units must be followed by a number. e.g. 1h30m, not 1hh 78 + if (digit > 9) 79 + return 0; 80 + // units must not be followed by a number if smallest unit, 81 + // i.e. seconds, was previously specified 82 + if (last_unit == 1) 83 + return 0; 84 + number = digit; 85 + state = NUMBER; 86 + } 87 + } 88 + 89 + if (UINT32_MAX - sum < number) 90 + return 0; 91 + 92 + sum += number; 93 + *ttl = (uint32_t)sum; 94 + return 1; 95 + } 96 + 97 + nonnull_all 98 + static really_inline int32_t parse_ttl( 99 + parser_t *parser, 100 + const type_info_t *type, 101 + const rdata_info_t *field, 102 + rdata_t *rdata, 103 + const token_t *token) 104 + { 105 + uint32_t ttl; 106 + if (!scan_ttl(token->data, token->length, parser->options.pretty_ttls, &ttl)) 107 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 108 + // FIXME: comment RFC2308 msb 109 + if (ttl & (1u << 31)) 110 + SEMANTIC_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 111 + ttl = htobe32(ttl); 112 + memcpy(rdata->octets, &ttl, sizeof(ttl)); 113 + rdata->octets += 4; 114 + return 0; 115 + } 116 + 117 + #endif // TTL_H
+205
usr.sbin/nsd/simdzone/src/generic/type.h
··· 1 + /* 2 + * type.h -- RRTYPE parser 3 + * 4 + * Copyright (c) 2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef TYPE_H 10 + #define TYPE_H 11 + 12 + #define V(code) { &(types[0].name), 0 } 13 + #define T(code) { &(types[code].name), 1 } 14 + #define C(code) { &(classes[code].name), 2 } 15 + 16 + // map hash to type or class descriptor (generated using hash.c) 17 + static const struct { 18 + const mnemonic_t *mnemonic; 19 + int32_t code; 20 + } types_and_classes[256] = { 21 + V(0), V(0), V(0), V(0), V(0), V(0), V(0), T(20), 22 + T(3), V(0), V(0), V(0), V(0), T(261), V(0), V(0), 23 + T(60), V(0), V(0), T(105), V(0), V(0), V(0), T(258), 24 + V(0), V(0), V(0), V(0), T(30), V(0), T(28), V(0), 25 + V(0), T(16), V(0), V(0), T(56), T(14), T(22), V(0), 26 + V(0), T(13), V(0), T(47), T(21), V(0), T(65), T(27), 27 + V(0), V(0), V(0), V(0), V(0), T(1), T(62), V(0), 28 + V(0), C(1), V(0), T(44), V(0), V(0), T(33), V(0), 29 + V(0), V(0), V(0), V(0), T(63), V(0), T(266), V(0), 30 + C(3), T(99), T(37), V(0), V(0), V(0), C(2), T(43), 31 + V(0), T(50), C(4), T(51), V(0), V(0), V(0), T(2), 32 + T(49), T(42), T(19), T(23), V(0), T(6), V(0), V(0), 33 + V(0), V(0), T(29), V(0), T(7), V(0), V(0), V(0), 34 + V(0), T(57), V(0), V(0), V(0), V(0), V(0), T(36), 35 + T(15), V(0), V(0), T(26), T(11), V(0), V(0), V(0), 36 + V(0), V(0), V(0), V(0), T(104), V(0), T(8), V(0), 37 + V(0), V(0), T(38), V(0), T(9), V(0), T(64), V(0), 38 + V(0), V(0), V(0), V(0), V(0), V(0), T(39), T(52), 39 + T(24), V(0), T(5), T(106), V(0), V(0), V(0), V(0), 40 + T(265), V(0), V(0), V(0), V(0), T(25), V(0), T(18), 41 + T(48), V(0), T(53), V(0), V(0), V(0), T(59), V(0), 42 + V(0), V(0), V(0), V(0), T(4), V(0), T(10), V(0), 43 + V(0), V(0), V(0), V(0), V(0), T(55), V(0), V(0), 44 + V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), 45 + V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), 46 + V(0), V(0), T(61), T(12), V(0), V(0), V(0), V(0), 47 + V(0), T(108), V(0), V(0), T(257), V(0), V(0), V(0), 48 + T(35), V(0), T(263), V(0), V(0), V(0), V(0), T(107), 49 + V(0), V(0), V(0), V(0), T(17), V(0), T(45), V(0), 50 + V(0), V(0), V(0), V(0), V(0), V(0), T(46), V(0), 51 + V(0), T(109), V(0), V(0), V(0), V(0), V(0), V(0), 52 + V(0), V(0), V(0), V(0), T(262), V(0), T(256), V(0) 53 + }; 54 + 55 + #undef V 56 + #undef T 57 + #undef C 58 + 59 + nonnull_all 60 + static really_inline int32_t scan_generic_type( 61 + const char *data, size_t length, uint16_t *code, const mnemonic_t **mnemonic) 62 + { 63 + if (scan_int16(data + 4, length - 4, code) == 0) 64 + return -1; 65 + if (*code <= 258) 66 + *mnemonic = &types[*code].name; 67 + else if (*code == 32769) 68 + *mnemonic = &types[259].name; 69 + else 70 + *mnemonic = &types[0].name; 71 + return 1; 72 + } 73 + 74 + nonnull_all 75 + static really_inline int32_t scan_generic_class( 76 + const char *data, size_t length, uint16_t *code, const mnemonic_t **mnemonic) 77 + { 78 + if (scan_int16(data + 5, length - 5, code) == 0) 79 + return -1; 80 + if (*code <= 4) 81 + *mnemonic = &classes[*code].name; 82 + else 83 + *mnemonic = &classes[0].name; 84 + return 2; 85 + } 86 + 87 + #if BYTE_ORDER == LITTLE_ENDIAN 88 + # define TYPE (0x45505954llu) 89 + # define TYPE_MASK (0xffffffffllu) 90 + # define CLASS (0x5353414c43llu) 91 + # define CLASS_MASK (0xffffffffffllu) 92 + #else 93 + # define TYPE (0x5459504500000000llu) 94 + # define TYPE_MASK (0xffffffff00000000llu) 95 + # define CLASS (0x434c415353000000llu) 96 + # define CLASS_MASK (0xffffffffff000000llu) 97 + #endif 98 + 99 + static const int8_t zero_masks[48] = { 100 + -1, -1, -1, -1, -1, -1, -1, -1, 101 + -1, -1, -1, -1, -1, -1, -1, -1, 102 + -1, -1, -1, -1, -1, -1, -1, -1, 103 + -1, -1, -1, -1, -1, -1, -1, -1, 104 + 0, 0, 0, 0, 0, 0, 0, 0, 105 + 0, 0, 0, 0, 0, 0, 0, 0 106 + }; 107 + 108 + static really_inline uint8_t hash(uint64_t prefix) 109 + { 110 + prefix = le64toh(prefix); 111 + uint32_t value = (uint32_t)((prefix >> 32) ^ prefix); 112 + // magic value is generated using hash.c, rerun when adding types 113 + return (uint8_t)((value * 3523548378ull) >> 32); 114 + } 115 + 116 + nonnull_all 117 + static really_inline int32_t scan_type_or_class( 118 + const char *data, size_t length, uint16_t *code, const mnemonic_t **mnemonic) 119 + { 120 + uint64_t input0, input1; 121 + static const uint64_t letter_mask = 0x4040404040404040llu; 122 + 123 + // safe, input is padded 124 + memcpy(&input0, data, 8); 125 + memcpy(&input1, data + 8, 8); 126 + 127 + // convert to upper case 128 + input0 = input0 & ~((input0 & letter_mask) >> 1); 129 + input1 = input1 & ~((input1 & letter_mask) >> 1); 130 + 131 + length &= 0x1f; 132 + const uint8_t *zero_mask = (const uint8_t *)&zero_masks[32 - (length & 0x1f)]; 133 + uint64_t zero_mask0, zero_mask1; 134 + 135 + // sanitize input 136 + memcpy(&zero_mask0, zero_mask, 8); 137 + memcpy(&zero_mask1, zero_mask + 8, 8); 138 + 139 + input0 &= zero_mask0; 140 + input1 &= zero_mask1; 141 + 142 + const uint8_t index = hash(input0); 143 + *code = (uint16_t)types_and_classes[index].mnemonic->value; 144 + *mnemonic = types_and_classes[index].mnemonic; 145 + 146 + uint64_t name0, name1; 147 + memcpy(&name0, (*mnemonic)->key.data, 8); 148 + memcpy(&name1, (*mnemonic)->key.data + 8, 8); 149 + 150 + if (likely(((input0 ^ name0) | (input1 ^ name1)) == 0) && *code) 151 + return types_and_classes[index].code; 152 + else if ((input0 & TYPE_MASK) == TYPE) 153 + return scan_generic_type(data, length, code, mnemonic); 154 + else if ((input0 & CLASS_MASK) == CLASS) 155 + return scan_generic_class(data, length, code, mnemonic); 156 + return 0; 157 + } 158 + 159 + nonnull_all 160 + static really_inline int32_t scan_type( 161 + const char *data, size_t length, uint16_t *code, const mnemonic_t **mnemonic) 162 + { 163 + uint64_t input0, input1; 164 + static const uint64_t letter_mask = 0x4040404040404040llu; 165 + 166 + // safe, input is padded 167 + memcpy(&input0, data, 8); 168 + memcpy(&input1, data + 8, 8); 169 + 170 + // convert to upper case 171 + input0 = input0 & ~((input0 & letter_mask) >> 1); 172 + input1 = input1 & ~((input1 & letter_mask) >> 1); 173 + 174 + length &= 0x1f; 175 + const uint8_t *zero_mask = (const uint8_t *)&zero_masks[32 - (length & 0x1f)]; 176 + uint64_t zero_mask0, zero_mask1; 177 + 178 + // sanitize input 179 + memcpy(&zero_mask0, zero_mask, 8); 180 + memcpy(&zero_mask1, zero_mask + 8, 8); 181 + 182 + input0 &= zero_mask0; 183 + input1 &= zero_mask1; 184 + 185 + const uint8_t index = hash(input0); 186 + *code = (uint16_t)types_and_classes[index].mnemonic->value; 187 + *mnemonic = types_and_classes[index].mnemonic; 188 + 189 + uint64_t name0, name1; 190 + memcpy(&name0, (*mnemonic)->key.data, 8); 191 + memcpy(&name1, (*mnemonic)->key.data + 8, 8); 192 + 193 + if (likely(((input0 ^ name0) | (input1 ^ name1)) == 0) && *code) 194 + return types_and_classes[index].code; 195 + else if ((input0 & TYPE_MASK) == TYPE) 196 + return scan_generic_type(data, length, code, mnemonic); 197 + return 0; 198 + } 199 + 200 + #undef TYPE 201 + #undef TYPE_MASK 202 + #undef CLASS 203 + #undef CLASS_MASK 204 + 205 + #endif // TYPE_H
+3306
usr.sbin/nsd/simdzone/src/generic/types.h
··· 1 + /* 2 + * types.h 3 + * 4 + * Copyright (c) 2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef TYPES_H 10 + #define TYPES_H 11 + 12 + nonnull_all 13 + static really_inline int32_t scan_type_or_class( 14 + const char *data, 15 + size_t length, 16 + uint16_t *code, 17 + const mnemonic_t **mnemonic); 18 + 19 + nonnull_all 20 + static really_inline int32_t parse_type( 21 + parser_t *parser, 22 + const type_info_t *type, 23 + const rdata_info_t *field, 24 + rdata_t *rdata, 25 + const token_t *token); 26 + 27 + nonnull_all 28 + static really_inline int32_t parse_name( 29 + parser_t *parser, 30 + const type_info_t *type, 31 + const rdata_info_t *field, 32 + rdata_t *rdata, 33 + const token_t *token); 34 + 35 + nonnull_all 36 + static really_inline int32_t parse_string( 37 + parser_t *parser, 38 + const type_info_t *type, 39 + const rdata_info_t *field, 40 + rdata_t *rdata, 41 + const token_t *token); 42 + 43 + nonnull_all 44 + static really_inline int32_t parse_text( 45 + parser_t *parser, 46 + const type_info_t *type, 47 + const rdata_info_t *field, 48 + rdata_t *rdata, 49 + const token_t *token); 50 + 51 + #define FIELDS(fields) \ 52 + { (sizeof(fields)/sizeof(fields[0])), fields } 53 + 54 + #define FIELD(name) \ 55 + { { { name, sizeof(name) - 1 } } } 56 + 57 + #define CLASS(name, code) \ 58 + { { { name, sizeof(name) - 1 }, code } } 59 + 60 + #define UNKNOWN_CLASS(code) \ 61 + { { { "", 0 }, code } } 62 + 63 + #define TYPE(name, code, _class, fields, check, parse) \ 64 + { { { name, sizeof(name) - 1 }, code }, _class, false, false, fields, check, parse } 65 + 66 + #define UNKNOWN_TYPE(code) \ 67 + { { { "", 0 }, code }, 0, false, false, { 0, NULL }, check_generic_rr, parse_unknown_rdata } 68 + 69 + nonnull((1,2,3,4)) 70 + static really_inline int32_t check_bytes( 71 + parser_t *parser, 72 + const type_info_t *type, 73 + const rdata_info_t *field, 74 + const uint8_t *data, 75 + const size_t length, 76 + const size_t size) 77 + { 78 + (void)data; 79 + if (length < size) 80 + SYNTAX_ERROR(parser, "Missing %s in %s", NAME(field), NAME(type)); 81 + return (int32_t)size; 82 + } 83 + 84 + #define check_int8(...) check_bytes(__VA_ARGS__, sizeof(uint8_t)) 85 + 86 + #define check_int16(...) check_bytes(__VA_ARGS__, sizeof(uint16_t)) 87 + 88 + #define check_int32(...) check_bytes(__VA_ARGS__, sizeof(uint32_t)) 89 + 90 + #define check_ip4(...) check_bytes(__VA_ARGS__, 4) 91 + 92 + #define check_ip6(...) check_bytes(__VA_ARGS__, 16) 93 + 94 + #define check_ilnp64(...) check_bytes(__VA_ARGS__, sizeof(uint64_t)) 95 + 96 + nonnull((1,2,3,4)) 97 + static really_inline int32_t check_ttl( 98 + parser_t *parser, 99 + const type_info_t *type, 100 + const rdata_info_t *field, 101 + const uint8_t *data, 102 + const size_t length) 103 + { 104 + uint32_t number; 105 + 106 + if (length < sizeof(number)) 107 + SYNTAX_ERROR(parser, "Missing %s in %s", NAME(field), NAME(type)); 108 + 109 + memcpy(&number, data, sizeof(number)); 110 + number = be32toh(number); 111 + 112 + if (number > INT32_MAX) 113 + SEMANTIC_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 114 + 115 + return 4; 116 + } 117 + 118 + zone_nonnull((1,2,3,4)) 119 + static really_inline int32_t check_name( 120 + parser_t *parser, 121 + const type_info_t *type, 122 + const rdata_info_t *field, 123 + const uint8_t *data, 124 + const size_t length) 125 + { 126 + int32_t label = 0, count = 0; 127 + while (count < (int32_t)length) { 128 + label = data[count]; 129 + count += 1 + label; 130 + if (!label) 131 + break; 132 + } 133 + 134 + if (!count || count > (int32_t)length) 135 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 136 + 137 + return count; 138 + } 139 + 140 + zone_nonnull((1,2,3,4)) 141 + static really_inline int32_t check_string( 142 + parser_t *parser, 143 + const type_info_t *type, 144 + const rdata_info_t *field, 145 + const uint8_t *data, 146 + const size_t length) 147 + { 148 + int32_t count; 149 + 150 + if (!length || (count = 1 + (int32_t)data[0]) > (int32_t)length) 151 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 152 + 153 + return count; 154 + } 155 + 156 + zone_nonnull((1,2,3,4)) 157 + static really_inline int32_t check_nsec( 158 + parser_t *parser, 159 + const type_info_t *type, 160 + const rdata_info_t *field, 161 + const uint8_t *data, 162 + const size_t length) 163 + { 164 + int32_t count = 0; 165 + int32_t last_window = -1; 166 + 167 + while ((count + 2) < (int32_t)length) { 168 + const int32_t window = (int32_t)data[0]; 169 + const int32_t blocks = (int32_t)data[1]; 170 + if (window <= last_window) 171 + SYNTAX_ERROR(parser, "Invalid %s in %s, windows are out-of-order", 172 + NAME(field), NAME(type)); 173 + if (!blocks || blocks > 32) 174 + SYNTAX_ERROR(parser, "Invalid %s in %s, blocks are out-of-bounds", 175 + NAME(field), NAME(type)); 176 + count += 2 + blocks; 177 + last_window = window; 178 + } 179 + 180 + if (count != (int32_t)length) 181 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 182 + 183 + return count; 184 + } 185 + 186 + zone_nonnull((1)) 187 + static really_inline int32_t check(size_t *length, int32_t count) 188 + { 189 + if (count < 0) 190 + return count; 191 + *length += (size_t)count; 192 + return 0; 193 + } 194 + 195 + nonnull_all 196 + static really_inline void adjust_line_count(file_t *file) 197 + { 198 + file->line += file->span; 199 + file->span = 0; 200 + } 201 + 202 + nonnull_all 203 + static really_inline int32_t accept_rr( 204 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 205 + { 206 + (void)type; 207 + 208 + assert(rdata->octets <= rdata->limit); 209 + assert(rdata->octets >= parser->rdata->octets); 210 + size_t length = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 211 + 212 + assert(length <= UINT16_MAX); 213 + assert(parser->owner->length <= UINT8_MAX); 214 + int32_t code = parser->options.accept.callback( 215 + parser, 216 + &(zone_name_t){ (uint8_t)parser->owner->length, parser->owner->octets }, 217 + parser->file->last_type, 218 + parser->file->last_class, 219 + *parser->file->ttl, 220 + (uint16_t)length, 221 + parser->rdata->octets, 222 + parser->user_data); 223 + 224 + adjust_line_count(parser->file); 225 + return code; 226 + } 227 + 228 + nonnull_all 229 + static int32_t check_a_rr( 230 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 231 + { 232 + assert(rdata->octets >= parser->rdata->octets); 233 + if ((uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets == 4) 234 + return accept_rr(parser, type, rdata); 235 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 236 + } 237 + 238 + nonnull_all 239 + static int32_t parse_a_rdata( 240 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 241 + { 242 + int32_t code; 243 + const rdata_info_t *fields = type->rdata.fields; 244 + 245 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 246 + return code; 247 + if ((code = parse_ip4(parser, type, &fields[0], rdata, token)) < 0) 248 + return code; 249 + if ((code = take_delimiter(parser, type, token)) < 0) 250 + return code; 251 + return accept_rr(parser, type, rdata); 252 + } 253 + 254 + nonnull_all 255 + static int32_t check_ns_rr( 256 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 257 + { 258 + int32_t r; 259 + size_t c = 0; 260 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 261 + const uint8_t *o = parser->rdata->octets; 262 + const rdata_info_t *f = type->rdata.fields; 263 + 264 + if ((r = check(&c, check_name(parser, type, &f[0], o, n))) < 0) 265 + return r; 266 + 267 + if (c != n) 268 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 269 + return accept_rr(parser, type, rdata); 270 + } 271 + 272 + nonnull_all 273 + static int32_t parse_ns_rdata( 274 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 275 + { 276 + int32_t code; 277 + const rdata_info_t *fields = type->rdata.fields; 278 + 279 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 280 + return code; 281 + if ((code = parse_name(parser, type, &fields[0], rdata, token)) < 0) 282 + return code; 283 + if ((code = take_delimiter(parser, type, token)) < 0) 284 + return code; 285 + return accept_rr(parser, type, rdata); 286 + } 287 + 288 + nonnull_all 289 + static int32_t check_soa_rr( 290 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 291 + { 292 + int32_t r; 293 + size_t c = 0; 294 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 295 + const uint8_t *o = parser->rdata->octets; 296 + const rdata_info_t *f = type->rdata.fields; 297 + 298 + if ((r = check(&c, check_name(parser, type, &f[0], o, n))) || 299 + (r = check(&c, check_name(parser, type, &f[1], o+c, n-c))) || 300 + (r = check(&c, check_int32(parser, type, &f[2], o+c, n-c))) || 301 + (r = check(&c, check_ttl(parser, type, &f[3], o+c, n-c))) || 302 + (r = check(&c, check_ttl(parser, type, &f[4], o+c, n-c))) || 303 + (r = check(&c, check_ttl(parser, type, &f[5], o+c, n-c))) || 304 + (r = check(&c, check_ttl(parser, type, &f[6], o+c, n-c)))) 305 + return r; 306 + 307 + if (c != n) 308 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 309 + return accept_rr(parser, type, rdata); 310 + } 311 + 312 + nonnull_all 313 + static int32_t parse_soa_rdata( 314 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 315 + { 316 + int32_t code; 317 + const rdata_info_t *fields = type->rdata.fields; 318 + 319 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 320 + return code; 321 + if ((code = parse_name(parser, type, &fields[0], rdata, token)) < 0) 322 + return code; 323 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 324 + return code; 325 + if ((code = parse_name(parser, type, &fields[1], rdata, token)) < 0) 326 + return code; 327 + if ((code = take_contiguous(parser, type, &fields[2], token)) < 0) 328 + return code; 329 + if ((code = parse_int32(parser, type, &fields[2], rdata, token)) < 0) 330 + return code; 331 + if ((code = take_contiguous(parser, type, &fields[3], token)) < 0) 332 + return code; 333 + if ((code = parse_ttl(parser, type, &fields[3], rdata, token)) < 0) 334 + return code; 335 + if ((code = take_contiguous(parser, type, &fields[4], token)) < 0) 336 + return code; 337 + if ((code = parse_ttl(parser, type, &fields[4], rdata, token)) < 0) 338 + return code; 339 + if ((code = take_contiguous(parser, type, &fields[5], token)) < 0) 340 + return code; 341 + if ((code = parse_ttl(parser, type, &fields[5], rdata, token)) < 0) 342 + return code; 343 + if ((code = take_contiguous(parser, type, &fields[6], token)) < 0) 344 + return code; 345 + if ((code = parse_ttl(parser, type, &fields[6], rdata, token)) < 0) 346 + return code; 347 + if ((code = take_delimiter(parser, type, token)) < 0) 348 + return code; 349 + return accept_rr(parser, type, rdata); 350 + } 351 + 352 + nonnull_all 353 + static int32_t check_wks_rr( 354 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 355 + { 356 + int32_t r; 357 + size_t c = 0; 358 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 359 + const uint8_t *o = parser->rdata->octets; 360 + const rdata_info_t *f = type->rdata.fields; 361 + 362 + if ((r = check(&c, check_ip4(parser, type, &f[0], o, n))) || 363 + (r = check(&c, check_int8(parser, type, &f[0], o+c, n-c)))) 364 + return r; 365 + 366 + // any bit may, or may not, be set. confirm the bitmap does not exceed the 367 + // maximum number of ports 368 + if (n > 8192 + 5) 369 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 370 + 371 + return accept_rr(parser, type, rdata); 372 + } 373 + 374 + nonnull_all 375 + static int32_t parse_wks_rdata( 376 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 377 + { 378 + int32_t code; 379 + const rdata_info_t *fields = type->rdata.fields; 380 + 381 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 382 + return code; 383 + if ((code = parse_ip4(parser, type, &fields[0], rdata, token) < 0)) 384 + return code; 385 + 386 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 387 + return code; 388 + 389 + uint8_t protocol; 390 + if (!scan_protocol(token->data, token->length, &protocol)) 391 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[1]), NAME(type)); 392 + 393 + *rdata->octets++ = protocol; 394 + uint8_t *bitmap = rdata->octets; 395 + int32_t highest_port = -1; 396 + 397 + take(parser, token); 398 + while (is_contiguous(token)) { 399 + uint16_t port; 400 + if (!scan_service(token->data, token->length, protocol, &port)) 401 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&type->rdata.fields[2]), NAME(type)); 402 + 403 + if (port > highest_port) { 404 + // ensure newly used octets are zeroed out before use 405 + size_t offset = highest_port < 0 ? 0 : (size_t)highest_port / 8 + 1; 406 + size_t length = (size_t)port / 8 + 1; 407 + memset(bitmap + offset, 0, length - offset); 408 + highest_port = port; 409 + } 410 + 411 + // bits are counted from left to right, so bit 0 is the left most bit 412 + bitmap[port / 8] |= (1 << (7 - port % 8)); 413 + take(parser, token); 414 + } 415 + 416 + rdata->octets += (size_t)highest_port / 8 + 1; 417 + 418 + if (have_delimiter(parser, type, token) < 0) 419 + return token->code; 420 + return accept_rr(parser, type, rdata); 421 + } 422 + 423 + nonnull_all 424 + static int32_t check_hinfo_rr( 425 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 426 + { 427 + int32_t r; 428 + size_t c = 0; 429 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 430 + const uint8_t *o = parser->rdata->octets; 431 + const rdata_info_t *f = type->rdata.fields; 432 + 433 + if ((r = check(&c, check_string(parser, type, &f[0], o, n))) || 434 + (r = check(&c, check_string(parser, type, &f[1], o+c, n-c)))) 435 + return r; 436 + 437 + if (c != n) 438 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 439 + return accept_rr(parser, type, rdata); 440 + } 441 + 442 + nonnull_all 443 + static int32_t parse_hinfo_rdata( 444 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 445 + { 446 + int32_t code; 447 + const rdata_info_t *fields = type->rdata.fields; 448 + 449 + if ((code = have_contiguous_or_quoted(parser, type, &fields[0], token)) < 0) 450 + return code; 451 + if ((code = parse_string(parser, type, &fields[0], rdata, token)) < 0) 452 + return code; 453 + if ((code = take_quoted_or_contiguous(parser, type, &fields[1], token)) < 0) 454 + return code; 455 + if ((code = parse_string(parser, type, &fields[1], rdata, token)) < 0) 456 + return code; 457 + if ((code = take_delimiter(parser, type, token)) < 0) 458 + return code; 459 + return accept_rr(parser, type, rdata); 460 + } 461 + 462 + nonnull_all 463 + static int32_t check_minfo_rr( 464 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 465 + { 466 + int32_t r; 467 + size_t c = 0; 468 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 469 + const uint8_t *o = parser->rdata->octets; 470 + const rdata_info_t *f = type->rdata.fields; 471 + 472 + if ((r = check(&c, check_name(parser, type, &f[0], o, n))) || 473 + (r = check(&c, check_name(parser, type, &f[1], o+c, n-c)))) 474 + return r; 475 + 476 + if (c != n) 477 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 478 + return accept_rr(parser, type, rdata); 479 + } 480 + 481 + nonnull_all 482 + static int32_t parse_minfo_rdata( 483 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 484 + { 485 + int32_t code; 486 + const rdata_info_t *fields = type->rdata.fields; 487 + 488 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 489 + return code; 490 + if ((code = parse_name(parser, type, &fields[0], rdata, token)) < 0) 491 + return code; 492 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 493 + return code; 494 + if ((code = parse_name(parser, type, &fields[1], rdata, token)) < 0) 495 + return code; 496 + if ((code = take_delimiter(parser, type, token)) < 0) 497 + return code; 498 + return accept_rr(parser, type, rdata); 499 + } 500 + 501 + nonnull_all 502 + static int32_t check_mx_rr( 503 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 504 + { 505 + int32_t r; 506 + size_t c = 0; 507 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 508 + const uint8_t *o = parser->rdata->octets; 509 + const rdata_info_t *f = type->rdata.fields; 510 + 511 + if ((r = check(&c, check_int16(parser, type, &f[0], o, n))) || 512 + (r = check(&c, check_name(parser, type, &f[1], o+c, n-c)))) 513 + return r; 514 + 515 + if (c != n) 516 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 517 + return accept_rr(parser, type, rdata); 518 + } 519 + 520 + nonnull_all 521 + static int32_t parse_mx_rdata( 522 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 523 + { 524 + int32_t code; 525 + const rdata_info_t *fields = type->rdata.fields; 526 + 527 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 528 + return code; 529 + if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0) 530 + return code; 531 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 532 + return code; 533 + if ((code = parse_name(parser, type, &fields[1], rdata, token)) < 0) 534 + return code; 535 + if ((code = take_delimiter(parser, type, token)) < 0) 536 + return code; 537 + return accept_rr(parser, type, rdata); 538 + } 539 + 540 + nonnull_all 541 + static int32_t check_txt_rr( 542 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 543 + { 544 + int32_t r; 545 + size_t c = 0; 546 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 547 + const uint8_t *o = parser->rdata->octets; 548 + const rdata_info_t *f = type->rdata.fields; 549 + 550 + if ((r = check(&c, check_string(parser, type, &f[0], o, n)))) 551 + return r; 552 + 553 + while (c < n) 554 + if ((r = check(&c, check_string(parser, type, &f[0], o+c, n-c)))) 555 + return r; 556 + 557 + if (c != n) 558 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 559 + return accept_rr(parser, type, rdata); 560 + } 561 + 562 + nonnull_all 563 + static int32_t parse_txt_rdata( 564 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 565 + { 566 + int32_t code; 567 + const rdata_info_t *fields = type->rdata.fields; 568 + 569 + while (is_contiguous_or_quoted(token)) { 570 + if ((code = parse_string(parser, type, &fields[0], rdata, token)) < 0) 571 + return code; 572 + take(parser, token); 573 + } 574 + 575 + if ((code = have_delimiter(parser, type, token)) < 0) 576 + return code; 577 + return accept_rr(parser, type, rdata); 578 + } 579 + 580 + nonnull_all 581 + static int32_t check_x25_rr( 582 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 583 + { 584 + int32_t r; 585 + size_t c = 0; 586 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 587 + const uint8_t *o = parser->rdata->octets; 588 + const rdata_info_t *f = type->rdata.fields; 589 + 590 + if ((r = check(&c, check_string(parser, type, &f[0], o, n)))) 591 + return r; 592 + 593 + if (c != n) 594 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 595 + return accept_rr(parser, type, rdata); 596 + } 597 + 598 + nonnull_all 599 + static int32_t parse_x25_rdata( 600 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 601 + { 602 + int32_t code; 603 + const rdata_info_t *fields = type->rdata.fields; 604 + 605 + if ((code = have_contiguous_or_quoted(parser, type, &fields[0], token)) < 0) 606 + return code; 607 + if ((code = parse_string(parser, type, &fields[0], rdata, token)) < 0) 608 + return code; 609 + if ((code = take_delimiter(parser, type, token)) < 0) 610 + return code; 611 + return accept_rr(parser, type, rdata); 612 + } 613 + 614 + nonnull_all 615 + static int32_t check_isdn_rr( 616 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 617 + { 618 + int32_t r; 619 + size_t c = 0; 620 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 621 + const uint8_t *o = parser->rdata->octets; 622 + const rdata_info_t *f = type->rdata.fields; 623 + 624 + if ((r = check(&c, check_string(parser, type, &f[0], o, n)))) 625 + return r; 626 + // subaddress is optional 627 + if (c < n && (r = check(&c, check_string(parser, type, &f[1], o+c, n-c)))) 628 + return r; 629 + 630 + if (c != n) 631 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 632 + return accept_rr(parser, type, rdata); 633 + } 634 + 635 + nonnull_all 636 + static int32_t parse_isdn_rdata( 637 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 638 + { 639 + int32_t code; 640 + const rdata_info_t *fields = type->rdata.fields; 641 + 642 + if ((code = have_contiguous_or_quoted(parser, type, &fields[0], token)) < 0) 643 + return code; 644 + if ((code = parse_string(parser, type, &fields[0], rdata, token)) < 0) 645 + return code; 646 + 647 + // subaddress is optional 648 + take(parser, token); 649 + if (is_contiguous_or_quoted(token)) { 650 + if ((code = parse_string(parser, type, &fields[1], rdata, token)) < 0) 651 + return code; 652 + take(parser, token); 653 + } 654 + 655 + if ((code = have_delimiter(parser, type, token)) < 0) 656 + return code; 657 + return accept_rr(parser, type, rdata); 658 + } 659 + 660 + nonnull_all 661 + static int32_t check_rt_rr( 662 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 663 + { 664 + int32_t r; 665 + size_t c = 0; 666 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 667 + const uint8_t *o = parser->rdata->octets; 668 + const rdata_info_t *f = type->rdata.fields; 669 + 670 + if ((r = check(&c, check_int16(parser, type, &f[0], o, n))) || 671 + (r = check(&c, check_name(parser, type, &f[1], o+c, n-c)))) 672 + return r; 673 + 674 + if (c != n) 675 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 676 + return accept_rr(parser, type, rdata); 677 + } 678 + 679 + nonnull_all 680 + static int32_t parse_rt_rdata( 681 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 682 + { 683 + int32_t code; 684 + const rdata_info_t *fields = type->rdata.fields; 685 + 686 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 687 + return code; 688 + if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0) 689 + return code; 690 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 691 + return code; 692 + if ((code = parse_name(parser, type, &fields[1], rdata, token)) < 0) 693 + return code; 694 + if ((code = take_delimiter(parser, type, token)) < 0) 695 + return code; 696 + return accept_rr(parser, type, rdata); 697 + } 698 + 699 + nonnull_all 700 + static int32_t check_nsap_rr( 701 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 702 + { 703 + if (rdata->octets == parser->rdata->octets) 704 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 705 + return accept_rr(parser, type, rdata); 706 + } 707 + 708 + nonnull_all 709 + static int32_t parse_nsap_rdata( 710 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 711 + { 712 + int32_t code; 713 + const rdata_info_t *fields = type->rdata.fields; 714 + 715 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 716 + return code; 717 + if ((code = parse_nsap(parser, type, &fields[0], rdata, token)) < 0) 718 + return code; 719 + if ((code = take_delimiter(parser, type, token)) < 0) 720 + return code; 721 + return accept_rr(parser, type, rdata); 722 + } 723 + 724 + nonnull_all 725 + static int32_t check_nsap_ptr_rr( 726 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 727 + { 728 + { 729 + int32_t r; 730 + size_t c = 0; 731 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 732 + const uint8_t *o = parser->rdata->octets; 733 + const rdata_info_t *f = type->rdata.fields; 734 + 735 + if ((r = check(&c, check_name(parser, type, &f[0], o, n)))) 736 + return r; 737 + 738 + if (c != n) 739 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 740 + } 741 + 742 + { 743 + // RFC1706 section 6 744 + // A domain name is generated from an NSAP by reversing the hex nibbles of 745 + // the NSAP, treating each nibble as a separate subdomain, and appending 746 + // the top-level subdomain name "NSAP.INT" to it. For example, the domain 747 + // name used in the reverse lookup for the NSAP 748 + // 749 + // 47.0005.80.005a00.0000.0001.e133.ffffff000162.00 750 + // 751 + // would appear as 752 + // 753 + // 0.0.2.6.1.0.0.0.f.f.f.f.f.f.3.3.1.e.1.0.0.0.0.0.0.0.0.0.a.5.0.0. 754 + // 0.8.5.0.0.0.7.4.NSAP.INT. 755 + size_t i = 0; 756 + const size_t n = parser->file->owner.length; 757 + const uint8_t *o = parser->file->owner.octets; 758 + for (; i < n; i += 2) 759 + if (o[i] != 1 || (base16_table_dec_32bit_d1[o[i+1]] > 0xff)) 760 + break; 761 + 762 + const uint8_t nsap_int[] = { 4, 'n', 's', 'a', 'p', 3, 'i', 'n', 't', 0 }; 763 + if (strncasecmp((const char *)o + i, (const char *)nsap_int, 9) != 0 || !i || i + 10 != n) 764 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 765 + } 766 + 767 + return accept_rr(parser, type, rdata); 768 + } 769 + 770 + nonnull_all 771 + static int32_t parse_nsap_ptr_rdata( 772 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 773 + { 774 + int32_t code; 775 + const rdata_info_t *fields = type->rdata.fields; 776 + 777 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 778 + return code; 779 + if ((code = parse_name(parser, type, &fields[0], rdata, token)) < 0) 780 + return code; 781 + if ((code = take_delimiter(parser, type, token)) < 0) 782 + return code; 783 + 784 + // RFC1706 section 6 states each nibble is treated as a separate subdomain 785 + return check_nsap_ptr_rr(parser, type, rdata); 786 + } 787 + 788 + nonnull_all 789 + static int32_t check_key_rr( 790 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 791 + { 792 + #if 0 793 + int32_t r; 794 + size_t c = 0; 795 + const size_t n = parser->rdata->length; 796 + const uint8_t *o = parser->rdata->octets; 797 + const rdata_info_t *f = type->rdata.fields; 798 + 799 + // 800 + // FIXME: implement (RFC2065) 801 + // 802 + // FIXME: verify the flag, algorithm and protocol combination is valid 803 + // FIXME: verify the key is valid for type(3)+algorithm(1) 804 + // 805 + // The combination is of course subject to secondary checks! 806 + // 807 + #endif 808 + (void)type; 809 + return accept_rr(parser, type, rdata); 810 + } 811 + 812 + nonnull_all 813 + static int32_t parse_key_rdata( 814 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 815 + { 816 + int32_t code; 817 + const rdata_info_t *fields = type->rdata.fields; 818 + 819 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 820 + return code; 821 + if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0) 822 + return code; 823 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 824 + return code; 825 + if ((code = parse_int8(parser, type, &fields[1], rdata, token)) < 0) 826 + return code; 827 + if ((code = take_contiguous(parser, type, &fields[2], token)) < 0) 828 + return code; 829 + if ((code = parse_int8(parser, type, &fields[2], rdata, token)) < 0) 830 + return code; 831 + take(parser, token); 832 + if ((code = parse_base64_sequence(parser, type, &fields[3], rdata, token)) < 0) 833 + return code; 834 + 835 + return check_key_rr(parser, type, rdata); 836 + } 837 + 838 + nonnull_all 839 + static int32_t check_px_rr( 840 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 841 + { 842 + int32_t r; 843 + size_t c = 0; 844 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 845 + const uint8_t *o = parser->rdata->octets; 846 + const rdata_info_t *f = type->rdata.fields; 847 + 848 + if ((r = check(&c, check_int16(parser, type, &f[0], o, n))) || 849 + (r = check(&c, check_name(parser, type, &f[1], o+c, n-c))) || 850 + (r = check(&c, check_name(parser, type, &f[2], o+c, n-c)))) 851 + return r; 852 + 853 + if (c != n) 854 + SYNTAX_ERROR(parser, "Invalid %s record", NAME(type)); 855 + return accept_rr(parser, type, rdata); 856 + } 857 + 858 + nonnull_all 859 + static int32_t parse_px_rdata( 860 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 861 + { 862 + int32_t code; 863 + const rdata_info_t *fields = type->rdata.fields; 864 + 865 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 866 + return code; 867 + if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0) 868 + return code; 869 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 870 + return code; 871 + if ((code = parse_name(parser, type, &fields[1], rdata, token)) < 0) 872 + return code; 873 + if ((code = take_contiguous(parser, type, &fields[2], token)) < 0) 874 + return code; 875 + if ((code = parse_name(parser, type, &fields[2], rdata, token)) < 0) 876 + return code; 877 + if ((code = take_delimiter(parser, type, token)) < 0) 878 + return code; 879 + return accept_rr(parser, type, rdata); 880 + } 881 + 882 + nonnull_all 883 + static int32_t check_gpos_rr( 884 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 885 + { 886 + int32_t r; 887 + size_t c = 0; 888 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 889 + const uint8_t *o = parser->rdata->octets; 890 + const rdata_info_t *f = type->rdata.fields; 891 + 892 + if ((r = check(&c, check_string(parser, type, &f[0], o, n))) || 893 + (r = check(&c, check_string(parser, type, &f[1], o+c, n-c))) || 894 + (r = check(&c, check_string(parser, type, &f[2], o+c, n-c)))) 895 + return r; 896 + 897 + if (c != n) 898 + SYNTAX_ERROR(parser, "Invalid %s record", NAME(type)); 899 + return accept_rr(parser, type, rdata); 900 + } 901 + 902 + static int32_t parse_gpos_rdata( 903 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 904 + { 905 + int32_t code; 906 + const rdata_info_t *fields = type->rdata.fields; 907 + 908 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 909 + return code; 910 + if ((code = parse_latitude(parser, type, &fields[0], rdata, token)) < 0) 911 + return code; 912 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 913 + return code; 914 + if ((code = parse_longitude(parser, type, &fields[1], rdata, token)) < 0) 915 + return code; 916 + if ((code = take_contiguous(parser, type, &fields[2], token)) < 0) 917 + return code; 918 + if ((code = parse_altitude(parser, type, &fields[2], rdata, token)) < 0) 919 + return code; 920 + if ((code = take_delimiter(parser, type, token)) < 0) 921 + return code; 922 + return accept_rr(parser, type, rdata); 923 + } 924 + 925 + nonnull_all 926 + static int32_t check_aaaa_rr( 927 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 928 + { 929 + int32_t r; 930 + size_t c = 0; 931 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 932 + const uint8_t *o = parser->rdata->octets; 933 + const rdata_info_t *f = type->rdata.fields; 934 + 935 + if ((r = check(&c, check_ip6(parser, type, &f[0], o, n)))) 936 + return r; 937 + 938 + if (c != n) 939 + SYNTAX_ERROR(parser, "Invalid %s record", NAME(type)); 940 + return accept_rr(parser, type, rdata); 941 + } 942 + 943 + nonnull_all 944 + static int32_t parse_aaaa_rdata( 945 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 946 + { 947 + int32_t code; 948 + const rdata_info_t *fields = type->rdata.fields; 949 + 950 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 951 + return code; 952 + if ((code = parse_ip6(parser, type, &fields[0], rdata, token)) < 0) 953 + return code; 954 + if ((code = take_delimiter(parser, type, token)) < 0) 955 + return code; 956 + return accept_rr(parser, type, rdata); 957 + } 958 + 959 + nonnull_all 960 + static int32_t check_loc_rr( 961 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 962 + { 963 + if ((uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets != 16) 964 + SYNTAX_ERROR(parser, "Invalid %s record", NAME(type)); 965 + return accept_rr(parser, type, rdata); 966 + 967 + // FIXME: check validity of latitude, longitude and latitude? 968 + } 969 + 970 + nonnull_all 971 + static int32_t parse_loc_rdata( 972 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 973 + { 974 + int32_t code; 975 + uint32_t degrees, minutes, seconds; 976 + uint32_t latitude, longitude, altitude; 977 + const rdata_info_t *fields = type->rdata.fields; 978 + static const uint8_t defaults[4] = { 0x00, 0x12, 0x16, 0x13 }; 979 + 980 + // RFC1876 section 3: 981 + // If omitted, minutes and seconds default to zero, size defaults to 1m, 982 + // horizontal precision defaults to 10000m, and vertical precision defaults 983 + // to 10m. 984 + memcpy(rdata->octets, &defaults, sizeof(defaults)); 985 + 986 + // latitude 987 + if ((code = have_contiguous(parser, type, &fields[4], token)) < 0) 988 + return code; 989 + if (scan_degrees(token->data, token->length, &degrees) == -1) 990 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[4]), NAME(type)); 991 + if ((code = take_contiguous(parser, type, &fields[4], token)) < 0) 992 + return code; 993 + if (scan_minutes(token->data, token->length, &minutes) == -1) 994 + goto north_south; // minutes default to zero 995 + degrees += minutes; 996 + if ((code = take_contiguous(parser, type, &fields[4], token)) < 0) 997 + return code; 998 + if (scan_seconds(token->data, token->length, &seconds) == -1) 999 + goto north_south; // seconds default to zero 1000 + degrees += seconds; 1001 + 1002 + if ((code = take_contiguous(parser, type, &fields[4], token)) < 0) 1003 + return code; 1004 + north_south: 1005 + if (token->data[0] == 'N') 1006 + latitude = htobe32((1u<<31) + degrees); 1007 + else if (token->data[0] == 'S') 1008 + latitude = htobe32((1u<<31) - degrees); 1009 + else 1010 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[4]), NAME(type)); 1011 + 1012 + memcpy(&rdata->octets[4], &latitude, sizeof(latitude)); 1013 + 1014 + // longitude 1015 + if ((code = take_contiguous(parser, type, &fields[5], token)) < 0) 1016 + return code; 1017 + if (scan_degrees(token->data, token->length, &degrees) == -1) 1018 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[5]), NAME(type)); 1019 + if ((code = take_contiguous(parser, type, &fields[5], token)) < 0) 1020 + return code; 1021 + if (scan_minutes(token->data, token->length, &minutes) == -1) 1022 + goto east_west; // minutes default to zero 1023 + degrees += minutes; 1024 + if ((code = take_contiguous(parser, type, &fields[5], token)) < 0) 1025 + return code; 1026 + if (scan_seconds(token->data, token->length, &seconds) == -1) 1027 + goto east_west; // seconds default to zero 1028 + degrees += seconds; 1029 + 1030 + if ((code = take_contiguous(parser, type, &fields[5], token)) < 0) 1031 + return code; 1032 + east_west: 1033 + if (token->data[0] == 'E') 1034 + longitude = htobe32((1u<<31) + degrees); 1035 + else if (token->data[0] == 'W') 1036 + longitude = htobe32((1u<<31) - degrees); 1037 + else 1038 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[5]), NAME(type)); 1039 + 1040 + memcpy(&rdata->octets[8], &longitude, sizeof(longitude)); 1041 + 1042 + // altitude 1043 + if ((code = take_contiguous(parser, type, &fields[6], token)) < 0) 1044 + return code; 1045 + if (scan_altitude(token->data, token->length, &altitude) == -1) 1046 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[6]), NAME(type)); 1047 + 1048 + altitude = htobe32(altitude); 1049 + memcpy(&rdata->octets[12], &altitude, sizeof(altitude)); 1050 + 1051 + // size 1052 + take(parser, token); 1053 + if (!is_contiguous(token)) 1054 + goto skip_optional; 1055 + if (scan_precision(token->data, token->length, &rdata->octets[1])) 1056 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[1]), NAME(type)); 1057 + 1058 + // horizontal precision 1059 + take(parser, token); 1060 + if (!is_contiguous(token)) 1061 + goto skip_optional; 1062 + if (scan_precision(token->data, token->length, &rdata->octets[2])) 1063 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[2]), NAME(type)); 1064 + 1065 + // vertical precision 1066 + take(parser, token); 1067 + if (!is_contiguous(token)) 1068 + goto skip_optional; 1069 + if (scan_precision(token->data, token->length, &rdata->octets[3])) 1070 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[3]), NAME(type)); 1071 + 1072 + take(parser, token); 1073 + skip_optional: 1074 + if ((code = have_delimiter(parser, type, token)) < 0) 1075 + return code; 1076 + 1077 + rdata->octets += 16; 1078 + return accept_rr(parser, type, rdata); 1079 + } 1080 + 1081 + nonnull_all 1082 + static int32_t check_nxt_rr( 1083 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 1084 + { 1085 + int32_t r; 1086 + size_t c = 0; 1087 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 1088 + const uint8_t *o = parser->rdata->octets; 1089 + const rdata_info_t *f = type->rdata.fields; 1090 + 1091 + if ((r = check(&c, check_name(parser, type, &f[0], o+c, n-c)))) 1092 + return r; 1093 + 1094 + return accept_rr(parser, type, rdata); 1095 + } 1096 + 1097 + nonnull_all 1098 + static int32_t parse_nxt_rdata( 1099 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 1100 + { 1101 + int32_t code; 1102 + const rdata_info_t *fields = type->rdata.fields; 1103 + 1104 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 1105 + return code; 1106 + if ((code = parse_name(parser, type, &fields[0], rdata, token)) < 0) 1107 + return code; 1108 + take(parser, token); 1109 + if ((code = parse_nxt(parser, type, &fields[1], rdata, token)) < 0) 1110 + return code; 1111 + 1112 + return accept_rr(parser, type, rdata); 1113 + } 1114 + 1115 + nonnull_all 1116 + static int32_t check_srv_rr( 1117 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 1118 + { 1119 + int32_t r; 1120 + size_t c = 0; 1121 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 1122 + const uint8_t *o = parser->rdata->octets; 1123 + const rdata_info_t *f = type->rdata.fields; 1124 + 1125 + if ((r = check(&c, check_int16(parser, type, &f[0], o, n))) || 1126 + (r = check(&c, check_int16(parser, type, &f[1], o+c, n-c))) || 1127 + (r = check(&c, check_int16(parser, type, &f[2], o+c, n-c))) || 1128 + (r = check(&c, check_name(parser, type, &f[3], o+c, n-c)))) 1129 + return r; 1130 + 1131 + if (c != n) 1132 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 1133 + return accept_rr(parser, type, rdata); 1134 + } 1135 + 1136 + nonnull_all 1137 + static int32_t parse_srv_rdata( 1138 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 1139 + { 1140 + int32_t code; 1141 + const rdata_info_t *fields = type->rdata.fields; 1142 + 1143 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 1144 + return code; 1145 + if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0) 1146 + return code; 1147 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 1148 + return code; 1149 + if ((code = parse_int16(parser, type, &fields[1], rdata, token)) < 0) 1150 + return code; 1151 + if ((code = take_contiguous(parser, type, &fields[2], token)) < 0) 1152 + return code; 1153 + if ((code = parse_int16(parser, type, &fields[2], rdata, token)) < 0) 1154 + return code; 1155 + if ((code = take_contiguous(parser, type, &fields[3], token)) < 0) 1156 + return code; 1157 + if ((code = parse_name(parser, type, &fields[3], rdata, token)) < 0) 1158 + return code; 1159 + if ((code = take_delimiter(parser, type, token)) < 0) 1160 + return code; 1161 + return accept_rr(parser, type, rdata); 1162 + } 1163 + 1164 + nonnull_all 1165 + static int32_t check_naptr_rr( 1166 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 1167 + { 1168 + // FIXME: implement actual checks 1169 + (void)type; 1170 + return accept_rr(parser, type, rdata); 1171 + } 1172 + 1173 + nonnull_all 1174 + static int32_t parse_naptr_rdata( 1175 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 1176 + { 1177 + int32_t code; 1178 + const rdata_info_t *fields = type->rdata.fields; 1179 + 1180 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 1181 + return code; 1182 + if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0) 1183 + return code; 1184 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 1185 + return code; 1186 + if ((code = parse_int16(parser, type, &fields[1], rdata, token)) < 0) 1187 + return code; 1188 + if ((code = take_quoted_or_contiguous(parser, type, &fields[2], token)) < 0) 1189 + return code; 1190 + if ((code = parse_string(parser, type, &fields[2], rdata, token)) < 0) 1191 + return code; 1192 + if ((code = take_quoted_or_contiguous(parser, type, &fields[3], token)) < 0) 1193 + return code; 1194 + if ((code = parse_string(parser, type, &fields[3], rdata, token)) < 0) 1195 + return code; 1196 + if ((code = take_quoted_or_contiguous(parser, type, &fields[4], token)) < 0) 1197 + return code; 1198 + if ((code = parse_string(parser, type, &fields[4], rdata, token)) < 0) 1199 + return code; 1200 + if ((code = take_contiguous(parser, type, &fields[5], token)) < 0) 1201 + return code; 1202 + if ((code = parse_name(parser, type, &fields[5], rdata, token)) < 0) 1203 + return code; 1204 + if ((code = take_delimiter(parser, type, token)) < 0) 1205 + return code; 1206 + return accept_rr(parser, type, rdata); 1207 + } 1208 + 1209 + nonnull_all 1210 + static int32_t check_cert_rr( 1211 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 1212 + { 1213 + // FIXME: implement actual checks 1214 + (void)type; 1215 + 1216 + assert(rdata->octets >= parser->rdata->octets); 1217 + if ((uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets < 6) 1218 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 1219 + return accept_rr(parser, type, rdata); 1220 + } 1221 + 1222 + nonnull_all 1223 + static int32_t parse_cert_rdata( 1224 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 1225 + { 1226 + int32_t code; 1227 + const rdata_info_t *fields = type->rdata.fields; 1228 + 1229 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 1230 + return code; 1231 + if ((code = parse_certificate_type(parser, type, &fields[0], rdata, token)) < 0) 1232 + return code; 1233 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 1234 + return code; 1235 + if ((code = parse_int16(parser, type, &fields[1], rdata, token)) < 0) 1236 + return code; 1237 + if ((code = take_contiguous(parser, type, &fields[2], token)) < 0) 1238 + return code; 1239 + if ((code = parse_algorithm(parser, type, &fields[2], rdata, token)) < 0) 1240 + return code; 1241 + take(parser, token); 1242 + if ((code = parse_base64_sequence(parser, type, &fields[3], rdata, token)) < 0) 1243 + return code; 1244 + 1245 + return accept_rr(parser, type, rdata); 1246 + } 1247 + 1248 + nonnull_all 1249 + static int32_t check_apl_rr( 1250 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 1251 + { 1252 + // FIXME: check correctness of fields and total length 1253 + return accept_rr(parser, type, rdata); 1254 + } 1255 + 1256 + nonnull_all 1257 + static int32_t parse_apl_rdata( 1258 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 1259 + { 1260 + int32_t code; 1261 + const rdata_info_t *fields = type->rdata.fields; 1262 + 1263 + // RDATA section for APL consists of zero or more fields 1264 + while (is_contiguous(token)) { 1265 + int32_t length; 1266 + const size_t size = (uintptr_t)rdata->limit - (uintptr_t)rdata->octets; 1267 + if ((length = scan_apl(token->data, token->length, rdata->octets, size)) < 0) 1268 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[0]), NAME(type)); 1269 + assert(length == 8 /* ipv4 */ || length == 20 /* ipv6 */); 1270 + rdata->octets += (size_t)length; 1271 + take(parser, token); 1272 + } 1273 + 1274 + if ((code = have_delimiter(parser, type, token)) < 0) 1275 + return code; 1276 + return accept_rr(parser, type, rdata); 1277 + } 1278 + 1279 + nonnull_all 1280 + static int32_t check_ds_rr( 1281 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 1282 + { 1283 + int32_t r; 1284 + size_t c = 0; 1285 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 1286 + const uint8_t *o = parser->rdata->octets; 1287 + const rdata_info_t *f = type->rdata.fields; 1288 + 1289 + if ((r = check(&c, check_int16(parser, type, &f[0], o, n))) || 1290 + (r = check(&c, check_int8(parser, type, &f[1], o+c, n-c))) || 1291 + (r = check(&c, check_int8(parser, type, &f[2], o+c, n-c)))) 1292 + return r; 1293 + 1294 + const uint8_t digest_algorithm = parser->rdata->octets[3]; 1295 + 1296 + if ((digest_algorithm & 0x7) == digest_algorithm) { 1297 + // https://www.iana.org/assignments/ds-rr-types 1298 + static const uint8_t digest_sizes[8] = { 1299 + 0, // 0: Reserved 1300 + 20, // 1: SHA-1 1301 + 32, // 2: SHA-256 1302 + 32, // 3: GOST R 34.11-94 1303 + 48, // 4: SHA-384 1304 + 48, // 5: GOST R 34.10-2012 1305 + 48, // 6: SM3 1306 + 0 // 7: Unassigned 1307 + }; 1308 + 1309 + const uint8_t digest_size = digest_sizes[ digest_algorithm ]; 1310 + 1311 + if (digest_size && n - 4 != digest_size) 1312 + SEMANTIC_ERROR(parser, "Invalid digest in %s", NAME(type)); 1313 + } 1314 + 1315 + if (c >= n) 1316 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 1317 + return accept_rr(parser, type, rdata); 1318 + } 1319 + 1320 + nonnull_all 1321 + static int32_t parse_ds_rdata( 1322 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 1323 + { 1324 + int32_t code; 1325 + const rdata_info_t *fields = type->rdata.fields; 1326 + 1327 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 1328 + return code; 1329 + if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0) 1330 + return code; 1331 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 1332 + return code; 1333 + if ((code = parse_algorithm(parser, type, &fields[1], rdata, token)) < 0) 1334 + return code; 1335 + if ((code = take_contiguous(parser, type, &fields[2], token)) < 0) 1336 + return code; 1337 + if ((code = parse_int8(parser, type, &fields[2], rdata, token)) < 0) 1338 + return code; 1339 + take(parser, token); 1340 + if ((code = parse_base16_sequence(parser, type, &fields[3], rdata, token)) < 0) 1341 + return code; 1342 + 1343 + const uint8_t digest_algorithm = parser->rdata->octets[3]; 1344 + 1345 + if ((digest_algorithm & 0x7) == digest_algorithm) { 1346 + // https://www.iana.org/assignments/ds-rr-types 1347 + static const uint8_t digest_sizes[8] = { 1348 + 0, // 0: Reserved 1349 + 20, // 1: SHA-1 1350 + 32, // 2: SHA-256 1351 + 32, // 3: GOST R 34.11-94 1352 + 48, // 4: SHA-384 1353 + 48, // 5: GOST R 34.10-2012 1354 + 48, // 6: SM3 1355 + 0 // 7: Unassigned 1356 + }; 1357 + 1358 + const uint8_t digest_size = digest_sizes[ digest_algorithm ]; 1359 + size_t length = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 1360 + 1361 + if (digest_size && length - 4 != digest_size) 1362 + SEMANTIC_ERROR(parser, "Invalid digest in %s", NAME(type)); 1363 + } 1364 + 1365 + return accept_rr(parser, type, rdata); 1366 + } 1367 + 1368 + nonnull_all 1369 + static int32_t check_sshfp_rr( 1370 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 1371 + { 1372 + int32_t r; 1373 + size_t c = 0; 1374 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 1375 + const uint8_t *o = parser->rdata->octets; 1376 + const rdata_info_t *f = type->rdata.fields; 1377 + 1378 + if ((r = check(&c, check_int8(parser, type, &f[0], o, n))) || 1379 + (r = check(&c, check_int8(parser, type, &f[1], o+c, n-c)))) 1380 + return r; 1381 + 1382 + // https://www.iana.org/assignments/dns-sshfp-rr-parameters 1383 + 1384 + if (c == n) 1385 + SYNTAX_ERROR(parser, "Missing %s in %s", NAME((&f[n!=0])), NAME(type)); 1386 + else if (o[1] == 1 && (n - c) != 20) 1387 + SEMANTIC_ERROR(parser, "Wrong fingerprint size for type %s in %s", 1388 + "SHA1", NAME(type)); 1389 + else if (o[1] == 2 && (n - c) != 32) 1390 + SEMANTIC_ERROR(parser, "Wrong fingerprint size for type %s in %s", 1391 + "SHA256", NAME(type)); 1392 + 1393 + return accept_rr(parser, type, rdata); 1394 + } 1395 + 1396 + nonnull_all 1397 + static int32_t parse_sshfp_rdata( 1398 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 1399 + { 1400 + int32_t code; 1401 + const rdata_info_t *fields = type->rdata.fields; 1402 + 1403 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 1404 + return code; 1405 + if ((code = parse_int8(parser, type, &fields[0], rdata, token)) < 0) 1406 + return code; 1407 + 1408 + const uint8_t *fingerprint_type = rdata->octets; 1409 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 1410 + return code; 1411 + if ((code = parse_int8(parser, type, &fields[1], rdata, token)) < 0) 1412 + return code; 1413 + 1414 + const uint8_t *fingerprint = rdata->octets; 1415 + take(parser, token); 1416 + if ((code = parse_base16_sequence(parser, type, &fields[2], rdata, token)) < 0) 1417 + return code; 1418 + 1419 + // https://www.iana.org/assignments/dns-sshfp-rr-parameters 1420 + size_t fingerprint_size = (uintptr_t)rdata->octets - (uintptr_t)fingerprint; 1421 + if (unlikely(*fingerprint_type == 1 && fingerprint_size != 20)) 1422 + SEMANTIC_ERROR(parser, "Wrong fingerprint size for type %s in %s", 1423 + "SHA1", NAME(type)); 1424 + if (unlikely(*fingerprint_type == 2 && fingerprint_size != 32)) 1425 + SEMANTIC_ERROR(parser, "Wrong fingerprint size for type %s in %s", 1426 + "SHA256", NAME(type)); 1427 + 1428 + return accept_rr(parser, type, rdata); 1429 + } 1430 + 1431 + nonnull_all 1432 + static int32_t check_ipseckey_rr( 1433 + parser_t *parser, const type_info_t *type, const rdata_t *rdata); 1434 + 1435 + nonnull_all 1436 + static int32_t parse_ipseckey_rdata( 1437 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token); 1438 + 1439 + diagnostic_push() 1440 + gcc_diagnostic_ignored(missing-field-initializers) 1441 + clang_diagnostic_ignored(missing-field-initializers) 1442 + 1443 + static const rdata_info_t ipseckey_ipv4_rdata_fields[] = { 1444 + FIELD("precedence"), 1445 + FIELD("gateway type"), 1446 + FIELD("algorithm"), 1447 + FIELD("gateway"), 1448 + FIELD("public key") 1449 + }; 1450 + 1451 + static const type_info_t ipseckey_ipv4[] = { 1452 + TYPE("IPSECKEY", ZONE_TYPE_IPSECKEY, ZONE_CLASS_IN, FIELDS(ipseckey_ipv4_rdata_fields), 1453 + check_ipseckey_rr, parse_ipseckey_rdata), 1454 + }; 1455 + 1456 + static const rdata_info_t ipseckey_ipv6_rdata_fields[] = { 1457 + FIELD("precedence"), 1458 + FIELD("gateway type"), 1459 + FIELD("algorithm"), 1460 + FIELD("gateway"), 1461 + FIELD("public key") 1462 + }; 1463 + 1464 + static const type_info_t ipseckey_ipv6[] = { 1465 + TYPE("IPSECKEY", ZONE_TYPE_IPSECKEY, ZONE_CLASS_IN, FIELDS(ipseckey_ipv6_rdata_fields), 1466 + check_ipseckey_rr, parse_ipseckey_rdata), 1467 + }; 1468 + 1469 + diagnostic_pop() 1470 + 1471 + nonnull_all 1472 + static int32_t check_ipseckey_rr( 1473 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 1474 + { 1475 + int32_t r; 1476 + size_t c = 0; 1477 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 1478 + const uint8_t *o = parser->rdata->octets; 1479 + const type_info_t *t = type; 1480 + const rdata_info_t *f = type->rdata.fields; 1481 + 1482 + if ((r = check(&c, check_int8(parser, type, &f[0], o, n))) || 1483 + (r = check(&c, check_int8(parser, type, &f[1], o+c, n-c))) || 1484 + (r = check(&c, check_int8(parser, type, &f[2], o+c, n-c)))) 1485 + return r; 1486 + 1487 + switch (parser->rdata->octets[1]) { 1488 + case 1: /* IPv4 address */ 1489 + t = (const type_info_t *)ipseckey_ipv4; 1490 + f = ipseckey_ipv4_rdata_fields; 1491 + if ((r = check(&c, check_ip4(parser, t, &f[3], o+c, n-c))) < 0) 1492 + return r; 1493 + break; 1494 + case 2: /* IPv6 address */ 1495 + t = (const type_info_t *)ipseckey_ipv6; 1496 + f = ipseckey_ipv6_rdata_fields; 1497 + if ((r = check(&c, check_ip6(parser, t, &f[3], o+c, n-c))) < 0) 1498 + return r; 1499 + break; 1500 + case 0: /* no gateway */ 1501 + break; 1502 + case 3: /* domain name */ 1503 + if ((r = check(&c, check_name(parser, t, &f[3], o+c, n-c))) < 0) 1504 + return r; 1505 + break; 1506 + default: 1507 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 1508 + } 1509 + 1510 + switch (parser->rdata->octets[2]) { 1511 + case 0: 1512 + if (c < n) 1513 + SYNTAX_ERROR(parser, "Trailing data in %s", NAME(t)); 1514 + break; 1515 + default: 1516 + if (c >= n) 1517 + SYNTAX_ERROR(parser, "Missing %s in %s", NAME(&f[4]), NAME(t)); 1518 + break; 1519 + } 1520 + 1521 + return accept_rr(parser, t, rdata); 1522 + } 1523 + 1524 + nonnull_all 1525 + static int32_t parse_ipseckey_rdata( 1526 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 1527 + { 1528 + int32_t code; 1529 + const rdata_info_t *fields = type->rdata.fields; 1530 + uint8_t *octets = rdata->octets; 1531 + 1532 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 1533 + return code; 1534 + if ((code = parse_int8(parser, type, &fields[0], rdata, token)) < 0) 1535 + return code; 1536 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 1537 + return code; 1538 + if ((code = parse_int8(parser, type, &fields[1], rdata, token)) < 0) 1539 + return code; 1540 + if ((code = take_contiguous(parser, type, &fields[2], token)) < 0) 1541 + return code; 1542 + if ((code = parse_int8(parser, type, &fields[2], rdata, token)) < 0) 1543 + return code; 1544 + if ((code = take_contiguous(parser, type, &fields[3], token)) < 0) 1545 + return code; 1546 + 1547 + switch (octets[1]) { 1548 + case 0: /* no gateway */ 1549 + if (token->length != 1 || token->data[0] != '.') 1550 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[3]), NAME(type)); 1551 + break; 1552 + case 1: /* IPv4 address */ 1553 + type = (const type_info_t *)ipseckey_ipv4; 1554 + fields = type->rdata.fields; 1555 + if ((code = parse_ip4(parser, type, &fields[3], rdata, token)) < 0) 1556 + return code; 1557 + break; 1558 + case 2: /* IPv6 address */ 1559 + type = (const type_info_t *)ipseckey_ipv6; 1560 + fields = type->rdata.fields; 1561 + if ((code = parse_ip6(parser, type, &fields[3], rdata, token)) < 0) 1562 + return code; 1563 + break; 1564 + case 3: /* domain name */ 1565 + if ((code = parse_name(parser, type, &fields[3], rdata, token)) < 0) 1566 + return code; 1567 + break; 1568 + default: 1569 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[3]), NAME(type)); 1570 + } 1571 + 1572 + take(parser, token); 1573 + switch (octets[2]) { 1574 + case 0: 1575 + if ((code = have_delimiter(parser, type, token)) < 0) 1576 + return code; 1577 + break; 1578 + default: 1579 + if ((code = parse_base64_sequence(parser, type, &fields[4], rdata, token)) < 0) 1580 + return code; 1581 + break; 1582 + } 1583 + 1584 + return accept_rr(parser, type, rdata); 1585 + } 1586 + 1587 + nonnull_all 1588 + static int32_t check_rrsig_rr( 1589 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 1590 + { 1591 + int32_t r; 1592 + size_t c = 0; 1593 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 1594 + const uint8_t *o = parser->rdata->octets; 1595 + const rdata_info_t *f = type->rdata.fields; 1596 + 1597 + if ((r = check(&c, check_int16(parser, type, &f[0], o, n))) || 1598 + (r = check(&c, check_int8(parser, type, &f[1], o+c, n-c))) || 1599 + (r = check(&c, check_int8(parser, type, &f[2], o+c, n-c))) || 1600 + (r = check(&c, check_ttl(parser, type, &f[3], o+c, n-c))) || 1601 + (r = check(&c, check_int32(parser, type, &f[4], o+c, n-c))) || 1602 + (r = check(&c, check_int32(parser, type, &f[5], o+c, n-c))) || 1603 + (r = check(&c, check_int16(parser, type, &f[6], o+c, n-c))) || 1604 + (r = check(&c, check_name(parser, type, &f[7], o+c, n-c)))) 1605 + return r; 1606 + 1607 + if (c > n) 1608 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 1609 + return accept_rr(parser, type, rdata); 1610 + } 1611 + 1612 + nonnull_all 1613 + static int32_t parse_rrsig_rdata( 1614 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 1615 + { 1616 + int32_t code; 1617 + const rdata_info_t *fields = type->rdata.fields; 1618 + 1619 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 1620 + return code; 1621 + if ((code = parse_type(parser, type, &fields[0], rdata, token)) < 0) 1622 + return code; 1623 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 1624 + return code; 1625 + if ((code = parse_algorithm(parser, type, &fields[1], rdata, token)) < 0) 1626 + return code; 1627 + if ((code = take_contiguous(parser, type, &fields[2], token)) < 0) 1628 + return code; 1629 + if ((code = parse_int8(parser, type, &fields[2], rdata, token)) < 0) 1630 + return code; 1631 + if ((code = take_contiguous(parser, type, &fields[3], token)) < 0) 1632 + return code; 1633 + if ((code = parse_ttl(parser, type, &fields[3], rdata, token)) < 0) 1634 + return code; 1635 + if ((code = take_contiguous(parser, type, &fields[4], token)) < 0) 1636 + return code; 1637 + if ((code = parse_time(parser, type, &fields[4], rdata, token)) < 0) 1638 + return code; 1639 + if ((code = take_contiguous(parser, type, &fields[5], token)) < 0) 1640 + return code; 1641 + if ((code = parse_time(parser, type, &fields[5], rdata, token)) < 0) 1642 + return code; 1643 + if ((code = take_contiguous(parser, type, &fields[6], token)) < 0) 1644 + return code; 1645 + if ((code = parse_int16(parser, type, &fields[6], rdata, token)) < 0) 1646 + return code; 1647 + if ((code = take_contiguous(parser, type, &fields[7], token)) < 0) 1648 + return code; 1649 + if ((code = parse_name(parser, type, &fields[7], rdata, token)) < 0) 1650 + return code; 1651 + take(parser, token); 1652 + if ((code = parse_base64_sequence(parser, type, &fields[8], rdata, token)) < 0) 1653 + return code; 1654 + 1655 + return accept_rr(parser, type, rdata); 1656 + } 1657 + 1658 + nonnull_all 1659 + static int32_t check_nsec_rr( 1660 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 1661 + { 1662 + int32_t r; 1663 + size_t c = 0; 1664 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 1665 + const uint8_t *o = parser->rdata->octets; 1666 + const rdata_info_t *f = type->rdata.fields; 1667 + 1668 + if ((r = check(&c, check_name(parser, type, &f[0], o, n))) || 1669 + (r = check(&c, check_nsec(parser, type, &f[1], o+c, n-c)))) 1670 + return r; 1671 + 1672 + if (c != n) 1673 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 1674 + return accept_rr(parser, type, rdata); 1675 + } 1676 + 1677 + nonnull_all 1678 + static int32_t parse_nsec_rdata( 1679 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 1680 + { 1681 + int32_t code; 1682 + const rdata_info_t *fields = type->rdata.fields; 1683 + 1684 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 1685 + return code; 1686 + if ((code = parse_name(parser, type, &fields[0], rdata, token)) < 0) 1687 + return code; 1688 + take(parser, token); 1689 + if ((code = parse_nsec(parser, type, &fields[1], rdata, token)) < 0) 1690 + return code; 1691 + 1692 + return accept_rr(parser, type, rdata); 1693 + } 1694 + 1695 + nonnull_all 1696 + static int32_t check_dnskey_rr( 1697 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 1698 + { 1699 + int32_t r; 1700 + size_t c = 0; 1701 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 1702 + const uint8_t *o = parser->rdata->octets; 1703 + const rdata_info_t *f = type->rdata.fields; 1704 + 1705 + if ((r = check(&c, check_int16(parser, type, &f[0], o, n))) || 1706 + (r = check(&c, check_int8(parser, type, &f[1], o+c, n-c))) || 1707 + (r = check(&c, check_int8(parser, type, &f[2], o+c, n-c)))) 1708 + return r; 1709 + 1710 + if (c >= n) 1711 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 1712 + return accept_rr(parser, type, rdata); 1713 + } 1714 + 1715 + nonnull_all 1716 + static int32_t parse_dnskey_rdata( 1717 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 1718 + { 1719 + int32_t code; 1720 + const rdata_info_t *fields = type->rdata.fields; 1721 + 1722 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 1723 + return code; 1724 + if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0) 1725 + return code; 1726 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 1727 + return code; 1728 + if ((code = parse_int8(parser, type, &fields[1], rdata, token)) < 0) 1729 + return code; 1730 + if ((code = take_contiguous(parser, type, &fields[2], token)) < 0) 1731 + return code; 1732 + if ((code = parse_algorithm(parser, type, &fields[2], rdata, token)) < 0) 1733 + return code; 1734 + take(parser, token); 1735 + if ((code = parse_base64_sequence(parser, type, &fields[3], rdata, token)) < 0) 1736 + return code; 1737 + 1738 + return accept_rr(parser, type, rdata); 1739 + } 1740 + 1741 + nonnull_all 1742 + static int32_t check_dhcid_rr( 1743 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 1744 + { 1745 + // RFC4701 section 3.1: 1746 + // 2-octet identifier type, 1-octet digest type, followed by one or more 1747 + // octets representing the actual identifier 1748 + if ((uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets < 4) 1749 + SEMANTIC_ERROR(parser, "Invalid %s", NAME(type)); 1750 + return accept_rr(parser, type, rdata); 1751 + } 1752 + 1753 + nonnull_all 1754 + static int32_t parse_dhcid_rdata( 1755 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 1756 + { 1757 + int32_t code; 1758 + const rdata_info_t *fields = type->rdata.fields; 1759 + 1760 + if ((code = parse_base64_sequence(parser, type, &fields[0], rdata, token)) < 0) 1761 + return code; 1762 + 1763 + return check_dhcid_rr(parser, type, rdata); 1764 + } 1765 + 1766 + nonnull_all 1767 + static int32_t check_nsec3_rr( 1768 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 1769 + { 1770 + int32_t r; 1771 + size_t c = 0; 1772 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 1773 + const uint8_t *o = parser->rdata->octets; 1774 + const rdata_info_t *f = type->rdata.fields; 1775 + 1776 + if ((r = check(&c, check_int8(parser, type, &f[0], o, n))) || 1777 + (r = check(&c, check_int8(parser, type, &f[1], o+c, n-c))) || 1778 + (r = check(&c, check_int16(parser, type, &f[2], o+c, n-c))) || 1779 + (r = check(&c, check_string(parser, type, &f[3], o+c, n-c))) || 1780 + (r = check(&c, check_string(parser, type, &f[4], o+c, n-c))) || 1781 + (r = check(&c, check_nsec(parser, type, &f[5], o+c, n-c)))) 1782 + return r; 1783 + 1784 + if (c != n) 1785 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 1786 + return accept_rr(parser, type, rdata); 1787 + } 1788 + 1789 + nonnull_all 1790 + static int32_t parse_nsec3_rdata( 1791 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 1792 + { 1793 + int32_t code; 1794 + const rdata_info_t *fields = type->rdata.fields; 1795 + 1796 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 1797 + return code; 1798 + if ((code = parse_int8(parser, type, &fields[0], rdata, token)) < 0) 1799 + return code; 1800 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 1801 + return code; 1802 + if ((code = parse_int8(parser, type, &fields[1], rdata, token)) < 0) 1803 + return code; 1804 + if ((code = take_contiguous(parser, type, &fields[2], token)) < 0) 1805 + return code; 1806 + if ((code = parse_int16(parser, type, &fields[2], rdata, token)) < 0) 1807 + return code; 1808 + if ((code = take_contiguous(parser, type, &fields[3], token)) < 0) 1809 + return code; 1810 + if ((code = parse_salt(parser, type, &fields[3], rdata, token)) < 0) 1811 + return code; 1812 + if ((code = take_contiguous(parser, type, &fields[4], token)) < 0) 1813 + return code; 1814 + if ((code = parse_base32(parser, type, &fields[4], rdata, token)) < 0) 1815 + return code; 1816 + take(parser, token); 1817 + if ((code = parse_nsec(parser, type, &fields[5], rdata, token)) < 0) 1818 + return code; 1819 + 1820 + return accept_rr(parser, type, rdata); 1821 + } 1822 + 1823 + nonnull_all 1824 + static int32_t check_nsec3param_rr( 1825 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 1826 + { 1827 + int32_t r; 1828 + size_t c = 0; 1829 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 1830 + const uint8_t *o = parser->rdata->octets; 1831 + const rdata_info_t *f = type->rdata.fields; 1832 + 1833 + if ((r = check(&c, check_int8(parser, type, &f[0], o, n))) || 1834 + (r = check(&c, check_int8(parser, type, &f[1], o+c, n-c))) || 1835 + (r = check(&c, check_int16(parser, type, &f[2], o+c, n-c))) || 1836 + (r = check(&c, check_string(parser, type, &f[3], o+c, n-c)))) 1837 + return r; 1838 + 1839 + if (c != n) 1840 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 1841 + return accept_rr(parser, type, rdata); 1842 + } 1843 + 1844 + nonnull_all 1845 + static int32_t parse_nsec3param_rdata( 1846 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 1847 + { 1848 + int32_t code; 1849 + const rdata_info_t *fields = type->rdata.fields; 1850 + 1851 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 1852 + return code; 1853 + if ((code = parse_int8(parser, type, &fields[0], rdata, token)) < 0) 1854 + return code; 1855 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 1856 + return code; 1857 + if ((code = parse_int8(parser, type, &fields[1], rdata, token)) < 0) 1858 + return code; 1859 + if ((code = take_contiguous(parser, type, &fields[2], token)) < 0) 1860 + return code; 1861 + if ((code = parse_int16(parser, type, &fields[2], rdata, token)) < 0) 1862 + return code; 1863 + if ((code = take_contiguous(parser, type, &fields[3], token)) < 0) 1864 + return code; 1865 + if ((code = parse_salt(parser, type, &fields[3], rdata, token)) < 0) 1866 + return code; 1867 + if ((code = take_delimiter(parser, type, token)) < 0) 1868 + return code; 1869 + return accept_rr(parser, type, rdata); 1870 + } 1871 + 1872 + nonnull_all 1873 + static int32_t check_tlsa_rr( 1874 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 1875 + { 1876 + int32_t r; 1877 + size_t c = 0; 1878 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 1879 + const uint8_t *o = parser->rdata->octets; 1880 + const rdata_info_t *f = type->rdata.fields; 1881 + 1882 + if ((r = check(&c, check_int8(parser, type, &f[0], o, n))) || 1883 + (r = check(&c, check_int8(parser, type, &f[1], o+c, n-c))) || 1884 + (r = check(&c, check_int8(parser, type, &f[2], o+c, n-c)))) 1885 + return r; 1886 + 1887 + if (c >= n) 1888 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 1889 + return accept_rr(parser, type, rdata); 1890 + } 1891 + 1892 + nonnull_all 1893 + static int32_t parse_tlsa_rdata( 1894 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 1895 + { 1896 + int32_t code; 1897 + const rdata_info_t *fields = type->rdata.fields; 1898 + 1899 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 1900 + return code; 1901 + if ((code = parse_int8(parser, type, &fields[0], rdata, token)) < 0) 1902 + return code; 1903 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 1904 + return code; 1905 + if ((code = parse_int8(parser, type, &fields[1], rdata, token)) < 0) 1906 + return code; 1907 + if ((code = take_contiguous(parser, type, &fields[2], token)) < 0) 1908 + return code; 1909 + if ((code = parse_int8(parser, type, &fields[2], rdata, token)) < 0) 1910 + return code; 1911 + take(parser, token); 1912 + if ((code = parse_base16_sequence(parser, type, &fields[3], rdata, token)) < 0) 1913 + return code; 1914 + 1915 + return accept_rr(parser, type, rdata); 1916 + } 1917 + 1918 + nonnull_all 1919 + static int32_t check_hip_rr( 1920 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 1921 + { 1922 + // FIXME: verify field lengths etc 1923 + return accept_rr(parser, type, rdata); 1924 + } 1925 + 1926 + nonnull_all 1927 + static int32_t parse_hip_rdata( 1928 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 1929 + { 1930 + int32_t code; 1931 + const rdata_info_t *fields = type->rdata.fields; 1932 + uint8_t *octets = rdata->octets; 1933 + 1934 + // reserve octet for HIT length 1935 + rdata->octets += 1; 1936 + 1937 + // PK algorithm 1938 + if ((code = have_contiguous(parser, type, &fields[1], token)) < 0) 1939 + return code; 1940 + if ((code = parse_int8(parser, type, &fields[1], rdata, token)) < 0) 1941 + return code; 1942 + 1943 + // reserve octets for PK length 1944 + rdata->octets += 2; 1945 + 1946 + // HIT 1947 + if ((code = take_contiguous(parser, type, &fields[3], token)) < 0) 1948 + return code; 1949 + if ((code = parse_base16(parser, type, &fields[3], rdata, token)) < 0) 1950 + return code; 1951 + 1952 + if ((rdata->octets - octets) > 255 + 4) 1953 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[3]), NAME(type)); 1954 + uint8_t hit_length = (uint8_t)((rdata->octets - octets) - 4); 1955 + octets[0] = hit_length; 1956 + 1957 + // Public Key 1958 + if ((code = take_contiguous(parser, type, &fields[4], token)) < 0) 1959 + return code; 1960 + if ((code = parse_base64(parser, type, &fields[4], rdata, token)) < 0) 1961 + return code; 1962 + 1963 + uint16_t pk_length = htobe16((uint16_t)(((rdata->octets - octets) - hit_length) - 4)); 1964 + memcpy(&octets[2], &pk_length, sizeof(pk_length)); 1965 + 1966 + take(parser, token); 1967 + while (is_contiguous(token)) { 1968 + if ((code = parse_name(parser, type, &fields[5], rdata, token)) < 0) 1969 + return code; 1970 + take(parser, token); 1971 + } 1972 + 1973 + if ((code = have_delimiter(parser, type, token)) < 0) 1974 + return code; 1975 + return accept_rr(parser, type, rdata); 1976 + } 1977 + 1978 + nonnull_all 1979 + static int32_t check_openpgpkey_rr( 1980 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 1981 + { 1982 + // FIXME: as the RDATA contains a digest, it is likely we can make this 1983 + // check stricter, at least, for known algorithms 1984 + if ((uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets < 4) 1985 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 1986 + return accept_rr(parser, type, rdata); 1987 + } 1988 + 1989 + nonnull_all 1990 + static int32_t parse_openpgpkey_rdata( 1991 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 1992 + { 1993 + int32_t code; 1994 + const rdata_info_t *fields = type->rdata.fields; 1995 + 1996 + if ((code = parse_base64_sequence(parser, type, &fields[0], rdata, token)) < 0) 1997 + return code; 1998 + 1999 + return accept_rr(parser, type, rdata); 2000 + } 2001 + 2002 + nonnull_all 2003 + static int32_t check_csync_rr( 2004 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 2005 + { 2006 + int32_t r; 2007 + size_t c = 0; 2008 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 2009 + const uint8_t *o = parser->rdata->octets; 2010 + const rdata_info_t *f = type->rdata.fields; 2011 + 2012 + if ((r = check(&c, check_int32(parser, type, &f[0], o, n))) || 2013 + (r = check(&c, check_int16(parser, type, &f[1], o+c, n-c))) || 2014 + (r = check(&c, check_nsec(parser, type, &f[2], o+c, n-c)))) 2015 + return r; 2016 + 2017 + if (c != n) 2018 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 2019 + return accept_rr(parser, type, rdata); 2020 + } 2021 + 2022 + nonnull_all 2023 + static int32_t parse_csync_rdata( 2024 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 2025 + { 2026 + int32_t code; 2027 + const rdata_info_t *fields = type->rdata.fields; 2028 + 2029 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 2030 + return code; 2031 + if ((code = parse_int32(parser, type, &fields[0], rdata, token)) < 0) 2032 + return code; 2033 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 2034 + return code; 2035 + if ((code = parse_int16(parser, type, &fields[1], rdata, token)) < 0) 2036 + return code; 2037 + take(parser, token); 2038 + if ((code = parse_nsec(parser, type, &fields[2], rdata, token)) < 0) 2039 + return code; 2040 + 2041 + return accept_rr(parser, type, rdata); 2042 + } 2043 + 2044 + nonnull_all 2045 + static int32_t check_zonemd_rr( 2046 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 2047 + { 2048 + int32_t r; 2049 + size_t c = 0; 2050 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 2051 + const uint8_t *o = parser->rdata->octets; 2052 + const rdata_info_t *f = type->rdata.fields; 2053 + 2054 + if ((r = check(&c, check_int32(parser, type, &f[0], o, n))) || 2055 + (r = check(&c, check_int8(parser, type, &f[1], o+c, n-c))) || 2056 + (r = check(&c, check_int8(parser, type, &f[2], o+c, n-c)))) 2057 + return r; 2058 + 2059 + const uint8_t digest_algorithm = parser->rdata->octets[5]; 2060 + if ((digest_algorithm & 0x3) == digest_algorithm) { 2061 + // https://www.iana.org/assignments/dns-parameters#zonemd-hash-algorithms 2062 + static const uint8_t digest_sizes[4] = { 2063 + 0, // 0: Reserved 2064 + 48, // 1: SHA-384 2065 + 64, // 2: SHA-512 2066 + 0 // 3: Unassigned 2067 + }; 2068 + 2069 + const uint8_t digest_size = digest_sizes[ digest_algorithm ]; 2070 + if (digest_size && n - 6 != digest_size) 2071 + SEMANTIC_ERROR(parser, "Invalid digest in %s", NAME(type)); 2072 + } 2073 + 2074 + return accept_rr(parser, type, rdata); 2075 + } 2076 + 2077 + nonnull_all 2078 + static int32_t parse_zonemd_rdata( 2079 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 2080 + { 2081 + int32_t code; 2082 + const rdata_info_t *fields = type->rdata.fields; 2083 + 2084 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 2085 + return code; 2086 + if ((code = parse_int32(parser, type, &fields[0], rdata, token)) < 0) 2087 + return code; 2088 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 2089 + return code; 2090 + if ((code = parse_int8(parser, type, &fields[1], rdata, token)) < 0) 2091 + return code; 2092 + if ((code = take_contiguous(parser, type, &fields[2], token)) < 0) 2093 + return code; 2094 + if ((code = parse_int8(parser, type, &fields[2], rdata, token)) < 0) 2095 + return code; 2096 + take(parser, token); 2097 + if ((code = parse_base16_sequence(parser, type, &fields[3], rdata, token)) < 0) 2098 + return code; 2099 + 2100 + const uint8_t digest_algorithm = parser->rdata->octets[5]; 2101 + if ((digest_algorithm & 0x3) == digest_algorithm) { 2102 + // https://www.iana.org/assignments/dns-parameters#zonemd-hash-algorithms 2103 + static const uint8_t digest_sizes[4] = { 2104 + 0, // 0: Reserved 2105 + 48, // 1: SHA-384 2106 + 64, // 2: SHA-512 2107 + 0 // 3: Unassigned 2108 + }; 2109 + 2110 + const uint8_t digest_size = digest_sizes[ digest_algorithm ]; 2111 + size_t length = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 2112 + if (digest_size && length - 6 != digest_size) 2113 + SEMANTIC_ERROR(parser, "Invalid digest in %s", NAME(type)); 2114 + } 2115 + 2116 + return accept_rr(parser, type, rdata); 2117 + } 2118 + 2119 + nonnull_all 2120 + static int32_t check_svcb_rr( 2121 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 2122 + { 2123 + // 2124 + // FIXME: implement checking parameters etc 2125 + // 2126 + // - check if all keys in mandatory exist 2127 + // - check if at least keys and key lengths are valid 2128 + // 2129 + // FIXME: implement reordering parameters in strict (primary) mode 2130 + // FIXME: note that when reordering or checking, rdata may not actually 2131 + // contain valid parameters 2132 + // 2133 + 2134 + return accept_rr(parser, type, rdata); 2135 + } 2136 + 2137 + nonnull_all 2138 + static int32_t parse_svcb_rdata( 2139 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 2140 + { 2141 + int32_t code; 2142 + const rdata_info_t *fields = type->rdata.fields; 2143 + 2144 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 2145 + return code; 2146 + if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0) 2147 + return code; 2148 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 2149 + return code; 2150 + if ((code = parse_name(parser, type, &fields[1], rdata, token)) < 0) 2151 + return code; 2152 + take(parser, token); 2153 + if ((code = parse_svc_params(parser, type, &fields[2], rdata, token)) < 0) 2154 + return code; 2155 + 2156 + return accept_rr(parser, type, rdata); 2157 + } 2158 + 2159 + nonnull_all 2160 + static int32_t check_https_rr( 2161 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 2162 + { 2163 + // 2164 + // FIXME: incorporate fixes mentioned in check_svcb_rr 2165 + // 2166 + 2167 + return accept_rr(parser, type, rdata); 2168 + } 2169 + 2170 + nonnull_all 2171 + static int32_t parse_https_rdata( 2172 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 2173 + { 2174 + int32_t code; 2175 + const rdata_info_t *fields = type->rdata.fields; 2176 + 2177 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 2178 + return code; 2179 + if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0) 2180 + return code; 2181 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 2182 + return code; 2183 + if ((code = parse_name(parser, type, &fields[1], rdata, token)) < 0) 2184 + return code; 2185 + take(parser, token); 2186 + if ((code = parse_svc_params(parser, type, &fields[2], rdata, token)) < 0) 2187 + return code; 2188 + 2189 + return accept_rr(parser, type, rdata); 2190 + } 2191 + 2192 + nonnull_all 2193 + static int32_t check_nid_rr( 2194 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 2195 + { 2196 + int32_t r; 2197 + size_t c = 0; 2198 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 2199 + const uint8_t *o = parser->rdata->octets; 2200 + const rdata_info_t *f = type->rdata.fields; 2201 + 2202 + if ((r = check(&c, check_int16(parser, type, &f[0], o, n))) || 2203 + (r = check(&c, check_ilnp64(parser, type, &f[1], o+c, n-c)))) 2204 + return r; 2205 + if (c != n) 2206 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 2207 + return accept_rr(parser, type, rdata); 2208 + } 2209 + 2210 + nonnull_all 2211 + static int32_t parse_nid_rdata( 2212 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 2213 + { 2214 + int32_t code; 2215 + const rdata_info_t *fields = type->rdata.fields; 2216 + 2217 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 2218 + return code; 2219 + if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0) 2220 + return code; 2221 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 2222 + return code; 2223 + if ((code = parse_ilnp64(parser, type, &fields[1], rdata, token)) < 0) 2224 + return code; 2225 + if ((code = take_delimiter(parser, type, token)) < 0) 2226 + return code; 2227 + return accept_rr(parser, type, rdata); 2228 + } 2229 + 2230 + nonnull_all 2231 + static int32_t check_l32_rr( 2232 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 2233 + { 2234 + int32_t r; 2235 + size_t c = 0; 2236 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 2237 + const uint8_t *o = parser->rdata->octets; 2238 + const rdata_info_t *f = type->rdata.fields; 2239 + 2240 + if ((r = check(&c, check_int16(parser, type, &f[0], o, n))) || 2241 + (r = check(&c, check_ip4(parser, type, &f[1], o+c, n-c)))) 2242 + return r; 2243 + 2244 + if (c != n) 2245 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 2246 + return accept_rr(parser, type, rdata); 2247 + } 2248 + 2249 + nonnull_all 2250 + static int32_t parse_l32_rdata( 2251 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 2252 + { 2253 + int32_t code; 2254 + const rdata_info_t *fields = type->rdata.fields; 2255 + 2256 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 2257 + return code; 2258 + if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0) 2259 + return code; 2260 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 2261 + return code; 2262 + if ((code = parse_ip4(parser, type, &fields[1], rdata, token)) < 0) 2263 + return code; 2264 + if ((code = take_delimiter(parser, type, token)) < 0) 2265 + return code; 2266 + return accept_rr(parser, type, rdata); 2267 + } 2268 + 2269 + nonnull_all 2270 + static int32_t check_l64_rr( 2271 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 2272 + { 2273 + int32_t r; 2274 + size_t c = 0; 2275 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 2276 + const uint8_t *o = parser->rdata->octets; 2277 + const rdata_info_t *f = type->rdata.fields; 2278 + 2279 + if ((r = check(&c, check_int16(parser, type, &f[0], o, n))) || 2280 + (r = check(&c, check_ilnp64(parser, type, &f[1], o+c, n-c)))) 2281 + return r; 2282 + if (c != n) 2283 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 2284 + return accept_rr(parser, type, rdata); 2285 + } 2286 + 2287 + nonnull_all 2288 + static int32_t parse_l64_rdata( 2289 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 2290 + { 2291 + int32_t code; 2292 + const rdata_info_t *fields = type->rdata.fields; 2293 + 2294 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 2295 + return code; 2296 + if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0) 2297 + return code; 2298 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 2299 + return code; 2300 + if ((code = parse_ilnp64(parser, type, &fields[1], rdata, token)) < 0) 2301 + return code; 2302 + if ((code = take_delimiter(parser, type, token)) < 0) 2303 + return code; 2304 + return accept_rr(parser, type, rdata); 2305 + } 2306 + 2307 + nonnull_all 2308 + static int32_t check_eui48_rr( 2309 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 2310 + { 2311 + if ((uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets != 6) 2312 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 2313 + return accept_rr(parser, type, rdata); 2314 + } 2315 + 2316 + nonnull_all 2317 + static int32_t parse_eui48_rdata( 2318 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 2319 + { 2320 + int32_t code; 2321 + const rdata_info_t *fields = type->rdata.fields; 2322 + 2323 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 2324 + return code; 2325 + if ((code = parse_eui48(parser, type, &fields[0], rdata, token)) < 0) 2326 + return code; 2327 + if ((code = take_delimiter(parser, type, token)) < 0) 2328 + return code; 2329 + return accept_rr(parser, type, rdata); 2330 + } 2331 + 2332 + nonnull_all 2333 + static int32_t check_eui64_rr( 2334 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 2335 + { 2336 + if ((uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets != 8) 2337 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 2338 + return accept_rr(parser, type, rdata); 2339 + } 2340 + 2341 + nonnull_all 2342 + static int32_t parse_eui64_rdata( 2343 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 2344 + { 2345 + int32_t code; 2346 + const rdata_info_t *fields = type->rdata.fields; 2347 + 2348 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 2349 + return code; 2350 + if ((code = parse_eui64(parser, type, &fields[0], rdata, token)) < 0) 2351 + return code; 2352 + if ((code = take_delimiter(parser, type, token)) < 0) 2353 + return code; 2354 + return accept_rr(parser, type, rdata); 2355 + } 2356 + 2357 + nonnull_all 2358 + static int32_t check_uri_rr( 2359 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 2360 + { 2361 + int32_t r; 2362 + size_t c = 0; 2363 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 2364 + const uint8_t *o = parser->rdata->octets; 2365 + const rdata_info_t *f = type->rdata.fields; 2366 + 2367 + if ((r = check(&c, check_int16(parser, type, &f[0], o, n))) || 2368 + (r = check(&c, check_int16(parser, type, &f[1], o+c, n-c)))) 2369 + return r; 2370 + if (c >= n) 2371 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 2372 + return accept_rr(parser, type, rdata); 2373 + } 2374 + 2375 + nonnull_all 2376 + static int32_t parse_uri_rdata( 2377 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 2378 + { 2379 + int32_t code; 2380 + const rdata_info_t *fields = type->rdata.fields; 2381 + 2382 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 2383 + return code; 2384 + if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0) 2385 + return code; 2386 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 2387 + return code; 2388 + if ((code = parse_int16(parser, type, &fields[1], rdata, token)) < 0) 2389 + return code; 2390 + if ((code = take_quoted(parser, type, &fields[2], token)) < 0) 2391 + return code; 2392 + if ((code = parse_text(parser, type, &fields[2], rdata, token)) < 0) 2393 + return code; 2394 + if ((code = take_delimiter(parser, type, token)) < 0) 2395 + return code; 2396 + return accept_rr(parser, type, rdata); 2397 + } 2398 + 2399 + nonnull_all 2400 + static int32_t check_caa_rr( 2401 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 2402 + { 2403 + int32_t r; 2404 + size_t c = 0; 2405 + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; 2406 + const uint8_t *o = parser->rdata->octets; 2407 + const rdata_info_t *f = type->rdata.fields; 2408 + 2409 + if ((r = check(&c, check_int8(parser, type, &f[0], o, n))) || 2410 + (r = check(&c, check_int8(parser, type, &f[1], o+c, n-c)))) 2411 + return r; 2412 + if (c >= n) 2413 + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); 2414 + return accept_rr(parser, type, rdata); 2415 + } 2416 + 2417 + nonnull_all 2418 + static int32_t parse_caa_rdata( 2419 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 2420 + { 2421 + int32_t code; 2422 + const rdata_info_t *fields = type->rdata.fields; 2423 + 2424 + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) 2425 + return code; 2426 + if ((code = parse_int8(parser, type, &fields[0], rdata, token)) < 0) 2427 + return code; 2428 + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) 2429 + return code; 2430 + if ((code = parse_caa_tag(parser, type, &fields[1], rdata, token)) < 0) 2431 + return code; 2432 + if ((code = take_quoted_or_contiguous(parser, type, &fields[2], token)) < 0) 2433 + return code; 2434 + if ((code = parse_text(parser, type, &fields[2], rdata, token)) < 0) 2435 + return code; 2436 + if ((code = take_delimiter(parser, type, token)) < 0) 2437 + return code; 2438 + return accept_rr(parser, type, rdata); 2439 + } 2440 + 2441 + nonnull_all 2442 + static int32_t check_generic_rr( 2443 + parser_t *parser, const type_info_t *type, const rdata_t *rdata) 2444 + { 2445 + return accept_rr(parser, type, rdata); 2446 + } 2447 + 2448 + nonnull_all 2449 + static int32_t parse_generic_rdata( 2450 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 2451 + { 2452 + int32_t code; 2453 + uint16_t rdlength; 2454 + static const rdata_info_t fields[] = { 2455 + FIELD("rdlength"), 2456 + FIELD("rdata") 2457 + }; 2458 + 2459 + // discard '\#' 2460 + if ((code = take_contiguous(parser, type, &fields[0], token)) < 0) 2461 + return code; 2462 + if (!scan_int16(token->data, token->length, &rdlength)) 2463 + SYNTAX_ERROR(parser, "Invalid RDLENGTH in %s", NAME(type)); 2464 + 2465 + take(parser, token); 2466 + if (is_contiguous(token)) { 2467 + struct base16_state state = { .eof = 0, .bytes = 0, .carry = 0 }; 2468 + 2469 + do { 2470 + size_t length = token->length + 1 / 2; 2471 + if (length > (uintptr_t)rdata->limit - (uintptr_t)rdata->octets) 2472 + SYNTAX_ERROR(parser, "Invalid RDATA in %s", NAME(type)); 2473 + if (!base16_stream_decode(&state, token->data, token->length, rdata->octets, &length)) 2474 + SYNTAX_ERROR(parser, "Invalid RDATA in %s", NAME(type)); 2475 + rdata->octets += length; 2476 + take(parser, token); 2477 + } while (is_contiguous(token)); 2478 + 2479 + if (state.bytes) 2480 + *rdata->octets++ = state.carry; 2481 + } 2482 + 2483 + if ((code = have_delimiter(parser, type, token)) < 0) 2484 + return code; 2485 + if (rdata->octets - parser->rdata->octets != rdlength) 2486 + SYNTAX_ERROR(parser, "Invalid RDATA in %s", NAME(type)); 2487 + return type->check(parser, type, rdata); 2488 + } 2489 + 2490 + nonnull_all 2491 + static int32_t parse_unknown_rdata( 2492 + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) 2493 + { 2494 + (void)type; 2495 + (void)rdata; 2496 + (void)token; 2497 + SYNTAX_ERROR(parser, "Unknown record type"); 2498 + } 2499 + 2500 + diagnostic_push() 2501 + gcc_diagnostic_ignored(missing-field-initializers) 2502 + clang_diagnostic_ignored(missing-field-initializers) 2503 + 2504 + static const class_info_t classes[] = { 2505 + UNKNOWN_CLASS(0), 2506 + CLASS("IN", ZONE_CLASS_IN), 2507 + CLASS("CS", ZONE_CLASS_CS), 2508 + CLASS("CH", ZONE_CLASS_CH), 2509 + CLASS("HS", ZONE_CLASS_HS) 2510 + }; 2511 + 2512 + static const rdata_info_t a_rdata_fields[] = { 2513 + FIELD("address") 2514 + }; 2515 + 2516 + static const rdata_info_t ns_rdata_fields[] = { 2517 + FIELD("host") 2518 + }; 2519 + 2520 + static const rdata_info_t md_rdata_fields[] = { 2521 + FIELD("madname") 2522 + }; 2523 + 2524 + static const rdata_info_t mf_rdata_fields[] = { 2525 + FIELD("madname") 2526 + }; 2527 + 2528 + static const rdata_info_t cname_rdata_fields[] = { 2529 + FIELD("host") 2530 + }; 2531 + 2532 + static const rdata_info_t soa_rdata_fields[] = { 2533 + FIELD("primary"), 2534 + FIELD("mailbox"), 2535 + FIELD("serial"), 2536 + FIELD("refresh"), 2537 + FIELD("retry"), 2538 + FIELD("expire"), 2539 + FIELD("minimum") 2540 + }; 2541 + 2542 + static const rdata_info_t mb_rdata_fields[] = { 2543 + FIELD("madname") 2544 + }; 2545 + 2546 + static const rdata_info_t mg_rdata_fields[] = { 2547 + FIELD("mgmname") 2548 + }; 2549 + 2550 + static const rdata_info_t mr_rdata_fields[] = { 2551 + FIELD("newname") 2552 + }; 2553 + 2554 + static const rdata_info_t ptr_rdata_fields[] = { 2555 + FIELD("ptrdname") 2556 + }; 2557 + 2558 + static const rdata_info_t hinfo_rdata_fields[] = { 2559 + FIELD("cpu"), 2560 + FIELD("os") 2561 + }; 2562 + 2563 + static const rdata_info_t minfo_rdata_fields[] = { 2564 + FIELD("rmailbx"), 2565 + FIELD("emailbx") 2566 + }; 2567 + 2568 + static const rdata_info_t null_rdata_fields[] = { 2569 + FIELD("anything") 2570 + }; 2571 + 2572 + static const rdata_info_t wks_rdata_fields[] = { 2573 + FIELD("address"), 2574 + FIELD("protocol"), 2575 + FIELD("bitmap") 2576 + }; 2577 + 2578 + static const rdata_info_t mx_rdata_fields[] = { 2579 + FIELD("priority"), 2580 + FIELD("hostname") 2581 + }; 2582 + 2583 + static const rdata_info_t txt_rdata_fields[] = { 2584 + FIELD("text") 2585 + }; 2586 + 2587 + static const rdata_info_t rp_rdata_fields[] = { 2588 + FIELD("mailbox"), 2589 + FIELD("text") 2590 + }; 2591 + 2592 + static const rdata_info_t afsdb_rdata_fields[] = { 2593 + FIELD("subtype"), 2594 + FIELD("hostname") 2595 + }; 2596 + 2597 + static const rdata_info_t x25_rdata_fields[] = { 2598 + FIELD("address") 2599 + }; 2600 + 2601 + static const rdata_info_t isdn_rdata_fields[] = { 2602 + FIELD("address"), 2603 + FIELD("subaddress") 2604 + }; 2605 + 2606 + static const rdata_info_t rt_rdata_fields[] = { 2607 + FIELD("preference"), 2608 + FIELD("hostname") 2609 + }; 2610 + 2611 + static const rdata_info_t nsap_rdata_fields[] = { 2612 + FIELD("address") 2613 + }; 2614 + 2615 + static const rdata_info_t nsap_ptr_rdata_fields[] = { 2616 + FIELD("hostname") 2617 + }; 2618 + 2619 + static const rdata_info_t key_rdata_fields[] = { 2620 + FIELD("flags"), 2621 + FIELD("protocol"), 2622 + FIELD("algorithm"), 2623 + FIELD("publickey") 2624 + }; 2625 + 2626 + static const rdata_info_t px_rdata_fields[] = { 2627 + FIELD("preference"), 2628 + FIELD("map822"), 2629 + FIELD("mapx400") 2630 + }; 2631 + 2632 + static const rdata_info_t gpos_rdata_fields[] = { 2633 + FIELD("latitude"), 2634 + FIELD("longitude"), 2635 + FIELD("altitude") 2636 + }; 2637 + 2638 + static const rdata_info_t aaaa_rdata_fields[] = { 2639 + FIELD("address") 2640 + }; 2641 + 2642 + static const rdata_info_t loc_rdata_fields[] = { 2643 + FIELD("version"), 2644 + FIELD("size"), 2645 + FIELD("horizontal precision"), 2646 + FIELD("vertical precision"), 2647 + FIELD("latitude"), 2648 + FIELD("longitude"), 2649 + FIELD("altitude") 2650 + }; 2651 + 2652 + static const rdata_info_t nxt_rdata_fields[] = { 2653 + FIELD("next domain name"), 2654 + FIELD("type bit map") 2655 + }; 2656 + 2657 + static const rdata_info_t srv_rdata_fields[] = { 2658 + FIELD("priority"), 2659 + FIELD("weight"), 2660 + FIELD("port"), 2661 + FIELD("target") 2662 + }; 2663 + 2664 + static const rdata_info_t naptr_rdata_fields[] = { 2665 + FIELD("order"), 2666 + FIELD("preference"), 2667 + FIELD("flags"), 2668 + FIELD("services"), 2669 + FIELD("regex"), 2670 + FIELD("replacement"), 2671 + }; 2672 + 2673 + static const rdata_info_t kx_rdata_fields[] = { 2674 + FIELD("preference"), 2675 + FIELD("exchanger") 2676 + }; 2677 + 2678 + static const rdata_info_t sig_rdata_fields[] = { 2679 + FIELD("sigtype"), 2680 + FIELD("algorithm"), 2681 + FIELD("labels"), 2682 + FIELD("origttl"), 2683 + FIELD("expire"), 2684 + FIELD("inception"), 2685 + FIELD("keytag"), 2686 + FIELD("signer"), 2687 + FIELD("signature") 2688 + }; 2689 + 2690 + static const rdata_info_t cert_rdata_fields[] = { 2691 + FIELD("type"), 2692 + FIELD("key tag"), 2693 + FIELD("algorithm"), 2694 + FIELD("certificate") 2695 + }; 2696 + 2697 + static const rdata_info_t dname_rdata_fields[] = { 2698 + FIELD("source") 2699 + }; 2700 + 2701 + static const rdata_info_t apl_rdata_fields[] = { 2702 + FIELD("prefix") 2703 + }; 2704 + 2705 + static const rdata_info_t ds_rdata_fields[] = { 2706 + FIELD("keytag"), 2707 + FIELD("algorithm"), 2708 + FIELD("digtype"), 2709 + FIELD("digest") 2710 + }; 2711 + 2712 + static const rdata_info_t sshfp_rdata_fields[] = { 2713 + FIELD("algorithm"), 2714 + FIELD("ftype"), 2715 + FIELD("fingerprint") 2716 + }; 2717 + 2718 + // IPSECKEY is different because the rdata depends on the algorithm 2719 + static const rdata_info_t ipseckey_rdata_fields[] = { 2720 + FIELD("precedence"), 2721 + FIELD("gateway type"), 2722 + FIELD("algorithm"), 2723 + FIELD("gateway"), 2724 + FIELD("public key") 2725 + }; 2726 + 2727 + static const rdata_info_t rrsig_rdata_fields[] = { 2728 + FIELD("rrtype"), 2729 + FIELD("algorithm"), 2730 + FIELD("labels"), 2731 + FIELD("origttl"), 2732 + FIELD("expire"), 2733 + FIELD("inception"), 2734 + FIELD("keytag"), 2735 + FIELD("signer"), 2736 + FIELD("signature") 2737 + }; 2738 + 2739 + static const rdata_info_t nsec_rdata_fields[] = { 2740 + FIELD("next"), 2741 + FIELD("types") 2742 + }; 2743 + 2744 + static const rdata_info_t dnskey_rdata_fields[] = { 2745 + FIELD("flags"), 2746 + FIELD("protocol"), 2747 + FIELD("algorithm"), 2748 + FIELD("publickey") 2749 + }; 2750 + 2751 + static const rdata_info_t dhcid_rdata_fields[] = { 2752 + FIELD("dhcpinfo") 2753 + }; 2754 + 2755 + static const rdata_info_t nsec3_rdata_fields[] = { 2756 + FIELD("algorithm"), 2757 + FIELD("flags"), 2758 + FIELD("iterations"), 2759 + FIELD("salt"), 2760 + FIELD("next"), 2761 + FIELD("types") 2762 + }; 2763 + 2764 + static const rdata_info_t nsec3param_rdata_fields[] = { 2765 + FIELD("algorithm"), 2766 + FIELD("flags"), 2767 + FIELD("iterations"), 2768 + FIELD("salt") 2769 + }; 2770 + 2771 + static const rdata_info_t tlsa_rdata_fields[] = { 2772 + FIELD("usage"), 2773 + FIELD("selector"), 2774 + FIELD("matching type"), 2775 + FIELD("certificate association data") 2776 + }; 2777 + 2778 + static const rdata_info_t smimea_rdata_fields[] = { 2779 + FIELD("usage"), 2780 + FIELD("selector"), 2781 + FIELD("matching type"), 2782 + FIELD("certificate association data") 2783 + }; 2784 + 2785 + static const rdata_info_t cds_rdata_fields[] = { 2786 + FIELD("keytag"), 2787 + FIELD("algorithm"), 2788 + FIELD("digtype"), 2789 + FIELD("digest") 2790 + }; 2791 + 2792 + static const rdata_info_t cdnskey_rdata_fields[] = { 2793 + FIELD("flags"), 2794 + FIELD("protocol"), 2795 + FIELD("algorithm"), 2796 + FIELD("publickey") 2797 + }; 2798 + 2799 + static const rdata_info_t hip_rdata_fields[] = { 2800 + FIELD("HIT length"), 2801 + FIELD("PK algorithm"), 2802 + FIELD("PK length"), 2803 + FIELD("HIT"), 2804 + FIELD("Public Key"), 2805 + FIELD("Rendezvous Servers") 2806 + }; 2807 + 2808 + // https://www.iana.org/assignments/dns-parameters/NINFO/ninfo-completed-template 2809 + static const rdata_info_t ninfo_rdata_fields[] = { 2810 + FIELD("text") 2811 + }; 2812 + 2813 + // https://www.iana.org/assignments/dns-parameters/RKEY/rkey-completed-template 2814 + static const rdata_info_t rkey_rdata_fields[] = { 2815 + FIELD("flags"), 2816 + FIELD("protocol"), 2817 + FIELD("algorithm"), 2818 + FIELD("publickey") 2819 + }; 2820 + 2821 + static const rdata_info_t openpgpkey_rdata_fields[] = { 2822 + FIELD("key") 2823 + }; 2824 + 2825 + static const rdata_info_t csync_rdata_fields[] = { 2826 + FIELD("serial"), 2827 + FIELD("flags"), 2828 + FIELD("types") 2829 + }; 2830 + 2831 + static const rdata_info_t zonemd_rdata_fields[] = { 2832 + FIELD("serial"), 2833 + FIELD("scheme"), 2834 + FIELD("algorithm"), 2835 + FIELD("digest"), 2836 + }; 2837 + 2838 + static const rdata_info_t svcb_rdata_fields[] = { 2839 + FIELD("priority"), 2840 + FIELD("target"), 2841 + FIELD("params") 2842 + }; 2843 + 2844 + static const rdata_info_t https_rdata_fields[] = { 2845 + FIELD("priority"), 2846 + FIELD("target"), 2847 + FIELD("params") 2848 + }; 2849 + 2850 + static const rdata_info_t spf_rdata_fields[] = { 2851 + FIELD("text") 2852 + }; 2853 + 2854 + static const rdata_info_t nid_rdata_fields[] = { 2855 + FIELD("preference"), 2856 + FIELD("nodeid") 2857 + }; 2858 + 2859 + // RFC6742 specifies the syntax for the locator is compatible with the syntax 2860 + // for IPv4 addresses, but then proceeds to provide an example with leading 2861 + // zeroes. The example is corrected in the errata. 2862 + static const rdata_info_t l32_rdata_fields[] = { 2863 + FIELD("preference"), 2864 + FIELD("locator") 2865 + }; 2866 + 2867 + static const rdata_info_t l64_rdata_fields[] = { 2868 + FIELD("preference"), 2869 + FIELD("locator") 2870 + }; 2871 + 2872 + static const rdata_info_t lp_rdata_fields[] = { 2873 + FIELD("preference"), 2874 + FIELD("pointer") 2875 + }; 2876 + 2877 + static const rdata_info_t eui48_rdata_fields[] = { 2878 + FIELD("address") 2879 + }; 2880 + 2881 + static const rdata_info_t eui64_rdata_fields[] = { 2882 + FIELD("address") 2883 + }; 2884 + 2885 + static const rdata_info_t uri_rdata_fields[] = { 2886 + FIELD("priority"), 2887 + FIELD("weight"), 2888 + FIELD("target") 2889 + }; 2890 + 2891 + static const rdata_info_t caa_rdata_fields[] = { 2892 + FIELD("flags"), 2893 + FIELD("tag"), 2894 + FIELD("value") 2895 + }; 2896 + 2897 + // https://www.iana.org/assignments/dns-parameters/AVC/avc-completed-template 2898 + static const rdata_info_t avc_rdata_fields[] = { 2899 + FIELD("text") 2900 + }; 2901 + 2902 + // RFC 9606 2903 + static const rdata_info_t resinfo_rdata_fields[] = { 2904 + FIELD("text") 2905 + }; 2906 + 2907 + // https://www.iana.org/assignments/dns-parameters/WALLET/wallet-completed-template 2908 + static const rdata_info_t wallet_rdata_fields[] = { 2909 + FIELD("text") 2910 + }; 2911 + 2912 + // https://www.iana.org/assignments/dns-parameters/CLA/cla-completed-template 2913 + static const rdata_info_t cla_rdata_fields[] = { 2914 + FIELD("text") 2915 + }; 2916 + 2917 + static const rdata_info_t ta_rdata_fields[] = { 2918 + FIELD("key"), 2919 + FIELD("algorithm"), 2920 + FIELD("type"), 2921 + FIELD("digest") 2922 + }; 2923 + 2924 + static const rdata_info_t dlv_rdata_fields[] = { 2925 + FIELD("key"), 2926 + FIELD("algorithm"), 2927 + FIELD("type"), 2928 + FIELD("digest") 2929 + }; 2930 + 2931 + // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml 2932 + static const type_info_t types[] = { 2933 + UNKNOWN_TYPE(0), 2934 + 2935 + TYPE("A", ZONE_TYPE_A, ZONE_CLASS_ANY, FIELDS(a_rdata_fields), 2936 + check_a_rr, parse_a_rdata), 2937 + TYPE("NS", ZONE_TYPE_NS, ZONE_CLASS_ANY, FIELDS(ns_rdata_fields), 2938 + check_ns_rr, parse_ns_rdata), 2939 + TYPE("MD", ZONE_TYPE_MD, ZONE_CLASS_ANY, FIELDS(md_rdata_fields), // obsolete 2940 + check_ns_rr, parse_ns_rdata), 2941 + TYPE("MF", ZONE_TYPE_MF, ZONE_CLASS_ANY, FIELDS(mf_rdata_fields), // obsolete 2942 + check_ns_rr, parse_ns_rdata), 2943 + TYPE("CNAME", ZONE_TYPE_CNAME, ZONE_CLASS_ANY, FIELDS(cname_rdata_fields), 2944 + check_ns_rr, parse_ns_rdata), 2945 + TYPE("SOA", ZONE_TYPE_SOA, ZONE_CLASS_ANY, FIELDS(soa_rdata_fields), 2946 + check_soa_rr, parse_soa_rdata), 2947 + TYPE("MB", ZONE_TYPE_MB, ZONE_CLASS_ANY, FIELDS(mb_rdata_fields), // experimental 2948 + check_ns_rr, parse_ns_rdata), 2949 + TYPE("MG", ZONE_TYPE_MG, ZONE_CLASS_ANY, FIELDS(mg_rdata_fields), // experimental 2950 + check_ns_rr, parse_ns_rdata), 2951 + TYPE("MR", ZONE_TYPE_MR, ZONE_CLASS_ANY, FIELDS(mr_rdata_fields), // experimental 2952 + check_ns_rr, parse_ns_rdata), 2953 + TYPE("NULL", ZONE_TYPE_NULL, ZONE_CLASS_ANY, FIELDS(null_rdata_fields), // experimetal 2954 + check_generic_rr, parse_unknown_rdata), 2955 + TYPE("WKS", ZONE_TYPE_WKS, ZONE_CLASS_IN, FIELDS(wks_rdata_fields), 2956 + check_wks_rr, parse_wks_rdata), 2957 + TYPE("PTR", ZONE_TYPE_PTR, ZONE_CLASS_ANY, FIELDS(ptr_rdata_fields), 2958 + check_ns_rr, parse_ns_rdata), 2959 + TYPE("HINFO", ZONE_TYPE_HINFO, ZONE_CLASS_ANY, FIELDS(hinfo_rdata_fields), 2960 + check_hinfo_rr, parse_hinfo_rdata), 2961 + TYPE("MINFO", ZONE_TYPE_MINFO, ZONE_CLASS_ANY, FIELDS(minfo_rdata_fields), 2962 + check_minfo_rr, parse_minfo_rdata), 2963 + TYPE("MX", ZONE_TYPE_MX, ZONE_CLASS_ANY, FIELDS(mx_rdata_fields), 2964 + check_mx_rr, parse_mx_rdata), 2965 + TYPE("TXT", ZONE_TYPE_TXT, ZONE_CLASS_ANY, FIELDS(txt_rdata_fields), 2966 + check_txt_rr, parse_txt_rdata), 2967 + TYPE("RP", ZONE_TYPE_RP, ZONE_CLASS_ANY, FIELDS(rp_rdata_fields), 2968 + check_minfo_rr, parse_minfo_rdata), 2969 + TYPE("AFSDB", ZONE_TYPE_AFSDB, ZONE_CLASS_ANY, FIELDS(afsdb_rdata_fields), 2970 + check_mx_rr, parse_mx_rdata), 2971 + TYPE("X25", ZONE_TYPE_X25, ZONE_CLASS_ANY, FIELDS(x25_rdata_fields), 2972 + check_x25_rr, parse_x25_rdata), 2973 + TYPE("ISDN", ZONE_TYPE_ISDN, ZONE_CLASS_ANY, FIELDS(isdn_rdata_fields), 2974 + check_isdn_rr, parse_isdn_rdata), 2975 + TYPE("RT", ZONE_TYPE_RT, ZONE_CLASS_ANY, FIELDS(rt_rdata_fields), 2976 + check_rt_rr, parse_rt_rdata), 2977 + TYPE("NSAP", ZONE_TYPE_NSAP, ZONE_CLASS_IN, FIELDS(nsap_rdata_fields), 2978 + check_nsap_rr, parse_nsap_rdata), 2979 + TYPE("NSAP-PTR", ZONE_TYPE_NSAP_PTR, ZONE_CLASS_IN, FIELDS(nsap_ptr_rdata_fields), 2980 + check_nsap_ptr_rr, parse_nsap_ptr_rdata), 2981 + TYPE("SIG", ZONE_TYPE_SIG, ZONE_CLASS_ANY, FIELDS(sig_rdata_fields), 2982 + check_rrsig_rr, parse_rrsig_rdata), 2983 + TYPE("KEY", ZONE_TYPE_KEY, ZONE_CLASS_ANY, FIELDS(key_rdata_fields), 2984 + check_key_rr, parse_key_rdata), 2985 + TYPE("PX", ZONE_TYPE_PX, ZONE_CLASS_IN, FIELDS(px_rdata_fields), 2986 + check_px_rr, parse_px_rdata), 2987 + TYPE("GPOS", ZONE_TYPE_GPOS, ZONE_CLASS_ANY, FIELDS(gpos_rdata_fields), 2988 + check_gpos_rr, parse_gpos_rdata), 2989 + TYPE("AAAA", ZONE_TYPE_AAAA, ZONE_CLASS_IN, FIELDS(aaaa_rdata_fields), 2990 + check_aaaa_rr, parse_aaaa_rdata), 2991 + TYPE("LOC", ZONE_TYPE_LOC, ZONE_CLASS_ANY, FIELDS(loc_rdata_fields), 2992 + check_loc_rr, parse_loc_rdata), 2993 + TYPE("NXT", ZONE_TYPE_NXT, ZONE_CLASS_ANY, FIELDS(nxt_rdata_fields), // obsolete 2994 + check_nxt_rr, parse_nxt_rdata), 2995 + 2996 + UNKNOWN_TYPE(31), 2997 + UNKNOWN_TYPE(32), 2998 + 2999 + TYPE("SRV", ZONE_TYPE_SRV, ZONE_CLASS_IN, FIELDS(srv_rdata_fields), 3000 + check_srv_rr, parse_srv_rdata), 3001 + 3002 + UNKNOWN_TYPE(34), 3003 + 3004 + TYPE("NAPTR", ZONE_TYPE_NAPTR, ZONE_CLASS_IN, FIELDS(naptr_rdata_fields), 3005 + check_naptr_rr, parse_naptr_rdata), 3006 + TYPE("KX", ZONE_TYPE_KX, ZONE_CLASS_IN, FIELDS(kx_rdata_fields), 3007 + check_mx_rr, parse_mx_rdata), 3008 + TYPE("CERT", ZONE_TYPE_CERT, ZONE_CLASS_ANY, FIELDS(cert_rdata_fields), 3009 + check_cert_rr, parse_cert_rdata), 3010 + 3011 + UNKNOWN_TYPE(38), 3012 + 3013 + TYPE("DNAME", ZONE_TYPE_DNAME, ZONE_CLASS_ANY, FIELDS(dname_rdata_fields), 3014 + check_ns_rr, parse_ns_rdata), 3015 + 3016 + UNKNOWN_TYPE(40), 3017 + UNKNOWN_TYPE(41), 3018 + 3019 + TYPE("APL", ZONE_TYPE_APL, ZONE_CLASS_IN, FIELDS(apl_rdata_fields), 3020 + check_apl_rr, parse_apl_rdata), 3021 + TYPE("DS", ZONE_TYPE_DS, ZONE_CLASS_ANY, FIELDS(ds_rdata_fields), 3022 + check_ds_rr, parse_ds_rdata), 3023 + TYPE("SSHFP", ZONE_TYPE_SSHFP, ZONE_CLASS_ANY, FIELDS(sshfp_rdata_fields), 3024 + check_sshfp_rr, parse_sshfp_rdata), 3025 + TYPE("IPSECKEY", ZONE_TYPE_IPSECKEY, ZONE_CLASS_IN, FIELDS(ipseckey_rdata_fields), 3026 + check_ipseckey_rr, parse_ipseckey_rdata), 3027 + TYPE("RRSIG", ZONE_TYPE_RRSIG, ZONE_CLASS_ANY, FIELDS(rrsig_rdata_fields), 3028 + check_rrsig_rr, parse_rrsig_rdata), 3029 + TYPE("NSEC", ZONE_TYPE_NSEC, ZONE_CLASS_ANY, FIELDS(nsec_rdata_fields), 3030 + check_nsec_rr, parse_nsec_rdata), 3031 + TYPE("DNSKEY", ZONE_TYPE_DNSKEY, ZONE_CLASS_ANY, FIELDS(dnskey_rdata_fields), 3032 + check_dnskey_rr, parse_dnskey_rdata), 3033 + TYPE("DHCID", ZONE_TYPE_DHCID, ZONE_CLASS_IN, FIELDS(dhcid_rdata_fields), 3034 + check_dhcid_rr, parse_dhcid_rdata), 3035 + TYPE("NSEC3", ZONE_TYPE_NSEC3, ZONE_CLASS_ANY, FIELDS(nsec3_rdata_fields), 3036 + check_nsec3_rr, parse_nsec3_rdata), 3037 + TYPE("NSEC3PARAM", ZONE_TYPE_NSEC3PARAM, ZONE_CLASS_ANY, FIELDS(nsec3param_rdata_fields), 3038 + check_nsec3param_rr, parse_nsec3param_rdata), 3039 + TYPE("TLSA", ZONE_TYPE_TLSA, ZONE_CLASS_ANY, FIELDS(tlsa_rdata_fields), 3040 + check_tlsa_rr, parse_tlsa_rdata), 3041 + TYPE("SMIMEA", ZONE_TYPE_SMIMEA, ZONE_CLASS_ANY, FIELDS(smimea_rdata_fields), 3042 + check_tlsa_rr, parse_tlsa_rdata), 3043 + 3044 + UNKNOWN_TYPE(54), 3045 + 3046 + TYPE("HIP", ZONE_TYPE_HIP, ZONE_CLASS_ANY, FIELDS(hip_rdata_fields), 3047 + check_hip_rr, parse_hip_rdata), 3048 + TYPE("NINFO", ZONE_TYPE_NINFO, ZONE_CLASS_ANY, FIELDS(ninfo_rdata_fields), 3049 + check_txt_rr, parse_txt_rdata), 3050 + TYPE("RKEY", ZONE_TYPE_RKEY, ZONE_CLASS_ANY, FIELDS(rkey_rdata_fields), 3051 + check_dnskey_rr, parse_dnskey_rdata), 3052 + 3053 + UNKNOWN_TYPE(58), 3054 + 3055 + TYPE("CDS", ZONE_TYPE_CDS, ZONE_CLASS_ANY, FIELDS(cds_rdata_fields), 3056 + check_ds_rr, parse_ds_rdata), 3057 + TYPE("CDNSKEY", ZONE_TYPE_CDNSKEY, ZONE_CLASS_ANY, FIELDS(cdnskey_rdata_fields), 3058 + check_dnskey_rr, parse_dnskey_rdata), 3059 + TYPE("OPENPGPKEY", ZONE_TYPE_OPENPGPKEY, ZONE_CLASS_ANY, FIELDS(openpgpkey_rdata_fields), 3060 + check_openpgpkey_rr, parse_openpgpkey_rdata), 3061 + TYPE("CSYNC", ZONE_TYPE_CSYNC, ZONE_CLASS_ANY, FIELDS(csync_rdata_fields), 3062 + check_csync_rr, parse_csync_rdata), 3063 + TYPE("ZONEMD", ZONE_TYPE_ZONEMD, ZONE_CLASS_ANY, FIELDS(zonemd_rdata_fields), 3064 + check_zonemd_rr, parse_zonemd_rdata), 3065 + TYPE("SVCB", ZONE_TYPE_SVCB, ZONE_CLASS_IN, FIELDS(svcb_rdata_fields), 3066 + check_svcb_rr, parse_svcb_rdata), 3067 + TYPE("HTTPS", ZONE_TYPE_HTTPS, ZONE_CLASS_IN, FIELDS(https_rdata_fields), 3068 + check_https_rr, parse_https_rdata), 3069 + 3070 + UNKNOWN_TYPE(66), 3071 + UNKNOWN_TYPE(67), 3072 + UNKNOWN_TYPE(68), 3073 + UNKNOWN_TYPE(69), 3074 + UNKNOWN_TYPE(70), 3075 + UNKNOWN_TYPE(71), 3076 + UNKNOWN_TYPE(72), 3077 + UNKNOWN_TYPE(73), 3078 + UNKNOWN_TYPE(74), 3079 + UNKNOWN_TYPE(75), 3080 + UNKNOWN_TYPE(76), 3081 + UNKNOWN_TYPE(77), 3082 + UNKNOWN_TYPE(78), 3083 + UNKNOWN_TYPE(79), 3084 + UNKNOWN_TYPE(80), 3085 + UNKNOWN_TYPE(81), 3086 + UNKNOWN_TYPE(82), 3087 + UNKNOWN_TYPE(83), 3088 + UNKNOWN_TYPE(84), 3089 + UNKNOWN_TYPE(85), 3090 + UNKNOWN_TYPE(86), 3091 + UNKNOWN_TYPE(87), 3092 + UNKNOWN_TYPE(88), 3093 + UNKNOWN_TYPE(89), 3094 + UNKNOWN_TYPE(90), 3095 + UNKNOWN_TYPE(91), 3096 + UNKNOWN_TYPE(92), 3097 + UNKNOWN_TYPE(93), 3098 + UNKNOWN_TYPE(94), 3099 + UNKNOWN_TYPE(95), 3100 + UNKNOWN_TYPE(96), 3101 + UNKNOWN_TYPE(97), 3102 + UNKNOWN_TYPE(98), 3103 + 3104 + TYPE("SPF", ZONE_TYPE_SPF, ZONE_CLASS_ANY, FIELDS(spf_rdata_fields), // obsolete 3105 + check_txt_rr, parse_txt_rdata), 3106 + 3107 + UNKNOWN_TYPE(100), 3108 + UNKNOWN_TYPE(101), 3109 + UNKNOWN_TYPE(102), 3110 + UNKNOWN_TYPE(103), 3111 + 3112 + TYPE("NID", ZONE_TYPE_NID, ZONE_CLASS_ANY, FIELDS(nid_rdata_fields), 3113 + check_nid_rr, parse_nid_rdata), 3114 + TYPE("L32", ZONE_TYPE_L32, ZONE_CLASS_ANY, FIELDS(l32_rdata_fields), 3115 + check_l32_rr, parse_l32_rdata), 3116 + TYPE("L64", ZONE_TYPE_L64, ZONE_CLASS_ANY, FIELDS(l64_rdata_fields), 3117 + check_l64_rr, parse_l64_rdata), 3118 + TYPE("LP", ZONE_TYPE_LP, ZONE_CLASS_ANY, FIELDS(lp_rdata_fields), 3119 + check_mx_rr, parse_mx_rdata), 3120 + TYPE("EUI48", ZONE_TYPE_EUI48, ZONE_CLASS_ANY, FIELDS(eui48_rdata_fields), 3121 + check_eui48_rr, parse_eui48_rdata), 3122 + TYPE("EUI64", ZONE_TYPE_EUI64, ZONE_CLASS_ANY, FIELDS(eui64_rdata_fields), 3123 + check_eui64_rr, parse_eui64_rdata), 3124 + 3125 + UNKNOWN_TYPE(110), 3126 + UNKNOWN_TYPE(111), 3127 + UNKNOWN_TYPE(112), 3128 + UNKNOWN_TYPE(113), 3129 + UNKNOWN_TYPE(114), 3130 + UNKNOWN_TYPE(115), 3131 + UNKNOWN_TYPE(116), 3132 + UNKNOWN_TYPE(117), 3133 + UNKNOWN_TYPE(118), 3134 + UNKNOWN_TYPE(119), 3135 + UNKNOWN_TYPE(120), 3136 + UNKNOWN_TYPE(121), 3137 + UNKNOWN_TYPE(122), 3138 + UNKNOWN_TYPE(123), 3139 + UNKNOWN_TYPE(124), 3140 + UNKNOWN_TYPE(125), 3141 + UNKNOWN_TYPE(126), 3142 + UNKNOWN_TYPE(127), 3143 + UNKNOWN_TYPE(128), 3144 + UNKNOWN_TYPE(129), 3145 + UNKNOWN_TYPE(130), 3146 + UNKNOWN_TYPE(131), 3147 + UNKNOWN_TYPE(132), 3148 + UNKNOWN_TYPE(133), 3149 + UNKNOWN_TYPE(134), 3150 + UNKNOWN_TYPE(135), 3151 + UNKNOWN_TYPE(136), 3152 + UNKNOWN_TYPE(137), 3153 + UNKNOWN_TYPE(138), 3154 + UNKNOWN_TYPE(139), 3155 + UNKNOWN_TYPE(140), 3156 + UNKNOWN_TYPE(141), 3157 + UNKNOWN_TYPE(142), 3158 + UNKNOWN_TYPE(143), 3159 + UNKNOWN_TYPE(144), 3160 + UNKNOWN_TYPE(145), 3161 + UNKNOWN_TYPE(146), 3162 + UNKNOWN_TYPE(147), 3163 + UNKNOWN_TYPE(148), 3164 + UNKNOWN_TYPE(149), 3165 + UNKNOWN_TYPE(150), 3166 + UNKNOWN_TYPE(151), 3167 + UNKNOWN_TYPE(152), 3168 + UNKNOWN_TYPE(153), 3169 + UNKNOWN_TYPE(154), 3170 + UNKNOWN_TYPE(155), 3171 + UNKNOWN_TYPE(156), 3172 + UNKNOWN_TYPE(157), 3173 + UNKNOWN_TYPE(158), 3174 + UNKNOWN_TYPE(159), 3175 + UNKNOWN_TYPE(160), 3176 + UNKNOWN_TYPE(161), 3177 + UNKNOWN_TYPE(162), 3178 + UNKNOWN_TYPE(163), 3179 + UNKNOWN_TYPE(164), 3180 + UNKNOWN_TYPE(165), 3181 + UNKNOWN_TYPE(166), 3182 + UNKNOWN_TYPE(167), 3183 + UNKNOWN_TYPE(168), 3184 + UNKNOWN_TYPE(169), 3185 + UNKNOWN_TYPE(170), 3186 + UNKNOWN_TYPE(171), 3187 + UNKNOWN_TYPE(172), 3188 + UNKNOWN_TYPE(173), 3189 + UNKNOWN_TYPE(174), 3190 + UNKNOWN_TYPE(175), 3191 + UNKNOWN_TYPE(176), 3192 + UNKNOWN_TYPE(177), 3193 + UNKNOWN_TYPE(178), 3194 + UNKNOWN_TYPE(179), 3195 + UNKNOWN_TYPE(180), 3196 + UNKNOWN_TYPE(181), 3197 + UNKNOWN_TYPE(182), 3198 + UNKNOWN_TYPE(183), 3199 + UNKNOWN_TYPE(184), 3200 + UNKNOWN_TYPE(185), 3201 + UNKNOWN_TYPE(186), 3202 + UNKNOWN_TYPE(187), 3203 + UNKNOWN_TYPE(188), 3204 + UNKNOWN_TYPE(189), 3205 + UNKNOWN_TYPE(190), 3206 + UNKNOWN_TYPE(191), 3207 + UNKNOWN_TYPE(192), 3208 + UNKNOWN_TYPE(193), 3209 + UNKNOWN_TYPE(194), 3210 + UNKNOWN_TYPE(195), 3211 + UNKNOWN_TYPE(196), 3212 + UNKNOWN_TYPE(197), 3213 + UNKNOWN_TYPE(198), 3214 + UNKNOWN_TYPE(199), 3215 + UNKNOWN_TYPE(200), 3216 + UNKNOWN_TYPE(201), 3217 + UNKNOWN_TYPE(202), 3218 + UNKNOWN_TYPE(203), 3219 + UNKNOWN_TYPE(204), 3220 + UNKNOWN_TYPE(205), 3221 + UNKNOWN_TYPE(206), 3222 + UNKNOWN_TYPE(207), 3223 + UNKNOWN_TYPE(208), 3224 + UNKNOWN_TYPE(209), 3225 + UNKNOWN_TYPE(210), 3226 + UNKNOWN_TYPE(211), 3227 + UNKNOWN_TYPE(212), 3228 + UNKNOWN_TYPE(213), 3229 + UNKNOWN_TYPE(214), 3230 + UNKNOWN_TYPE(215), 3231 + UNKNOWN_TYPE(216), 3232 + UNKNOWN_TYPE(217), 3233 + UNKNOWN_TYPE(218), 3234 + UNKNOWN_TYPE(219), 3235 + UNKNOWN_TYPE(220), 3236 + UNKNOWN_TYPE(221), 3237 + UNKNOWN_TYPE(222), 3238 + UNKNOWN_TYPE(223), 3239 + UNKNOWN_TYPE(224), 3240 + UNKNOWN_TYPE(225), 3241 + UNKNOWN_TYPE(226), 3242 + UNKNOWN_TYPE(227), 3243 + UNKNOWN_TYPE(228), 3244 + UNKNOWN_TYPE(229), 3245 + UNKNOWN_TYPE(230), 3246 + UNKNOWN_TYPE(231), 3247 + UNKNOWN_TYPE(232), 3248 + UNKNOWN_TYPE(233), 3249 + UNKNOWN_TYPE(234), 3250 + UNKNOWN_TYPE(235), 3251 + UNKNOWN_TYPE(236), 3252 + UNKNOWN_TYPE(237), 3253 + UNKNOWN_TYPE(238), 3254 + UNKNOWN_TYPE(239), 3255 + UNKNOWN_TYPE(240), 3256 + UNKNOWN_TYPE(241), 3257 + UNKNOWN_TYPE(242), 3258 + UNKNOWN_TYPE(243), 3259 + UNKNOWN_TYPE(244), 3260 + UNKNOWN_TYPE(245), 3261 + UNKNOWN_TYPE(246), 3262 + UNKNOWN_TYPE(247), 3263 + UNKNOWN_TYPE(248), 3264 + UNKNOWN_TYPE(249), 3265 + UNKNOWN_TYPE(250), 3266 + UNKNOWN_TYPE(251), 3267 + UNKNOWN_TYPE(252), 3268 + UNKNOWN_TYPE(253), 3269 + UNKNOWN_TYPE(254), 3270 + UNKNOWN_TYPE(255), 3271 + 3272 + TYPE("URI", ZONE_TYPE_URI, ZONE_CLASS_ANY, FIELDS(uri_rdata_fields), 3273 + check_uri_rr, parse_uri_rdata), 3274 + TYPE("CAA", ZONE_TYPE_CAA, ZONE_CLASS_ANY, FIELDS(caa_rdata_fields), 3275 + check_caa_rr, parse_caa_rdata), 3276 + TYPE("AVC", ZONE_TYPE_AVC, ZONE_CLASS_ANY, FIELDS(avc_rdata_fields), 3277 + check_txt_rr, parse_txt_rdata), 3278 + 3279 + UNKNOWN_TYPE(259), 3280 + UNKNOWN_TYPE(260), 3281 + 3282 + TYPE("RESINFO", ZONE_TYPE_RESINFO, ZONE_CLASS_ANY, FIELDS(resinfo_rdata_fields), 3283 + check_txt_rr, parse_txt_rdata), 3284 + TYPE("WALLET", ZONE_TYPE_WALLET, ZONE_CLASS_ANY, FIELDS(wallet_rdata_fields), 3285 + check_txt_rr, parse_txt_rdata), 3286 + TYPE("CLA", ZONE_TYPE_CLA, ZONE_CLASS_ANY, FIELDS(cla_rdata_fields), 3287 + check_txt_rr, parse_txt_rdata), 3288 + 3289 + UNKNOWN_TYPE(264), 3290 + 3291 + /* Map 32768 in hash.c to 265 */ 3292 + TYPE("TA", ZONE_TYPE_TA, ZONE_CLASS_ANY, FIELDS(ta_rdata_fields), // obsolete 3293 + check_ds_rr, parse_ds_rdata), 3294 + /* Map 32769 in hash.c to 266 */ 3295 + TYPE("DLV", ZONE_TYPE_DLV, ZONE_CLASS_ANY, FIELDS(dlv_rdata_fields), // obsolete 3296 + check_ds_rr, parse_ds_rdata) 3297 + }; 3298 + 3299 + #undef UNKNOWN_CLASS 3300 + #undef CLASS 3301 + #undef UNKNOWN_TYPE 3302 + #undef TYPE 3303 + 3304 + diagnostic_pop() 3305 + 3306 + #endif // TYPES_H
+254
usr.sbin/nsd/simdzone/src/generic/wks.h
··· 1 + /* 2 + * wks.c -- Well-Known Services (WKS) RDATA parser 3 + * 4 + * Copyright (c) 2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef WKS_H 10 + #define WKS_H 11 + 12 + // RFC1035 section 3.4.2: 13 + // The purpose of WKS RRs is to provide availability information for servers 14 + // for TCP and UDP. 15 + // 16 + // NSD and BIND use getprotobyname, which reads /etc/protocols (optimizations 17 + // may be in place for TCP and UDP). Note that BIND passes the protocol to 18 + // getservbyname for TCP and UDP only, NULL otherwise, which means any 19 + // protocol matches. Unfortunately, getprotobyname is NOT thread-safe. 20 + // getprotobyname_r exist on most BSDs and Linux, but not Windows. 21 + // The list of known protocols and services also differs between operating 22 + // systems and no list covers all IANA (links below) registered protocols 23 + // and services, which may cause compatibility issues. Furthermore, even 24 + // getprotobyname_r and getservbyname_r are marked locale, meaning the locale 25 + // object is read without any form of synchronization, which may be an issue 26 + // for a library. 27 + // 28 + // https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml 29 + // https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml 30 + // 31 + // https://www.gnu.org/software/libc/manual/html_node/Protocols-Database.html 32 + // https://www.gnu.org/software/libc/manual/html_node/Services-Database.html 33 + // https://www.gnu.org/software/libc/manual/html_node/POSIX-Safety-Concepts.html 34 + // https://www.gnu.org/software/libc/manual/html_node/Other-Safety-Remarks.html 35 + // 36 + // WKS RRs are rarely used and a document to deprecate the RRTYPE (among 37 + // others) has been drafted (WKS removed from the second draft). 38 + // 39 + // https://datatracker.ietf.org/doc/html/draft-sury-deprecate-obsolete-resource-records-00 40 + // https://mailarchive.ietf.org/arch/msg/dnsop/YCVvXuM8HbJLF2SoXyDqyOGao34/ 41 + // 42 + // 43 + // WKS RRs have been said to be deprecated in an informational document (NOT 44 + // a standard), although it wrongly claims WKS RRs are in fact deprecated. 45 + // 46 + // RFC1912 section 2.6.1 (informational): 47 + // WKS records are deprecated in [RFC 1123]. They serve no known useful 48 + // function, except internally among LISP machines. Don't use them. 49 + // 50 + // https://datatracker.ietf.org/doc/html/rfc1912 51 + // 52 + // RFC1123 section 2.2 (standard): 53 + // An application SHOULD NOT rely on the ability to locate a WKS record 54 + // containing an accurate listing of all services at a particular host 55 + // address, since the WKS RR type is not often used by Internet sites. 56 + // To confirm that a service is present, simply attempt to use it. 57 + // 58 + // https://datatracker.ietf.org/doc/html/rfc1123 59 + // 60 + // RFC1127 section 2 (informational): 61 + // WKS Records Detracted [AS 2.2, 5.2.12, 6.1.3.6] 62 + // Recommend against using WKS records from DNS. 63 + // 64 + // https://datatracker.ietf.org/doc/html/rfc1127 65 + // 66 + // 67 + // Rather than supporting any protocol registered by IANA, support a small 68 + // subset of mnemonics (TCP and UDP) as well as numeric values and add 69 + // support (or remove it entirely) for additional protocols on demand. 70 + 71 + #if BYTE_ORDER == LITTLE_ENDIAN 72 + # define TCP (0x0000000000706374llu) 73 + # define UDP (0x0000000000706475llu) 74 + #elif BYTE_ORDER == BIG_ENDIAN 75 + # define TCP (0x7463700000000000llu) 76 + # define UDP (0x7564700000000000llu) 77 + #else 78 + # error "byte order unknown" 79 + #endif 80 + 81 + static really_inline int32_t scan_protocol( 82 + const char *name, size_t length, uint8_t *protocol) 83 + { 84 + static const int8_t zero_masks[48] = { 85 + -1, -1, -1, -1, -1, -1, -1, -1, 86 + -1, -1, -1, -1, -1, -1, -1, -1, 87 + -1, -1, -1, -1, -1, -1, -1, -1, 88 + -1, -1, -1, -1, -1, -1, -1, -1, 89 + 0, 0, 0, 0, 0, 0, 0, 0, 90 + 0, 0, 0, 0, 0, 0, 0, 0 91 + }; 92 + 93 + uint64_t key; 94 + uint64_t mask; 95 + const int8_t *zero_mask = &zero_masks[32 - (length & 0x1f)]; 96 + memcpy(&mask, zero_mask, 8); 97 + 98 + memcpy(&key, name, sizeof(key)); // safe, input is padded 99 + key |= (key & 0x4040404040404040) >> 1; // convert to lower case 100 + key &= mask; 101 + 102 + if (key == TCP) 103 + return (void)(*protocol = 6), 1; 104 + else if (key == UDP) 105 + return (void)(*protocol = 17), 1; 106 + else 107 + return scan_int8(name, length, protocol); 108 + } 109 + 110 + typedef struct service service_t; 111 + struct service { 112 + struct { 113 + const char name[16]; 114 + size_t length; 115 + } key; 116 + uint16_t port; 117 + }; 118 + 119 + #define UNKNOWN_SERVICE() { { "", 0 }, 0 } 120 + #define SERVICE(name, port) { { name, sizeof(name) - 1 }, port } 121 + 122 + static const service_t services[64] = { 123 + UNKNOWN_SERVICE(), 124 + SERVICE("snmptrap", 162), 125 + SERVICE("pop3s", 995), 126 + SERVICE("pop3", 110), 127 + SERVICE("ldaps", 636), 128 + SERVICE("domain", 53), 129 + SERVICE("nntps", 563), 130 + SERVICE("nntp", 119), 131 + UNKNOWN_SERVICE(), 132 + UNKNOWN_SERVICE(), 133 + UNKNOWN_SERVICE(), 134 + UNKNOWN_SERVICE(), 135 + SERVICE("ftps-data", 989), 136 + UNKNOWN_SERVICE(), 137 + UNKNOWN_SERVICE(), 138 + SERVICE("imaps", 993), 139 + SERVICE("imap", 143), 140 + SERVICE("time", 37), 141 + UNKNOWN_SERVICE(), 142 + UNKNOWN_SERVICE(), 143 + SERVICE("kerberos", 88), 144 + UNKNOWN_SERVICE(), 145 + UNKNOWN_SERVICE(), 146 + SERVICE("ftp", 21), 147 + SERVICE("ntp", 123), 148 + SERVICE("whoispp", 63), 149 + SERVICE("ssh", 22), 150 + UNKNOWN_SERVICE(), 151 + SERVICE("nicname", 43), 152 + UNKNOWN_SERVICE(), 153 + UNKNOWN_SERVICE(), 154 + UNKNOWN_SERVICE(), 155 + SERVICE("ptp-general", 320), 156 + UNKNOWN_SERVICE(), 157 + UNKNOWN_SERVICE(), 158 + SERVICE("domain-s", 853), 159 + SERVICE("ftp-data", 20), 160 + SERVICE("ftps", 990), 161 + UNKNOWN_SERVICE(), 162 + UNKNOWN_SERVICE(), 163 + SERVICE("snmp", 161), 164 + UNKNOWN_SERVICE(), 165 + UNKNOWN_SERVICE(), 166 + UNKNOWN_SERVICE(), 167 + UNKNOWN_SERVICE(), 168 + SERVICE("bgmp", 264), 169 + SERVICE("echo", 7), 170 + UNKNOWN_SERVICE(), 171 + SERVICE("nnsp", 433), 172 + SERVICE("submission", 587), 173 + // submissions cannot be distinguished from submission by hash value because 174 + // the shared prefix is too long. include length to generate a unique key 175 + SERVICE("submissions", 465), 176 + UNKNOWN_SERVICE(), 177 + SERVICE("ptp-event", 319), 178 + UNKNOWN_SERVICE(), 179 + SERVICE("npp", 92), 180 + UNKNOWN_SERVICE(), 181 + SERVICE("https", 443), 182 + SERVICE("http", 80), 183 + UNKNOWN_SERVICE(), 184 + SERVICE("telnet", 23), 185 + SERVICE("tcpmux", 1), 186 + UNKNOWN_SERVICE(), 187 + SERVICE("lmtp", 24), 188 + SERVICE("smtp", 25) 189 + }; 190 + 191 + #undef SERVICE 192 + #undef UNKNOWN_SERVICE 193 + 194 + // magic (139898079) generated using wks-hash.c 195 + static really_inline uint8_t service_hash(uint64_t input, size_t length) 196 + { 197 + // le64toh is required for big endian, no-op on little endian 198 + input = le64toh(input); 199 + uint32_t input32 = (uint32_t)((input >> 32) ^ input); 200 + return (((input32 * 139898079llu) >> 32) + length) & 0x3f; 201 + } 202 + 203 + nonnull((1,4)) 204 + static really_inline int32_t scan_service( 205 + const char *data, size_t length, int32_t protocol, uint16_t *port) 206 + { 207 + uint8_t digit = (uint8_t)*data - '0'; 208 + static const int8_t zero_masks[48] = { 209 + -1, -1, -1, -1, -1, -1, -1, -1, 210 + -1, -1, -1, -1, -1, -1, -1, -1, 211 + -1, -1, -1, -1, -1, -1, -1, -1, 212 + -1, -1, -1, -1, -1, -1, -1, -1, 213 + 0, 0, 0, 0, 0, 0, 0, 0, 214 + 0, 0, 0, 0, 0, 0, 0, 0 215 + }; 216 + 217 + (void)protocol; // all supported services map to tcp and udp 218 + 219 + if (digit > 9) { 220 + uint64_t input0, input1; 221 + static const uint64_t upper_mask = 0xdfdfdfdfdfdfdfdfllu; 222 + static const uint64_t letter_mask = 0x4040404040404040llu; 223 + memcpy(&input0, data, 8); 224 + memcpy(&input1, data+8, 8); 225 + // convert to upper case, unconditionally transforms digits (0x30-0x39) 226 + // and dash (0x2d), but does not introduce clashes 227 + uint64_t key = input0 & upper_mask; 228 + // zero out non-relevant bytes 229 + uint64_t zero_mask0, zero_mask1; 230 + const int8_t *zero_mask = &zero_masks[32 - (length & 0xf)]; 231 + memcpy(&zero_mask0, zero_mask, 8); 232 + memcpy(&zero_mask1, zero_mask+8, 8); 233 + uint8_t index = service_hash(key & zero_mask0, length); 234 + assert(index < 64); 235 + 236 + input0 |= (input0 & letter_mask) >> 1; 237 + input0 &= zero_mask0; 238 + input1 |= (input1 & letter_mask) >> 1; 239 + input1 &= zero_mask1; 240 + 241 + uint64_t name0, name1; 242 + memcpy(&name0, services[index].key.name, 8); 243 + memcpy(&name1, services[index].key.name+8, 8); 244 + 245 + *port = services[index].port; 246 + return (input0 == name0) & 247 + (input1 == name1) & 248 + (services[index].key.length == length); 249 + } 250 + 251 + return scan_int16(data, length, port); 252 + } 253 + 254 + #endif // WKS_H
+97
usr.sbin/nsd/simdzone/src/haswell/base32.h
··· 1 + /* 2 + * base32.h -- Fast Base32 decoder 3 + * 4 + * Copyright (c) 2023, Daniel Lemire and @aqrit. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef BASE32_H 10 + #define BASE32_H 11 + 12 + #include <stdint.h> 13 + 14 + ////////////////////////// 15 + /// Source: Wojciech Muła, Daniel Lemire, Faster Base64 Encoding and Decoding Using AVX2 Instructions, 16 + /// ACM Transactions on the Web 12 (3), 2018 17 + /// https://arxiv.org/abs/1704.00605 18 + ////////////////////////// 19 + 20 + static size_t base32hex_avx(uint8_t *dst, const uint8_t *src) { 21 + static int8_t zero_masks256[64] = { 22 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; 26 + bool valid = true; 27 + const __m256i delta_check = _mm256_setr_epi8( 28 + -16, -32, -48, 70, -65, 41, -97, 9, 0, 0, 0, 0, 0, 0, 0, 0, -16, -32, -48, 29 + 70, -65, 41, -97, 9, 0, 0, 0, 0, 0, 0, 0, 0); 30 + const __m256i delta_rebase = _mm256_setr_epi8( 31 + 0, 0, 0, -48, -55, -55, -87, -87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -48, 32 + -55, -55, -87, -87, 0, 0, 0, 0, 0, 0, 0, 0); 33 + const uint8_t *srcinit = src; 34 + do { 35 + __m256i v = _mm256_loadu_si256((__m256i *)src); 36 + 37 + __m256i hash_key = 38 + _mm256_and_si256(_mm256_srli_epi32(v, 4), _mm256_set1_epi8(0x0F)); 39 + __m256i check = 40 + _mm256_add_epi8(_mm256_shuffle_epi8(delta_check, hash_key), v); 41 + v = _mm256_add_epi8(v, _mm256_shuffle_epi8(delta_rebase, hash_key)); 42 + unsigned int m = (unsigned)_mm256_movemask_epi8(check); 43 + 44 + if (m) { 45 + int length = (int)trailing_zeroes(m); 46 + if (length == 0) { 47 + break; 48 + } 49 + src += length; 50 + __m256i zero_mask = 51 + _mm256_loadu_si256((__m256i *)(zero_masks256 + 32 - length)); 52 + v = _mm256_andnot_si256(zero_mask, v); 53 + valid = false; 54 + } else { // common case 55 + src += 32; 56 + } 57 + v = _mm256_maddubs_epi16(v, _mm256_set1_epi32(0x01200120)); 58 + v = _mm256_madd_epi16( 59 + v, _mm256_set_epi32(0x00010400, 0x00104000, 0x00010400, 0x00104000, 60 + 0x00010400, 0x00104000, 0x00010400, 0x00104000)); 61 + // ...00000000`0000eeee`efffffgg`ggghhhhh`00000000`aaaaabbb`bbcccccd`dddd0000 62 + v = _mm256_or_si256(v, _mm256_srli_epi64(v, 48)); 63 + v = _mm256_shuffle_epi8( 64 + v, _mm256_set_epi8(0, 0, 0, 0, 0, 0, 12, 13, 8, 9, 10, 4, 5, 0, 1, 2, 0, 65 + 0, 0, 0, 0, 0, 12, 13, 8, 9, 10, 4, 5, 0, 1, 2)); 66 + // 5. store bytes 67 + _mm_storeu_si128((__m128i *)dst, _mm256_castsi256_si128(v)); 68 + dst += 10; 69 + _mm_storeu_si128((__m128i *)dst, _mm256_extractf128_si256(v, 1)); 70 + dst += 10; 71 + 72 + } while (valid); 73 + 74 + return (size_t)(src - srcinit); 75 + } 76 + 77 + nonnull_all 78 + static really_inline int32_t parse_base32( 79 + parser_t *parser, 80 + const type_info_t *type, 81 + const rdata_info_t *field, 82 + rdata_t *rdata, 83 + const token_t *token) 84 + { 85 + size_t length = (token->length * 5) / 8; 86 + if (length > 255 || (uintptr_t)rdata->limit - (uintptr_t)rdata->octets < (length + 1)) 87 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 88 + 89 + size_t decoded = base32hex_avx(rdata->octets+1, (const uint8_t*)token->data); 90 + if (decoded != token->length) 91 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 92 + *rdata->octets = (uint8_t)length; 93 + rdata->octets += 1 + length; 94 + return 0; 95 + } 96 + 97 + #endif // BASE32_H
+34
usr.sbin/nsd/simdzone/src/haswell/bench.c
··· 1 + /* 2 + * bench.c -- AVX2 compilation target for benchmark function(s) 3 + * 4 + * Copyright (c) 2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #include "zone.h" 10 + #include "attributes.h" 11 + #include "diagnostic.h" 12 + #include "haswell/simd.h" 13 + #include "haswell/bits.h" 14 + #include "generic/parser.h" 15 + #include "generic/scanner.h" 16 + 17 + diagnostic_push() 18 + clang_diagnostic_ignored(missing-prototypes) 19 + 20 + int32_t zone_bench_haswell_lex(zone_parser_t *parser, size_t *tokens) 21 + { 22 + token_t token; 23 + 24 + (*tokens) = 0; 25 + take(parser, &token); 26 + while (token.code > 0) { 27 + (*tokens)++; 28 + take(parser, &token); 29 + } 30 + 31 + return token.code ? -1 : 0; 32 + } 33 + 34 + diagnostic_pop()
+61
usr.sbin/nsd/simdzone/src/haswell/bits.h
··· 1 + /* 2 + * bits.h -- Haswell specific implementation of bit manipulation instructions 3 + * 4 + * Copyright (c) 2018-2023 The simdjson authors 5 + * Copyright (c) 2023, NLnet Labs. All rights reserved. 6 + * 7 + * SPDX-License-Identifier: BSD-3-Clause 8 + */ 9 + #ifndef BITS_H 10 + #define BITS_H 11 + 12 + #include <stdbool.h> 13 + #include <stdint.h> 14 + #include <immintrin.h> 15 + 16 + static inline bool add_overflow(uint64_t value1, uint64_t value2, uint64_t *result) { 17 + #if has_builtin(__builtin_uaddll_overflow) 18 + return __builtin_uaddll_overflow(value1, value2, (unsigned long long *)result); 19 + #else 20 + *result = value1 + value2; 21 + return *result < value1; 22 + #endif 23 + } 24 + 25 + static inline uint64_t count_ones(uint64_t bits) { 26 + return (uint64_t)_mm_popcnt_u64(bits); 27 + } 28 + 29 + no_sanitize_undefined 30 + static inline uint64_t trailing_zeroes(uint64_t bits) { 31 + return (uint64_t)_tzcnt_u64(bits); 32 + } 33 + 34 + // result might be undefined when bits is zero 35 + static inline uint64_t clear_lowest_bit(uint64_t bits) { 36 + return bits & (bits - 1); 37 + } 38 + 39 + static inline uint64_t leading_zeroes(uint64_t bits) { 40 + return (uint64_t)_lzcnt_u64(bits); 41 + } 42 + 43 + static inline uint64_t prefix_xor(const uint64_t bitmask) { 44 + __m128i all_ones = _mm_set1_epi8('\xFF'); 45 + __m128i mask = _mm_set_epi64x(0ULL, (long long)bitmask); 46 + #if defined __SUNPRO_C 47 + // Oracle Developer Studio has issues generating vpclmulqdq 48 + // Oracle Solaris and Intel assembler use the opposite order for source and 49 + // destination operands. See x86 Assemble Language Reference Manual. 50 + __asm volatile ("vpclmulqdq $0,%[all_ones],%[mask],%[mask]" 51 + : [mask] "+x" (mask) 52 + : [all_ones] "x" (all_ones)); 53 + #else 54 + // There should be no such thing with a processor supporting avx2 55 + // but not clmul. 56 + mask = _mm_clmulepi64_si128(mask, all_ones, 0); 57 + #endif 58 + return (uint64_t)_mm_cvtsi128_si64(mask); 59 + } 60 + 61 + #endif // BITS_H
+52
usr.sbin/nsd/simdzone/src/haswell/parser.c
··· 1 + /* 2 + * parser.c -- AVX2 specific compilation target for (DNS) zone file parser 3 + * 4 + * Copyright (c) 2022, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause. 7 + * 8 + */ 9 + #include "zone.h" 10 + #include "attributes.h" 11 + #include "diagnostic.h" 12 + #include "haswell/simd.h" 13 + #include "generic/endian.h" 14 + #include "haswell/bits.h" 15 + #include "generic/parser.h" 16 + #include "generic/scanner.h" 17 + #include "generic/number.h" 18 + #include "generic/ttl.h" 19 + #include "westmere/time.h" 20 + #include "westmere/ip4.h" 21 + #include "generic/ip6.h" 22 + #include "generic/text.h" 23 + #include "generic/name.h" 24 + #include "generic/base16.h" 25 + #include "haswell/base32.h" 26 + #include "generic/base64.h" 27 + #include "generic/nsec.h" 28 + #include "generic/nxt.h" 29 + #include "generic/caa.h" 30 + #include "generic/ilnp64.h" 31 + #include "generic/eui.h" 32 + #include "generic/nsap.h" 33 + #include "generic/wks.h" 34 + #include "generic/loc.h" 35 + #include "generic/gpos.h" 36 + #include "generic/apl.h" 37 + #include "generic/svcb.h" 38 + #include "generic/cert.h" 39 + #include "generic/algorithm.h" 40 + #include "generic/types.h" 41 + #include "westmere/type.h" 42 + #include "generic/format.h" 43 + 44 + diagnostic_push() 45 + clang_diagnostic_ignored(missing-prototypes) 46 + 47 + int32_t zone_haswell_parse(parser_t *parser) 48 + { 49 + return parse(parser); 50 + } 51 + 52 + diagnostic_pop()
+123
usr.sbin/nsd/simdzone/src/haswell/simd.h
··· 1 + /* 2 + * haswell.h -- SIMD abstractions targeting AVX2 3 + * 4 + * Copyright (c) 2022, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + */ 8 + #ifndef SIMD_H 9 + #define SIMD_H 10 + 11 + #include <stdint.h> 12 + #include <immintrin.h> 13 + 14 + #define SIMD_8X_SIZE (32) 15 + 16 + typedef uint8_t simd_table_t[SIMD_8X_SIZE]; 17 + 18 + #define SIMD_TABLE(v00, v01, v02, v03, v04, v05, v06, v07, \ 19 + v08, v09, v0a, v0b, v0c, v0d, v0e, v0f) \ 20 + { \ 21 + v00, v01, v02, v03, v04, v05, v06, v07, \ 22 + v08, v09, v0a, v0b, v0c, v0d, v0e, v0f, \ 23 + v00, v01, v02, v03, v04, v05, v06, v07, \ 24 + v08, v09, v0a, v0b, v0c, v0d, v0e, v0f \ 25 + } 26 + 27 + typedef struct { __m256i chunks[1]; } simd_8x_t; 28 + 29 + typedef struct { __m128i chunks[1]; } simd_8x16_t; 30 + 31 + typedef simd_8x_t simd_8x32_t; 32 + 33 + typedef struct { __m256i chunks[2]; } simd_8x64_t; 34 + 35 + 36 + nonnull_all 37 + static really_inline void simd_loadu_8x(simd_8x_t *simd, const void *address) 38 + { 39 + simd->chunks[0] = _mm256_loadu_si256((const __m256i *)(address)); 40 + } 41 + 42 + nonnull_all 43 + static really_inline void simd_storeu_8x(void *address, simd_8x_t *simd) 44 + { 45 + _mm256_storeu_si256((__m256i *)address, simd->chunks[0]); 46 + } 47 + 48 + nonnull_all 49 + static really_inline uint64_t simd_find_8x(const simd_8x_t *simd, char key) 50 + { 51 + const __m256i k = _mm256_set1_epi8(key); 52 + const __m256i r = _mm256_cmpeq_epi8(simd->chunks[0], k); 53 + return (uint32_t)_mm256_movemask_epi8(r); 54 + } 55 + 56 + nonnull_all 57 + static really_inline uint64_t simd_find_any_8x( 58 + const simd_8x_t *simd, const simd_table_t table) 59 + { 60 + const __m256i t = _mm256_loadu_si256((const __m256i *)table); 61 + const __m256i r = _mm256_cmpeq_epi8( 62 + _mm256_shuffle_epi8(t, simd->chunks[0]), simd->chunks[0]); 63 + return (uint32_t)_mm256_movemask_epi8(r); 64 + } 65 + 66 + nonnull_all 67 + static really_inline void simd_loadu_8x16(simd_8x16_t *simd, const uint8_t *address) 68 + { 69 + simd->chunks[0] = _mm_loadu_si128((const __m128i *)address); 70 + } 71 + 72 + nonnull_all 73 + static really_inline uint64_t simd_find_8x16(const simd_8x16_t *simd, char key) 74 + { 75 + const __m128i k = _mm_set1_epi8(key); 76 + const __m128i r = _mm_cmpeq_epi8(simd->chunks[0], k); 77 + const uint64_t m = (uint16_t)_mm_movemask_epi8(r); 78 + return m; 79 + } 80 + 81 + #define simd_loadu_8x32(simd, address) simd_loadu_8x(simd, address) 82 + #define simd_storeu_8x32(address, simd) simd_storeu_8x(address, simd) 83 + #define simd_find_8x32(simd, key) simd_find_8x(simd, key) 84 + 85 + nonnull_all 86 + static really_inline void simd_loadu_8x64(simd_8x64_t *simd, const uint8_t *address) 87 + { 88 + simd->chunks[0] = _mm256_loadu_si256((const __m256i *)(address)); 89 + simd->chunks[1] = _mm256_loadu_si256((const __m256i *)(address+32)); 90 + } 91 + 92 + nonnull_all 93 + static really_inline uint64_t simd_find_8x64(const simd_8x64_t *simd, char key) 94 + { 95 + const __m256i k = _mm256_set1_epi8(key); 96 + 97 + const __m256i r0 = _mm256_cmpeq_epi8(simd->chunks[0], k); 98 + const __m256i r1 = _mm256_cmpeq_epi8(simd->chunks[1], k); 99 + 100 + const uint64_t m0 = (uint32_t)_mm256_movemask_epi8(r0); 101 + const uint64_t m1 = (uint32_t)_mm256_movemask_epi8(r1); 102 + 103 + return m0 | (m1 << 32); 104 + } 105 + 106 + nonnull_all 107 + static really_inline uint64_t simd_find_any_8x64( 108 + const simd_8x64_t *simd, const simd_table_t table) 109 + { 110 + const __m256i t = _mm256_loadu_si256((const __m256i *)table); 111 + 112 + const __m256i r0 = _mm256_cmpeq_epi8( 113 + _mm256_shuffle_epi8(t, simd->chunks[0]), simd->chunks[0]); 114 + const __m256i r1 = _mm256_cmpeq_epi8( 115 + _mm256_shuffle_epi8(t, simd->chunks[1]), simd->chunks[1]); 116 + 117 + const uint64_t m0 = (uint32_t)_mm256_movemask_epi8(r0); 118 + const uint64_t m1 = (uint32_t)_mm256_movemask_epi8(r1); 119 + 120 + return m0 | (m1 << 32); 121 + } 122 + 123 + #endif // SIMD_H
+269
usr.sbin/nsd/simdzone/src/isadetection.h
··· 1 + /* 2 + * isadetection.h -- detect supported instruction set(s) 3 + * 4 + * Slightly modified version of isadetection.h in simdjson. 5 + * 6 + * Copyright (c) 2024 NLnet Labs (Jeroen Koekkoek) 7 + * Copyright (c) 2020- simdjson (Daniel Lemire, 8 + * Geoff Langdale, 9 + * John Keiser) 10 + * Copyright (c) 2016- Facebook, Inc (Adam Paszke) 11 + * Copyright (c) 2014- Facebook, Inc (Soumith Chintala) 12 + * Copyright (c) 2011-2014 Idiap Research Institute (Ronan Collobert) 13 + * Copyright (c) 2012-2014 Deepmind Technologies (Koray Kavukcuoglu) 14 + * Copyright (c) 2011-2012 NEC Laboratories America (Koray Kavukcuoglu) 15 + * Copyright (c) 2011-2013 NYU (Clement Farabet) 16 + * Copyright (c) 2006-2010 NEC Laboratories America (Ronan Collobert, 17 + * Leon Bottou, 18 + * Iain Melvin, 19 + * Jason Weston) 20 + * Copyright (c) 2006 Idiap Research Institute (Samy Bengio) 21 + * Copyright (c) 2001-2004 Idiap Research Institute (Ronan Collobert, 22 + * Samy Bengio, 23 + * Johnny Mariethoz) 24 + * 25 + * All rights reserved. 26 + * 27 + * Redistribution and use in source and binary forms, with or without 28 + * modification, are permitted provided that the following conditions are met: 29 + * 30 + * 1. Redistributions of source code must retain the above copyright 31 + * notice, this list of conditions and the following disclaimer. 32 + * 33 + * 2. Redistributions in binary form must reproduce the above copyright 34 + * notice, this list of conditions and the following disclaimer in the 35 + * documentation and/or other materials provided with the distribution. 36 + * 37 + * 3. Neither the names of simdjson, Facebook, Deepmind Technologies, NYU, 38 + * NEC Laboratories America and IDIAP Research Institute nor the names of 39 + * its contributors may be used to endorse or promote products derived from 40 + * this software without specific prior written permission. 41 + * 42 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 43 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 44 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 45 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 46 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 47 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 48 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 49 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 50 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 51 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 52 + * POSSIBILITY OF SUCH DAMAGE. 53 + */ 54 + 55 + #ifndef ISADETECTION_H 56 + #define ISADETECTION_H 57 + 58 + #include <stdbool.h> 59 + #include <stdint.h> 60 + #include <stdlib.h> 61 + #if defined(_MSC_VER) 62 + #include <intrin.h> 63 + #include <immintrin.h> 64 + #elif defined(HAVE_CPUID) 65 + #include <cpuid.h> 66 + #endif 67 + 68 + enum instruction_set { 69 + DEFAULT = 0x0, 70 + NEON = 0x1, 71 + AVX2 = 0x4, 72 + SSE42 = 0x8, 73 + PCLMULQDQ = 0x10, 74 + BMI1 = 0x20, 75 + BMI2 = 0x40, 76 + ALTIVEC = 0x80, 77 + AVX512F = 0x100, 78 + AVX512DQ = 0x200, 79 + AVX512IFMA = 0x400, 80 + AVX512PF = 0x800, 81 + AVX512ER = 0x1000, 82 + AVX512CD = 0x2000, 83 + AVX512BW = 0x4000, 84 + AVX512VL = 0x8000, 85 + AVX512VBMI2 = 0x10000 86 + }; 87 + 88 + #if defined(__PPC64__) 89 + 90 + static inline uint32_t detect_supported_architectures() { 91 + return ALTIVEC; 92 + } 93 + 94 + #elif defined(__arm__) || defined(__aarch64__) // incl. armel, armhf, arm64 95 + 96 + #if defined(__ARM_NEON) 97 + 98 + static inline uint32_t detect_supported_architectures() { 99 + return NEON; 100 + } 101 + 102 + #else // ARM without NEON 103 + 104 + static inline uint32_t detect_supported_architectures() { 105 + return DEFAULT; 106 + } 107 + 108 + #endif 109 + 110 + #elif defined(__x86_64__) || defined(_M_AMD64) // x64 111 + 112 + // Can be found on Intel ISA Reference for CPUID 113 + static const uint32_t cpuid_avx2_bit = 1 << 5; ///< @private Bit 5 of EBX for EAX=0x7 114 + static const uint32_t cpuid_bmi1_bit = 1 << 3; ///< @private bit 3 of EBX for EAX=0x7 115 + static const uint32_t cpuid_bmi2_bit = 1 << 8; ///< @private bit 8 of EBX for EAX=0x7 116 + static const uint32_t cpuid_avx512f_bit = 1 << 16; ///< @private bit 16 of EBX for EAX=0x7 117 + static const uint32_t cpuid_avx512dq_bit = 1 << 17; ///< @private bit 17 of EBX for EAX=0x7 118 + static const uint32_t cpuid_avx512ifma_bit = 1 << 21; ///< @private bit 21 of EBX for EAX=0x7 119 + static const uint32_t cpuid_avx512pf_bit = 1 << 26; ///< @private bit 26 of EBX for EAX=0x7 120 + static const uint32_t cpuid_avx512er_bit = 1 << 27; ///< @private bit 27 of EBX for EAX=0x7 121 + static const uint32_t cpuid_avx512cd_bit = 1 << 28; ///< @private bit 28 of EBX for EAX=0x7 122 + static const uint32_t cpuid_avx512bw_bit = 1 << 30; ///< @private bit 30 of EBX for EAX=0x7 123 + static const uint32_t cpuid_avx512vl_bit = 1U << 31; ///< @private bit 31 of EBX for EAX=0x7 124 + static const uint32_t cpuid_avx512vbmi2_bit = 1 << 6; ///< @private bit 6 of ECX for EAX=0x7 125 + static const uint32_t cpuid_sse42_bit = 1 << 20; ///< @private bit 20 of ECX for EAX=0x1 126 + static const uint32_t cpuid_pclmulqdq_bit = 1 << 1; ///< @private bit 1 of ECX for EAX=0x1 127 + static const uint32_t cpuid_have_xgetbv_bit = 1 << 27; ///< @private bit 27 of ECX for EAX=0x1 128 + static const uint32_t cpuid_have_avx_bit = 1 << 28; ///< @private bit 28 of ECX for EAX=0x1 129 + 130 + static inline void cpuid( 131 + uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) 132 + { 133 + #if defined(_MSC_VER) 134 + int cpu_info[4]; 135 + __cpuid(cpu_info, *eax); 136 + *eax = cpu_info[0]; 137 + *ebx = cpu_info[1]; 138 + *ecx = cpu_info[2]; 139 + *edx = cpu_info[3]; 140 + #elif defined(HAVE_CPUID) 141 + uint32_t level = *eax; 142 + __get_cpuid(level, eax, ebx, ecx, edx); 143 + #else 144 + uint32_t a = *eax, b, c = *ecx, d; 145 + asm volatile("cpuid\n\t" : "+a"(a), "=b"(b), "+c"(c), "=d"(d)); 146 + *eax = a; 147 + *ebx = b; 148 + *ecx = c; 149 + *edx = d; 150 + #endif 151 + } 152 + 153 + static inline uint64_t xgetbv(uint32_t ecx) 154 + { 155 + #if defined(_MSC_VER) 156 + return _xgetbv(ecx); 157 + #else 158 + uint32_t a, c = ecx, d; 159 + asm volatile("xgetbv\n\t" : "=d"(d), "=a"(a) : "c"(c)); 160 + uint64_t xcr0 = ((uint64_t)d << 32) | (uint64_t)a; 161 + return xcr0; 162 + #endif 163 + } 164 + 165 + static inline uint32_t detect_supported_architectures(void) 166 + { 167 + uint32_t eax, ebx, ecx, edx; 168 + uint32_t host_isa = 0x0, host_avx_isa = 0x0; 169 + 170 + // ECX for EAX=0x7 171 + eax = 0x7; 172 + ecx = 0x0; 173 + cpuid(&eax, &ebx, &ecx, &edx); 174 + if (ebx & cpuid_bmi1_bit) { 175 + host_isa |= BMI1; 176 + } 177 + 178 + if (ebx & cpuid_bmi2_bit) { 179 + host_isa |= BMI2; 180 + } 181 + 182 + if (ebx & cpuid_avx2_bit) { 183 + host_avx_isa |= AVX2; 184 + } 185 + 186 + if (ebx & cpuid_avx512f_bit) { 187 + host_avx_isa |= AVX512F; 188 + } 189 + 190 + if (ebx & cpuid_avx512dq_bit) { 191 + host_avx_isa |= AVX512DQ; 192 + } 193 + 194 + if (ebx & cpuid_avx512ifma_bit) { 195 + host_avx_isa |= AVX512IFMA; 196 + } 197 + 198 + if (ebx & cpuid_avx512pf_bit) { 199 + host_avx_isa |= AVX512PF; 200 + } 201 + 202 + if (ebx & cpuid_avx512er_bit) { 203 + host_avx_isa |= AVX512ER; 204 + } 205 + 206 + if (ebx & cpuid_avx512cd_bit) { 207 + host_avx_isa |= AVX512CD; 208 + } 209 + 210 + if (ebx & cpuid_avx512bw_bit) { 211 + host_avx_isa |= AVX512BW; 212 + } 213 + 214 + if (ebx & cpuid_avx512vl_bit) { 215 + host_avx_isa |= AVX512VL; 216 + } 217 + 218 + if (ecx & cpuid_avx512vbmi2_bit) { 219 + host_avx_isa |= AVX512VBMI2; 220 + } 221 + 222 + bool have_avx = false, have_xgetbv = false; 223 + 224 + // EBX for EAX=0x1 225 + eax = 0x1; 226 + cpuid(&eax, &ebx, &ecx, &edx); 227 + if (ecx & cpuid_sse42_bit) { 228 + host_isa |= SSE42; 229 + } 230 + 231 + if (ecx & cpuid_pclmulqdq_bit) { 232 + host_isa |= PCLMULQDQ; 233 + } 234 + 235 + // Correct detection of AVX2 support requires more than checking the CPUID 236 + // bit. Peter Cordes provides an excellent answer on Stack Overflow 237 + // (https://stackoverflow.com/a/34071400) quoting the article Introduction 238 + // to Intel Advanced Vector Extensions (search Wayback Machine). 239 + // 240 + // 1. Verify that the operating system supports XGETBV using 241 + // CPUID.1:ECX.OSXSAVE bit 27 = 1. 242 + // 2. Verify the processor supports the AVX instruction extensions using: 243 + // CPUID.1:ECX bit 28 = 1. 244 + // 3. Issue XGETBV, and verify that the feature-enabled mask at bits 1 and 2 245 + // are 11b (XMM state and YMM state enabled by the operating system). 246 + 247 + 248 + // Determine if the CPU supports AVX 249 + have_avx = (ecx & cpuid_have_avx_bit) != 0; 250 + // Determine if the Operating System supports XGETBV 251 + have_xgetbv = (ecx & cpuid_have_xgetbv_bit) != 0; 252 + 253 + if (have_avx && have_xgetbv) { 254 + uint64_t xcr0 = xgetbv(0x0); 255 + if ((xcr0 & 0x6) == 0x6) 256 + host_isa |= host_avx_isa; 257 + } 258 + 259 + return host_isa; 260 + } 261 + #else // fallback 262 + 263 + static inline uint32_t detect_supported_architectures() { 264 + return DEFAULT; 265 + } 266 + 267 + #endif // end SIMD extension detection code 268 + 269 + #endif // ISADETECTION_H
+88
usr.sbin/nsd/simdzone/src/westmere/base32.h
··· 1 + /* 2 + * base32.h -- Fast Base32 decoder 3 + * 4 + * Copyright (c) 2023, Daniel Lemire and @aqrit. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef BASE32_H 10 + #define BASE32_H 11 + 12 + #include <stdint.h> 13 + #include <immintrin.h> 14 + 15 + 16 + ////////////////////////// 17 + /// Source: Wojciech Muła, Daniel Lemire, Faster Base64 Encoding and Decoding Using AVX2 Instructions, 18 + /// ACM Transactions on the Web 12 (3), 2018 19 + /// https://arxiv.org/abs/1704.00605 20 + ////////////////////////// 21 + static size_t base32hex_sse(uint8_t *dst, const uint8_t *src) { 22 + static int8_t zero_masks[32] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23 + 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, 24 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; 25 + bool valid = true; 26 + const __m128i delta_check = 27 + _mm_setr_epi8(-16, -32, -48, 70, -65, 41, -97, 9, 0, 0, 0, 0, 0, 0, 0, 0); 28 + const __m128i delta_rebase = 29 + _mm_setr_epi8(0, 0, 0, -48, -55, -55, -87, -87, 0, 0, 0, 0, 0, 0, 0, 0); 30 + const uint8_t *srcinit = src; 31 + do { 32 + __m128i v = _mm_loadu_si128((__m128i *)src); 33 + 34 + __m128i hash_key = _mm_and_si128(_mm_srli_epi32(v, 4), _mm_set1_epi8(0x0F)); 35 + __m128i check = _mm_add_epi8(_mm_shuffle_epi8(delta_check, hash_key), v); 36 + v = _mm_add_epi8(v, _mm_shuffle_epi8(delta_rebase, hash_key)); 37 + unsigned int m = (unsigned)_mm_movemask_epi8(check); 38 + 39 + if (m) { 40 + int length = (int)trailing_zeroes(m); 41 + if (length == 0) { 42 + break; 43 + } 44 + src += length; 45 + __m128i zero_mask = 46 + _mm_loadu_si128((__m128i *)(zero_masks + 16 - length)); 47 + v = _mm_andnot_si128(zero_mask, v); 48 + valid = false; 49 + } else { // common case 50 + src += 16; 51 + } 52 + v = _mm_maddubs_epi16(v, _mm_set1_epi32(0x01200120)); 53 + v = _mm_madd_epi16( 54 + v, _mm_set_epi32(0x00010400, 0x00104000, 0x00010400, 0x00104000)); 55 + // ...00000000`0000eeee`efffffgg`ggghhhhh`00000000`aaaaabbb`bbcccccd`dddd0000 56 + v = _mm_or_si128(v, _mm_srli_epi64(v, 48)); 57 + v = _mm_shuffle_epi8( 58 + v, _mm_set_epi8(0, 0, 0, 0, 0, 0, 12, 13, 8, 9, 10, 4, 5, 0, 1, 2)); 59 + 60 + /* decoded 10 bytes... but write 16 cause why not? */ 61 + _mm_storeu_si128((__m128i *)dst, v); 62 + dst += 10; 63 + } while (valid); 64 + 65 + return (size_t)(src - srcinit); 66 + } 67 + 68 + nonnull_all 69 + static really_inline int32_t parse_base32( 70 + parser_t *parser, 71 + const type_info_t *type, 72 + const rdata_info_t *field, 73 + rdata_t *rdata, 74 + const token_t *token) 75 + { 76 + size_t length = (token->length * 5) / 8; 77 + if (length > 255 || (uintptr_t)rdata->limit - (uintptr_t)rdata->octets < (length + 1)) 78 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 79 + 80 + size_t decoded = base32hex_sse(rdata->octets+1, (const uint8_t*)token->data); 81 + if (decoded != token->length) 82 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 83 + *rdata->octets = (uint8_t)length; 84 + rdata->octets += 1 + length; 85 + return 0; 86 + } 87 + 88 + #endif // BASE32_H
+34
usr.sbin/nsd/simdzone/src/westmere/bench.c
··· 1 + /* 2 + * bench.c -- SSE4.2 compilation target for benchmark function(s) 3 + * 4 + * Copyright (c) 2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #include "zone.h" 10 + #include "attributes.h" 11 + #include "diagnostic.h" 12 + #include "westmere/simd.h" 13 + #include "westmere/bits.h" 14 + #include "generic/parser.h" 15 + #include "generic/scanner.h" 16 + 17 + diagnostic_push() 18 + clang_diagnostic_ignored(missing-prototypes) 19 + 20 + int32_t zone_bench_westmere_lex(zone_parser_t *parser, size_t *tokens) 21 + { 22 + token_t token; 23 + 24 + (*tokens) = 0; 25 + take(parser, &token); 26 + while (token.code > 0) { 27 + (*tokens)++; 28 + take(parser, &token); 29 + } 30 + 31 + return token.code ? -1 : 0; 32 + } 33 + 34 + diagnostic_pop()
+65
usr.sbin/nsd/simdzone/src/westmere/bits.h
··· 1 + /* 2 + * bits.h -- Westmere specific implementation of bit manipulation instructions 3 + * 4 + * Copyright (c) 2018-2022 The simdjson authors 5 + * Copyright (c) 2023, NLnet Labs. All rights reserved. 6 + * 7 + * SPDX-License-Identifier: BSD-3-Clause 8 + */ 9 + #ifndef BITS_H 10 + #define BITS_H 11 + 12 + #include <stdbool.h> 13 + #include <stdint.h> 14 + #include <immintrin.h> 15 + 16 + static inline bool add_overflow(uint64_t value1, uint64_t value2, uint64_t *result) { 17 + #if has_builtin(__builtin_uaddll_overflow) 18 + return __builtin_uaddll_overflow(value1, value2, (unsigned long long *)result); 19 + #else 20 + *result = value1 + value2; 21 + return *result < value1; 22 + #endif 23 + } 24 + 25 + static inline uint64_t count_ones(uint64_t input_num) { 26 + return (uint64_t)_mm_popcnt_u64(input_num); 27 + } 28 + 29 + no_sanitize_undefined 30 + static inline uint64_t trailing_zeroes(uint64_t mask) { 31 + #if has_builtin(__builtin_ctzll) 32 + return (uint64_t)__builtin_ctzll(mask); 33 + #else 34 + uint64_t result; 35 + asm("bsfq %[mask], %[result]" 36 + : [result] "=r" (result) 37 + : [mask] "mr" (mask)); 38 + return result; 39 + #endif 40 + } 41 + 42 + // result might be undefined when input_num is zero 43 + static inline uint64_t clear_lowest_bit(uint64_t input_num) { 44 + return input_num & (input_num-1); 45 + } 46 + 47 + static inline uint64_t leading_zeroes(uint64_t mask) { 48 + #if has_builtin(__builtin_clzll) 49 + return (uint64_t)__builtin_clzll(mask); 50 + #else 51 + uint64_t result; 52 + asm("bsrq %[mask], %[result]" : 53 + [result] "=r" (result) : 54 + [mask] "mr" (mask)); 55 + return 63 ^ (int)result; 56 + #endif 57 + } 58 + 59 + static inline uint64_t prefix_xor(const uint64_t bitmask) { 60 + __m128i all_ones = _mm_set1_epi8('\xFF'); 61 + __m128i result = _mm_clmulepi64_si128(_mm_set_epi64x(0ULL, (long long)bitmask), all_ones, 0); 62 + return (uint64_t)_mm_cvtsi128_si64(result); 63 + } 64 + 65 + #endif // BITS_H
+206
usr.sbin/nsd/simdzone/src/westmere/ip4.h
··· 1 + /* 2 + * ip4.h -- SSE 4.1 parser for IPv4 addresses 3 + * https://lemire.me/blog/2023/06/08/parsing-ip-addresses-crazily-fast/ 4 + * 5 + * Copyright (c) 2023. Daniel Lemire 6 + * 7 + * SPDX-License-Identifier: BSD-3-Clause 8 + * 9 + */ 10 + #ifndef IP4_H 11 + #define IP4_H 12 + 13 + static const uint8_t patterns_id[256] = { 14 + 38, 65, 255, 56, 73, 255, 255, 255, 255, 255, 255, 3, 255, 255, 6, 15 + 255, 255, 9, 255, 27, 255, 12, 30, 255, 255, 255, 255, 15, 255, 33, 16 + 255, 255, 255, 255, 18, 36, 255, 255, 255, 54, 21, 255, 39, 255, 255, 17 + 57, 255, 255, 255, 255, 255, 255, 255, 255, 24, 42, 255, 255, 255, 60, 18 + 255, 255, 255, 255, 255, 255, 255, 255, 45, 255, 255, 63, 255, 255, 255, 19 + 255, 255, 255, 255, 255, 255, 48, 53, 255, 255, 66, 71, 255, 255, 16, 20 + 255, 34, 255, 255, 255, 255, 255, 255, 255, 52, 255, 255, 22, 70, 40, 21 + 255, 255, 58, 51, 255, 255, 69, 255, 255, 255, 255, 255, 255, 255, 255, 22 + 255, 5, 255, 255, 255, 255, 255, 255, 11, 29, 46, 255, 255, 64, 255, 23 + 255, 72, 0, 77, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 24 + 255, 255, 255, 255, 255, 76, 255, 255, 255, 255, 255, 255, 255, 75, 255, 25 + 80, 255, 255, 255, 26, 255, 44, 255, 7, 62, 255, 255, 25, 255, 43, 26 + 13, 31, 61, 255, 255, 255, 255, 255, 255, 255, 255, 255, 2, 19, 37, 27 + 255, 255, 50, 55, 79, 68, 255, 255, 255, 255, 49, 255, 255, 67, 255, 28 + 255, 255, 255, 17, 255, 35, 78, 255, 4, 255, 255, 255, 255, 255, 255, 29 + 10, 23, 28, 41, 255, 255, 59, 255, 255, 255, 8, 255, 255, 255, 255, 30 + 255, 1, 14, 32, 255, 255, 255, 255, 255, 255, 255, 255, 74, 255, 47, 31 + 20, 32 + }; 33 + 34 + static const uint8_t patterns[81][16] = { 35 + {0, 128, 2, 128, 4, 128, 6, 128, 128, 128, 128, 128, 128, 128, 128, 128}, 36 + {0, 128, 2, 128, 4, 128, 7, 6, 128, 128, 128, 128, 128, 128, 128, 6}, 37 + {0, 128, 2, 128, 4, 128, 8, 7, 128, 128, 128, 128, 128, 128, 6, 6}, 38 + {0, 128, 2, 128, 5, 4, 7, 128, 128, 128, 128, 128, 128, 4, 128, 128}, 39 + {0, 128, 2, 128, 5, 4, 8, 7, 128, 128, 128, 128, 128, 4, 128, 7}, 40 + {0, 128, 2, 128, 5, 4, 9, 8, 128, 128, 128, 128, 128, 4, 7, 7}, 41 + {0, 128, 2, 128, 6, 5, 8, 128, 128, 128, 128, 128, 4, 4, 128, 128}, 42 + {0, 128, 2, 128, 6, 5, 9, 8, 128, 128, 128, 128, 4, 4, 128, 8}, 43 + {0, 128, 2, 128, 6, 5, 10, 9, 128, 128, 128, 128, 4, 4, 8, 8}, 44 + {0, 128, 3, 2, 5, 128, 7, 128, 128, 128, 128, 2, 128, 128, 128, 128}, 45 + {0, 128, 3, 2, 5, 128, 8, 7, 128, 128, 128, 2, 128, 128, 128, 7}, 46 + {0, 128, 3, 2, 5, 128, 9, 8, 128, 128, 128, 2, 128, 128, 7, 7}, 47 + {0, 128, 3, 2, 6, 5, 8, 128, 128, 128, 128, 2, 128, 5, 128, 128}, 48 + {0, 128, 3, 2, 6, 5, 9, 8, 128, 128, 128, 2, 128, 5, 128, 8}, 49 + {0, 128, 3, 2, 6, 5, 10, 9, 128, 128, 128, 2, 128, 5, 8, 8}, 50 + {0, 128, 3, 2, 7, 6, 9, 128, 128, 128, 128, 2, 5, 5, 128, 128}, 51 + {0, 128, 3, 2, 7, 6, 10, 9, 128, 128, 128, 2, 5, 5, 128, 9}, 52 + {0, 128, 3, 2, 7, 6, 11, 10, 128, 128, 128, 2, 5, 5, 9, 9}, 53 + {0, 128, 4, 3, 6, 128, 8, 128, 128, 128, 2, 2, 128, 128, 128, 128}, 54 + {0, 128, 4, 3, 6, 128, 9, 8, 128, 128, 2, 2, 128, 128, 128, 8}, 55 + {0, 128, 4, 3, 6, 128, 10, 9, 128, 128, 2, 2, 128, 128, 8, 8}, 56 + {0, 128, 4, 3, 7, 6, 9, 128, 128, 128, 2, 2, 128, 6, 128, 128}, 57 + {0, 128, 4, 3, 7, 6, 10, 9, 128, 128, 2, 2, 128, 6, 128, 9}, 58 + {0, 128, 4, 3, 7, 6, 11, 10, 128, 128, 2, 2, 128, 6, 9, 9}, 59 + {0, 128, 4, 3, 8, 7, 10, 128, 128, 128, 2, 2, 6, 6, 128, 128}, 60 + {0, 128, 4, 3, 8, 7, 11, 10, 128, 128, 2, 2, 6, 6, 128, 10}, 61 + {0, 128, 4, 3, 8, 7, 12, 11, 128, 128, 2, 2, 6, 6, 10, 10}, 62 + {1, 0, 3, 128, 5, 128, 7, 128, 128, 0, 128, 128, 128, 128, 128, 128}, 63 + {1, 0, 3, 128, 5, 128, 8, 7, 128, 0, 128, 128, 128, 128, 128, 7}, 64 + {1, 0, 3, 128, 5, 128, 9, 8, 128, 0, 128, 128, 128, 128, 7, 7}, 65 + {1, 0, 3, 128, 6, 5, 8, 128, 128, 0, 128, 128, 128, 5, 128, 128}, 66 + {1, 0, 3, 128, 6, 5, 9, 8, 128, 0, 128, 128, 128, 5, 128, 8}, 67 + {1, 0, 3, 128, 6, 5, 10, 9, 128, 0, 128, 128, 128, 5, 8, 8}, 68 + {1, 0, 3, 128, 7, 6, 9, 128, 128, 0, 128, 128, 5, 5, 128, 128}, 69 + {1, 0, 3, 128, 7, 6, 10, 9, 128, 0, 128, 128, 5, 5, 128, 9}, 70 + {1, 0, 3, 128, 7, 6, 11, 10, 128, 0, 128, 128, 5, 5, 9, 9}, 71 + {1, 0, 4, 3, 6, 128, 8, 128, 128, 0, 128, 3, 128, 128, 128, 128}, 72 + {1, 0, 4, 3, 6, 128, 9, 8, 128, 0, 128, 3, 128, 128, 128, 8}, 73 + {1, 0, 4, 3, 6, 128, 10, 9, 128, 0, 128, 3, 128, 128, 8, 8}, 74 + {1, 0, 4, 3, 7, 6, 9, 128, 128, 0, 128, 3, 128, 6, 128, 128}, 75 + {1, 0, 4, 3, 7, 6, 10, 9, 128, 0, 128, 3, 128, 6, 128, 9}, 76 + {1, 0, 4, 3, 7, 6, 11, 10, 128, 0, 128, 3, 128, 6, 9, 9}, 77 + {1, 0, 4, 3, 8, 7, 10, 128, 128, 0, 128, 3, 6, 6, 128, 128}, 78 + {1, 0, 4, 3, 8, 7, 11, 10, 128, 0, 128, 3, 6, 6, 128, 10}, 79 + {1, 0, 4, 3, 8, 7, 12, 11, 128, 0, 128, 3, 6, 6, 10, 10}, 80 + {1, 0, 5, 4, 7, 128, 9, 128, 128, 0, 3, 3, 128, 128, 128, 128}, 81 + {1, 0, 5, 4, 7, 128, 10, 9, 128, 0, 3, 3, 128, 128, 128, 9}, 82 + {1, 0, 5, 4, 7, 128, 11, 10, 128, 0, 3, 3, 128, 128, 9, 9}, 83 + {1, 0, 5, 4, 8, 7, 10, 128, 128, 0, 3, 3, 128, 7, 128, 128}, 84 + {1, 0, 5, 4, 8, 7, 11, 10, 128, 0, 3, 3, 128, 7, 128, 10}, 85 + {1, 0, 5, 4, 8, 7, 12, 11, 128, 0, 3, 3, 128, 7, 10, 10}, 86 + {1, 0, 5, 4, 9, 8, 11, 128, 128, 0, 3, 3, 7, 7, 128, 128}, 87 + {1, 0, 5, 4, 9, 8, 12, 11, 128, 0, 3, 3, 7, 7, 128, 11}, 88 + {1, 0, 5, 4, 9, 8, 13, 12, 128, 0, 3, 3, 7, 7, 11, 11}, 89 + {2, 1, 4, 128, 6, 128, 8, 128, 0, 0, 128, 128, 128, 128, 128, 128}, 90 + {2, 1, 4, 128, 6, 128, 9, 8, 0, 0, 128, 128, 128, 128, 128, 8}, 91 + {2, 1, 4, 128, 6, 128, 10, 9, 0, 0, 128, 128, 128, 128, 8, 8}, 92 + {2, 1, 4, 128, 7, 6, 9, 128, 0, 0, 128, 128, 128, 6, 128, 128}, 93 + {2, 1, 4, 128, 7, 6, 10, 9, 0, 0, 128, 128, 128, 6, 128, 9}, 94 + {2, 1, 4, 128, 7, 6, 11, 10, 0, 0, 128, 128, 128, 6, 9, 9}, 95 + {2, 1, 4, 128, 8, 7, 10, 128, 0, 0, 128, 128, 6, 6, 128, 128}, 96 + {2, 1, 4, 128, 8, 7, 11, 10, 0, 0, 128, 128, 6, 6, 128, 10}, 97 + {2, 1, 4, 128, 8, 7, 12, 11, 0, 0, 128, 128, 6, 6, 10, 10}, 98 + {2, 1, 5, 4, 7, 128, 9, 128, 0, 0, 128, 4, 128, 128, 128, 128}, 99 + {2, 1, 5, 4, 7, 128, 10, 9, 0, 0, 128, 4, 128, 128, 128, 9}, 100 + {2, 1, 5, 4, 7, 128, 11, 10, 0, 0, 128, 4, 128, 128, 9, 9}, 101 + {2, 1, 5, 4, 8, 7, 10, 128, 0, 0, 128, 4, 128, 7, 128, 128}, 102 + {2, 1, 5, 4, 8, 7, 11, 10, 0, 0, 128, 4, 128, 7, 128, 10}, 103 + {2, 1, 5, 4, 8, 7, 12, 11, 0, 0, 128, 4, 128, 7, 10, 10}, 104 + {2, 1, 5, 4, 9, 8, 11, 128, 0, 0, 128, 4, 7, 7, 128, 128}, 105 + {2, 1, 5, 4, 9, 8, 12, 11, 0, 0, 128, 4, 7, 7, 128, 11}, 106 + {2, 1, 5, 4, 9, 8, 13, 12, 0, 0, 128, 4, 7, 7, 11, 11}, 107 + {2, 1, 6, 5, 8, 128, 10, 128, 0, 0, 4, 4, 128, 128, 128, 128}, 108 + {2, 1, 6, 5, 8, 128, 11, 10, 0, 0, 4, 4, 128, 128, 128, 10}, 109 + {2, 1, 6, 5, 8, 128, 12, 11, 0, 0, 4, 4, 128, 128, 10, 10}, 110 + {2, 1, 6, 5, 9, 8, 11, 128, 0, 0, 4, 4, 128, 8, 128, 128}, 111 + {2, 1, 6, 5, 9, 8, 12, 11, 0, 0, 4, 4, 128, 8, 128, 11}, 112 + {2, 1, 6, 5, 9, 8, 13, 12, 0, 0, 4, 4, 128, 8, 11, 11}, 113 + {2, 1, 6, 5, 10, 9, 12, 128, 0, 0, 4, 4, 8, 8, 128, 128}, 114 + {2, 1, 6, 5, 10, 9, 13, 12, 0, 0, 4, 4, 8, 8, 128, 12}, 115 + {2, 1, 6, 5, 10, 9, 14, 13, 0, 0, 4, 4, 8, 8, 12, 12}, 116 + }; 117 + 118 + // convert IPv4 from text to binary form. 119 + // 120 + // ipv4_string points to a character string containing an IPv4 network address in dotted-decimal format 121 + // "ddd.ddd.ddd.ddd" of length ipv4_string_length (the string does not have to be null terminated), 122 + // where ddd is a decimal number of up to three digits in the range 0 to 255. 123 + // The address is converted to a 32-bit integer (destination) (in network byte order). 124 + // 125 + // Important: the function will systematically read 16 bytes at the provided address (ipv4_string). We infer 126 + // the network address size in bytes by looking for a sequence of dots and decimal digits. 127 + // 128 + // returns 1 on success (network address was successfully converted). 129 + // 130 + // This function assumes that the processor supports SSE 4.1 instructions or better. That's true of most 131 + // processors in operation today (June 2023). 132 + static inline int sse_inet_aton(const char* ipv4_string, uint8_t* destination, size_t* restrict ipv4_string_length) { 133 + 134 + __m128i v = _mm_loadu_si128((const __m128i *)ipv4_string); 135 + 136 + __m128i is_dot = _mm_cmpeq_epi8(v, _mm_set1_epi8(0x2E)); 137 + uint32_t dot_mask = (uint32_t)_mm_movemask_epi8(is_dot); 138 + 139 + // set non-digits to 0x80..0x89, set digits to 0x00..0x09 140 + const __m128i saturation_distance = _mm_set1_epi8(0x76); // 0x7F - 9 141 + v = _mm_xor_si128(v, _mm_set1_epi8(0x30)); // ascii '0' 142 + v = _mm_adds_epu8(v, saturation_distance); 143 + uint32_t non_digit_mask = (uint32_t)_mm_movemask_epi8(v); 144 + v = _mm_subs_epi8(v, saturation_distance); 145 + 146 + uint32_t bad_mask = dot_mask ^ non_digit_mask; 147 + uint32_t clip_mask = bad_mask ^ (bad_mask - 1); 148 + uint32_t partition_mask = non_digit_mask & clip_mask; 149 + 150 + const uint32_t length = (uint32_t)count_ones(clip_mask) - 1; 151 + 152 + uint32_t hash_key = (partition_mask * 0x00CF7800) >> 24; 153 + uint8_t hash_id = patterns_id[hash_key]; 154 + if (hash_id >= 81) 155 + return 0; 156 + const uint8_t* const pattern_ptr = &patterns[hash_id][0]; 157 + 158 + __m128i shuf = _mm_loadu_si128((const __m128i *)pattern_ptr); 159 + v = _mm_shuffle_epi8(v, shuf); 160 + 161 + const __m128i mul_weights = 162 + _mm_set_epi8(0,100, 0,100, 0,100, 0,100, 10,1, 10,1, 10,1, 10,1); 163 + __m128i acc = _mm_maddubs_epi16(mul_weights, v); 164 + __m128i swapped = _mm_shuffle_epi32(acc, _MM_SHUFFLE(1,0,3,2)); 165 + acc = _mm_adds_epu16(acc, swapped); 166 + 167 + // check `v` for leading zeros in each partition, ignore lanes if partition has only one digit 168 + // if hibyte of `acc` then bad_char or overflow 169 + __m128i check_lz = _mm_xor_si128(_mm_cmpeq_epi8(_mm_setzero_si128(), v), shuf); 170 + __m128i check_of = _mm_adds_epu16(_mm_set1_epi16(0x7F00), acc); 171 + __m128i checks = _mm_or_si128(check_lz, check_of); 172 + uint32_t check_mask = (uint32_t)_mm_movemask_epi8(checks); 173 + check_mask &= 0x0000AA00; // the only lanes wanted 174 + 175 + // pack and we are done! 176 + uint32_t address = (uint32_t)_mm_cvtsi128_si32(_mm_packus_epi16(acc, acc)); 177 + *ipv4_string_length = length; 178 + memcpy(destination, &address, 4); 179 + return (int)(length + check_mask - pattern_ptr[6]); 180 + } 181 + 182 + nonnull_all 183 + static really_inline int32_t scan_ip4(const char *text, uint8_t *wire) 184 + { 185 + size_t len; 186 + if (sse_inet_aton(text, wire, &len) != 1) 187 + return 0; 188 + return (int32_t)len; 189 + } 190 + 191 + nonnull_all 192 + static really_inline int32_t parse_ip4( 193 + parser_t *parser, 194 + const type_info_t *type, 195 + const rdata_info_t *field, 196 + rdata_t *rdata, 197 + const token_t *token) 198 + { 199 + // Note that this assumes that reading up to token->data + 16 is safe (i.e., we do not cross a page). 200 + if ((size_t)scan_ip4(token->data, rdata->octets) != token->length) 201 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 202 + rdata->octets += 4; 203 + return 0; 204 + } 205 + 206 + #endif // IP4_H
+52
usr.sbin/nsd/simdzone/src/westmere/parser.c
··· 1 + /* 2 + * parser.c -- SSE4.2 specific compilation target for (DNS) zone file parser 3 + * 4 + * Copyright (c) 2022, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause. 7 + * 8 + */ 9 + #include "zone.h" 10 + #include "attributes.h" 11 + #include "diagnostic.h" 12 + #include "westmere/simd.h" 13 + #include "generic/endian.h" 14 + #include "westmere/bits.h" 15 + #include "generic/parser.h" 16 + #include "generic/scanner.h" 17 + #include "generic/number.h" 18 + #include "generic/ttl.h" 19 + #include "westmere/time.h" 20 + #include "westmere/ip4.h" 21 + #include "generic/ip6.h" 22 + #include "generic/text.h" 23 + #include "generic/name.h" 24 + #include "generic/base16.h" 25 + #include "westmere/base32.h" 26 + #include "generic/base64.h" 27 + #include "generic/nsec.h" 28 + #include "generic/nxt.h" 29 + #include "generic/caa.h" 30 + #include "generic/ilnp64.h" 31 + #include "generic/eui.h" 32 + #include "generic/nsap.h" 33 + #include "generic/wks.h" 34 + #include "generic/loc.h" 35 + #include "generic/gpos.h" 36 + #include "generic/apl.h" 37 + #include "generic/svcb.h" 38 + #include "generic/cert.h" 39 + #include "generic/algorithm.h" 40 + #include "generic/types.h" 41 + #include "westmere/type.h" 42 + #include "generic/format.h" 43 + 44 + diagnostic_push() 45 + clang_diagnostic_ignored(missing-prototypes) 46 + 47 + int32_t zone_westmere_parse(parser_t *parser) 48 + { 49 + return parse(parser); 50 + } 51 + 52 + diagnostic_pop()
+142
usr.sbin/nsd/simdzone/src/westmere/simd.h
··· 1 + /* 2 + * simd.h -- SIMD abstractions targeting SSE4.2 3 + * 4 + * Copyright (c) 2022, NLnet Labs. All rights reserved. 5 + * 6 + * See LICENSE for the license. 7 + * 8 + */ 9 + #ifndef SIMD_H 10 + #define SIMD_H 11 + 12 + #include <stdint.h> 13 + #include <immintrin.h> 14 + 15 + #define SIMD_8X_SIZE (16) 16 + 17 + typedef uint8_t simd_table_t[SIMD_8X_SIZE]; 18 + 19 + #define SIMD_TABLE(v00, v01, v02, v03, v04, v05, v06, v07, \ 20 + v08, v09, v0a, v0b, v0c, v0d, v0e, v0f) \ 21 + { \ 22 + v00, v01, v02, v03, v04, v05, v06, v07, \ 23 + v08, v09, v0a, v0b, v0c, v0d, v0e, v0f \ 24 + } 25 + 26 + typedef struct { __m128i chunks[1]; } simd_8x_t; 27 + 28 + typedef simd_8x_t simd_8x16_t; 29 + 30 + typedef struct { __m128i chunks[2]; } simd_8x32_t; 31 + 32 + typedef struct { __m128i chunks[4]; } simd_8x64_t; 33 + 34 + nonnull_all 35 + static really_inline void simd_loadu_8x(simd_8x_t *simd, const uint8_t *address) 36 + { 37 + simd->chunks[0] = _mm_loadu_si128((const __m128i *)address); 38 + } 39 + 40 + nonnull_all 41 + static really_inline void simd_storeu_8x(uint8_t *address, const simd_8x_t *simd) 42 + { 43 + _mm_storeu_si128((__m128i *)address, simd->chunks[0]); 44 + } 45 + 46 + nonnull_all 47 + static really_inline uint64_t simd_find_8x(const simd_8x_t *simd, char key) 48 + { 49 + const __m128i k = _mm_set1_epi8(key); 50 + const __m128i r = _mm_cmpeq_epi8(simd->chunks[0], k); 51 + return (uint16_t)_mm_movemask_epi8(r); 52 + } 53 + 54 + nonnull_all 55 + static really_inline uint64_t simd_find_any_8x( 56 + const simd_8x_t *simd, const simd_table_t table) 57 + { 58 + const __m128i t = _mm_loadu_si128((const __m128i *)table); 59 + const __m128i r = _mm_cmpeq_epi8( 60 + _mm_shuffle_epi8(t, simd->chunks[0]), simd->chunks[0]); 61 + return (uint16_t)_mm_movemask_epi8(r); 62 + } 63 + 64 + #define simd_loadu_8x16(simd, address) simd_loadu_8x(simd, address) 65 + #define simd_find_8x16(simd, key) simd_find_8x(simd, key) 66 + 67 + nonnull_all 68 + static really_inline void simd_loadu_8x32(simd_8x32_t *simd, const char *address) 69 + { 70 + simd->chunks[0] = _mm_loadu_si128((const __m128i *)(address)); 71 + simd->chunks[1] = _mm_loadu_si128((const __m128i *)(address+16)); 72 + } 73 + 74 + nonnull_all 75 + static really_inline void simd_storeu_8x32(uint8_t *address, const simd_8x32_t *simd) 76 + { 77 + _mm_storeu_si128((__m128i *)(address), simd->chunks[0]); 78 + _mm_storeu_si128((__m128i *)(address+16), simd->chunks[1]); 79 + } 80 + 81 + nonnull_all 82 + static really_inline uint64_t simd_find_8x32(const simd_8x32_t *simd, char key) 83 + { 84 + const __m128i k = _mm_set1_epi8(key); 85 + const __m128i r0 = _mm_cmpeq_epi8(simd->chunks[0], k); 86 + const __m128i r1 = _mm_cmpeq_epi8(simd->chunks[1], k); 87 + const uint32_t m0 = (uint16_t)_mm_movemask_epi8(r0); 88 + const uint32_t m1 = (uint16_t)_mm_movemask_epi8(r1); 89 + return m0 | (m1 << 16); 90 + } 91 + 92 + nonnull_all 93 + static really_inline void simd_loadu_8x64(simd_8x64_t *simd, const uint8_t *address) 94 + { 95 + simd->chunks[0] = _mm_loadu_si128((const __m128i *)(address)); 96 + simd->chunks[1] = _mm_loadu_si128((const __m128i *)(address+16)); 97 + simd->chunks[2] = _mm_loadu_si128((const __m128i *)(address+32)); 98 + simd->chunks[3] = _mm_loadu_si128((const __m128i *)(address+48)); 99 + } 100 + 101 + nonnull_all 102 + static really_inline uint64_t simd_find_8x64(const simd_8x64_t *simd, char key) 103 + { 104 + const __m128i k = _mm_set1_epi8(key); 105 + 106 + const __m128i r0 = _mm_cmpeq_epi8(simd->chunks[0], k); 107 + const __m128i r1 = _mm_cmpeq_epi8(simd->chunks[1], k); 108 + const __m128i r2 = _mm_cmpeq_epi8(simd->chunks[2], k); 109 + const __m128i r3 = _mm_cmpeq_epi8(simd->chunks[3], k); 110 + 111 + const uint64_t m0 = (uint16_t)_mm_movemask_epi8(r0); 112 + const uint64_t m1 = (uint16_t)_mm_movemask_epi8(r1); 113 + const uint64_t m2 = (uint16_t)_mm_movemask_epi8(r2); 114 + const uint64_t m3 = (uint16_t)_mm_movemask_epi8(r3); 115 + 116 + return m0 | (m1 << 16) | (m2 << 32) | (m3 << 48); 117 + } 118 + 119 + nonnull_all 120 + static really_inline uint64_t simd_find_any_8x64( 121 + const simd_8x64_t *simd, const simd_table_t table) 122 + { 123 + const __m128i t = _mm_loadu_si128((const __m128i *)table); 124 + 125 + const __m128i r0 = _mm_cmpeq_epi8( 126 + _mm_shuffle_epi8(t, simd->chunks[0]), simd->chunks[0]); 127 + const __m128i r1 = _mm_cmpeq_epi8( 128 + _mm_shuffle_epi8(t, simd->chunks[1]), simd->chunks[1]); 129 + const __m128i r2 = _mm_cmpeq_epi8( 130 + _mm_shuffle_epi8(t, simd->chunks[2]), simd->chunks[2]); 131 + const __m128i r3 = _mm_cmpeq_epi8( 132 + _mm_shuffle_epi8(t, simd->chunks[3]), simd->chunks[3]); 133 + 134 + const uint64_t m0 = (uint16_t)_mm_movemask_epi8(r0); 135 + const uint64_t m1 = (uint16_t)_mm_movemask_epi8(r1); 136 + const uint64_t m2 = (uint16_t)_mm_movemask_epi8(r2); 137 + const uint64_t m3 = (uint16_t)_mm_movemask_epi8(r3); 138 + 139 + return m0 | (m1 << 16) | (m2 << 32) | (m3 << 48); 140 + } 141 + 142 + #endif // SIMD_H
+144
usr.sbin/nsd/simdzone/src/westmere/time.h
··· 1 + /* 2 + * ip4.h -- SSE 4.1 parser for time stamps 3 + * https://lemire.me/blog/2023/07/01/parsing-time-stamps-faster-with-simd-instructions/ 4 + * 5 + * Copyright (c) 2023. Daniel Lemire 6 + * 7 + * SPDX-License-Identifier: BSD-3-Clause 8 + * 9 + */ 10 + #ifndef SSE_TIME_H 11 + #define SSE_TIME_H 12 + 13 + static const int mdays_minus_one[] = {30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30}; 14 + 15 + static const int mdays_cumulative[] = {0, 31, 59, 90, 120, 151, 181, 16 + 212, 243, 273, 304, 334, 365}; 17 + 18 + /* 19 + The 32-bit timestamp spans from year 1970 to 2106. 20 + Therefore, the only special case for leap years is 2100. 21 + We use that to produce fast functions. 22 + */ 23 + static inline uint32_t is_leap_year(uint32_t year) { 24 + return (year % 4 == 0) & (year != 2100); 25 + } 26 + 27 + static inline uint32_t leap_days(uint32_t year) { 28 + --year; 29 + return (year/4 - 1970/4) - (year >= 2100); 30 + } 31 + 32 + static bool sse_parse_time(const char *date_string, uint32_t *time_in_second) { 33 + // We load the block of digits. We subtract 0x30 (the code point value of the 34 + // character '0'), and all bytes values should be between 0 and 9, 35 + // inclusively. We know that some character must be smaller that 9, for 36 + // example, we cannot have more than 59 seconds and never 60 seconds, in the 37 + // time stamp string. So one character must be between 0 and 5. Similarly, we 38 + // start the hours at 00 and end at 23, so one character must be between 0 39 + // and 2. We do a saturating subtraction of the maximum: the result of such a 40 + // subtraction should be zero if the value is no larger. We then use a special 41 + // instruction to multiply one byte by 10, and sum it up with the next byte, 42 + // getting a 16-bit value. We then repeat the same approach as before, 43 + // checking that the result is not too large. 44 + // 45 + // We compute the month the good old ways, as an integer in [0,11], we 46 + // check for overflows later. 47 + uint64_t mo = (uint64_t)((date_string[4]-0x30)*10 + (date_string[5]-0x30) - 1); 48 + __m128i v = _mm_loadu_si128((const __m128i *)date_string); 49 + // loaded YYYYMMDDHHmmSS..... 50 + v = _mm_xor_si128(v, _mm_set1_epi8(0x30)); 51 + // W can use _mm_sub_epi8 or _mm_xor_si128 for the subtraction above. 52 + // subtracting by 0x30 (or '0'), turns all values into a byte value between 0 53 + // and 9 if the initial input was made of digits. 54 + __m128i limit = 55 + _mm_setr_epi8(9, 9, 9, 9, 1, 9, 3, 9, 2, 9, 5, 9, 5, 9, -1, -1); 56 + // credit @aqrit 57 + // overflows are still possible, if hours are in the range 24 to 29 58 + // of if days are in the range 32 to 39 59 + // or if months are in the range 12 to 19. 60 + __m128i abide_by_limits = _mm_subs_epu8(v, limit); // must be all zero 61 + 62 + #if defined __SUNPRO_C 63 + __m128i byteflip = _mm_setr_epi64((__m64){0x0607040502030001ULL}, 64 + (__m64){0x0e0f0c0d0a0b0809ULL}); 65 + #else 66 + __m128i byteflip = _mm_setr_epi64((__m64)0x0607040502030001ULL, 67 + (__m64)0x0e0f0c0d0a0b0809ULL); 68 + #endif 69 + 70 + __m128i little_endian = _mm_shuffle_epi8(v, byteflip); 71 + __m128i limit16 = _mm_setr_epi16(0x0909, 0x0909, 0x0102, 0x0301, 0x0203, 72 + 0x0509, 0x0509, -1); 73 + __m128i abide_by_limits16 = 74 + _mm_subs_epu16(little_endian, limit16); // must be all zero 75 + 76 + __m128i combined_limits = 77 + _mm_or_si128(abide_by_limits16, abide_by_limits); // must be all zero 78 + 79 + if (!_mm_test_all_zeros(combined_limits, combined_limits)) { 80 + return false; 81 + } 82 + // 0x000000SS0mmm0HHH`00DD00MM00YY00YY 83 + ////////////////////////////////////////////////////// 84 + // pmaddubsw has a high latency (e.g., 5 cycles) and is 85 + // likely a performance bottleneck. 86 + ///////////////////////////////////////////////////// 87 + const __m128i weights = _mm_setr_epi8( 88 + // Y Y Y Y m m d d H H M M S S - - 89 + 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 0, 0); 90 + v = _mm_maddubs_epi16(v, weights); 91 + 92 + uint64_t hi = (uint64_t)_mm_extract_epi64(v, 1); 93 + uint64_t seconds = (hi * 0x0384000F00004000) >> 46; 94 + uint64_t lo = (uint64_t)_mm_extract_epi64(v, 0); 95 + uint64_t yr = (lo * 0x64000100000000) >> 48; 96 + 97 + // We compute the day (starting at zero). We implicitly 98 + // check for overflows later. 99 + uint64_t dy = (uint64_t)_mm_extract_epi8(v, 6) - 1; 100 + 101 + bool is_leap_yr = (bool)is_leap_year((uint32_t)yr); 102 + if(yr < 1970 || mo > 11) { return false; } // unlikely branch 103 + if (dy > (uint64_t)mdays_minus_one[mo]) { // unlikely branch 104 + if (mo == 1 && is_leap_yr) { 105 + if (dy != 29 - 1) { 106 + return false; 107 + } 108 + } else { 109 + return false; 110 + } 111 + } 112 + uint64_t days = 365 * (yr - 1970) + (uint64_t)leap_days((uint32_t)yr); 113 + 114 + days += (uint64_t)mdays_cumulative[mo]; 115 + days += is_leap_yr & (mo > 1); 116 + 117 + days += dy; 118 + uint64_t time_in_second64 = seconds + days * 60 * 60 * 24; 119 + *time_in_second = (uint32_t)time_in_second64; 120 + return true; 121 + } 122 + 123 + nonnull_all 124 + static really_inline int32_t parse_time( 125 + parser_t *parser, 126 + const type_info_t *type, 127 + const rdata_info_t *field, 128 + rdata_t *rdata, 129 + const token_t *token) 130 + { 131 + uint32_t time; 132 + 133 + if (unlikely(token->length != 14)) 134 + return parse_int32(parser, type, field, rdata, token); 135 + if (!sse_parse_time(token->data, &time)) 136 + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); 137 + 138 + time = htobe32(time); 139 + memcpy(rdata->octets, &time, sizeof(time)); 140 + rdata->octets += sizeof(time); 141 + return 0; 142 + } 143 + 144 + #endif // TIME_H
+184
usr.sbin/nsd/simdzone/src/westmere/type.h
··· 1 + /* 2 + * type.h -- SSE4.1 RRTYPE parser 3 + * 4 + * Copyright (c) 2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #ifndef TYPE_H 10 + #define TYPE_H 11 + 12 + #define V(code) { &(types[0].name), 0 } 13 + #define T(code) { &(types[code].name), 1 } 14 + #define C(code) { &(classes[code].name), 2 } 15 + 16 + // map hash to type or class descriptor (generated using hash.c) 17 + static const struct { 18 + const mnemonic_t *mnemonic; 19 + int32_t code; 20 + } types_and_classes[256] = { 21 + V(0), V(0), V(0), V(0), V(0), V(0), V(0), T(20), 22 + T(3), V(0), V(0), V(0), V(0), T(261), V(0), V(0), 23 + T(60), V(0), V(0), T(105), V(0), V(0), V(0), T(258), 24 + V(0), V(0), V(0), V(0), T(30), V(0), T(28), V(0), 25 + V(0), T(16), V(0), V(0), T(56), T(14), T(22), V(0), 26 + V(0), T(13), V(0), T(47), T(21), V(0), T(65), T(27), 27 + V(0), V(0), V(0), V(0), V(0), T(1), T(62), V(0), 28 + V(0), C(1), V(0), T(44), V(0), V(0), T(33), V(0), 29 + V(0), V(0), V(0), V(0), T(63), V(0), T(266), V(0), 30 + C(3), T(99), T(37), V(0), V(0), V(0), C(2), T(43), 31 + V(0), T(50), C(4), T(51), V(0), V(0), V(0), T(2), 32 + T(49), T(42), T(19), T(23), V(0), T(6), V(0), V(0), 33 + V(0), V(0), T(29), V(0), T(7), V(0), V(0), V(0), 34 + V(0), T(57), V(0), V(0), V(0), V(0), V(0), T(36), 35 + T(15), V(0), V(0), T(26), T(11), V(0), V(0), V(0), 36 + V(0), V(0), V(0), V(0), T(104), V(0), T(8), V(0), 37 + V(0), V(0), T(38), V(0), T(9), V(0), T(64), V(0), 38 + V(0), V(0), V(0), V(0), V(0), V(0), T(39), T(52), 39 + T(24), V(0), T(5), T(106), V(0), V(0), V(0), V(0), 40 + T(265), V(0), V(0), V(0), V(0), T(25), V(0), T(18), 41 + T(48), V(0), T(53), V(0), V(0), V(0), T(59), V(0), 42 + V(0), V(0), V(0), V(0), T(4), V(0), T(10), V(0), 43 + V(0), V(0), V(0), V(0), V(0), T(55), V(0), V(0), 44 + V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), 45 + V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), 46 + V(0), V(0), T(61), T(12), V(0), V(0), V(0), V(0), 47 + V(0), T(108), V(0), V(0), T(257), V(0), V(0), V(0), 48 + T(35), V(0), T(263), V(0), V(0), V(0), V(0), T(107), 49 + V(0), V(0), V(0), V(0), T(17), V(0), T(45), V(0), 50 + V(0), V(0), V(0), V(0), V(0), V(0), T(46), V(0), 51 + V(0), T(109), V(0), V(0), V(0), V(0), V(0), V(0), 52 + V(0), V(0), V(0), V(0), T(262), V(0), T(256), V(0) 53 + }; 54 + 55 + #undef V 56 + #undef T 57 + #undef C 58 + 59 + nonnull_all 60 + static really_inline int32_t scan_generic_type( 61 + const char *data, size_t length, uint16_t *code, const mnemonic_t **mnemonic) 62 + { 63 + if (scan_int16(data + 4, length - 4, code) == 0) 64 + return -1; 65 + if (*code <= 258) 66 + *mnemonic = &types[*code].name; 67 + else if (*code == 32769) 68 + *mnemonic = &types[259].name; 69 + else 70 + *mnemonic = &types[0].name; 71 + return 1; 72 + } 73 + 74 + nonnull_all 75 + static really_inline int32_t scan_generic_class( 76 + const char *data, size_t length, uint16_t *code, const mnemonic_t **mnemonic) 77 + { 78 + if (scan_int16(data + 5, length - 5, code) == 0) 79 + return -1; 80 + if (*code <= 4) 81 + *mnemonic = &classes[*code].name; 82 + else 83 + *mnemonic = &classes[0].name; 84 + return 2; 85 + } 86 + 87 + #define TYPE (0x45505954llu) 88 + #define TYPE_MASK (0xffffffffllu) 89 + #define CLASS (0x5353414c43llu) 90 + #define CLASS_MASK (0xffffffffffllu) 91 + 92 + static const int8_t zero_masks[48] = { 93 + -1, -1, -1, -1, -1, -1, -1, -1, 94 + -1, -1, -1, -1, -1, -1, -1, -1, 95 + -1, -1, -1, -1, -1, -1, -1, -1, 96 + -1, -1, -1, -1, -1, -1, -1, -1, 97 + 0, 0, 0, 0, 0, 0, 0, 0, 98 + 0, 0, 0, 0, 0, 0, 0, 0 99 + }; 100 + 101 + static really_inline uint8_t hash(uint64_t prefix) 102 + { 103 + uint32_t value = (uint32_t)((prefix >> 32) ^ prefix); 104 + // magic value is generated using hash.c, rerun when adding types 105 + return (uint8_t)((value * 3523548378ull) >> 32); 106 + } 107 + 108 + nonnull_all 109 + static really_inline int32_t scan_type_or_class( 110 + const char *data, size_t length, uint16_t *code, const mnemonic_t **mnemonic) 111 + { 112 + __m128i input = _mm_loadu_si128((const __m128i *)data); 113 + 114 + const __m128i letter_mask = 115 + _mm_srli_epi32(_mm_and_si128(input, _mm_set1_epi8(0x40)), 1); 116 + 117 + // convert to upper case 118 + input = _mm_andnot_si128(letter_mask, input); 119 + 120 + // sanitize input 121 + const __m128i zero_mask = 122 + _mm_loadu_si128((const __m128i *)&zero_masks[32 - (length & 0x1f)]); 123 + input = _mm_and_si128(input, zero_mask); 124 + 125 + // input is now sanitized and upper case 126 + 127 + const uint64_t prefix = (uint64_t)_mm_cvtsi128_si64(input); 128 + const uint8_t index = hash(prefix); 129 + *code = (uint16_t)types_and_classes[index].mnemonic->value; 130 + *mnemonic = types_and_classes[index].mnemonic; 131 + 132 + const __m128i compar = _mm_loadu_si128((const __m128i *)(*mnemonic)->key.data); 133 + const __m128i xorthem = _mm_xor_si128(compar, input); 134 + 135 + if (likely(_mm_test_all_zeros(xorthem, xorthem))) 136 + return types_and_classes[index].code; 137 + else if ((prefix & TYPE_MASK) == TYPE) 138 + return scan_generic_type(data, length, code, mnemonic); 139 + else if ((prefix & CLASS_MASK) == CLASS) 140 + return scan_generic_class(data, length, code, mnemonic); 141 + return 0; 142 + } 143 + 144 + nonnull_all 145 + static really_inline int32_t scan_type( 146 + const char *data, size_t length, uint16_t *code, const mnemonic_t **mnemonic) 147 + { 148 + __m128i input = _mm_loadu_si128((const __m128i *)data); 149 + 150 + const __m128i letter_mask = 151 + _mm_srli_epi32(_mm_and_si128(input, _mm_set1_epi8(0x40)), 1); 152 + 153 + // convert to upper case 154 + input = _mm_andnot_si128(letter_mask, input); 155 + 156 + // sanitize input 157 + const __m128i zero_mask = 158 + _mm_loadu_si128((const __m128i *)&zero_masks[32 - (length & 0x1f)]); 159 + input = _mm_and_si128(input, zero_mask); 160 + 161 + // input is now sanitized and upper case 162 + 163 + const uint64_t prefix = (uint64_t)_mm_cvtsi128_si64(input); 164 + const uint8_t index = hash(prefix); 165 + *code = (uint16_t)types_and_classes[index].mnemonic->value; 166 + *mnemonic = types_and_classes[index].mnemonic; 167 + 168 + const __m128i compar = _mm_loadu_si128((const __m128i *)(*mnemonic)->key.data); 169 + const __m128i xorthem = _mm_xor_si128(compar, input); 170 + 171 + // FIXME: make sure length matches too! 172 + if (likely(_mm_test_all_zeros(xorthem, xorthem))) 173 + return types_and_classes[index].code == 1; 174 + else if ((prefix & TYPE_MASK) == TYPE) 175 + return scan_generic_type(data, length, code, mnemonic); 176 + return 0; 177 + } 178 + 179 + #undef TYPE 180 + #undef TYPE_MASK 181 + #undef CLASS 182 + #undef CLASS_MASK 183 + 184 + #endif // TYPE_H
+525
usr.sbin/nsd/simdzone/src/zone.c
··· 1 + /* 2 + * zone.c -- zone parser 3 + * 4 + * Copyright (c) 2022-2023, NLnet Labs. All rights reserved. 5 + * 6 + * SPDX-License-Identifier: BSD-3-Clause 7 + * 8 + */ 9 + #include "config.h" 10 + 11 + #include <assert.h> 12 + #include <errno.h> 13 + #include <string.h> 14 + #include <fcntl.h> 15 + #include <stdarg.h> 16 + #include <sys/stat.h> 17 + #include <stdlib.h> 18 + #include <limits.h> 19 + #include <stddef.h> 20 + #if _WIN32 21 + # include <direct.h> 22 + #else 23 + # include <unistd.h> 24 + #endif 25 + 26 + #include "zone.h" 27 + 28 + typedef zone_parser_t parser_t; // convenience 29 + typedef zone_file_t file_t; 30 + 31 + #include "attributes.h" 32 + #include "diagnostic.h" 33 + 34 + #if _MSC_VER 35 + # define strcasecmp(s1, s2) _stricmp(s1, s2) 36 + # define strncasecmp(s1, s2, n) _strnicmp(s1, s2, n) 37 + #else 38 + #include <strings.h> 39 + #endif 40 + 41 + static const char not_a_file[] = "<string>"; 42 + 43 + #include "isadetection.h" 44 + 45 + #ifndef PATH_MAX 46 + #define PATH_MAX 4096 47 + #endif 48 + 49 + #if HAVE_HASWELL 50 + extern int32_t zone_haswell_parse(parser_t *); 51 + #endif 52 + 53 + #if HAVE_WESTMERE 54 + extern int32_t zone_westmere_parse(parser_t *); 55 + #endif 56 + 57 + extern int32_t zone_fallback_parse(parser_t *); 58 + 59 + typedef struct kernel kernel_t; 60 + struct kernel { 61 + const char *name; 62 + uint32_t instruction_set; 63 + int32_t (*parse)(parser_t *); 64 + }; 65 + 66 + static const kernel_t kernels[] = { 67 + #if HAVE_HASWELL 68 + { "haswell", AVX2, &zone_haswell_parse }, 69 + #endif 70 + #if HAVE_WESTMERE 71 + { "westmere", SSE42|PCLMULQDQ, &zone_westmere_parse }, 72 + #endif 73 + { "fallback", DEFAULT, &zone_fallback_parse } 74 + }; 75 + 76 + diagnostic_push() 77 + msvc_diagnostic_ignored(4996) 78 + 79 + static inline const kernel_t * 80 + select_kernel(void) 81 + { 82 + const char *preferred; 83 + const uint32_t supported = detect_supported_architectures(); 84 + const size_t length = sizeof(kernels)/sizeof(kernels[0]); 85 + size_t count = 0; 86 + 87 + if ((preferred = getenv("ZONE_KERNEL"))) { 88 + for (; count < length; count++) 89 + if (strcasecmp(preferred, kernels[count].name) == 0) 90 + break; 91 + if (count == length) 92 + count = 0; 93 + } 94 + 95 + for (; count < length; count++) 96 + if ((kernels[count].instruction_set & supported) == (kernels[count].instruction_set)) 97 + return &kernels[count]; 98 + 99 + return &kernels[length - 1]; 100 + } 101 + 102 + diagnostic_pop() 103 + 104 + static int32_t parse(parser_t *parser, void *user_data) 105 + { 106 + const kernel_t *kernel; 107 + 108 + kernel = select_kernel(); 109 + assert(kernel); 110 + parser->user_data = user_data; 111 + return kernel->parse(parser); 112 + } 113 + 114 + diagnostic_push() 115 + msvc_diagnostic_ignored(4996) 116 + 117 + #if _WIN32 118 + // The Win32 API offers PathIsRelative, but it requires linking with shlwapi. 119 + // Rewriting a relative path is not too complex, unlike correct conversion of 120 + // Windows paths in general (https://googleprojectzero.blogspot.com/2016/02/). 121 + // Rooted paths, relative or not, unc and extended paths are never resolved 122 + // relative to the includer. 123 + nonnull_all 124 + static int32_t resolve_path(const char *include, char **path) 125 + { 126 + if ((*path = _fullpath(NULL, include, 0))) 127 + return 0; 128 + return (errno == ENOMEM) ? ZONE_OUT_OF_MEMORY : ZONE_NOT_A_FILE; 129 + } 130 + #else 131 + nonnull_all 132 + static int32_t resolve_path(const char *include, char **path) 133 + { 134 + char *resolved; 135 + char buffer[PATH_MAX + 1]; 136 + 137 + if (!(resolved = realpath(include, buffer))) 138 + return (errno == ENOMEM) ? ZONE_OUT_OF_MEMORY : ZONE_NOT_A_FILE; 139 + assert(resolved == buffer); 140 + size_t length = strlen(buffer); 141 + if (!(resolved = malloc(length + 1))) 142 + return ZONE_OUT_OF_MEMORY; 143 + memcpy(resolved, buffer, length + 1); 144 + *path = resolved; 145 + return 0; 146 + } 147 + #endif 148 + 149 + nonnull((1)) 150 + static void close_file( 151 + parser_t *parser, file_t *file) 152 + { 153 + assert((file->name == not_a_file) == (file->path == not_a_file)); 154 + 155 + const bool is_string = file->name == not_a_file || file->path == not_a_file; 156 + 157 + assert(!is_string || file == &parser->first); 158 + assert(!is_string || file->handle == NULL); 159 + (void)parser; 160 + 161 + const bool is_stdin = file->name && 162 + file->name != not_a_file && 163 + strcmp(file->name, "-") == 0; 164 + assert(!is_stdin || (!file->handle || file->handle == stdin)); 165 + 166 + if (file->buffer.data && !is_string) 167 + free(file->buffer.data); 168 + file->buffer.data = NULL; 169 + if (file->name && file->name != not_a_file) 170 + free((char *)file->name); 171 + file->name = NULL; 172 + if (file->path && file->path != not_a_file) 173 + free((char *)file->path); 174 + file->path = NULL; 175 + // stdin is not opened, it must not be closed 176 + if (file->handle && file->handle != stdin) 177 + (void)fclose(file->handle); 178 + file->handle = NULL; 179 + } 180 + 181 + nonnull_all 182 + static void initialize_file( 183 + parser_t *parser, file_t *file) 184 + { 185 + const size_t size = offsetof(file_t, fields.head); 186 + memset(file, 0, size); 187 + 188 + if (file == &parser->first) { 189 + file->includer = NULL; 190 + memcpy(file->origin.octets, 191 + parser->options.origin.octets, 192 + parser->options.origin.length); 193 + file->origin.length = parser->options.origin.length; 194 + file->last_class = parser->options.default_class; 195 + file->dollar_ttl = parser->options.default_ttl; 196 + file->last_ttl = parser->options.default_ttl; 197 + file->ttl = file->default_ttl = &file->last_ttl; 198 + } else { 199 + assert(parser->file); 200 + file->includer = parser->file; 201 + memcpy(&file->origin, &parser->file->origin, sizeof(file->origin)); 202 + // Retain class and TTL values. 203 + file->last_class = parser->file->last_class; 204 + file->dollar_ttl = parser->file->dollar_ttl; 205 + file->last_ttl = parser->file->last_ttl; 206 + // RRs appearing after the $TTL directive that do not explicitly include 207 + // a TTL value, have their TTL set to the TTL in the $TTL directive. RRs 208 + // appearing before a $TTL directive use the last explicitly stated value. 209 + if (parser->file->default_ttl == &parser->file->last_ttl) 210 + file->ttl = file->default_ttl = &file->last_ttl; 211 + else 212 + file->ttl = file->default_ttl = &file->dollar_ttl; 213 + } 214 + 215 + file->line = 1; 216 + file->name = (char *)not_a_file; 217 + file->path = (char *)not_a_file; 218 + file->handle = NULL; 219 + file->buffer.data = NULL; 220 + file->start_of_line = true; 221 + file->end_of_file = 1; 222 + file->fields.tape[0] = NULL; 223 + file->fields.head = file->fields.tail = file->fields.tape; 224 + file->delimiters.tape[0] = NULL; 225 + file->delimiters.head = file->delimiters.tail = file->delimiters.tape; 226 + file->newlines.tape[0] = 0; 227 + file->newlines.head = file->newlines.tail = file->newlines.tape; 228 + } 229 + 230 + nonnull_all 231 + static int32_t open_file( 232 + parser_t *parser, file_t *file, const char *include, size_t length) 233 + { 234 + int32_t code; 235 + const size_t size = ZONE_WINDOW_SIZE + 1 + ZONE_BLOCK_SIZE; 236 + 237 + initialize_file(parser, file); 238 + 239 + file->path = NULL; 240 + if (!(file->name = malloc(length + 1))) 241 + return ZONE_OUT_OF_MEMORY; 242 + memcpy(file->name, include, length); 243 + file->name[length] = '\0'; 244 + if (!(file->buffer.data = malloc(size))) 245 + return (void)close_file(parser, file), ZONE_OUT_OF_MEMORY; 246 + file->buffer.data[0] = '\0'; 247 + file->buffer.size = ZONE_WINDOW_SIZE; 248 + file->end_of_file = 0; 249 + file->fields.tape[0] = &file->buffer.data[0]; 250 + file->fields.tape[1] = &file->buffer.data[0]; 251 + 252 + if(file == &parser->first && strcmp(file->name, "-") == 0) { 253 + if (!(file->path = malloc(2))) 254 + return (void)close_file(parser, file), ZONE_OUT_OF_MEMORY; 255 + file->path[0] = '-'; 256 + file->path[1] = '\0'; 257 + } else { 258 + // The file is resolved relative to the working directory. The absolute 259 + // path is used to protect against recusive includes. Not for opening the 260 + // file as file descriptors for pipes and sockets the entries will be 261 + // symoblic links whose content is the file type with the inode. 262 + // See NLnetLabs/nsd#380. 263 + if ((code = resolve_path(file->name, &file->path))) 264 + return (void)close_file(parser, file), code; 265 + } 266 + 267 + if(strcmp(file->path, "-") == 0) { 268 + file->handle = stdin; 269 + return 0; 270 + } else { 271 + if ((file->handle = fopen(file->name, "rb"))) 272 + return 0; 273 + } 274 + 275 + switch (errno) { 276 + case ENOMEM: 277 + code = ZONE_OUT_OF_MEMORY; 278 + break; 279 + case EACCES: 280 + code = ZONE_NOT_PERMITTED; 281 + break; 282 + default: 283 + code = ZONE_NOT_A_FILE; 284 + break; 285 + } 286 + 287 + close_file(parser, file); 288 + return code; 289 + } 290 + 291 + diagnostic_pop() 292 + 293 + diagnostic_push() 294 + clang_diagnostic_ignored(missing-prototypes) 295 + 296 + nonnull((1)) 297 + void zone_close_file( 298 + parser_t *parser, zone_file_t *file) 299 + { 300 + if (!file) 301 + return; 302 + close_file(parser, file); 303 + free(file); 304 + } 305 + 306 + nonnull_all 307 + int32_t zone_open_file( 308 + parser_t *parser, const char *path, size_t length, zone_file_t **file) 309 + { 310 + int32_t code; 311 + 312 + if (!(*file = malloc(sizeof(**file)))) 313 + return ZONE_OUT_OF_MEMORY; 314 + if ((code = open_file(parser, *file, path, length)) == 0) 315 + return 0; 316 + 317 + free(*file); 318 + 319 + const char *reason = NULL; 320 + switch (code) { 321 + case ZONE_OUT_OF_MEMORY: reason = "out of memory"; break; 322 + case ZONE_NOT_PERMITTED: reason = "access denied"; break; 323 + case ZONE_NOT_A_FILE: reason = "no such file"; break; 324 + } 325 + 326 + assert(reason); 327 + zone_error(parser, "Cannot open %.*s, %s", (int)length, path, reason); 328 + return code; 329 + } 330 + 331 + nonnull_all 332 + void zone_close(parser_t *parser) 333 + { 334 + assert(parser); 335 + for (zone_file_t *file = parser->file, *includer; file; file = includer) { 336 + includer = file->includer; 337 + close_file(parser, file); 338 + if (file != &parser->first) 339 + free(file); 340 + } 341 + } 342 + 343 + nonnull((1,2,3)) 344 + static int32_t initialize_parser( 345 + zone_parser_t *parser, 346 + const zone_options_t *options, 347 + zone_buffers_t *buffers, 348 + void *user_data) 349 + { 350 + if (!options->accept.callback) 351 + return ZONE_BAD_PARAMETER; 352 + if (!options->default_ttl) 353 + return ZONE_BAD_PARAMETER; 354 + if (!options->secondary && options->default_ttl > INT32_MAX) 355 + return ZONE_BAD_PARAMETER; 356 + if (!options->origin.octets || !options->origin.length) 357 + return ZONE_BAD_PARAMETER; 358 + 359 + const uint8_t *root = &options->origin.octets[options->origin.length - 1]; 360 + if (root[0] != 0) 361 + return ZONE_BAD_PARAMETER; 362 + const uint8_t *label = &options->origin.octets[0]; 363 + while (label < root) { 364 + if (root - label < label[0]) 365 + return ZONE_BAD_PARAMETER; 366 + label += label[0] + 1; 367 + } 368 + 369 + if (label != root) 370 + return ZONE_BAD_PARAMETER; 371 + 372 + const size_t size = offsetof(parser_t, file); 373 + memset(parser, 0, size); 374 + parser->options = *options; 375 + parser->user_data = user_data; 376 + parser->file = &parser->first; 377 + parser->buffers.size = buffers->size; 378 + parser->buffers.owner.active = 0; 379 + parser->buffers.owner.blocks = buffers->owner; 380 + parser->buffers.rdata.active = 0; 381 + parser->buffers.rdata.blocks = buffers->rdata; 382 + parser->owner = &parser->buffers.owner.blocks[0]; 383 + parser->owner->length = 0; 384 + parser->rdata = &parser->buffers.rdata.blocks[0]; 385 + 386 + if (!parser->options.no_includes && !parser->options.include_limit) 387 + parser->options.include_limit = 10; // arbitrary, default in NSD 388 + 389 + return 0; 390 + } 391 + 392 + int32_t zone_open( 393 + zone_parser_t *parser, 394 + const zone_options_t *options, 395 + zone_buffers_t *buffers, 396 + const char *path, 397 + void *user_data) 398 + { 399 + int32_t code; 400 + 401 + if ((code = initialize_parser(parser, options, buffers, user_data)) < 0) 402 + return code; 403 + if ((code = open_file(parser, &parser->first, path, strlen(path))) == 0) 404 + return 0; 405 + 406 + const char *reason = NULL; 407 + switch (code) { 408 + case ZONE_OUT_OF_MEMORY: reason = "out of memory"; break; 409 + case ZONE_NOT_PERMITTED: reason = "access denied"; break; 410 + case ZONE_NOT_A_FILE: reason = "no such file"; break; 411 + } 412 + 413 + assert(reason); 414 + zone_error(parser, "Cannot open %s, %s", path, reason); 415 + return code; 416 + } 417 + 418 + diagnostic_pop() 419 + 420 + int32_t zone_parse( 421 + zone_parser_t *parser, 422 + const zone_options_t *options, 423 + zone_buffers_t *buffers, 424 + const char *path, 425 + void *user_data) 426 + { 427 + int32_t code; 428 + 429 + if ((code = zone_open(parser, options, buffers, path, user_data)) < 0) 430 + return code; 431 + code = parse(parser, user_data); 432 + zone_close(parser); 433 + return code; 434 + } 435 + 436 + int32_t zone_parse_string( 437 + parser_t *parser, 438 + const zone_options_t *options, 439 + zone_buffers_t *buffers, 440 + const char *string, 441 + size_t length, 442 + void *user_data) 443 + { 444 + int32_t code; 445 + 446 + if ((code = initialize_parser(parser, options, buffers, user_data)) < 0) 447 + return code; 448 + if (!length || string[length] != '\0') 449 + return ZONE_BAD_PARAMETER; 450 + initialize_file(parser, parser->file); 451 + parser->file->buffer.data = (char *)string; 452 + parser->file->buffer.size = length; 453 + parser->file->buffer.length = length; 454 + parser->file->fields.tape[0] = &string[length]; 455 + parser->file->fields.tape[1] = &string[length]; 456 + assert(parser->file->end_of_file == 1); 457 + 458 + code = parse(parser, user_data); 459 + zone_close(parser); 460 + return code; 461 + } 462 + 463 + zone_nonnull((1,5)) 464 + static void print_message( 465 + zone_parser_t *parser, 466 + uint32_t priority, 467 + const char *file, 468 + size_t line, 469 + const char *message, 470 + void *user_data) 471 + { 472 + (void)parser; 473 + (void)user_data; 474 + 475 + assert(parser->file); 476 + FILE *output = priority == ZONE_INFO ? stdout : stderr; 477 + 478 + if (file) 479 + fprintf(output, "%s:%zu: %s\n", file, line, message); 480 + else 481 + fprintf(output, "%s\n", message); 482 + } 483 + 484 + void zone_vlog( 485 + zone_parser_t *parser, 486 + uint32_t priority, 487 + const char *format, 488 + va_list arguments); 489 + 490 + void zone_vlog( 491 + zone_parser_t *parser, 492 + uint32_t priority, 493 + const char *format, 494 + va_list arguments) 495 + { 496 + char message[2048]; 497 + int length; 498 + zone_log_t callback = print_message; 499 + 500 + if (!(priority & ~parser->options.log.mask)) 501 + return; 502 + 503 + length = vsnprintf(message, sizeof(message), format, arguments); 504 + assert(length >= 0); 505 + if ((size_t)length >= sizeof(message)) 506 + memcpy(message+(sizeof(message) - 4), "...", 3); 507 + if (parser->options.log.callback) 508 + callback = parser->options.log.callback; 509 + assert(parser->file); 510 + const char *file = parser->file->name; 511 + const size_t line = parser->file->line; 512 + callback(parser, priority, file, line, message, parser->user_data); 513 + } 514 + 515 + void zone_log( 516 + zone_parser_t *parser, 517 + uint32_t priority, 518 + const char *format, 519 + ...) 520 + { 521 + va_list arguments; 522 + va_start(arguments, format); 523 + zone_vlog(parser, priority, format, arguments); 524 + va_end(arguments); 525 + }